From fe8bddc0f25c78af3cd98ba06b0768f2a99b9093 Mon Sep 17 00:00:00 2001 From: Jay Lau Date: Sat, 11 May 2013 21:53:20 +0800 Subject: Add notification for live migration Fix bug 1167759 Currently, if live migration failed, nova compute did not send notification, this causes other services such as nova-scheduler to have no chance to do some operations The fix add notification logic for live_migration like other VM instance operations such as resize, run instance etc. Change-Id: Iaf61f5268e07284fd7d69ff331ce3bacd380c02b --- nova/compute/manager.py | 23 +++++++++++++++++++++ nova/tests/compute/test_compute.py | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index b63ca10a1..91a814f98 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -3188,6 +3188,7 @@ class ComputeManager(manager.SchedulerDependentManager): return self.driver.check_can_live_migrate_source(ctxt, instance, dest_check_data) + @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) def pre_live_migration(self, context, instance, block_migration=False, disk=None, migrate_data=None): @@ -3206,6 +3207,9 @@ class ComputeManager(manager.SchedulerDependentManager): context, instance, bdms=bdms) network_info = self._get_instance_nw_info(context, instance) + self._notify_about_instance_usage( + context, instance, "live_migration.pre.start", + network_info=network_info) # TODO(tr3buchet): figure out how on the earth this is necessary fixed_ips = network_info.fixed_ips() @@ -3236,8 +3240,13 @@ class ComputeManager(manager.SchedulerDependentManager): if block_migration: self.driver.pre_block_migration(context, instance, disk) + self._notify_about_instance_usage( + context, instance, "live_migration.pre.end", + network_info=network_info) + return pre_live_migration_data + @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) def live_migration(self, context, dest, instance, block_migration=False, migrate_data=None): """Executing live migration. @@ -3354,6 +3363,7 @@ class ComputeManager(manager.SchedulerDependentManager): "This error can be safely ignored."), instance=instance_ref) + @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) def post_live_migration_at_destination(self, context, instance, block_migration=False): """Post operations for live migration . @@ -3379,6 +3389,9 @@ class ComputeManager(manager.SchedulerDependentManager): migration) network_info = self._get_instance_nw_info(context, instance) + self._notify_about_instance_usage( + context, instance, "live_migration.post.dest.start", + network_info=network_info) block_device_info = self._get_instance_volume_block_device_info( context, instance) @@ -3402,6 +3415,9 @@ class ComputeManager(manager.SchedulerDependentManager): # NOTE(vish): this is necessary to update dhcp self.network_api.setup_networks_on_host(context, instance, self.host) + self._notify_about_instance_usage( + context, instance, "live_migration.post.dest.end", + network_info=network_info) def _rollback_live_migration(self, context, instance, dest, block_migration, migrate_data=None): @@ -3445,6 +3461,7 @@ class ComputeManager(manager.SchedulerDependentManager): self.compute_rpcapi.rollback_live_migration_at_destination(context, instance, dest) + @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) def rollback_live_migration_at_destination(self, context, instance): """Cleaning up image directory that is created pre_live_migration. @@ -3452,6 +3469,9 @@ class ComputeManager(manager.SchedulerDependentManager): :param instance: an Instance dict sent over rpc """ network_info = self._get_instance_nw_info(context, instance) + self._notify_about_instance_usage( + context, instance, "live_migration.rollback.dest.start", + network_info=network_info) # NOTE(tr3buchet): tear down networks on destination host self.network_api.setup_networks_on_host(context, instance, @@ -3463,6 +3483,9 @@ class ComputeManager(manager.SchedulerDependentManager): context, instance) self.driver.destroy(instance, self._legacy_nw_info(network_info), block_device_info) + self._notify_about_instance_usage( + context, instance, "live_migration.rollback.dest.end", + network_info=network_info) @periodic_task.periodic_task def _heal_instance_info_cache(self, context): diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 3101e3aa2..3580d4839 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -3493,6 +3493,7 @@ class ComputeTestCase(BaseTestCase): self.compute.driver.ensure_filtering_rules_for_instance( mox.IsA(instance), nw_info) + test_notifier.NOTIFICATIONS = [] # start test self.mox.ReplayAll() migrate_data = {'is_shared_storage': False} @@ -3500,6 +3501,13 @@ class ComputeTestCase(BaseTestCase): block_migration=False, migrate_data=migrate_data) self.assertEqual(ret, None) + self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) + msg = test_notifier.NOTIFICATIONS[0] + self.assertEqual(msg['event_type'], + 'compute.instance.live_migration.pre.start') + msg = test_notifier.NOTIFICATIONS[1] + self.assertEqual(msg['event_type'], + 'compute.instance.live_migration.pre.end') # cleanup db.instance_destroy(c, instance['uuid']) @@ -3719,11 +3727,20 @@ class ComputeTestCase(BaseTestCase): self.compute.network_api.setup_networks_on_host(self.admin_ctxt, mox.IgnoreArg(), self.compute.host) + test_notifier.NOTIFICATIONS = [] self.mox.ReplayAll() self.compute.post_live_migration_at_destination(self.admin_ctxt, self.instance) + self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) + msg = test_notifier.NOTIFICATIONS[0] + self.assertEqual(msg['event_type'], + 'compute.instance.live_migration.post.dest.start') + msg = test_notifier.NOTIFICATIONS[1] + self.assertEqual(msg['event_type'], + 'compute.instance.live_migration.post.dest.end') + return self.compute.conductor_api.instance_get_by_uuid(self.admin_ctxt, self.instance['uuid']) @@ -3749,6 +3766,31 @@ class ComputeTestCase(BaseTestCase): updated = self._finish_post_live_migration_at_destination() self.assertIsNone(updated['node']) + def test_rollback_live_migration_at_destination_correctly(self): + # creating instance testdata + c = context.get_admin_context() + instance_ref = self._create_fake_instance({'host': 'dummy'}) + inst_uuid = instance_ref['uuid'] + inst_id = instance_ref['id'] + + instance = jsonutils.to_primitive(db.instance_get(c, inst_id)) + test_notifier.NOTIFICATIONS = [] + # start test + self.mox.ReplayAll() + ret = self.compute.rollback_live_migration_at_destination(c, + instance=instance) + self.assertEqual(ret, None) + self.assertEqual(len(test_notifier.NOTIFICATIONS), 2) + msg = test_notifier.NOTIFICATIONS[0] + self.assertEqual(msg['event_type'], + 'compute.instance.live_migration.rollback.dest.start') + msg = test_notifier.NOTIFICATIONS[1] + self.assertEqual(msg['event_type'], + 'compute.instance.live_migration.rollback.dest.end') + + # cleanup + db.instance_destroy(c, inst_uuid) + def test_run_kill_vm(self): # Detect when a vm is terminated behind the scenes. self.stubs.Set(compute_manager.ComputeManager, -- cgit