summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/consoles.py3
-rw-r--r--nova/api/openstack/contrib/multinic.py5
-rw-r--r--nova/api/openstack/contrib/vifs.py85
-rw-r--r--nova/api/openstack/contrib/volumes.py5
-rw-r--r--nova/api/openstack/faults.py1
-rw-r--r--nova/api/openstack/servers.py49
-rw-r--r--nova/compute/manager.py17
-rw-r--r--nova/db/api.py18
-rw-r--r--nova/db/sqlalchemy/api.py43
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py44
-rw-r--r--nova/db/sqlalchemy/models.py2
-rw-r--r--nova/exception.py5
-rw-r--r--nova/network/api.py18
-rw-r--r--nova/network/linux_net.py40
-rw-r--r--nova/network/manager.py245
-rw-r--r--nova/tests/__init__.py3
-rw-r--r--nova/tests/api/openstack/test_faults.py5
-rw-r--r--nova/tests/test_libvirt.py4
-rw-r--r--nova/tests/test_network.py24
-rw-r--r--nova/tests/test_xenapi.py2
-rw-r--r--nova/virt/driver.py1
-rw-r--r--nova/virt/libvirt/connection.py2
-rw-r--r--nova/virt/libvirt/vif.py53
-rw-r--r--nova/virt/vmwareapi/vif.py26
-rw-r--r--nova/virt/vmwareapi/vmops.py1
-rw-r--r--nova/virt/vmwareapi_conn.py1
-rw-r--r--nova/virt/xenapi/vif.py108
-rw-r--r--nova/virt/xenapi/vm_utils.py2
-rw-r--r--nova/virt/xenapi/vmops.py5
29 files changed, 435 insertions, 382 deletions
diff --git a/nova/api/openstack/consoles.py b/nova/api/openstack/consoles.py
index 7a43fba96..9c7b37f0d 100644
--- a/nova/api/openstack/consoles.py
+++ b/nova/api/openstack/consoles.py
@@ -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():
diff --git a/nova/api/openstack/contrib/multinic.py b/nova/api/openstack/contrib/multinic.py
index 841061721..da8dcee5d 100644
--- a/nova/api/openstack/contrib/multinic.py
+++ b/nova/api/openstack/contrib/multinic.py
@@ -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)
diff --git a/nova/api/openstack/contrib/vifs.py b/nova/api/openstack/contrib/vifs.py
deleted file mode 100644
index a54f412a6..000000000
--- a/nova/api/openstack/contrib/vifs.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (C) 2011 Midokura KK
-#
-# 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 webob import exc
-
-from nova import exception
-from nova import network
-from nova.api.openstack import extensions
-
-
-def _translate_vif_view(vif):
- result = {'id': vif['id'],
- 'mac': vif['address'],
- 'network_id': vif['network_id']}
- return {'vif': result}
-
-
-def _translate_vifs_view(vifs):
- return {'vifs': [_translate_vif_view(vif) for vif in vifs]}
-
-
-class ServerVIFController(object):
- """The controller for VIFs attached to servers.
-
- A child resource of the server.
- """
-
- _serialization_metadata = {
- 'application/xml': {
- "attributes": {
- "vif": [
- "id",
- "mac",
- "network_id",
- ]}}}
-
- def __init__(self):
- self.network_api = network.API()
- super(ServerVIFController, self).__init__()
-
- def index(self, req, server_id):
- """Return data about the vifs of the server."""
- context = req.environ['nova.context']
-
- vifs = self.network_api.get_vifs_by_instance(context, server_id)
-
- return _translate_vifs_view(vifs)
-
-
-class VIFs(extensions.ExtensionDescriptor):
- def get_name(self):
- return "VIFs"
-
- def get_alias(self):
- return "os-vifs"
-
- def get_description(self):
- return "VIF support"
-
- def get_namespace(self):
- return "http://docs.openstack.org/ext/vifs/api/v1.1"
-
- def get_updated(self):
- return "2011-07-11T00:00:00+00:00"
-
- def get_resources(self):
- resources = []
-
- res = extensions.ResourceExtension('os-server_vifs',
- ServerVIFController())
- resources.append(res)
-
- return resources
diff --git a/nova/api/openstack/contrib/volumes.py b/nova/api/openstack/contrib/volumes.py
index e5e2c5b50..827e36097 100644
--- a/nova/api/openstack/contrib/volumes.py
+++ b/nova/api/openstack/contrib/volumes.py
@@ -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."""
diff --git a/nova/api/openstack/faults.py b/nova/api/openstack/faults.py
index b9a23c126..24cde69e4 100644
--- a/nova/api/openstack/faults.py
+++ b/nova/api/openstack/faults.py
@@ -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):
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 93f8e832c..3b3d0685d 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -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
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 367ac4a8d..e60781c6d 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -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,
diff --git a/nova/db/api.py b/nova/db/api.py
index cb4da169c..2efbf957d 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -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)
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 189be0714..33bdd767a 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -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).\
@@ -800,6 +802,20 @@ def fixed_ip_get_by_instance(context, instance_id):
@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()
rv = session.query(models.FixedIp).\
@@ -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
###################
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py b/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py
new file mode 100644
index 000000000..3a5f7eba8
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/033_ha_network.py
@@ -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)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 1bcc8eaec..e42f605c4 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -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):
diff --git a/nova/exception.py b/nova/exception.py
index ad6c005f8..cb015e694 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -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'.")
diff --git a/nova/network/api.py b/nova/network/api.py
index 4b8e9fbc6..33a9fe239 100644
--- a/nova/network/api.py
+++ b/nova/network/api.py
@@ -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})
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py
index 4e39a57c4..8ace07884 100644
--- a/nova/network/linux_net.py
+++ b/nova/network/linux_net.py
@@ -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'])),
diff --git a/nova/network/manager.py b/nova/network/manager.py
index 827fd04e8..83d0519c9 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -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
@@ -411,7 +427,12 @@ class NetworkManager(manager.SchedulerDependentManager):
and info = dict containing pertinent networking data
"""
# TODO(tr3buchet) should handle floating IPs as well?
- fixed_ips = self.db.fixed_ip_get_by_instance(context, instance_id)
+ try:
+ fixed_ips = self.db.fixed_ip_get_by_instance(context, instance_id)
+ except exception.FixedIpNotFoundForInstance, ex:
+ LOG.warn(_('No fixed IPs for instance %s'), instance_id)
+ fixed_ips = []
+
vifs = self.db.virtual_interface_get_by_instance(context, instance_id)
flavor = self.db.instance_type_get_by_id(context,
instance_type_id)
@@ -446,15 +467,25 @@ 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'],
'dns': [network['dns']],
- 'ips': [ip_dict(ip) for ip in network_IPs]}
+ 'ips': [ip_dict(ip) for ip in network_IPs],
+ 'create_bridge': self._create_bridge,
+ 'create_vlan': self._create_vlan}
if network['cidr_v6']:
info['ip6s'] = [ip6_dict()]
# TODO(tr3buchet): handle ip6 routes here as well
@@ -489,10 +520,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 +550,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 +596,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 +618,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,14 +694,25 @@ 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()
+ @property
+ def _create_bridge(self):
+ """Indicate whether this manager requires VIF to create a bridge."""
+ return False
+
+ @property
+ def _create_vlan(self):
+ """Indicate whether this manager requires VIF to create a VLAN tag."""
+ return False
+
class FlatManager(NetworkManager):
"""Basic network where no vlans are used.
@@ -700,7 +744,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 +756,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 +785,24 @@ 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)
+ 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'])
-
- 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)
- 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 _create_bridge(self):
+ """Indicate whether this manager requires VIF to create a bridge."""
+ return True
class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
@@ -809,8 +851,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 +861,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 +880,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):
@@ -879,3 +920,13 @@ class VlanManager(RPCAllocateFixedIP, FloatingIP, NetworkManager):
"""Number of reserved ips at the top of the range."""
parent_reserved = super(VlanManager, self)._top_reserved_ips
return parent_reserved + FLAGS.cnt_vpn_clients
+
+ @property
+ def _create_bridge(self):
+ """Indicate whether this manager requires VIF to create a bridge."""
+ return True
+
+ @property
+ def _create_vlan(self):
+ """Indicate whether this manager requires VIF to create a VLAN tag."""
+ return True
diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py
index e4ed75d37..7df6c06eb 100644
--- a/nova/tests/__init__.py
+++ b/nova/tests/__init__.py
@@ -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)
diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py
index 4d86ffb26..927009e77 100644
--- a/nova/tests/api/openstack/test_faults.py
+++ b/nova/tests/api/openstack/test_faults.py
@@ -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)
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 4878ed8d1..ad0931a89 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -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}]}
@@ -721,6 +722,9 @@ class LibvirtConnTestCase(test.TestCase):
return vdmock
self.create_fake_libvirt_mock(lookupByName=fake_lookup)
+ self.mox.StubOutWithMock(self.compute, "recover_live_migration")
+ self.compute.recover_live_migration(self.context, instance_ref,
+ dest='dest')
# Start test
self.mox.ReplayAll()
diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py
index 3ced1e5c4..57aa04ece 100644
--- a/nova/tests/test_network.py
+++ b/nova/tests/test_network.py
@@ -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)
@@ -159,6 +147,7 @@ class FlatNetworkTestCase(test.TestCase):
'cidr': '192.168.%s.0/24' % i,
'cidr_v6': '2001:db%s::/64' % i8,
'id': i,
+ 'multi_host': False,
'injected': 'DONTCARE',
'bridge_interface': 'fake_fa%s' % i,
'vlan': None}
@@ -166,6 +155,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,
@@ -173,7 +163,9 @@ class FlatNetworkTestCase(test.TestCase):
'ips': 'DONTCARE',
'label': 'test%s' % i,
'mac': 'DE:AD:BE:EF:00:0%s' % i,
- 'rxtx_cap': 'DONTCARE'}
+ 'rxtx_cap': 'DONTCARE',
+ 'create_vlan': False,
+ 'create_bridge': False}
self.assertDictMatch(nw[1], check)
check = [{'enabled': 'DONTCARE',
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 4cb7447d3..199a8bc52 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -647,7 +647,7 @@ class XenAPIVMTestCase(test.TestCase):
self.flags(xenapi_inject_image=False)
instance = self._create_instance()
conn = xenapi_conn.get_connection(False)
- conn.rescue(instance, None)
+ conn.rescue(instance, None, [])
def test_unrescue(self):
instance = self._create_instance()
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index e8dcf138b..2faff0a1e 100644
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -257,4 +257,3 @@ class ComputeDriver(object):
def plug_vifs(self, instance, network_info):
"""Plugs in VIFs to networks."""
raise NotImplementedError()
-
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 7b2ff49b2..585cd74a3 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -126,7 +126,7 @@ flags.DEFINE_bool('start_guests_on_host_boot', False,
flags.DEFINE_string('libvirt_vif_type', 'bridge',
'Type of VIF to create.')
flags.DEFINE_string('libvirt_vif_driver',
- 'nova.virt.libvirt.vif.LibvirtVlanBridgeDriver',
+ 'nova.virt.libvirt.vif.LibvirtBridgeDriver',
'The libvirt VIF driver to configure the VIFs.')
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 4e3dcddff..bf3579608 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -19,26 +19,26 @@
"""VIF drivers for libvirt."""
from nova import flags
+from nova import log as logging
from nova.network import linux_net
from nova.virt.libvirt import netutils
from nova import utils
from nova.virt.vif import VIFDriver
+LOG = logging.getLogger('nova.virt.libvirt.vif')
+
FLAGS = flags.FLAGS
-flags.DEFINE_bool('allow_project_net_traffic',
- True,
- 'Whether to allow in project network traffic')
flags.DEFINE_string('libvirt_ovs_integration_bridge', 'br-int',
- 'Name of Integration Bridge used by Open vSwitch')
+ 'Name of Integration Bridge used by Open vSwitch')
+
-class LibvirtBridge(object):
- """Linux bridge VIF for Libvirt."""
+class LibvirtBridgeDriver(VIFDriver):
+ """VIF driver for Linux bridge."""
- def get_configurations(self, network, mapping):
+ 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(':', '')
@@ -61,7 +61,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,
}
@@ -70,30 +70,25 @@ class LibvirtBridge(object):
return result
-
-class LibvirtBridgeDriver(VIFDriver, LibvirtBridge):
- """VIF driver for Linux bridge."""
-
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'])
- return self.get_configurations(network, mapping)
-
- def unplug(self, instance, network, mapping):
- pass
-
-
-class LibvirtVlanBridgeDriver(VIFDriver, LibvirtBridge):
- """VIF driver for Linux bridge with VLAN."""
-
- 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'])
- return self.get_configurations(network, mapping)
+ if not network.get('multi_host') and mapping.get('create_bridge'):
+ if mapping.get('create_vlan'):
+ LOG.debug(_('Ensuring vlan %(vlan)s and bridge %(bridge)s'),
+ {'vlan': network['vlan'],
+ 'bridge': network['bridge']})
+ linux_net.ensure_vlan_bridge(network['vlan'],
+ network['bridge'],
+ network['bridge_interface'])
+ else:
+ LOG.debug(_("Ensuring bridge %s"), network['bridge'])
+ linux_net.ensure_bridge(network['bridge'],
+ network['bridge_interface'])
+
+ return self._get_configurations(network, mapping)
def unplug(self, instance, network, mapping):
+ """No manual unplugging required."""
pass
diff --git a/nova/virt/vmwareapi/vif.py b/nova/virt/vmwareapi/vif.py
index 902699089..281565bbc 100644
--- a/nova/virt/vmwareapi/vif.py
+++ b/nova/virt/vmwareapi/vif.py
@@ -53,7 +53,8 @@ class VMWareVlanBridgeDriver(VIFDriver):
session = VMWareAPISession(host_ip, host_username, host_password,
FLAGS.vmwareapi_api_retry_count)
vlan_interface = bridge_interface
- # Check if the vlan_interface physical network adapter exists on the host
+ # Check if the vlan_interface physical network adapter exists on the
+ # host.
if not network_utils.check_if_vlan_interface_exists(session,
vlan_interface):
raise exception.NetworkAdapterNotFound(adapter=vlan_interface)
@@ -62,32 +63,33 @@ class VMWareVlanBridgeDriver(VIFDriver):
vswitch_associated = network_utils.get_vswitch_for_vlan_interface(
session, vlan_interface)
if vswitch_associated is None:
- raise exception.SwicthNotFoundForNetworkAdapter(adapter=vlan_interface)
+ raise exception.SwicthNotFoundForNetworkAdapter(
+ adapter=vlan_interface)
# Check whether bridge already exists and retrieve the the ref of the
# network whose name_label is "bridge"
network_ref = network_utils.get_network_with_the_name(session, bridge)
if network_ref is None:
- # Create a port group on the vSwitch associated with the vlan_interface
- # corresponding physical network adapter on the ESX host
- network_utils.create_port_group(session, bridge, vswitch_associated,
- vlan_num)
+ # Create a port group on the vSwitch associated with the
+ # vlan_interface corresponding physical network adapter on the ESX
+ # host.
+ network_utils.create_port_group(session, bridge,
+ vswitch_associated, vlan_num)
else:
# Get the vlan id and vswitch corresponding to the port group
pg_vlanid, pg_vswitch = \
- network_utils.get_vlanid_and_vswitch_for_portgroup(session, bridge)
+ network_utils.get_vlanid_and_vswitch_for_portgroup(session,
+ bridge)
# Check if the vswitch associated is proper
if pg_vswitch != vswitch_associated:
- raise exception.InvalidVLANPortGroup(bridge=bridge,
- expected=vswitch_associated,
- actual=pg_vswitch)
+ raise exception.InvalidVLANPortGroup(
+ bridge=bridge, expected=vswitch_associated,
+ actual=pg_vswitch)
# Check if the vlan id is proper for the port group
if pg_vlanid != vlan_num:
raise exception.InvalidVLANTag(bridge=bridge, tag=vlan_num,
pgroup=pg_vlanid)
-
def unplug(self, instance, network, mapping):
pass
-
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index eded4391e..6cc130809 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -806,4 +806,3 @@ class VMWareVMOps(object):
"""Unplug VIFs from networks."""
for (network, mapping) in network_info:
self._vif_driver.unplug(instance, network, mapping)
-
diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py
index 2492c9951..ce57847b2 100644
--- a/nova/virt/vmwareapi_conn.py
+++ b/nova/virt/vmwareapi_conn.py
@@ -198,6 +198,7 @@ class VMWareESXConnection(driver.ComputeDriver):
"""Plugs in VIFs to networks."""
self._vmops.plug_vifs(instance, network_info)
+
class VMWareAPISession(object):
"""
Sets up a session with the ESX host and handles all
diff --git a/nova/virt/xenapi/vif.py b/nova/virt/xenapi/vif.py
index 3604ef8a9..beee2390d 100644
--- a/nova/virt/xenapi/vif.py
+++ b/nova/virt/xenapi/vif.py
@@ -26,17 +26,18 @@ from nova.virt.xenapi.network_utils import NetworkHelper
FLAGS = flags.FLAGS
flags.DEFINE_string('xenapi_ovs_integration_bridge', 'xapi1',
- 'Name of Integration Bridge used by Open vSwitch')
+ 'Name of Integration Bridge used by Open vSwitch')
LOG = logging.getLogger("nova.virt.xenapi.vif")
+
class XenAPIBridgeDriver(VIFDriver):
"""Combined VIF and Bridge class for XenAPI."""
def get_vif_rec(self, xenapi_session, vm_ref, instance, device, network,
network_mapping):
- network_ref = NetworkHelper.find_network_with_bridge(xenapi_session,
- network['bridge'])
+ network_ref = NetworkHelper.find_network_with_bridge(xenapi_session,
+ network['bridge'])
rxtx_cap = network_mapping.pop('rxtx_cap')
vif_rec = {}
vif_rec['device'] = str(device)
@@ -55,66 +56,68 @@ class XenAPIBridgeDriver(VIFDriver):
vlan_num = network['vlan']
if vlan_num is None:
- return # no plugging done for non-VLAN networks
- bridge = network['bridge']
+ return # no plugging done for non-VLAN networks
+ bridge = network['bridge']
bridge_interface = network['bridge_interface']
- # Check whether bridge already exists
- # Retrieve network whose name_label is "bridge"
- network_ref = network_utils.NetworkHelper.find_network_with_name_label(
- xenapi_session,
- bridge)
+ # Check whether bridge already exists
+ # Retrieve network whose name_label is "bridge"
+ network_ref = network_utils.NetworkHelper.find_network_with_name_label(
+ xenapi_session, bridge)
+
if network_ref is None:
- # If bridge does not exists
- # 1 - create network
- description = 'network for nova bridge %s' % bridge
- network_rec = {'name_label': bridge,
- 'name_description': description,
- 'other_config': {}}
- network_ref = xenapi_session.call_xenapi('network.create', network_rec)
- # 2 - find PIF for VLAN NOTE(salvatore-orlando): using double
- # quotes inside single quotes as xapi filter only support
- # tokens in double quotes
- expr = 'field "device" = "%s" and \
+ # If bridge does not exists
+ # 1 - create network
+ description = 'network for nova bridge %s' % bridge
+ network_rec = {'name_label': bridge,
+ 'name_description': description,
+ 'other_config': {}}
+ network_ref = xenapi_session.call_xenapi('network.create',
+ network_rec)
+ # 2 - find PIF for VLAN NOTE(salvatore-orlando): using double
+ # quotes inside single quotes as xapi filter only support
+ # tokens in double quotes
+ expr = 'field "device" = "%s" and \
field "VLAN" = "-1"' % bridge_interface
- pifs = xenapi_session.call_xenapi('PIF.get_all_records_where', expr)
- pif_ref = None
- # Multiple PIF are ok: we are dealing with a pool
- if len(pifs) == 0:
- raise Exception(
- _('Found no PIF for device %s') % bridge_interface)
+ pifs = xenapi_session.call_xenapi('PIF.get_all_records_where',
+ expr)
+ pif_ref = None
+ # Multiple PIF are ok: we are dealing with a pool
+ if len(pifs) == 0:
+ raise Exception(_('Found no PIF for device %s') %
+ bridge_interface)
+
# 3 - create vlan for network
for pif_ref in pifs.keys():
- xenapi_session.call_xenapi('VLAN.create',
- pif_ref,
- str(vlan_num),
- network_ref)
- else:
- # Check VLAN tag is appropriate
- network_rec = xenapi_session.call_xenapi('network.get_record',
- network_ref)
- # Retrieve PIFs from network
- for pif_ref in network_rec['PIFs']:
- # Retrieve VLAN from PIF
- pif_rec = xenapi_session.call_xenapi('PIF.get_record', pif_ref)
- pif_vlan = int(pif_rec['VLAN'])
- # Raise an exception if VLAN != vlan_num
- if pif_vlan != vlan_num:
- raise Exception(_("PIF %(pif_rec['uuid'])s for network "
- "%(bridge)s has VLAN id %(pif_vlan)d. "
- "Expected %(vlan_num)d") % locals())
+ xenapi_session.call_xenapi('VLAN.create', pif_ref,
+ str(vlan_num), network_ref)
+ else:
+ # Check VLAN tag is appropriate
+ network_rec = xenapi_session.call_xenapi('network.get_record',
+ network_ref)
+ # Retrieve PIFs from network
+ for pif_ref in network_rec['PIFs']:
+ # Retrieve VLAN from PIF
+ pif_rec = xenapi_session.call_xenapi('PIF.get_record', pif_ref)
+ pif_vlan = int(pif_rec['VLAN'])
+ # Raise an exception if VLAN != vlan_num
+ if pif_vlan != vlan_num:
+ raise Exception(_("PIF %(pif_rec['uuid'])s for network "
+ "%(bridge)s has VLAN id %(pif_vlan)d. "
+ "Expected %(vlan_num)d") % locals())
def unplug(self, instance, network, mapping):
pass
+
class XenAPIOpenVswitchDriver(VIFDriver):
"""VIF driver for Open vSwitch with XenAPI."""
def get_vif_rec(self, xenapi_session, vm_ref, instance, device, network,
network_mapping):
- # with OVS model, always plug into OVS integration bridge
- network_ref = NetworkHelper.find_network_with_bridge(xenapi_session,
- FLAGS.xenapi_ovs_integration_bridge)
+ # with OVS model, always plug into OVS integration bridge
+ network_ref = NetworkHelper.find_network_with_bridge(
+ xenapi_session, FLAGS.xenapi_ovs_integration_bridge)
vif_rec = {}
vif_rec['device'] = str(device)
vif_rec['network'] = network_ref
@@ -126,14 +129,13 @@ class XenAPIOpenVswitchDriver(VIFDriver):
vif_rec['qos_algorithm_params'] = {}
# OVS on the hypervisor monitors this key and uses it to
# set the iface-id attribute
- vif_rec['other_config'] = {"nicira-iface-id" : vif_id }
+ vif_rec['other_config'] = {"nicira-iface-id": vif_id}
return vif_rec
def plug(self, xenapi_session, instance, network, mapping):
- # nothing to do, as this driver assumes that integration bridge
- # was created by administrator
+ # nothing to do, as this driver assumes that integration bridge
+ # was created by administrator
pass
def unplug(self, instance, network, mapping):
- pass
-
+ pass
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
index e63582b54..62863c6d8 100644
--- a/nova/virt/xenapi/vm_utils.py
+++ b/nova/virt/xenapi/vm_utils.py
@@ -282,7 +282,6 @@ class VMHelper(HelperBase):
LOG.exception(exc)
raise StorageError(_('Unable to destroy VDI %s') % vdi_ref)
-
@classmethod
def create_vdi(cls, session, sr_ref, name_label, virtual_size, read_only):
"""Create a VDI record and returns its reference."""
@@ -1095,6 +1094,7 @@ def _stream_disk(dev, image_type, virtual_size, image_file):
for chunk in image_file:
f.write(chunk)
+
def _write_partition(virtual_size, dev):
dest = '/dev/%s' % dev
primary_first = MBR_SIZE_SECTORS
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index bdf471d16..4fa59b6b7 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -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):
@@ -886,7 +884,6 @@ class VMOps(object):
instance['name'])
raise
-
def _wait_with_callback(self, instance_id, task, callback):
ret = None
try: