Nova shelve creates duplicated images in cells

Calling super method in cells_api.py causes duplicated method call in
nova-api and nova-cell. I found the problem in shelve and unshelve,
so fix about them. (Nova cell v1 may have similar problems)

Change-Id: I8030b6ffc1710bca733e38a9a6fb0d7de5f24268
Closes-bug: #1588657
This commit is contained in:
Ryo Miki 2016-06-08 19:29:22 +09:00 committed by Rikimaru Honjo
parent 110c12b414
commit 32be810836
3 changed files with 64 additions and 3 deletions

View File

@ -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

View File

@ -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):

View File

@ -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()