diff --git a/nova/compute/cells_api.py b/nova/compute/cells_api.py index e276697977cd..0919b166d91f 100644 --- a/nova/compute/cells_api.py +++ b/nova/compute/cells_api.py @@ -24,6 +24,7 @@ from nova.cells import rpcapi as cells_rpcapi from nova.cells import utils as cells_utils from nova.compute import api as compute_api from nova.compute import rpcapi as compute_rpcapi +from nova.compute import vm_states from nova import exception from nova import objects from nova.objects import base as obj_base @@ -348,10 +349,10 @@ class ComputeCellsAPI(compute_api.API): self._cast_to_cells(context, instance, 'unrescue') @check_instance_cell + @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED, + vm_states.PAUSED, vm_states.SUSPENDED]) def shelve(self, context, instance, clean_shutdown=True): """Shelve the given instance.""" - super(ComputeCellsAPI, self).shelve(context, instance, - clean_shutdown=clean_shutdown) self._cast_to_cells(context, instance, 'shelve', clean_shutdown=clean_shutdown) @@ -364,9 +365,10 @@ class ComputeCellsAPI(compute_api.API): clean_shutdown=clean_shutdown) @check_instance_cell + @check_instance_state(vm_state=[vm_states.SHELVED, + vm_states.SHELVED_OFFLOADED]) def unshelve(self, context, instance): """Unshelve the given instance.""" - super(ComputeCellsAPI, self).unshelve(context, instance) self._cast_to_cells(context, instance, 'unshelve') @check_instance_cell diff --git a/nova/tests/unit/compute/test_compute_api.py b/nova/tests/unit/compute/test_compute_api.py index daef89339c2c..faf67231174c 100644 --- a/nova/tests/unit/compute/test_compute_api.py +++ b/nova/tests/unit/compute/test_compute_api.py @@ -4526,6 +4526,20 @@ class ComputeAPIAPICellUnitTestCase(_ComputeAPIUnitTestMixIn, self.context, requested_networks, 5) self.assertEqual(5, count) + def _test_shelve(self, vm_state=vm_states.ACTIVE, + boot_from_volume=False, clean_shutdown=True): + params = dict(task_state=None, vm_state=vm_state, + display_name='fake-name') + instance = self._create_instance_obj(params=params) + with mock.patch.object(self.compute_api, + '_cast_to_cells') as cast_to_cells: + self.compute_api.shelve(self.context, instance, + clean_shutdown=clean_shutdown) + cast_to_cells.assert_called_once_with(self.context, + instance, 'shelve', + clean_shutdown=clean_shutdown + ) + class ComputeAPIComputeCellUnitTestCase(_ComputeAPIUnitTestMixIn, test.NoDBTestCase): diff --git a/nova/tests/unit/compute/test_compute_cells.py b/nova/tests/unit/compute/test_compute_cells.py index 8b5074397800..78d255bf15c3 100644 --- a/nova/tests/unit/compute/test_compute_cells.py +++ b/nova/tests/unit/compute/test_compute_cells.py @@ -28,6 +28,7 @@ from nova.cells import manager from nova.compute import api as compute_api from nova.compute import cells_api as compute_cells_api from nova.compute import flavors +from nova.compute import task_states from nova.compute import utils as compute_utils from nova.compute import vm_states import nova.conf @@ -38,6 +39,7 @@ from nova import objects from nova import quota from nova import test from nova.tests.unit.compute import test_compute +from nova.tests.unit.compute import test_shelve from nova.tests.unit import fake_instance from nova.tests.unit.objects import test_flavor from nova.tests import uuidsentinel as uuids @@ -425,6 +427,49 @@ class CellsComputeAPITestCase(test_compute.ComputeAPITestCase): cells_enabled=True) +class CellsShelveComputeAPITestCase(test_shelve.ShelveComputeAPITestCase): + def setUp(self): + super(CellsShelveComputeAPITestCase, self).setUp() + global ORIG_COMPUTE_API + ORIG_COMPUTE_API = self.compute_api + self.compute_api = compute_cells_api.ComputeCellsAPI() + + def _fake_validate_cell(*args, **kwargs): + return + + def _fake_cast_to_cells(self, context, instance, method, + *args, **kwargs): + fn = getattr(ORIG_COMPUTE_API, method) + fn(context, instance, *args, **kwargs) + + self.stub_out('nova.compute.api.API._validate_cell', + _fake_validate_cell) + self.stub_out('nova.compute.cells_api.ComputeCellsAPI._cast_to_cells', + _fake_cast_to_cells) + + def test_unshelve(self): + # Ensure instance can be unshelved on cell environment. + # The super class tests nova-shelve. + instance = self._create_fake_instance_obj() + + self.assertIsNone(instance['task_state']) + + self.compute_api.shelve(self.context, instance) + + instance.task_state = None + instance.vm_state = vm_states.SHELVED + instance.save() + + self.compute_api.unshelve(self.context, instance) + + self.assertEqual(task_states.UNSHELVING, instance.task_state) + + def tearDown(self): + global ORIG_COMPUTE_API + self.compute_api = ORIG_COMPUTE_API + super(CellsShelveComputeAPITestCase, self).tearDown() + + class CellsConductorAPIRPCRedirect(test.NoDBTestCase): def setUp(self): super(CellsConductorAPIRPCRedirect, self).setUp()