From d96102b6251d489574132104f8ad9db110286415 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Wed, 31 Oct 2012 10:22:46 -0500 Subject: Add rxtx_factor to network migration logic Currently, when an instance is migrated from one host to another, the only action the network API is able to take is moving floating IP addresses. We also need to be able to update the rxtx_factor value to update QoS settings. This change makes sure that the network APIs will be passed the rxtx_factor value during a migration. Change-Id: If4e1e96b84ee082c2d277c3d91da7df0325fc1ff --- nova/compute/manager.py | 30 ++++++++++------------ nova/network/api.py | 52 +++++++++++++++++++++++++------------- nova/network/manager.py | 28 ++++++++++++++++---- nova/network/quantumv2/api.py | 6 +++-- nova/network/rpcapi.py | 46 +++++++++++++++++++++------------ nova/tests/network/test_manager.py | 9 ++++--- 6 files changed, 111 insertions(+), 60 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f43aa0096..82051ecb4 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1486,10 +1486,8 @@ class ComputeManager(manager.SchedulerDependentManager): self.network_api.setup_networks_on_host(context, instance, teardown=True) - if migration_ref['dest_compute'] != \ - migration_ref['source_compute']: - self.network_api.migrate_instance_start(context, instance, - migration_ref['dest_compute']) + self.network_api.migrate_instance_start(context, instance, + migration_ref) network_info = self._get_instance_nw_info(context, instance) block_device_info = self._get_instance_volume_block_device_info( @@ -1548,11 +1546,6 @@ class ComputeManager(manager.SchedulerDependentManager): self._legacy_nw_info(network_info), block_device_info) - if migration_ref['dest_compute'] != \ - migration_ref['source_compute']: - self.network_api.migrate_instance_finish(context, instance, - migration_ref['source_compute']) - # Just roll back the record. There's no need to resize down since # the 'old' VM already has the preferred attributes self._instance_update(context, @@ -1563,11 +1556,16 @@ class ComputeManager(manager.SchedulerDependentManager): ephemeral_gb=instance_type['ephemeral_gb'], instance_type_id=instance_type['id'], launched_at=timeutils.utcnow(), - vm_state=vm_states.ACTIVE, - task_state=None, expected_task_state=task_states. RESIZE_REVERTING) + self.network_api.migrate_instance_finish(context, instance, + migration_ref) + + self._instance_update(context, instance['uuid'], + vm_state=vm_states.ACTIVE, + task_state=None) + self.db.migration_update(elevated, migration_id, {'status': 'reverted'}) @@ -1673,9 +1671,8 @@ class ComputeManager(manager.SchedulerDependentManager): self._terminate_volume_connections(context, instance) - if migration['dest_compute'] != migration['source_compute']: - self.network_api.migrate_instance_start(context, instance, - self.host) + self.network_api.migrate_instance_start(context, instance, + migration) migration = self.db.migration_update(elevated, migration['id'], @@ -1725,9 +1722,8 @@ class ComputeManager(manager.SchedulerDependentManager): self.network_api.setup_networks_on_host(context, instance, migration['dest_compute']) - if migration['dest_compute'] != migration['source_compute']: - self.network_api.migrate_instance_finish(context, instance, - migration['dest_compute']) + self.network_api.migrate_instance_finish(context, instance, + migration) network_info = self._get_instance_nw_info(context, instance) diff --git a/nova/network/api.py b/nova/network/api.py index 5f2c2ff8b..bb05a0c2a 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -21,6 +21,7 @@ import functools import inspect from nova.db import base +from nova import exception from nova import flags from nova.network import model as network_model from nova.network import rpcapi as network_rpcapi @@ -324,8 +325,11 @@ class API(base.Base): self.network_rpcapi.setup_networks_on_host(context, **args) def _is_multi_host(self, context, instance): - fixed_ips = self.db.fixed_ip_get_by_instance(context, instance['uuid']) - + try: + fixed_ips = self.db.fixed_ip_get_by_instance(context, + instance['uuid']) + except exception.FixedIpNotFoundForInstance: + return False network = self.db.network_get(context, fixed_ips[0]['network_id'], project_only=True) return network['multi_host'] @@ -335,22 +339,36 @@ class API(base.Base): instance['uuid']) return [floating_ip['address'] for floating_ip in floating_ips] - def migrate_instance_start(self, context, instance, host): + def migrate_instance_start(self, context, instance, migration): """Start to migrate the network of an instance""" + args = dict( + instance_uuid=instance['uuid'], + rxtx_factor=instance['instance_type']['rxtx_factor'], + project_id=instance['project_id'], + source_compute=migration['source_compute'], + dest_compute=migration['dest_compute'], + floating_addresses=None, + ) + if self._is_multi_host(context, instance): - addresses = self._get_floating_ip_addresses(context, instance) - if addresses: - self.network_rpcapi.migrate_instance_start(context, - instance['uuid'], - addresses, - host) - - def migrate_instance_finish(self, context, instance, dest): + args['floating_addresses'] = \ + self._get_floating_ip_addresses(context, instance) + + self.network_rpcapi.migrate_instance_start(context, **args) + + def migrate_instance_finish(self, context, instance, migration): """Finish migrating the network of an instance""" + args = dict( + instance_uuid=instance['uuid'], + rxtx_factor=instance['instance_type']['rxtx_factor'], + project_id=instance['project_id'], + source_compute=migration['source_compute'], + dest_compute=migration['dest_compute'], + floating_addresses=None, + ) + if self._is_multi_host(context, instance): - addresses = self._get_floating_ip_addresses(context, instance) - if addresses: - self.network_rpcapi.migrate_instance_finish(context, - instance['uuid'], - addresses, - dest) + args['floating_addresses'] = \ + self._get_floating_ip_addresses(context, instance) + + self.network_rpcapi.migrate_instance_finish(context, **args) diff --git a/nova/network/manager.py b/nova/network/manager.py index 39eed6e7e..a944ebd40 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -663,8 +663,13 @@ class FloatingIP(object): return False if floating_ip.get('fixed_ip_id') else True @wrap_check_policy - def migrate_instance_start(self, context, instance_uuid, - floating_addresses): + def migrate_instance_start(self, context, instance_uuid, rxtx_factor, + project_id, source, dest, floating_addresses): + # We only care if floating_addresses are provided and we're + # switching hosts + if not floating_addresses or source == dest: + return + LOG.info(_("Starting migration network for instance" " %(instance_uuid)s"), locals()) for address in floating_addresses: @@ -691,8 +696,13 @@ class FloatingIP(object): {'host': None}) @wrap_check_policy - def migrate_instance_finish(self, context, instance_uuid, - floating_addresses, host): + def migrate_instance_finish(self, context, instance_uuid, rxtx_factor, + project_id, source, dest, floating_addresses): + # We only care if floating_addresses are provided and we're + # switching hosts + if not floating_addresses or source == dest: + return + LOG.info(_("Finishing migration network for instance" " %(instance_uuid)s"), locals()) @@ -708,7 +718,7 @@ class FloatingIP(object): self.db.floating_ip_update(context, floating_ip['address'], - {'host': host}) + {'host': dest}) interface = FLAGS.public_interface or floating_ip['interface'] fixed_ip = self.db.fixed_ip_get(context, @@ -1944,6 +1954,14 @@ class FlatManager(NetworkManager): """Returns the floating IPs associated with a fixed_address""" return [] + def migrate_instance_start(self, context, instance_uuid, rxtx_factor, + project_id, source, dest, floating_addresses): + pass + + def migrate_instance_finish(self, context, instance_uuid, rxtx_factor, + project_id, source, dest, floating_addresses): + pass + class FlatDHCPManager(RPCAllocateFixedIP, FloatingIP, NetworkManager): """Flat networking with dhcp. diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index 594d7b2f2..241bb1a2d 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -508,13 +508,15 @@ class API(base.Base): fip = self._get_floating_ip_by_address(client, address) client.update_floatingip(fip['id'], {'floatingip': {'port_id': None}}) - def migrate_instance_start(self, context, instance, host): + def migrate_instance_start(self, context, instance_uuid, rxtx_factor, + project_id, source, dest, floating_addresses): """Start to migrate the network of an instance""" # NOTE(wenjianhn): just pass to make migrate instance doesn't # raise for now. pass - def migrate_instance_finish(self, context, instance, dest): + def migrate_instance_finish(self, context, instance_uuid, rxtx_factor, + project_id, source, dest, floating_addresses): """Finish migrating the network of an instance""" # NOTE(wenjianhn): just pass to make migrate instance doesn't # raise for now. diff --git a/nova/network/rpcapi.py b/nova/network/rpcapi.py index ffeddf316..6f31e140b 100644 --- a/nova/network/rpcapi.py +++ b/nova/network/rpcapi.py @@ -34,6 +34,7 @@ class NetworkAPI(rpc_proxy.RpcProxy): 1.0 - Initial version. 1.1 - Adds migrate_instance_[start|finish] + 1.2 - Make migrate_instance_[start|finish] a little more flexible ''' # @@ -264,19 +265,32 @@ class NetworkAPI(rpc_proxy.RpcProxy): self.cast(ctxt, self.make_msg('release_fixed_ip', address=address), topic=rpc.queue_get_for(ctxt, self.topic, host)) - def migrate_instance_start(self, ctxt, instance_uuid, - floating_addresses, host): - return self.call(ctxt, self.make_msg('migrate_instance_start', - instance_uuid=instance_uuid, - floating_addresses=floating_addresses), - topic=rpc.queue_get_for(ctxt, self.topic, host), - version='1.1') - - def migrate_instance_finish(self, ctxt, instance_uuid, - floating_addresses, dest): - return self.call(ctxt, self.make_msg('migrate_instance_finish', - instance_uuid=instance_uuid, - floating_addresses=floating_addresses, - host=dest), - topic=rpc.queue_get_for(ctxt, self.topic, dest), - version='1.1') + def migrate_instance_start(self, ctxt, instance_uuid, rxtx_factor, + project_id, source_compute, dest_compute, + floating_addresses): + return self.call(ctxt, self.make_msg( + 'migrate_instance_start', + instance_uuid=instance_uuid, + rxtx_factor=rxtx_factor, + project_id=project_id, + source=source_compute, + dest=dest_compute, + floating_addresses=floating_addresses), + topic=rpc.queue_get_for(ctxt, self.topic, + dest_compute), + version='1.2') + + def migrate_instance_finish(self, ctxt, instance_uuid, rxtx_factor, + project_id, source_compute, dest_compute, + floating_addresses): + return self.call(ctxt, self.make_msg( + 'migrate_instance_finish', + instance_uuid=instance_uuid, + rxtx_factor=rxtx_factor, + project_id=project_id, + source=source_compute, + dest=dest_compute, + floating_addresses=floating_addresses), + topic=rpc.queue_get_for(ctxt, self.topic, + dest_compute), + version='1.2') diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index 952f1ba33..77fccd904 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -1667,7 +1667,9 @@ class FloatingIPTestCase(test.TestCase): self.mox.ReplayAll() floating_ip_addresses = ['172.24.4.23', '172.24.4.24', '172.24.4.25'] self.network.migrate_instance_start(self.context, FAKEUUID, - floating_ip_addresses) + 3, self.project_id, + 'fake_source', 'fake_dest', + floating_ip_addresses) self.assertEqual(called['count'], 2) @@ -1703,8 +1705,9 @@ class FloatingIPTestCase(test.TestCase): self.mox.ReplayAll() floating_ip_addresses = ['172.24.4.23', '172.24.4.24', '172.24.4.25'] self.network.migrate_instance_finish(self.context, FAKEUUID, - floating_ip_addresses, - 'fake_dest') + 3, self.project_id, + 'fake_source', 'fake_dest', + floating_ip_addresses) self.assertEqual(called['count'], 2) -- cgit