Merge "Improve BlockDeviceMapping object cells awareness"

This commit is contained in:
Jenkins 2014-07-11 18:25:57 +00:00 committed by Gerrit Code Review
commit 0309d191b0
2 changed files with 91 additions and 20 deletions

View File

@ -13,6 +13,7 @@
# under the License.
from nova import block_device
from nova.cells import opts as cells_opts
from nova.cells import rpcapi as cells_rpcapi
from nova import db
from nova import exception
@ -81,6 +82,13 @@ class BlockDeviceMapping(base.NovaPersistentObject, base.NovaObject):
@base.remotable
def create(self, context):
cell_type = cells_opts.get_cell_type()
if cell_type == 'api':
raise exception.ObjectActionError(
action='create',
reason='BlockDeviceMapping cannot be '
'created in the API cell.')
if self.obj_attr_is_set('id'):
raise exception.ObjectActionError(action='create',
reason='already created')
@ -90,8 +98,9 @@ class BlockDeviceMapping(base.NovaPersistentObject, base.NovaObject):
reason='instance assigned')
db_bdm = db.block_device_mapping_create(context, updates, legacy=False)
cells_api = cells_rpcapi.CellsAPI()
cells_api.bdm_update_or_create_at_top(context, db_bdm, create=True)
if cell_type == 'compute':
cells_api = cells_rpcapi.CellsAPI()
cells_api.bdm_update_or_create_at_top(context, db_bdm, create=True)
self._from_db_object(context, self, db_bdm)
@base.remotable
@ -101,10 +110,13 @@ class BlockDeviceMapping(base.NovaPersistentObject, base.NovaObject):
reason='already destroyed')
db.block_device_mapping_destroy(context, self.id)
delattr(self, base.get_attrname('id'))
cells_api = cells_rpcapi.CellsAPI()
cells_api.bdm_destroy_at_top(context, self.instance_uuid,
device_name=self.device_name,
volume_id=self.volume_id)
cell_type = cells_opts.get_cell_type()
if cell_type == 'compute':
cells_api = cells_rpcapi.CellsAPI()
cells_api.bdm_destroy_at_top(context, self.instance_uuid,
device_name=self.device_name,
volume_id=self.volume_id)
@base.remotable
def save(self, context):
@ -115,8 +127,10 @@ class BlockDeviceMapping(base.NovaPersistentObject, base.NovaObject):
updates.pop('id', None)
updated = db.block_device_mapping_update(self._context, self.id,
updates, legacy=False)
cells_api = cells_rpcapi.CellsAPI()
cells_api.bdm_update_or_create_at_top(context, updated)
cell_type = cells_opts.get_cell_type()
if cell_type == 'compute':
cells_api = cells_rpcapi.CellsAPI()
cells_api.bdm_update_or_create_at_top(context, updated)
self._from_db_object(context, self, updated)
@base.remotable_classmethod

View File

@ -43,7 +43,12 @@ class _TestBlockDeviceMappingObject(object):
fake_bdm['instance'] = instance
return fake_bdm
def test_save(self):
def _test_save(self, cell_type=None):
if cell_type:
self.flags(enable=True, cell_type=cell_type, group='cells')
else:
self.flags(enable=False, group='cells')
fake_bdm = self.fake_bdm()
with contextlib.nested(
mock.patch.object(
@ -59,7 +64,20 @@ class _TestBlockDeviceMappingObject(object):
bdm_update_mock.assert_called_once_with(
self.context, 123, {'volume_id': 'fake_volume_id'},
legacy=False)
cells_update_mock.assert_called_once_with(self.context, fake_bdm)
if cell_type != 'compute':
self.assertFalse(cells_update_mock.called)
else:
cells_update_mock.assert_called_once_with(
self.context, fake_bdm)
def test_save_nocells(self):
self._test_save()
def test_save_apicell(self):
self._test_save(cell_type='api')
def test_save_computecell(self):
self._test_save(cell_type='compute')
def test_save_instance_changed(self):
bdm_object = objects.BlockDeviceMapping()
@ -108,7 +126,11 @@ class _TestBlockDeviceMappingObject(object):
['instance'])
self.assertRemotes()
def test_create_mocked(self):
def _test_create_mocked(self, cell_type=None):
if cell_type:
self.flags(enable=True, cell_type=cell_type, group='cells')
else:
self.flags(enable=False, group='cells')
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
'destination_type': 'volume',
'instance_uuid': 'fake-instance'}
@ -121,11 +143,30 @@ class _TestBlockDeviceMappingObject(object):
'bdm_update_or_create_at_top')
) as (bdm_create_mock, cells_update_mock):
bdm = objects.BlockDeviceMapping(**values)
bdm.create(self.context)
bdm_create_mock.assert_called_once_with(
if cell_type == 'api':
self.assertRaises(exception.ObjectActionError,
bdm.create, self.context)
elif cell_type == 'compute':
bdm.create(self.context)
bdm_create_mock.assert_called_once_with(
self.context, values, legacy=False)
cells_update_mock.assert_called_once_with(
self.context, fake_bdm, create=True)
cells_update_mock.assert_called_once_with(
self.context, fake_bdm, create=True)
else:
bdm.create(self.context)
self.assertFalse(cells_update_mock.called)
bdm_create_mock.assert_called_once_with(
self.context, values, legacy=False)
def test_create_nocells(self):
self._test_create_mocked()
def test_create_apicell(self):
self._test_create_mocked(cell_type='api')
def test_create_computecell(self):
self._test_create_mocked(cell_type='compute')
def test_create(self):
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
@ -158,10 +199,14 @@ class _TestBlockDeviceMappingObject(object):
self.assertRaises(exception.ObjectActionError,
bdm.create, self.context)
def test_destroy_mocked(self):
def _test_destroy_mocked(self, cell_type=None):
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
'destination_type': 'volume', 'id': 1,
'instance_uuid': 'fake-instance', 'device_name': 'fake'}
if cell_type:
self.flags(enable=True, cell_type=cell_type, group='cells')
else:
self.flags(enable=False, group='cells')
with contextlib.nested(
mock.patch.object(db, 'block_device_mapping_destroy'),
mock.patch.object(cells_rpcapi.CellsAPI, 'bdm_destroy_at_top')
@ -169,10 +214,22 @@ class _TestBlockDeviceMappingObject(object):
bdm = objects.BlockDeviceMapping(**values)
bdm.destroy(self.context)
bdm_del.assert_called_once_with(self.context, values['id'])
cells_destroy.assert_called_once_with(
self.context, values['instance_uuid'],
device_name=values['device_name'],
volume_id=values['volume_id'])
if cell_type != 'compute':
self.assertFalse(cells_destroy.called)
else:
cells_destroy.assert_called_once_with(
self.context, values['instance_uuid'],
device_name=values['device_name'],
volume_id=values['volume_id'])
def test_destroy_nocells(self):
self._test_destroy_mocked()
def test_destroy_apicell(self):
self._test_destroy_mocked(cell_type='api')
def test_destroy_computecell(self):
self._test_destroy_mocked(cell_type='compute')
class TestBlockDeviceMappingObject(test_objects._LocalTest,