Merged trunk
This commit is contained in:
1
Authors
1
Authors
@@ -1,3 +1,4 @@
|
||||
Adam Gandelman <adamg@canonical.com>
|
||||
Alex Meade <alex.meade@rackspace.com>
|
||||
Alexander Sakhnov <asakhnov@mirantis.com>
|
||||
Andrey Brindeyev <abrindeyev@griddynamics.com>
|
||||
|
||||
@@ -91,7 +91,7 @@ def init_leases(interface):
|
||||
"""Get the list of hosts for an interface."""
|
||||
ctxt = context.get_admin_context()
|
||||
network_ref = db.network_get_by_bridge(ctxt, interface)
|
||||
return linux_net.get_dhcp_leases(ctxt, network_ref['id'])
|
||||
return linux_net.get_dhcp_leases(ctxt, network_ref)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -479,7 +479,7 @@ class ProjectCommands(object):
|
||||
except db.api.NoMoreNetworks:
|
||||
print _('No more networks available. If this is a new '
|
||||
'installation, you need\nto call something like this:\n\n'
|
||||
' nova-manage network create 10.0.0.0/8 10 64\n\n')
|
||||
' nova-manage network create pvt 10.0.0.0/8 10 64\n\n')
|
||||
except exception.ProcessExecutionError, e:
|
||||
print e
|
||||
print _("The above error may show that the certificate db has not "
|
||||
@@ -500,7 +500,7 @@ class FixedIpCommands(object):
|
||||
if host is None:
|
||||
fixed_ips = db.fixed_ip_get_all(ctxt)
|
||||
else:
|
||||
fixed_ips = db.fixed_ip_get_all_by_host(ctxt, host)
|
||||
fixed_ips = db.fixed_ip_get_all_by_instance_host(ctxt, host)
|
||||
except exception.NotFound as ex:
|
||||
print "error: %s" % ex
|
||||
sys.exit(2)
|
||||
@@ -564,17 +564,17 @@ class NetworkCommands(object):
|
||||
"""Class for managing networks."""
|
||||
|
||||
def create(self, label=None, fixed_range=None, num_networks=None,
|
||||
network_size=None, vlan_start=None,
|
||||
network_size=None, multi_host=None, vlan_start=None,
|
||||
vpn_start=None, fixed_range_v6=None, gateway_v6=None,
|
||||
flat_network_bridge=None, bridge_interface=None):
|
||||
"""Creates fixed ips for host by range
|
||||
arguments: label, fixed_range, [num_networks=FLAG],
|
||||
[network_size=FLAG], [vlan_start=FLAG],
|
||||
[network_size=FLAG], [multi_host=FLAG], [vlan_start=FLAG],
|
||||
[vpn_start=FLAG], [fixed_range_v6=FLAG], [gateway_v6=FLAG],
|
||||
[flat_network_bridge=FLAG], [bridge_interface=FLAG]
|
||||
If you wish to use a later argument fill in the gaps with 0s
|
||||
Ex: network create private 10.0.0.0/8 1 15 0 0 0 0 xenbr1 eth1
|
||||
network create private 10.0.0.0/8 1 15
|
||||
If you wish to use a later argument fill in the gaps with ""s
|
||||
Ex: network create private 10.0.0.0/8 1 16 T "" "" "" "" xenbr1 eth1
|
||||
network create private 10.0.0.0/8 1 16
|
||||
"""
|
||||
if not label:
|
||||
msg = _('a label (ex: public) is required to create networks.')
|
||||
@@ -589,6 +589,10 @@ class NetworkCommands(object):
|
||||
num_networks = FLAGS.num_networks
|
||||
if not network_size:
|
||||
network_size = FLAGS.network_size
|
||||
if not multi_host:
|
||||
multi_host = FLAGS.multi_host
|
||||
else:
|
||||
multi_host = multi_host == 'T'
|
||||
if not vlan_start:
|
||||
vlan_start = FLAGS.vlan_start
|
||||
if not vpn_start:
|
||||
@@ -607,6 +611,7 @@ class NetworkCommands(object):
|
||||
net_manager.create_networks(context.get_admin_context(),
|
||||
label=label,
|
||||
cidr=fixed_range,
|
||||
multi_host=multi_host,
|
||||
num_networks=int(num_networks),
|
||||
network_size=int(network_size),
|
||||
vlan_start=int(vlan_start),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# under the License.
|
||||
|
||||
from webob import exc
|
||||
import webob
|
||||
|
||||
from nova import console
|
||||
from nova import exception
|
||||
@@ -86,7 +87,7 @@ class Controller(object):
|
||||
int(id))
|
||||
except exception.NotFound:
|
||||
return faults.Fault(exc.HTTPNotFound())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
|
||||
def create_resource():
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"""The multinic extension."""
|
||||
|
||||
from webob import exc
|
||||
import webob
|
||||
|
||||
from nova import compute
|
||||
from nova import log as logging
|
||||
@@ -103,7 +104,7 @@ class Multinic(extensions.ExtensionDescriptor):
|
||||
except Exception, e:
|
||||
LOG.exception(_("Error in addFixedIp %s"), e)
|
||||
return faults.Fault(exc.HTTPBadRequest())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _remove_fixed_ip(self, input_dict, req, id):
|
||||
"""Removes an IP from an instance."""
|
||||
@@ -122,4 +123,4 @@ class Multinic(extensions.ExtensionDescriptor):
|
||||
except Exception, e:
|
||||
LOG.exception(_("Error in removeFixedIp %s"), e)
|
||||
return faults.Fault(exc.HTTPBadRequest())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"""The volumes extension."""
|
||||
|
||||
from webob import exc
|
||||
import webob
|
||||
|
||||
from nova import compute
|
||||
from nova import exception
|
||||
@@ -104,7 +105,7 @@ class VolumeController(object):
|
||||
self.volume_api.delete(context, volume_id=id)
|
||||
except exception.NotFound:
|
||||
return faults.Fault(exc.HTTPNotFound())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def index(self, req):
|
||||
"""Returns a summary list of volumes."""
|
||||
@@ -279,7 +280,7 @@ class VolumeAttachmentController(object):
|
||||
self.compute_api.detach_volume(context,
|
||||
volume_id=volume_id)
|
||||
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _items(self, req, server_id, entity_maker):
|
||||
"""Returns a list of attachments, transformed through entity_maker."""
|
||||
|
||||
@@ -40,6 +40,7 @@ class Fault(webob.exc.HTTPException):
|
||||
def __init__(self, exception):
|
||||
"""Create a Fault for the given webob.exc.exception."""
|
||||
self.wrapped_exc = exception
|
||||
self.status_int = exception.status_int
|
||||
|
||||
@webob.dec.wsgify(RequestClass=wsgi.Request)
|
||||
def __call__(self, req):
|
||||
|
||||
@@ -17,6 +17,7 @@ import base64
|
||||
import traceback
|
||||
|
||||
from webob import exc
|
||||
import webob
|
||||
|
||||
from nova import compute
|
||||
from nova import db
|
||||
@@ -189,7 +190,7 @@ class Controller(object):
|
||||
except Exception, e:
|
||||
LOG.exception(_("Error in revert-resize %s"), e)
|
||||
return faults.Fault(exc.HTTPBadRequest())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _action_resize(self, input_dict, req, id):
|
||||
return exc.HTTPNotImplemented()
|
||||
@@ -207,7 +208,7 @@ class Controller(object):
|
||||
except Exception, e:
|
||||
LOG.exception(_("Error in reboot %s"), e)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _action_migrate(self, input_dict, req, id):
|
||||
try:
|
||||
@@ -215,7 +216,7 @@ class Controller(object):
|
||||
except Exception, e:
|
||||
LOG.exception(_("Error in migrate %s"), e)
|
||||
return faults.Fault(exc.HTTPBadRequest())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def lock(self, req, id):
|
||||
@@ -231,7 +232,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("Compute.api::lock %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def unlock(self, req, id):
|
||||
@@ -247,7 +248,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("Compute.api::unlock %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def get_lock(self, req, id):
|
||||
@@ -262,7 +263,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("Compute.api::get_lock %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def reset_network(self, req, id, body):
|
||||
@@ -277,7 +278,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("Compute.api::reset_network %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def inject_network_info(self, req, id, body):
|
||||
@@ -292,7 +293,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("Compute.api::inject_network_info %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def pause(self, req, id, body):
|
||||
@@ -304,7 +305,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("Compute.api::pause %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def unpause(self, req, id, body):
|
||||
@@ -316,7 +317,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("Compute.api::unpause %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def suspend(self, req, id, body):
|
||||
@@ -328,7 +329,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("compute.api::suspend %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def resume(self, req, id, body):
|
||||
@@ -340,7 +341,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("compute.api::resume %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def rescue(self, req, id):
|
||||
@@ -352,7 +353,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("compute.api::rescue %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def unrescue(self, req, id):
|
||||
@@ -364,7 +365,7 @@ class Controller(object):
|
||||
readable = traceback.format_exc()
|
||||
LOG.exception(_("compute.api::unrescue %s"), readable)
|
||||
return faults.Fault(exc.HTTPUnprocessableEntity())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def get_ajax_console(self, req, id):
|
||||
@@ -374,7 +375,7 @@ class Controller(object):
|
||||
int(id))
|
||||
except exception.NotFound:
|
||||
return faults.Fault(exc.HTTPNotFound())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def get_vnc_console(self, req, id):
|
||||
@@ -384,7 +385,7 @@ class Controller(object):
|
||||
int(id))
|
||||
except exception.NotFound:
|
||||
return faults.Fault(exc.HTTPNotFound())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@scheduler_api.redirect_handler
|
||||
def diagnostics(self, req, id):
|
||||
@@ -416,7 +417,7 @@ class ControllerV10(Controller):
|
||||
self.compute_api.delete(req.environ['nova.context'], id)
|
||||
except exception.NotFound:
|
||||
return faults.Fault(exc.HTTPNotFound())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _image_ref_from_req_data(self, data):
|
||||
return data['server']['imageId']
|
||||
@@ -450,7 +451,7 @@ class ControllerV10(Controller):
|
||||
except Exception, e:
|
||||
LOG.exception(_("Error in resize %s"), e)
|
||||
return faults.Fault(exc.HTTPBadRequest())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _action_rebuild(self, info, request, instance_id):
|
||||
context = request.environ['nova.context']
|
||||
@@ -470,9 +471,7 @@ class ControllerV10(Controller):
|
||||
LOG.debug(msg)
|
||||
return faults.Fault(exc.HTTPConflict(explanation=msg))
|
||||
|
||||
response = exc.HTTPAccepted()
|
||||
response.empty_body = True
|
||||
return response
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _get_server_admin_password(self, server):
|
||||
""" Determine the admin password for a server on creation """
|
||||
@@ -519,7 +518,7 @@ class ControllerV11(Controller):
|
||||
msg = _("Invalid adminPass")
|
||||
return exc.HTTPBadRequest(explanation=msg)
|
||||
self.compute_api.set_admin_password(context, id, password)
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _limit_items(self, items, req):
|
||||
return common.limited_by_marker(items, req)
|
||||
@@ -565,7 +564,7 @@ class ControllerV11(Controller):
|
||||
except Exception, e:
|
||||
LOG.exception(_("Error in resize %s"), e)
|
||||
return faults.Fault(exc.HTTPBadRequest())
|
||||
return exc.HTTPAccepted()
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def _action_rebuild(self, info, request, instance_id):
|
||||
context = request.environ['nova.context']
|
||||
@@ -594,9 +593,7 @@ class ControllerV11(Controller):
|
||||
LOG.debug(msg)
|
||||
return faults.Fault(exc.HTTPConflict(explanation=msg))
|
||||
|
||||
response = exc.HTTPAccepted()
|
||||
response.empty_body = True
|
||||
return response
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def get_default_xmlns(self, req):
|
||||
return common.XML_NS_V11
|
||||
|
||||
@@ -77,8 +77,6 @@ flags.DEFINE_integer('live_migration_retry_count', 30,
|
||||
flags.DEFINE_integer("rescue_timeout", 0,
|
||||
"Automatically unrescue an instance after N seconds."
|
||||
" Set to 0 to disable.")
|
||||
flags.DEFINE_bool('auto_assign_floating_ip', False,
|
||||
'Autoassigning floating ip to VM')
|
||||
flags.DEFINE_integer('host_state_interval', 120,
|
||||
'Interval in seconds for querying the host status')
|
||||
|
||||
@@ -283,16 +281,19 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
"""Launch a new instance with specified options."""
|
||||
context = context.elevated()
|
||||
instance = self.db.instance_get(context, instance_id)
|
||||
instance.injected_files = kwargs.get('injected_files', [])
|
||||
instance.admin_pass = kwargs.get('admin_password', None)
|
||||
if instance['name'] in self.driver.list_instances():
|
||||
raise exception.Error(_("Instance has already been created"))
|
||||
LOG.audit(_("instance %s: starting..."), instance_id,
|
||||
context=context)
|
||||
self.db.instance_update(context,
|
||||
instance_id,
|
||||
{'host': self.host, 'launched_on': self.host})
|
||||
|
||||
updates = {}
|
||||
updates['host'] = self.host
|
||||
updates['launched_on'] = self.host
|
||||
# NOTE(vish): used by virt but not in database
|
||||
updates['injected_files'] = kwargs.get('injected_files', [])
|
||||
updates['admin_pass'] = kwargs.get('admin_password', None)
|
||||
instance = self.db.instance_update(context,
|
||||
instance_id,
|
||||
updates)
|
||||
self.db.instance_set_state(context,
|
||||
instance_id,
|
||||
power_state.NOSTATE,
|
||||
|
||||
@@ -332,13 +332,14 @@ def fixed_ip_associate(context, address, instance_id):
|
||||
return IMPL.fixed_ip_associate(context, address, instance_id)
|
||||
|
||||
|
||||
def fixed_ip_associate_pool(context, network_id, instance_id):
|
||||
"""Find free ip in network and associate it to instance.
|
||||
def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None):
|
||||
"""Find free ip in network and associate it to instance or host.
|
||||
|
||||
Raises if one is not available.
|
||||
|
||||
"""
|
||||
return IMPL.fixed_ip_associate_pool(context, network_id, instance_id)
|
||||
return IMPL.fixed_ip_associate_pool(context, network_id,
|
||||
instance_id, host)
|
||||
|
||||
|
||||
def fixed_ip_create(context, values):
|
||||
@@ -361,9 +362,9 @@ def fixed_ip_get_all(context):
|
||||
return IMPL.fixed_ip_get_all(context)
|
||||
|
||||
|
||||
def fixed_ip_get_all_by_host(context, host):
|
||||
"""Get all defined fixed ips used by a host."""
|
||||
return IMPL.fixed_ip_get_all_by_host(context, host)
|
||||
def fixed_ip_get_all_by_instance_host(context, host):
|
||||
"""Get all allocated fixed ips filtered by instance host."""
|
||||
return IMPL.fixed_ip_get_all_instance_by_host(context, host)
|
||||
|
||||
|
||||
def fixed_ip_get_by_address(context, address):
|
||||
@@ -376,6 +377,11 @@ def fixed_ip_get_by_instance(context, instance_id):
|
||||
return IMPL.fixed_ip_get_by_instance(context, instance_id)
|
||||
|
||||
|
||||
def fixed_ip_get_by_network_host(context, network_id, host):
|
||||
"""Get fixed ip for a host in a network."""
|
||||
return IMPL.fixed_ip_get_by_network_host(context, network_id, host)
|
||||
|
||||
|
||||
def fixed_ip_get_by_virtual_interface(context, vif_id):
|
||||
"""Get fixed ips by virtual interface or raise if none exist."""
|
||||
return IMPL.fixed_ip_get_by_virtual_interface(context, vif_id)
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"""
|
||||
Implementation of SQLAlchemy backend.
|
||||
"""
|
||||
import traceback
|
||||
import warnings
|
||||
|
||||
from nova import db
|
||||
@@ -33,7 +32,6 @@ from sqlalchemy import or_
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy.orm import joinedload_all
|
||||
from sqlalchemy.sql import exists
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.sql.expression import literal_column
|
||||
|
||||
@@ -672,7 +670,7 @@ def fixed_ip_associate(context, address, instance_id):
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def fixed_ip_associate_pool(context, network_id, instance_id):
|
||||
def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
network_or_none = or_(models.FixedIp.network_id == network_id,
|
||||
@@ -682,6 +680,7 @@ def fixed_ip_associate_pool(context, network_id, instance_id):
|
||||
filter_by(reserved=False).\
|
||||
filter_by(deleted=False).\
|
||||
filter_by(instance=None).\
|
||||
filter_by(host=None).\
|
||||
with_lockmode('update').\
|
||||
first()
|
||||
# NOTE(vish): if with_lockmode isn't supported, as in sqlite,
|
||||
@@ -692,9 +691,12 @@ def fixed_ip_associate_pool(context, network_id, instance_id):
|
||||
fixed_ip_ref.network = network_get(context,
|
||||
network_id,
|
||||
session=session)
|
||||
fixed_ip_ref.instance = instance_get(context,
|
||||
instance_id,
|
||||
session=session)
|
||||
if instance_id:
|
||||
fixed_ip_ref.instance = instance_get(context,
|
||||
instance_id,
|
||||
session=session)
|
||||
if host:
|
||||
fixed_ip_ref.host = host
|
||||
session.add(fixed_ip_ref)
|
||||
return fixed_ip_ref['address']
|
||||
|
||||
@@ -750,7 +752,7 @@ def fixed_ip_get_all(context, session=None):
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def fixed_ip_get_all_by_host(context, host=None):
|
||||
def fixed_ip_get_all_by_instance_host(context, host=None):
|
||||
session = get_session()
|
||||
|
||||
result = session.query(models.FixedIp).\
|
||||
@@ -799,6 +801,20 @@ def fixed_ip_get_by_instance(context, instance_id):
|
||||
return rv
|
||||
|
||||
|
||||
@require_context
|
||||
def fixed_ip_get_by_network_host(context, network_id, host):
|
||||
session = get_session()
|
||||
rv = session.query(models.FixedIp).\
|
||||
filter_by(network_id=network_id).\
|
||||
filter_by(host=host).\
|
||||
filter_by(deleted=False).\
|
||||
first()
|
||||
if not rv:
|
||||
raise exception.FixedIpNotFoundForNetworkHost(network_id=network_id,
|
||||
host=host)
|
||||
return rv
|
||||
|
||||
|
||||
@require_context
|
||||
def fixed_ip_get_by_virtual_interface(context, vif_id):
|
||||
session = get_session()
|
||||
@@ -1480,8 +1496,6 @@ def network_associate(context, project_id, force=False):
|
||||
called by project_get_networks under certain conditions
|
||||
and network manager add_network_to_project()
|
||||
|
||||
only associates projects with networks that have configured hosts
|
||||
|
||||
only associate if the project doesn't already have a network
|
||||
or if force is True
|
||||
|
||||
@@ -1497,7 +1511,6 @@ def network_associate(context, project_id, force=False):
|
||||
def network_query(project_filter):
|
||||
return session.query(models.Network).\
|
||||
filter_by(deleted=False).\
|
||||
filter(models.Network.host != None).\
|
||||
filter_by(project_id=project_filter).\
|
||||
with_lockmode('update').\
|
||||
first()
|
||||
@@ -1704,9 +1717,16 @@ def network_get_all_by_instance(_context, instance_id):
|
||||
def network_get_all_by_host(context, host):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
# NOTE(vish): return networks that have host set
|
||||
# or that have a fixed ip with host set
|
||||
host_filter = or_(models.Network.host == host,
|
||||
models.FixedIp.host == host)
|
||||
|
||||
return session.query(models.Network).\
|
||||
filter_by(deleted=False).\
|
||||
filter_by(host=host).\
|
||||
join(models.Network.fixed_ips).\
|
||||
filter(host_filter).\
|
||||
filter_by(deleted=False).\
|
||||
all()
|
||||
|
||||
|
||||
@@ -1738,6 +1758,7 @@ def network_update(context, network_id, values):
|
||||
network_ref = network_get(context, network_id, session=session)
|
||||
network_ref.update(values)
|
||||
network_ref.save(session=session)
|
||||
return network_ref
|
||||
|
||||
|
||||
###################
|
||||
|
||||
44
nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py
Normal file
44
nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2011 OpenStack, LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from sqlalchemy import Column, Table, MetaData, Boolean, String
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
fixed_ips_host = Column('host', String(255))
|
||||
|
||||
networks_multi_host = Column('multi_host', Boolean, default=False)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
|
||||
fixed_ips = Table('fixed_ips', meta, autoload=True)
|
||||
fixed_ips.create_column(fixed_ips_host)
|
||||
|
||||
networks = Table('networks', meta, autoload=True)
|
||||
networks.create_column(networks_multi_host)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
|
||||
fixed_ips = Table('fixed_ips', meta, autoload=True)
|
||||
fixed_ips.drop_column(fixed_ips_host)
|
||||
|
||||
networks = Table('networks', meta, autoload=True)
|
||||
networks.drop_column(networks_multi_host)
|
||||
@@ -545,6 +545,7 @@ class Network(BASE, NovaBase):
|
||||
injected = Column(Boolean, default=False)
|
||||
cidr = Column(String(255), unique=True)
|
||||
cidr_v6 = Column(String(255), unique=True)
|
||||
multi_host = Column(Boolean, default=False)
|
||||
|
||||
gateway_v6 = Column(String(255))
|
||||
netmask_v6 = Column(String(255))
|
||||
@@ -603,6 +604,7 @@ class FixedIp(BASE, NovaBase):
|
||||
# leased means dhcp bridge has leased the ip
|
||||
leased = Column(Boolean, default=False)
|
||||
reserved = Column(Boolean, default=False)
|
||||
host = Column(String(255))
|
||||
|
||||
|
||||
class FloatingIp(BASE, NovaBase):
|
||||
|
||||
@@ -408,6 +408,11 @@ class FixedIpNotFoundForInstance(FixedIpNotFound):
|
||||
message = _("Instance %(instance_id)s has zero fixed ips.")
|
||||
|
||||
|
||||
class FixedIpNotFoundForNetworkHost(FixedIpNotFound):
|
||||
message = _("Network host %(host)s has zero fixed ips "
|
||||
"in network %(network_id)s.")
|
||||
|
||||
|
||||
class FixedIpNotFoundForSpecificInstance(FixedIpNotFound):
|
||||
message = _("Instance %(instance_id)s doesn't have fixed ip '%(ip)s'.")
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
"""Handles all requests relating to instances (guest vms)."""
|
||||
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
@@ -112,7 +111,11 @@ class API(base.Base):
|
||||
'(%(project)s)') %
|
||||
{'address': floating_ip['address'],
|
||||
'project': context.project_id})
|
||||
host = fixed_ip['network']['host']
|
||||
# NOTE(vish): if we are multi_host, send to the instances host
|
||||
if fixed_ip['network']['multi_host']:
|
||||
host = fixed_ip['instance']['host']
|
||||
else:
|
||||
host = fixed_ip['network']['host']
|
||||
rpc.cast(context,
|
||||
self.db.queue_get_for(context, FLAGS.network_topic, host),
|
||||
{'method': 'associate_floating_ip',
|
||||
@@ -127,7 +130,11 @@ class API(base.Base):
|
||||
return
|
||||
if not floating_ip.get('fixed_ip'):
|
||||
raise exception.ApiError('Address is not associated.')
|
||||
host = floating_ip['fixed_ip']['network']['host']
|
||||
# NOTE(vish): if we are multi_host, send to the instances host
|
||||
if floating_ip['fixed_ip']['network']['multi_host']:
|
||||
host = floating_ip['fixed_ip']['instance']['host']
|
||||
else:
|
||||
host = floating_ip['fixed_ip']['network']['host']
|
||||
rpc.call(context,
|
||||
self.db.queue_get_for(context, FLAGS.network_topic, host),
|
||||
{'method': 'disassociate_floating_ip',
|
||||
@@ -141,7 +148,9 @@ class API(base.Base):
|
||||
args = kwargs
|
||||
args['instance_id'] = instance['id']
|
||||
args['project_id'] = instance['project_id']
|
||||
args['host'] = instance['host']
|
||||
args['instance_type_id'] = instance['instance_type_id']
|
||||
|
||||
return rpc.call(context, FLAGS.network_topic,
|
||||
{'method': 'allocate_for_instance',
|
||||
'args': args})
|
||||
@@ -180,7 +189,8 @@ class API(base.Base):
|
||||
def get_instance_nw_info(self, context, instance):
|
||||
"""Returns all network info related to an instance."""
|
||||
args = {'instance_id': instance['id'],
|
||||
'instance_type_id': instance['instance_type_id']}
|
||||
'instance_type_id': instance['instance_type_id'],
|
||||
'host': instance['host']}
|
||||
return rpc.call(context, FLAGS.network_topic,
|
||||
{'method': 'get_instance_nw_info',
|
||||
'args': args})
|
||||
|
||||
@@ -498,7 +498,7 @@ def ensure_bridge(bridge, interface, net_attrs=None):
|
||||
suffix = net_attrs['cidr'].rpartition('/')[2]
|
||||
out, err = _execute('sudo', 'ip', 'addr', 'add',
|
||||
'%s/%s' %
|
||||
(net_attrs['gateway'], suffix),
|
||||
(net_attrs['dhcp_server'], suffix),
|
||||
'brd',
|
||||
net_attrs['broadcast'],
|
||||
'dev',
|
||||
@@ -552,21 +552,27 @@ def ensure_bridge(bridge, interface, net_attrs=None):
|
||||
bridge)
|
||||
|
||||
|
||||
def get_dhcp_leases(context, network_id):
|
||||
def get_dhcp_leases(context, network_ref):
|
||||
"""Return a network's hosts config in dnsmasq leasefile format."""
|
||||
hosts = []
|
||||
for fixed_ip_ref in db.network_get_associated_fixed_ips(context,
|
||||
network_id):
|
||||
hosts.append(_host_lease(fixed_ip_ref))
|
||||
for fixed_ref in db.network_get_associated_fixed_ips(context,
|
||||
network_ref['id']):
|
||||
host = fixed_ref['instance']['host']
|
||||
if network_ref['multi_host'] and FLAGS.host != host:
|
||||
continue
|
||||
hosts.append(_host_lease(fixed_ref))
|
||||
return '\n'.join(hosts)
|
||||
|
||||
|
||||
def get_dhcp_hosts(context, network_id):
|
||||
def get_dhcp_hosts(context, network_ref):
|
||||
"""Get network's hosts config in dhcp-host format."""
|
||||
hosts = []
|
||||
for fixed_ip_ref in db.network_get_associated_fixed_ips(context,
|
||||
network_id):
|
||||
hosts.append(_host_dhcp(fixed_ip_ref))
|
||||
for fixed_ref in db.network_get_associated_fixed_ips(context,
|
||||
network_ref['id']):
|
||||
host = fixed_ref['instance']['host']
|
||||
if network_ref['multi_host'] and FLAGS.host != host:
|
||||
continue
|
||||
hosts.append(_host_dhcp(fixed_ref))
|
||||
return '\n'.join(hosts)
|
||||
|
||||
|
||||
@@ -574,18 +580,16 @@ def get_dhcp_hosts(context, network_id):
|
||||
# configuration options (like dchp-range, vlan, ...)
|
||||
# aren't reloaded.
|
||||
@utils.synchronized('dnsmasq_start')
|
||||
def update_dhcp(context, network_id):
|
||||
def update_dhcp(context, network_ref):
|
||||
"""(Re)starts a dnsmasq server for a given network.
|
||||
|
||||
If a dnsmasq instance is already running then send a HUP
|
||||
signal causing it to reload, otherwise spawn a new instance.
|
||||
|
||||
"""
|
||||
network_ref = db.network_get(context, network_id)
|
||||
|
||||
conffile = _dhcp_file(network_ref['bridge'], 'conf')
|
||||
with open(conffile, 'w') as f:
|
||||
f.write(get_dhcp_hosts(context, network_id))
|
||||
f.write(get_dhcp_hosts(context, network_ref))
|
||||
|
||||
# Make sure dnsmasq can actually read it (it setuid()s to "nobody")
|
||||
os.chmod(conffile, 0644)
|
||||
@@ -613,9 +617,7 @@ def update_dhcp(context, network_id):
|
||||
|
||||
|
||||
@utils.synchronized('radvd_start')
|
||||
def update_ra(context, network_id):
|
||||
network_ref = db.network_get(context, network_id)
|
||||
|
||||
def update_ra(context, network_ref):
|
||||
conffile = _ra_file(network_ref['bridge'], 'conf')
|
||||
with open(conffile, 'w') as f:
|
||||
conf_str = """
|
||||
@@ -651,9 +653,6 @@ interface %s
|
||||
LOG.debug(_('Pid %d is stale, relaunching radvd'), pid)
|
||||
command = _ra_cmd(network_ref)
|
||||
_execute(*command)
|
||||
db.network_update(context, network_id,
|
||||
{'gateway_v6':
|
||||
utils.get_my_linklocal(network_ref['bridge'])})
|
||||
|
||||
|
||||
def _host_lease(fixed_ip_ref):
|
||||
@@ -702,10 +701,11 @@ def _dnsmasq_cmd(net):
|
||||
cmd = ['sudo', '-E', 'dnsmasq',
|
||||
'--strict-order',
|
||||
'--bind-interfaces',
|
||||
'--interface=%s' % net['bridge'],
|
||||
'--conf-file=%s' % FLAGS.dnsmasq_config_file,
|
||||
'--domain=%s' % FLAGS.dhcp_domain,
|
||||
'--pid-file=%s' % _dhcp_file(net['bridge'], 'pid'),
|
||||
'--listen-address=%s' % net['gateway'],
|
||||
'--listen-address=%s' % net['dhcp_server'],
|
||||
'--except-interface=lo',
|
||||
'--dhcp-range=%s,static,120s' % net['dhcp_start'],
|
||||
'--dhcp-lease-max=%s' % len(netaddr.IPNetwork(net['cidr'])),
|
||||
|
||||
@@ -28,7 +28,6 @@ topologies. All of the network commands are issued to a subclass of
|
||||
:flat_network_bridge: Bridge device for simple network instances
|
||||
:flat_interface: FlatDhcp will bridge into this interface if set
|
||||
:flat_network_dns: Dns for simple network
|
||||
:flat_network_dhcp_start: Dhcp start for FlatDhcp
|
||||
:vlan_start: First VLAN for private networks
|
||||
:vpn_ip: Public IP for the cloudpipe VPN servers
|
||||
:vpn_start: First Vpn port for private networks
|
||||
@@ -49,7 +48,6 @@ import datetime
|
||||
import math
|
||||
import netaddr
|
||||
import socket
|
||||
import pickle
|
||||
from eventlet import greenpool
|
||||
|
||||
from nova import context
|
||||
@@ -78,8 +76,6 @@ flags.DEFINE_bool('flat_injected', True,
|
||||
'Whether to attempt to inject network setup into guest')
|
||||
flags.DEFINE_string('flat_interface', None,
|
||||
'FlatDhcp will bridge into this interface if set')
|
||||
flags.DEFINE_string('flat_network_dhcp_start', '10.0.0.2',
|
||||
'Dhcp start for FlatDhcp')
|
||||
flags.DEFINE_integer('vlan_start', 100, 'First VLAN for private networks')
|
||||
flags.DEFINE_string('vlan_interface', None,
|
||||
'vlans will bridge into this interface if set')
|
||||
@@ -87,6 +83,8 @@ flags.DEFINE_integer('num_networks', 1, 'Number of networks to support')
|
||||
flags.DEFINE_string('vpn_ip', '$my_ip',
|
||||
'Public IP for the cloudpipe VPN servers')
|
||||
flags.DEFINE_integer('vpn_start', 1000, 'First Vpn port for private networks')
|
||||
flags.DEFINE_bool('multi_host', False,
|
||||
'Default value for multi_host in networks')
|
||||
flags.DEFINE_integer('network_size', 256,
|
||||
'Number of addresses in each private subnet')
|
||||
flags.DEFINE_string('floating_range', '4.4.4.0/24',
|
||||
@@ -104,7 +102,8 @@ flags.DEFINE_integer('fixed_ip_disassociate_timeout', 600,
|
||||
'Seconds after which a deallocated ip is disassociated')
|
||||
flags.DEFINE_integer('create_unique_mac_address_attempts', 5,
|
||||
'Number of attempts to create unique mac address')
|
||||
|
||||
flags.DEFINE_bool('auto_assign_floating_ip', False,
|
||||
'Autoassigning floating ip to VM')
|
||||
flags.DEFINE_bool('use_ipv6', False,
|
||||
'use the ipv6')
|
||||
flags.DEFINE_string('network_host', socket.gethostname(),
|
||||
@@ -124,16 +123,26 @@ class RPCAllocateFixedIP(object):
|
||||
used since they share code to RPC.call allocate_fixed_ip on the
|
||||
correct network host to configure dnsmasq
|
||||
"""
|
||||
def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
|
||||
def _allocate_fixed_ips(self, context, instance_id, host, networks,
|
||||
**kwargs):
|
||||
"""Calls allocate_fixed_ip once for each network."""
|
||||
green_pool = greenpool.GreenPool()
|
||||
|
||||
vpn = kwargs.pop('vpn')
|
||||
for network in networks:
|
||||
if network['host'] != self.host:
|
||||
# NOTE(vish): if we are not multi_host pass to the network host
|
||||
if not network['multi_host']:
|
||||
host = network['host']
|
||||
# NOTE(vish): if there is no network host, set one
|
||||
if host == None:
|
||||
host = rpc.call(context, FLAGS.network_topic,
|
||||
{'method': 'set_network_host',
|
||||
'args': {'network_ref': network}})
|
||||
if host != self.host:
|
||||
# need to call allocate_fixed_ip to correct network host
|
||||
topic = self.db.queue_get_for(context, FLAGS.network_topic,
|
||||
network['host'])
|
||||
topic = self.db.queue_get_for(context,
|
||||
FLAGS.network_topic,
|
||||
host)
|
||||
args = {}
|
||||
args['instance_id'] = instance_id
|
||||
args['network_id'] = network['id']
|
||||
@@ -149,12 +158,13 @@ class RPCAllocateFixedIP(object):
|
||||
# wait for all of the allocates (if any) to finish
|
||||
green_pool.waitall()
|
||||
|
||||
def _rpc_allocate_fixed_ip(self, context, instance_id, network_id):
|
||||
def _rpc_allocate_fixed_ip(self, context, instance_id, network_id,
|
||||
**kwargs):
|
||||
"""Sits in between _allocate_fixed_ips and allocate_fixed_ip to
|
||||
perform network lookup on the far side of rpc.
|
||||
"""
|
||||
network = self.db.network_get(context, network_id)
|
||||
self.allocate_fixed_ip(context, instance_id, network)
|
||||
self.allocate_fixed_ip(context, instance_id, network, **kwargs)
|
||||
|
||||
|
||||
class FloatingIP(object):
|
||||
@@ -193,7 +203,7 @@ class FloatingIP(object):
|
||||
# which is currently the NetworkManager version
|
||||
# do this first so fixed ip is already allocated
|
||||
ips = super(FloatingIP, self).allocate_for_instance(context, **kwargs)
|
||||
if hasattr(FLAGS, 'auto_assign_floating_ip'):
|
||||
if FLAGS.auto_assign_floating_ip:
|
||||
# allocate a floating ip (public_ip is just the address string)
|
||||
public_ip = self.allocate_floating_ip(context, project_id)
|
||||
# set auto_assigned column to true for the floating ip
|
||||
@@ -300,15 +310,36 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
super(NetworkManager, self).__init__(service_name='network',
|
||||
*args, **kwargs)
|
||||
|
||||
@utils.synchronized('get_dhcp')
|
||||
def _get_dhcp_ip(self, context, network_ref, host=None):
|
||||
"""Get the proper dhcp address to listen on."""
|
||||
# NOTE(vish): this is for compatibility
|
||||
if not network_ref['multi_host']:
|
||||
return network_ref['gateway']
|
||||
|
||||
if not host:
|
||||
host = self.host
|
||||
network_id = network_ref['id']
|
||||
try:
|
||||
fip = self.db.fixed_ip_get_by_network_host(context,
|
||||
network_id,
|
||||
host)
|
||||
return fip['address']
|
||||
except exception.FixedIpNotFoundForNetworkHost:
|
||||
elevated = context.elevated()
|
||||
return self.db.fixed_ip_associate_pool(elevated,
|
||||
network_id,
|
||||
host=host)
|
||||
|
||||
def init_host(self):
|
||||
"""Do any initialization that needs to be run if this is a
|
||||
standalone service.
|
||||
"""
|
||||
# Set up this host for networks in which it's already
|
||||
# the designated network host.
|
||||
# NOTE(vish): Set up networks for which this host already has
|
||||
# an ip address.
|
||||
ctxt = context.get_admin_context()
|
||||
for network in self.db.network_get_all_by_host(ctxt, self.host):
|
||||
self._on_set_network_host(ctxt, network['id'])
|
||||
self._setup_network(ctxt, network)
|
||||
|
||||
def periodic_tasks(self, context=None):
|
||||
"""Tasks to be run at a periodic interval."""
|
||||
@@ -323,32 +354,13 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
if num:
|
||||
LOG.debug(_('Dissassociated %s stale fixed ip(s)'), num)
|
||||
|
||||
# setup any new networks which have been created
|
||||
self.set_network_hosts(context)
|
||||
|
||||
def set_network_host(self, context, network_id):
|
||||
def set_network_host(self, context, network_ref):
|
||||
"""Safely sets the host of the network."""
|
||||
LOG.debug(_('setting network host'), context=context)
|
||||
host = self.db.network_set_host(context,
|
||||
network_id,
|
||||
network_ref['id'],
|
||||
self.host)
|
||||
if host == self.host:
|
||||
self._on_set_network_host(context, network_id)
|
||||
|
||||
def set_network_hosts(self, context):
|
||||
"""Set the network hosts for any networks which are unset."""
|
||||
try:
|
||||
networks = self.db.network_get_all(context)
|
||||
except exception.NoNetworksFound:
|
||||
# no networks found, nothing to do
|
||||
return
|
||||
|
||||
for network in networks:
|
||||
host = network['host']
|
||||
if not host:
|
||||
# break so worker will only grab 1 (to help scale flatter)
|
||||
self.set_network_host(context, network['id'])
|
||||
break
|
||||
return host
|
||||
|
||||
def _get_networks_for_instance(self, context, instance_id, project_id):
|
||||
"""Determine & return which networks an instance should connect to."""
|
||||
@@ -361,9 +373,9 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
# we don't care if no networks are found
|
||||
pass
|
||||
|
||||
# return only networks which are not vlan networks and have host set
|
||||
# return only networks which are not vlan networks
|
||||
return [network for network in networks if
|
||||
not network['vlan'] and network['host']]
|
||||
not network['vlan']]
|
||||
|
||||
def allocate_for_instance(self, context, **kwargs):
|
||||
"""Handles allocating the various network resources for an instance.
|
||||
@@ -371,6 +383,7 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
rpc.called by network_api
|
||||
"""
|
||||
instance_id = kwargs.pop('instance_id')
|
||||
host = kwargs.pop('host')
|
||||
project_id = kwargs.pop('project_id')
|
||||
type_id = kwargs.pop('instance_type_id')
|
||||
vpn = kwargs.pop('vpn')
|
||||
@@ -379,9 +392,11 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
context=context)
|
||||
networks = self._get_networks_for_instance(admin_context, instance_id,
|
||||
project_id)
|
||||
LOG.warn(networks)
|
||||
self._allocate_mac_addresses(context, instance_id, networks)
|
||||
self._allocate_fixed_ips(admin_context, instance_id, networks, vpn=vpn)
|
||||
return self.get_instance_nw_info(context, instance_id, type_id)
|
||||
self._allocate_fixed_ips(admin_context, instance_id, host, networks,
|
||||
vpn=vpn)
|
||||
return self.get_instance_nw_info(context, instance_id, type_id, host)
|
||||
|
||||
def deallocate_for_instance(self, context, **kwargs):
|
||||
"""Handles deallocating various network resources for an instance.
|
||||
@@ -401,7 +416,8 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
# deallocate vifs (mac addresses)
|
||||
self.db.virtual_interface_delete_by_instance(context, instance_id)
|
||||
|
||||
def get_instance_nw_info(self, context, instance_id, instance_type_id):
|
||||
def get_instance_nw_info(self, context, instance_id,
|
||||
instance_type_id, host):
|
||||
"""Creates network info list for instance.
|
||||
|
||||
called by allocate_for_instance and netowrk_api
|
||||
@@ -446,10 +462,18 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
'cidr_v6': network['cidr_v6'],
|
||||
'injected': network['injected'],
|
||||
'vlan': network['vlan'],
|
||||
'bridge_interface': network['bridge_interface']}
|
||||
'bridge_interface': network['bridge_interface'],
|
||||
'multi_host': network['multi_host']}
|
||||
if network['multi_host']:
|
||||
dhcp_server = self._get_dhcp_ip(context, network, host)
|
||||
else:
|
||||
dhcp_server = self._get_dhcp_ip(context,
|
||||
network,
|
||||
network['host'])
|
||||
info = {
|
||||
'label': network['label'],
|
||||
'gateway': network['gateway'],
|
||||
'dhcp_server': dhcp_server,
|
||||
'broadcast': network['broadcast'],
|
||||
'mac': vif['address'],
|
||||
'rxtx_cap': flavor['rxtx_cap'],
|
||||
@@ -489,10 +513,10 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
random.randint(0x00, 0xff)]
|
||||
return ':'.join(map(lambda x: "%02x" % x, mac))
|
||||
|
||||
def add_fixed_ip_to_instance(self, context, instance_id, network_id):
|
||||
def add_fixed_ip_to_instance(self, context, instance_id, host, network_id):
|
||||
"""Adds a fixed ip to an instance from specified network."""
|
||||
networks = [self.db.network_get(context, network_id)]
|
||||
self._allocate_fixed_ips(context, instance_id, networks)
|
||||
self._allocate_fixed_ips(context, instance_id, host, networks)
|
||||
|
||||
def remove_fixed_ip_from_instance(self, context, instance_id, address):
|
||||
"""Removes a fixed ip from an instance from specified network."""
|
||||
@@ -519,6 +543,7 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
values = {'allocated': True,
|
||||
'virtual_interface_id': vif['id']}
|
||||
self.db.fixed_ip_update(context, address, values)
|
||||
self._setup_network(context, network)
|
||||
return address
|
||||
|
||||
def deallocate_fixed_ip(self, context, address, **kwargs):
|
||||
@@ -564,10 +589,10 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
# means there will stale entries in the conf file
|
||||
# the code below will update the file if necessary
|
||||
if FLAGS.update_dhcp_on_disassociate:
|
||||
network = self.db.fixed_ip_get_network(context, address)
|
||||
self.driver.update_dhcp(context, network['id'])
|
||||
network_ref = self.db.fixed_ip_get_network(context, address)
|
||||
self._setup_network(context, network_ref)
|
||||
|
||||
def create_networks(self, context, label, cidr, num_networks,
|
||||
def create_networks(self, context, label, cidr, multi_host, num_networks,
|
||||
network_size, cidr_v6, gateway_v6, bridge,
|
||||
bridge_interface, **kwargs):
|
||||
"""Create networks based on parameters."""
|
||||
@@ -586,6 +611,7 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
net['bridge_interface'] = bridge_interface
|
||||
net['dns'] = FLAGS.flat_network_dns
|
||||
net['cidr'] = cidr
|
||||
net['multi_host'] = multi_host
|
||||
net['netmask'] = str(project_net.netmask)
|
||||
net['gateway'] = str(project_net[1])
|
||||
net['broadcast'] = str(project_net.broadcast)
|
||||
@@ -661,12 +687,13 @@ class NetworkManager(manager.SchedulerDependentManager):
|
||||
'address': address,
|
||||
'reserved': reserved})
|
||||
|
||||
def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
|
||||
def _allocate_fixed_ips(self, context, instance_id, host, networks,
|
||||
**kwargs):
|
||||
"""Calls allocate_fixed_ip once for each network."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def _on_set_network_host(self, context, network_id):
|
||||
"""Called when this host becomes the host for a network."""
|
||||
def _setup_network(self, context, network_ref):
|
||||
"""Sets up network on this host."""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@@ -700,7 +727,8 @@ class FlatManager(NetworkManager):
|
||||
|
||||
timeout_fixed_ips = False
|
||||
|
||||
def _allocate_fixed_ips(self, context, instance_id, networks, **kwargs):
|
||||
def _allocate_fixed_ips(self, context, instance_id, host, networks,
|
||||
**kwargs):
|
||||
"""Calls allocate_fixed_ip once for each network."""
|
||||
for network in networks:
|
||||
self.allocate_fixed_ip(context, instance_id, network)
|
||||
@@ -711,12 +739,12 @@ class FlatManager(NetworkManager):
|
||||
**kwargs)
|
||||
self.db.fixed_ip_disassociate(context, address)
|
||||
|
||||
def _on_set_network_host(self, context, network_id):
|
||||
"""Called when this host becomes the host for a network."""
|
||||
def _setup_network(self, context, network_ref):
|
||||
"""Setup Network on this host."""
|
||||
net = {}
|
||||
net['injected'] = FLAGS.flat_injected
|
||||
net['dns'] = FLAGS.flat_network_dns
|
||||
self.db.network_update(context, network_id, net)
|
||||
self.db.network_update(context, network_ref['id'], net)
|
||||
|
||||
|
||||
class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager):
|
||||
@@ -740,27 +768,20 @@ class FlatDHCPManager(FloatingIP, RPCAllocateFixedIP, NetworkManager):
|
||||
|
||||
self.driver.metadata_forward()
|
||||
|
||||
def allocate_fixed_ip(self, context, instance_id, network, **kwargs):
|
||||
"""Allocate flat_network fixed_ip, then setup dhcp for this network."""
|
||||
address = super(FlatDHCPManager, self).allocate_fixed_ip(context,
|
||||
instance_id,
|
||||
network)
|
||||
if not FLAGS.fake_network:
|
||||
self.driver.update_dhcp(context, network['id'])
|
||||
|
||||
def _on_set_network_host(self, context, network_id):
|
||||
"""Called when this host becomes the host for a project."""
|
||||
net = {}
|
||||
net['dhcp_start'] = FLAGS.flat_network_dhcp_start
|
||||
self.db.network_update(context, network_id, net)
|
||||
network = db.network_get(context, network_id)
|
||||
self.driver.ensure_bridge(network['bridge'],
|
||||
network['bridge_interface'],
|
||||
network)
|
||||
def _setup_network(self, context, network_ref):
|
||||
"""Sets up network on this host."""
|
||||
network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref)
|
||||
self.driver.ensure_bridge(network_ref['bridge'],
|
||||
network_ref['bridge_interface'],
|
||||
network_ref)
|
||||
if not FLAGS.fake_network:
|
||||
self.driver.update_dhcp(context, network_id)
|
||||
self.driver.update_dhcp(context, network_ref)
|
||||
if(FLAGS.use_ipv6):
|
||||
self.driver.update_ra(context, network_id)
|
||||
self.driver.update_ra(context, network_ref)
|
||||
gateway = utils.get_my_linklocal(network_ref['bridge'])
|
||||
self.db.network_update(context, network_ref['id'],
|
||||
{'gateway_v6': gateway})
|
||||
|
||||
|
||||
class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
|
||||
@@ -809,8 +830,8 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
|
||||
values = {'allocated': True,
|
||||
'virtual_interface_id': vif['id']}
|
||||
self.db.fixed_ip_update(context, address, values)
|
||||
if not FLAGS.fake_network:
|
||||
self.driver.update_dhcp(context, network['id'])
|
||||
self._setup_network(context, network)
|
||||
return address
|
||||
|
||||
def add_network_to_project(self, context, project_id):
|
||||
"""Force adds another network to a project."""
|
||||
@@ -819,10 +840,7 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
|
||||
def _get_networks_for_instance(self, context, instance_id, project_id):
|
||||
"""Determine which networks an instance should connect to."""
|
||||
# get networks associated with project
|
||||
networks = self.db.project_get_networks(context, project_id)
|
||||
|
||||
# return only networks which have host set
|
||||
return [network for network in networks if network['host']]
|
||||
return self.db.project_get_networks(context, project_id)
|
||||
|
||||
def create_networks(self, context, **kwargs):
|
||||
"""Create networks based on parameters."""
|
||||
@@ -841,33 +859,35 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
|
||||
|
||||
NetworkManager.create_networks(self, context, vpn=True, **kwargs)
|
||||
|
||||
def _on_set_network_host(self, context, network_id):
|
||||
"""Called when this host becomes the host for a network."""
|
||||
network = self.db.network_get(context, network_id)
|
||||
if not network['vpn_public_address']:
|
||||
def _setup_network(self, context, network_ref):
|
||||
"""Sets up network on this host."""
|
||||
network_ref['dhcp_server'] = self._get_dhcp_ip(context, network_ref)
|
||||
if not network_ref['vpn_public_address']:
|
||||
net = {}
|
||||
address = FLAGS.vpn_ip
|
||||
net['vpn_public_address'] = address
|
||||
db.network_update(context, network_id, net)
|
||||
network_ref = db.network_update(context, network_ref['id'], net)
|
||||
else:
|
||||
address = network['vpn_public_address']
|
||||
|
||||
self.driver.ensure_vlan_bridge(network['vlan'],
|
||||
network['bridge'],
|
||||
network['bridge_interface'],
|
||||
network)
|
||||
address = network_ref['vpn_public_address']
|
||||
self.driver.ensure_vlan_bridge(network_ref['vlan'],
|
||||
network_ref['bridge'],
|
||||
network_ref['bridge_interface'],
|
||||
network_ref)
|
||||
|
||||
# NOTE(vish): only ensure this forward if the address hasn't been set
|
||||
# manually.
|
||||
if address == FLAGS.vpn_ip and hasattr(self.driver,
|
||||
"ensure_vlan_forward"):
|
||||
self.driver.ensure_vlan_forward(FLAGS.vpn_ip,
|
||||
network['vpn_public_port'],
|
||||
network['vpn_private_address'])
|
||||
network_ref['vpn_public_port'],
|
||||
network_ref['vpn_private_address'])
|
||||
if not FLAGS.fake_network:
|
||||
self.driver.update_dhcp(context, network_id)
|
||||
self.driver.update_dhcp(context, network_ref)
|
||||
if(FLAGS.use_ipv6):
|
||||
self.driver.update_ra(context, network_id)
|
||||
self.driver.update_ra(context, network_ref)
|
||||
gateway = utils.get_my_linklocal(network_ref['bridge'])
|
||||
self.db.network_update(context, network_ref['id'],
|
||||
{'gateway_v6': gateway})
|
||||
|
||||
@property
|
||||
def _bottom_reserved_ips(self):
|
||||
|
||||
@@ -59,6 +59,7 @@ def setup():
|
||||
network.create_networks(ctxt,
|
||||
label='test',
|
||||
cidr=FLAGS.fixed_range,
|
||||
multi_host=FLAGS.multi_host,
|
||||
num_networks=FLAGS.num_networks,
|
||||
network_size=FLAGS.network_size,
|
||||
cidr_v6=FLAGS.fixed_range_v6,
|
||||
@@ -68,7 +69,7 @@ def setup():
|
||||
vpn_start=FLAGS.vpn_start,
|
||||
vlan_start=FLAGS.vlan_start)
|
||||
for net in db.network_get_all(ctxt):
|
||||
network.set_network_host(ctxt, net['id'])
|
||||
network.set_network_host(ctxt, net)
|
||||
|
||||
cleandb = os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db)
|
||||
shutil.copyfile(testdb, cleandb)
|
||||
|
||||
@@ -139,3 +139,8 @@ class TestFaults(test.TestCase):
|
||||
self.assertEqual(resp.content_type, "application/xml")
|
||||
self.assertEqual(resp.status_int, 404)
|
||||
self.assertTrue('whut?' in resp.body)
|
||||
|
||||
def test_fault_has_status_int(self):
|
||||
"""Ensure the status_int is set correctly on faults"""
|
||||
fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='what?'))
|
||||
self.assertEqual(fault.status_int, 400)
|
||||
|
||||
@@ -62,6 +62,7 @@ def _create_network_info(count=1, ipv6=None):
|
||||
'vlan': fake_vlan,
|
||||
'bridge_interface': fake_bridge_interface}
|
||||
mapping = {'mac': fake,
|
||||
'dhcp_server': fake,
|
||||
'gateway': fake,
|
||||
'gateway6': fake,
|
||||
'ips': [{'ip': fake_ip}, {'ip': fake_ip}]}
|
||||
|
||||
@@ -45,6 +45,7 @@ class FakeModel(dict):
|
||||
networks = [{'id': 0,
|
||||
'label': 'test0',
|
||||
'injected': False,
|
||||
'multi_host': False,
|
||||
'cidr': '192.168.0.0/24',
|
||||
'cidr_v6': '2001:db8::/64',
|
||||
'gateway_v6': '2001:db8::1',
|
||||
@@ -62,6 +63,7 @@ networks = [{'id': 0,
|
||||
{'id': 1,
|
||||
'label': 'test1',
|
||||
'injected': False,
|
||||
'multi_host': False,
|
||||
'cidr': '192.168.1.0/24',
|
||||
'cidr_v6': '2001:db9::/64',
|
||||
'gateway_v6': '2001:db9::1',
|
||||
@@ -122,20 +124,6 @@ class FlatNetworkTestCase(test.TestCase):
|
||||
self.network = network_manager.FlatManager(host=HOST)
|
||||
self.network.db = db
|
||||
|
||||
def test_set_network_hosts(self):
|
||||
self.mox.StubOutWithMock(db, 'network_get_all')
|
||||
self.mox.StubOutWithMock(db, 'network_set_host')
|
||||
self.mox.StubOutWithMock(db, 'network_update')
|
||||
|
||||
db.network_get_all(mox.IgnoreArg()).AndReturn([networks[0]])
|
||||
db.network_set_host(mox.IgnoreArg(),
|
||||
networks[0]['id'],
|
||||
mox.IgnoreArg()).AndReturn(HOST)
|
||||
db.network_update(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.network.set_network_hosts(None)
|
||||
|
||||
def test_get_instance_nw_info(self):
|
||||
self.mox.StubOutWithMock(db, 'fixed_ip_get_by_instance')
|
||||
self.mox.StubOutWithMock(db, 'virtual_interface_get_by_instance')
|
||||
@@ -149,7 +137,7 @@ class FlatNetworkTestCase(test.TestCase):
|
||||
mox.IgnoreArg()).AndReturn(flavor)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
nw_info = self.network.get_instance_nw_info(None, 0, 0)
|
||||
nw_info = self.network.get_instance_nw_info(None, 0, 0, None)
|
||||
|
||||
self.assertTrue(nw_info)
|
||||
|
||||
@@ -166,6 +154,7 @@ class FlatNetworkTestCase(test.TestCase):
|
||||
self.assertDictMatch(nw[0], check)
|
||||
|
||||
check = {'broadcast': '192.168.%s.255' % i,
|
||||
'dhcp_server': '192.168.%s.1' % i,
|
||||
'dns': 'DONTCARE',
|
||||
'gateway': '192.168.%s.1' % i,
|
||||
'gateway6': '2001:db%s::1' % i8,
|
||||
|
||||
@@ -35,7 +35,6 @@ class LibvirtBridge(object):
|
||||
def get_configurations(self, network, mapping):
|
||||
"""Get a dictionary of VIF configurations for bridge type."""
|
||||
# Assume that the gateway also acts as the dhcp server.
|
||||
dhcp_server = mapping['gateway']
|
||||
gateway6 = mapping.get('gateway6')
|
||||
mac_id = mapping['mac'].replace(':', '')
|
||||
|
||||
@@ -58,7 +57,7 @@ class LibvirtBridge(object):
|
||||
'bridge_name': network['bridge'],
|
||||
'mac_address': mapping['mac'],
|
||||
'ip_address': mapping['ips'][0]['ip'],
|
||||
'dhcp_server': dhcp_server,
|
||||
'dhcp_server': mapping['dhcp_server'],
|
||||
'extra_params': extra_params,
|
||||
}
|
||||
|
||||
@@ -73,8 +72,9 @@ class LibvirtBridgeDriver(VIFDriver, LibvirtBridge):
|
||||
|
||||
def plug(self, instance, network, mapping):
|
||||
"""Ensure that the bridge exists, and add VIF to it."""
|
||||
linux_net.ensure_bridge(network['bridge'],
|
||||
network['bridge_interface'])
|
||||
if not network.get('multi_host'):
|
||||
linux_net.ensure_bridge(network['bridge'],
|
||||
network['bridge_interface'])
|
||||
return self.get_configurations(network, mapping)
|
||||
|
||||
def unplug(self, instance, network, mapping):
|
||||
@@ -86,8 +86,9 @@ class LibvirtVlanBridgeDriver(VIFDriver, LibvirtBridge):
|
||||
|
||||
def plug(self, instance, network, mapping):
|
||||
"""Ensure that VLAN and bridge exist and add VIF to the bridge."""
|
||||
linux_net.ensure_vlan_bridge(network['vlan'], network['bridge'],
|
||||
network['bridge_interface'])
|
||||
if not network.get('multi_host'):
|
||||
linux_net.ensure_vlan_bridge(network['vlan'], network['bridge'],
|
||||
network['bridge_interface'])
|
||||
return self.get_configurations(network, mapping)
|
||||
|
||||
def unplug(self, instance, network, mapping):
|
||||
|
||||
@@ -344,6 +344,7 @@ class VMOps(object):
|
||||
_check_agent_version()
|
||||
_inject_files()
|
||||
_set_admin_password()
|
||||
self.reset_network(instance, vm_ref)
|
||||
return True
|
||||
except Exception, exc:
|
||||
LOG.warn(exc)
|
||||
@@ -353,9 +354,6 @@ class VMOps(object):
|
||||
|
||||
timer.f = _wait_for_boot
|
||||
|
||||
# call to reset network to configure network from xenstore
|
||||
self.reset_network(instance, vm_ref)
|
||||
|
||||
return timer.start(interval=0.5, now=True)
|
||||
|
||||
def _handle_spawn_error(self, vdis, spawn_error):
|
||||
|
||||
@@ -72,7 +72,9 @@ def key_init(self, arg_dict):
|
||||
info to be passed, such as passwords. Returns the shared
|
||||
secret key value.
|
||||
"""
|
||||
pub = int(arg_dict["pub"])
|
||||
# WARNING: Some older Windows agents will crash if the public key isn't
|
||||
# a string
|
||||
pub = arg_dict["pub"]
|
||||
arg_dict["value"] = json.dumps({"name": "keyinit", "value": pub})
|
||||
request_id = arg_dict["id"]
|
||||
arg_dict["path"] = "data/host/%s" % request_id
|
||||
|
||||
Reference in New Issue
Block a user