From 2c52aca7965bf3c9dd4c17b4f7706bdef401463f Mon Sep 17 00:00:00 2001 From: Sujitha Date: Tue, 8 Mar 2016 20:57:36 +0000 Subject: [PATCH] Added new exception to handle CinderClientException When Cinder client exception is thrown in initialize_connection (which is called during prechecks for Live migration), instance is moved to ERROR state. It is not sensible to move the instance to ERROR state when the precheck fails. Adding new exception changes this behavior. Instance will be reset to Active state when the precheck fails. Closes bug: #1544744 Change-Id: I7a5fcc070ff53086f37417f12e2b9f383e220747 --- nova/compute/manager.py | 7 ++++- nova/conductor/manager.py | 2 ++ nova/exception.py | 4 +++ .../openstack/compute/test_migrate_server.py | 6 +++++ nova/tests/unit/compute/test_compute_mgr.py | 26 +++++++++++++++++++ nova/tests/unit/conductor/test_conductor.py | 1 + 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 0f388ef0e7..5f38efcef2 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -5166,8 +5166,13 @@ class ComputeManager(manager.Manager): migrate_data_obj.LiveMigrateData.detect_implementation( dest_check_data) dest_check_data.is_volume_backed = is_volume_backed - block_device_info = self._get_instance_block_device_info( + try: + block_device_info = self._get_instance_block_device_info( ctxt, instance, refresh_conn_info=True) + except cinder_exception.ClientException as exc: + raise exception.MigrationPreCheckClientException( + reason=six.text_type(exc)) + result = self.driver.check_can_live_migrate_source(ctxt, instance, dest_check_data, block_device_info) diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 707b98ddec..ff723189fb 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -172,6 +172,7 @@ class ComputeTaskManager(base.Base): exception.HypervisorUnavailable, exception.InstanceInvalidState, exception.MigrationPreCheckError, + exception.MigrationPreCheckClientException, exception.LiveMigrationWithOldNovaNotSupported, exception.UnsupportedPolicyException) def migrate_server(self, context, instance, scheduler_hint, live, rebuild, @@ -319,6 +320,7 @@ class ComputeTaskManager(base.Base): exception.HypervisorUnavailable, exception.InstanceInvalidState, exception.MigrationPreCheckError, + exception.MigrationPreCheckClientException, exception.LiveMigrationWithOldNovaNotSupported, exception.MigrationSchedulerRPCError) as ex: with excutils.save_and_reraise_exception(): diff --git a/nova/exception.py b/nova/exception.py index d250c49e83..d9c7f5dca2 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -1334,6 +1334,10 @@ class MigrationPreCheckError(MigrationError): msg_fmt = _("Migration pre-check error: %(reason)s") +class MigrationPreCheckClientException(MigrationError): + msg_fmt = _("Client exception during Migration Pre check: %(reason)s") + + class MigrationSchedulerRPCError(MigrationError): msg_fmt = _("Migration select destinations error: %(reason)s") diff --git a/nova/tests/unit/api/openstack/compute/test_migrate_server.py b/nova/tests/unit/api/openstack/compute/test_migrate_server.py index 2d00de42db..749dfb446c 100644 --- a/nova/tests/unit/api/openstack/compute/test_migrate_server.py +++ b/nova/tests/unit/api/openstack/compute/test_migrate_server.py @@ -264,6 +264,12 @@ class MigrateServerTestsV21(admin_only_action_common.CommonTests): self._test_migrate_live_failed_with_exception( exception.MigrationPreCheckError(reason='')) + def test_migrate_live_migration_precheck_client_exception(self): + self._test_migrate_live_failed_with_exception( + exception.MigrationPreCheckClientException(reason=''), + expected_exc=webob.exc.HTTPInternalServerError, + check_response=False) + def test_migrate_live_migration_with_unexpected_error(self): self._test_migrate_live_failed_with_exception( exception.MigrationError(reason=''), diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index eac8d8b81d..0bb8609f84 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -1799,6 +1799,32 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): instance.uuid) self.assertTrue(dest_check_data.is_volume_backed) + def test_can_live_migrate_source_for_cinder_client_exception(self): + + is_volume_backed = 'volume_backed' + dest_check_data = migrate_data_obj.LiveMigrateData() + db_instance = fake_instance.fake_db_instance() + instance = objects.Instance._from_db_object( + self.context, objects.Instance(), db_instance) + + @mock.patch.object(compute_utils, 'EventReporter') + @mock.patch.object(compute_utils, 'add_instance_fault_from_exc') + @mock.patch.object(self.compute.compute_api, + 'is_volume_backed_instance') + @mock.patch.object(self.compute, + '_get_instance_block_device_info') + def do_test(mock_block_info, mock_volume_backed, + mock_inst_fault, mock_event): + mock_volume_backed.return_value = is_volume_backed + mock_block_info.side_effect = cinder_exception.ClientException( + 'test', 'test') + + self.assertRaises(exception.MigrationPreCheckClientException, + self.compute.check_can_live_migrate_source, + self.context, instance, + dest_check_data) + do_test() + @mock.patch.object(compute_utils, 'EventReporter') def _test_check_can_live_migrate_destination(self, event_mock, do_raise=False): diff --git a/nova/tests/unit/conductor/test_conductor.py b/nova/tests/unit/conductor/test_conductor.py index 3b3dde144f..3274727876 100644 --- a/nova/tests/unit/conductor/test_conductor.py +++ b/nova/tests/unit/conductor/test_conductor.py @@ -1302,6 +1302,7 @@ class ConductorTaskTestCase(_BaseTaskTestCase, test_compute.BaseTestCase): exc.HypervisorUnavailable(host='dummy'), exc.LiveMigrationWithOldNovaNotSupported(), exc.MigrationPreCheckError(reason='dummy'), + exc.MigrationPreCheckClientException(reason='dummy'), exc.InvalidSharedStorage(path='dummy', reason='dummy'), exc.NoValidHost(reason='dummy'), exc.ComputeServiceUnavailable(host='dummy'),