summaryrefslogtreecommitdiff
path: root/nova/conductor
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-07-26 19:45:05 +0000
committerGerrit Code Review <review@openstack.org>2018-07-26 19:45:05 +0000
commit2fcec35d38f35a77ccd838f124fbdcfe933e71fe (patch)
tree8089f4d470b2b7abc195a571a448b89cdd3f4d66 /nova/conductor
parent6071dd0e76cf2e30f9e2f45b0c5e77337d905a58 (diff)
parent2d5c6fd8eb677e8e223251bc8cdb0427da0f33ba (diff)
downloadnova-2fcec35d38f35a77ccd838f124fbdcfe933e71fe.tar.gz
Merge "conductor: use port binding extended API in during live migrate"
Diffstat (limited to 'nova/conductor')
-rw-r--r--nova/conductor/tasks/live_migrate.py55
1 files changed, 55 insertions, 0 deletions
diff --git a/nova/conductor/tasks/live_migrate.py b/nova/conductor/tasks/live_migrate.py
index b9b3c9a3b5..16731a99b8 100644
--- a/nova/conductor/tasks/live_migrate.py
+++ b/nova/conductor/tasks/live_migrate.py
@@ -21,6 +21,7 @@ from nova.conductor.tasks import migrate
import nova.conf
from nova import exception
from nova.i18n import _
+from nova import network
from nova import objects
from nova.scheduler import utils as scheduler_utils
from nova import utils
@@ -35,6 +36,19 @@ def should_do_migration_allocation(context):
return minver >= 25
+def supports_extended_port_binding(context, host):
+ """Checks if the compute host service is new enough to support the neutron
+ port binding-extended details.
+
+ :param context: The user request context.
+ :param host: The nova-compute host to check.
+ :returns: True if the compute host is new enough to support extended
+ port binding information, False otherwise.
+ """
+ svc = objects.Service.get_by_host_and_binary(context, host, 'nova-compute')
+ return svc.version >= 35
+
+
class LiveMigrationTask(base.TaskBase):
def __init__(self, context, instance, destination,
block_migration, disk_over_commit, migration, compute_rpcapi,
@@ -53,6 +67,7 @@ class LiveMigrationTask(base.TaskBase):
self.request_spec = request_spec
self._source_cn = None
self._held_allocations = None
+ self.network_api = network.API()
def _execute(self):
self._check_instance_is_active()
@@ -227,6 +242,46 @@ class LiveMigrationTask(base.TaskBase):
"%s") % destination
raise exception.MigrationPreCheckError(msg)
+ if not self.network_api.supports_port_binding_extension(self.context):
+ LOG.debug('Extended port binding is not available.',
+ instance=self.instance)
+ # Neutron doesn't support the binding-extended API so we can't
+ # attempt port binding on the destination host.
+ return
+
+ # Check to see that both the source and destination compute hosts
+ # are new enough to support the new port binding flow.
+ if (supports_extended_port_binding(self.context, self.source) and
+ supports_extended_port_binding(self.context, destination)):
+ self.migrate_data.vifs = (
+ self._bind_ports_on_destination(destination))
+
+ def _bind_ports_on_destination(self, destination):
+ LOG.debug('Start binding ports on destination host: %s', destination,
+ instance=self.instance)
+ # Bind ports on the destination host; returns a dict, keyed by
+ # port ID, of a new destination host port binding dict per port
+ # that was bound. This information is then stuffed into the
+ # migrate_data.
+ try:
+ bindings = self.network_api.bind_ports_to_host(
+ self.context, self.instance, destination)
+ except exception.PortBindingFailed as e:
+ # Port binding failed for that host, try another one.
+ raise exception.MigrationPreCheckError(
+ reason=e.format_message())
+
+ source_vif_map = {
+ vif['id']: vif for vif in self.instance.get_network_info()
+ }
+ migrate_vifs = []
+ for port_id, binding in bindings.items():
+ migrate_vif = objects.VIFMigrateData(
+ port_id=port_id, **binding)
+ migrate_vif.source_vif = source_vif_map[port_id]
+ migrate_vifs.append(migrate_vif)
+ return migrate_vifs
+
def _get_source_cell_mapping(self):
"""Returns the CellMapping for the cell in which the instance lives