diff options
author | Zuul <zuul@review.openstack.org> | 2018-07-26 19:45:05 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2018-07-26 19:45:05 +0000 |
commit | 2fcec35d38f35a77ccd838f124fbdcfe933e71fe (patch) | |
tree | 8089f4d470b2b7abc195a571a448b89cdd3f4d66 /nova/conductor | |
parent | 6071dd0e76cf2e30f9e2f45b0c5e77337d905a58 (diff) | |
parent | 2d5c6fd8eb677e8e223251bc8cdb0427da0f33ba (diff) | |
download | nova-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.py | 55 |
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 |