Cells: Add support for global cinder
Implements cinder support for compute cells when cinder is a global installation. Adds syncing of the block device mapping table between child cells and API cells. Implements blueprint cells-cinder-support Change-Id: Ife5be9922db0742c8ee4f970517396be86597cce
This commit is contained in:
parent
9b5e206027
commit
39e8f5bd3b
|
@ -64,7 +64,7 @@ class CellsManager(manager.Manager):
|
|||
|
||||
Scheduling requests get passed to the scheduler class.
|
||||
"""
|
||||
RPC_API_VERSION = '1.9'
|
||||
RPC_API_VERSION = '1.10'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Mostly for tests.
|
||||
|
@ -390,3 +390,14 @@ class CellsManager(manager.Manager):
|
|||
|
||||
def get_capacities(self, ctxt, cell_name):
|
||||
return self.state_manager.get_capacities(cell_name)
|
||||
|
||||
def bdm_update_or_create_at_top(self, ctxt, bdm, create=None):
|
||||
"""BDM was created/updated in this cell. Tell the API cells."""
|
||||
self.msg_runner.bdm_update_or_create_at_top(ctxt, bdm, create=create)
|
||||
|
||||
def bdm_destroy_at_top(self, ctxt, instance_uuid, device_name=None,
|
||||
volume_id=None):
|
||||
"""BDM was destroyed for instance in this cell. Tell the API cells."""
|
||||
self.msg_runner.bdm_destroy_at_top(ctxt, instance_uuid,
|
||||
device_name=device_name,
|
||||
volume_id=volume_id)
|
||||
|
|
|
@ -848,7 +848,8 @@ class _BroadcastMessageMethods(_BaseMessageMethods):
|
|||
except exception.NotFound:
|
||||
# FIXME(comstud): Strange. Need to handle quotas here,
|
||||
# if we actually want this code to remain..
|
||||
self.db.instance_create(message.ctxt, instance)
|
||||
self.db.instance_create(message.ctxt, instance,
|
||||
legacy=False)
|
||||
if info_cache:
|
||||
try:
|
||||
self.db.instance_info_cache_update(
|
||||
|
@ -959,6 +960,60 @@ class _BroadcastMessageMethods(_BaseMessageMethods):
|
|||
self.consoleauth_rpcapi.delete_tokens_for_instance(message.ctxt,
|
||||
instance_uuid)
|
||||
|
||||
def bdm_update_or_create_at_top(self, message, bdm, create):
|
||||
"""Create or update a block device mapping in API cells. If
|
||||
create is True, only try to create. If create is None, try to
|
||||
update but fall back to create. If create is False, only attempt
|
||||
to update. This maps to nova-conductor's behavior.
|
||||
"""
|
||||
if not self._at_the_top():
|
||||
return
|
||||
items_to_remove = ['id']
|
||||
for key in items_to_remove:
|
||||
bdm.pop(key, None)
|
||||
if create is None:
|
||||
self.db.block_device_mapping_update_or_create(message.ctxt,
|
||||
bdm,
|
||||
legacy=False)
|
||||
return
|
||||
elif create is True:
|
||||
self.db.block_device_mapping_create(message.ctxt, bdm,
|
||||
legacy=False)
|
||||
return
|
||||
# Unfortunately this update call wants BDM ID... but we don't know
|
||||
# what it is in this cell. Search for it.. try matching either
|
||||
# device_name or volume_id.
|
||||
dev_name = bdm['device_name']
|
||||
vol_id = bdm['volume_id']
|
||||
instance_bdms = self.db.block_device_mapping_get_all_by_instance(
|
||||
message.ctxt, bdm['instance_uuid'])
|
||||
for instance_bdm in instance_bdms:
|
||||
if dev_name and instance_bdm['device_name'] == dev_name:
|
||||
break
|
||||
if vol_id and instance_bdm['volume_id'] == vol_id:
|
||||
break
|
||||
else:
|
||||
LOG.warn(_("No match when trying to update BDM: %(bdm)s"),
|
||||
dict(bdm=bdm))
|
||||
return
|
||||
self.db.block_device_mapping_update(message.ctxt,
|
||||
instance_bdm['id'], bdm,
|
||||
legacy=False)
|
||||
|
||||
def bdm_destroy_at_top(self, message, instance_uuid, device_name,
|
||||
volume_id):
|
||||
"""Destroy a block device mapping in API cells by device name
|
||||
or volume_id. device_name or volume_id can be None, but not both.
|
||||
"""
|
||||
if not self._at_the_top():
|
||||
return
|
||||
if device_name:
|
||||
self.db.block_device_mapping_destroy_by_instance_and_device(
|
||||
message.ctxt, instance_uuid, device_name)
|
||||
elif volume_id:
|
||||
self.db.block_device_mapping_destroy_by_instance_and_volume(
|
||||
message.ctxt, instance_uuid, volume_id)
|
||||
|
||||
|
||||
_CELL_MESSAGE_TYPE_TO_MESSAGE_CLS = {'targeted': _TargetedMessage,
|
||||
'broadcast': _BroadcastMessage,
|
||||
|
@ -1344,6 +1399,25 @@ class MessageRunner(object):
|
|||
cell_name, need_response=True)
|
||||
return message.process()
|
||||
|
||||
def bdm_update_or_create_at_top(self, ctxt, bdm, create=None):
|
||||
"""Update/Create a BDM at top level cell."""
|
||||
message = _BroadcastMessage(self, ctxt,
|
||||
'bdm_update_or_create_at_top',
|
||||
dict(bdm=bdm, create=create),
|
||||
'up', run_locally=False)
|
||||
message.process()
|
||||
|
||||
def bdm_destroy_at_top(self, ctxt, instance_uuid, device_name=None,
|
||||
volume_id=None):
|
||||
"""Destroy a BDM at top level cell."""
|
||||
method_kwargs = dict(instance_uuid=instance_uuid,
|
||||
device_name=device_name,
|
||||
volume_id=volume_id)
|
||||
message = _BroadcastMessage(self, ctxt, 'bdm_destroy_at_top',
|
||||
method_kwargs,
|
||||
'up', run_locally=False)
|
||||
message.process()
|
||||
|
||||
@staticmethod
|
||||
def get_message_types():
|
||||
return _CELL_MESSAGE_TYPE_TO_MESSAGE_CLS.keys()
|
||||
|
|
|
@ -26,9 +26,11 @@ from oslo.config import cfg
|
|||
|
||||
from nova import exception
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova.openstack.common import log as logging
|
||||
from nova.openstack.common.rpc import proxy as rpc_proxy
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
CONF.import_opt('enable', 'nova.cells.opts', group='cells')
|
||||
CONF.import_opt('topic', 'nova.cells.opts', group='cells')
|
||||
|
@ -52,6 +54,7 @@ class CellsAPI(rpc_proxy.RpcProxy):
|
|||
1.7 - Adds service_update()
|
||||
1.8 - Adds build_instances(), deprecates schedule_run_instance()
|
||||
1.9 - Adds get_capacities()
|
||||
1.10 - Adds bdm_update_or_create_at_top(), and bdm_destroy_at_top()
|
||||
'''
|
||||
BASE_RPC_API_VERSION = '1.0'
|
||||
|
||||
|
@ -298,3 +301,34 @@ class CellsAPI(rpc_proxy.RpcProxy):
|
|||
return self.call(ctxt,
|
||||
self.make_msg('get_capacities', cell_name=cell_name),
|
||||
version='1.9')
|
||||
|
||||
def bdm_update_or_create_at_top(self, ctxt, bdm, create=None):
|
||||
"""Create or update a block device mapping in API cells. If
|
||||
create is True, only try to create. If create is None, try to
|
||||
update but fall back to create. If create is False, only attempt
|
||||
to update. This maps to nova-conductor's behavior.
|
||||
"""
|
||||
if not CONF.cells.enable:
|
||||
return
|
||||
try:
|
||||
self.cast(ctxt, self.make_msg('bdm_update_or_create_at_top',
|
||||
bdm=bdm, create=create),
|
||||
version='1.10')
|
||||
except Exception:
|
||||
LOG.exception(_("Failed to notify cells of BDM update/create."))
|
||||
|
||||
def bdm_destroy_at_top(self, ctxt, instance_uuid, device_name=None,
|
||||
volume_id=None):
|
||||
"""Broadcast upwards that a block device mapping was destroyed.
|
||||
One of device_name or volume_id should be specified.
|
||||
"""
|
||||
if not CONF.cells.enable:
|
||||
return
|
||||
try:
|
||||
self.cast(ctxt, self.make_msg('bdm_destroy_at_top',
|
||||
instance_uuid=instance_uuid,
|
||||
device_name=device_name,
|
||||
volume_id=volume_id),
|
||||
version='1.10')
|
||||
except Exception:
|
||||
LOG.exception(_("Failed to notify cells of BDM destroy."))
|
||||
|
|
|
@ -520,8 +520,6 @@ class ComputeCellsAPI(compute_api.API):
|
|||
"""Attach an existing volume to an existing instance."""
|
||||
if device and not block_device.match_device(device):
|
||||
raise exception.InvalidDevicePath(path=device)
|
||||
device = self.compute_rpcapi.reserve_block_device_name(
|
||||
context, device=device, instance=instance, volume_id=volume_id)
|
||||
try:
|
||||
volume = self.volume_api.get(context, volume_id)
|
||||
self.volume_api.check_attach(context, volume, instance=instance)
|
||||
|
@ -529,7 +527,7 @@ class ComputeCellsAPI(compute_api.API):
|
|||
with excutils.save_and_reraise_exception():
|
||||
self.db.block_device_mapping_destroy_by_instance_and_device(
|
||||
context, instance['uuid'], device)
|
||||
self._cast_to_cells(context, instance, 'attach_volume',
|
||||
return self._call_to_cells(context, instance, 'attach_volume',
|
||||
volume_id, device)
|
||||
|
||||
@validate_cell
|
||||
|
|
|
@ -18,6 +18,7 @@ import copy
|
|||
|
||||
from nova.api.ec2 import ec2utils
|
||||
from nova import block_device
|
||||
from nova.cells import rpcapi as cells_rpcapi
|
||||
from nova.compute import api as compute_api
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova import exception
|
||||
|
@ -78,6 +79,7 @@ class ConductorManager(manager.Manager):
|
|||
self._compute_api = None
|
||||
self.compute_task_mgr = ComputeTaskManager()
|
||||
self.quotas = quota.QUOTAS
|
||||
self.cells_rpcapi = cells_rpcapi.CellsAPI()
|
||||
|
||||
def create_rpc_dispatcher(self, *args, **kwargs):
|
||||
kwargs['additional_apis'] = [self.compute_task_mgr]
|
||||
|
@ -259,11 +261,18 @@ class ConductorManager(manager.Manager):
|
|||
def block_device_mapping_update_or_create(self, context, values,
|
||||
create=None):
|
||||
if create is None:
|
||||
self.db.block_device_mapping_update_or_create(context, values)
|
||||
bdm = self.db.block_device_mapping_update_or_create(context,
|
||||
values)
|
||||
elif create is True:
|
||||
self.db.block_device_mapping_create(context, values)
|
||||
bdm = self.db.block_device_mapping_create(context, values)
|
||||
else:
|
||||
self.db.block_device_mapping_update(context, values['id'], values)
|
||||
bdm = self.db.block_device_mapping_update(context,
|
||||
values['id'],
|
||||
values)
|
||||
# NOTE:comstud): 'bdm' is always in the new format, so we
|
||||
# account for this in cells/messaging.py
|
||||
self.cells_rpcapi.bdm_update_or_create_at_top(context, bdm,
|
||||
create=create)
|
||||
|
||||
def block_device_mapping_get_all_by_instance(self, context, instance,
|
||||
legacy=True):
|
||||
|
@ -279,12 +288,36 @@ class ConductorManager(manager.Manager):
|
|||
if bdms is not None:
|
||||
for bdm in bdms:
|
||||
self.db.block_device_mapping_destroy(context, bdm['id'])
|
||||
# NOTE(comstud): bdm['id'] will be different in API cell,
|
||||
# so we must try to destroy by device_name or volume_id.
|
||||
# We need an instance_uuid in order to do this properly,
|
||||
# too.
|
||||
# I hope to clean a lot of this up in the object
|
||||
# implementation.
|
||||
instance_uuid = (bdm['instance_uuid'] or
|
||||
(instance and instance['uuid']))
|
||||
if not instance_uuid:
|
||||
continue
|
||||
# Better to be safe than sorry. device_name is not
|
||||
# NULLable, however it could be an empty string.
|
||||
if bdm['device_name']:
|
||||
self.cells_rpcapi.bdm_destroy_at_top(
|
||||
context, instance_uuid,
|
||||
device_name=bdm['device_name'])
|
||||
elif bdm['volume_id']:
|
||||
self.cells_rpcapi.bdm_destroy_at_top(
|
||||
context, instance_uuid,
|
||||
volume_id=bdm['volume_id'])
|
||||
elif instance is not None and volume_id is not None:
|
||||
self.db.block_device_mapping_destroy_by_instance_and_volume(
|
||||
context, instance['uuid'], volume_id)
|
||||
self.cells_rpcapi.bdm_destroy_at_top(
|
||||
context, instance['uuid'], volume_id=volume_id)
|
||||
elif instance is not None and device_name is not None:
|
||||
self.db.block_device_mapping_destroy_by_instance_and_device(
|
||||
context, instance['uuid'], device_name)
|
||||
self.cells_rpcapi.bdm_destroy_at_top(
|
||||
context, instance['uuid'], device_name=device_name)
|
||||
else:
|
||||
# NOTE(danms): This shouldn't happen
|
||||
raise exception.Invalid(_("Invalid block_device_mapping_destroy"
|
||||
|
|
|
@ -3139,15 +3139,16 @@ def block_device_mapping_create(context, values, legacy=True):
|
|||
bdm_ref = models.BlockDeviceMapping()
|
||||
bdm_ref.update(values)
|
||||
bdm_ref.save()
|
||||
return bdm_ref
|
||||
|
||||
|
||||
@require_context
|
||||
def block_device_mapping_update(context, bdm_id, values, legacy=True):
|
||||
_scrub_empty_str_values(values, ['volume_size'])
|
||||
values = _from_legacy_values(values, legacy, allow_updates=True)
|
||||
_block_device_mapping_get_query(context).\
|
||||
filter_by(id=bdm_id).\
|
||||
update(values)
|
||||
query = _block_device_mapping_get_query(context).filter_by(id=bdm_id)
|
||||
query.update(values)
|
||||
return query.first()
|
||||
|
||||
|
||||
def block_device_mapping_update_or_create(context, values, legacy=True):
|
||||
|
@ -3163,6 +3164,7 @@ def block_device_mapping_update_or_create(context, values, legacy=True):
|
|||
bdm_ref = models.BlockDeviceMapping()
|
||||
bdm_ref.update(values)
|
||||
bdm_ref.save(session=session)
|
||||
result = bdm_ref
|
||||
else:
|
||||
values = _from_legacy_values(values, legacy, allow_updates=True)
|
||||
result.update(values)
|
||||
|
@ -3185,6 +3187,7 @@ def block_device_mapping_update_or_create(context, values, legacy=True):
|
|||
models.BlockDeviceMapping.guest_format == None,
|
||||
models.BlockDeviceMapping.guest_format != 'swap')).
|
||||
soft_delete())
|
||||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
|
|
|
@ -2121,6 +2121,7 @@ class CloudTestCase(test.TestCase):
|
|||
return [dict(id=1,
|
||||
source_type='snapshot',
|
||||
destination_type='volume',
|
||||
instance_uuid=inst_id,
|
||||
snapshot_id=snapshots[0],
|
||||
volume_id=volumes[0],
|
||||
volume_size=1,
|
||||
|
|
|
@ -548,3 +548,27 @@ class CellsManagerClassTestCase(test.TestCase):
|
|||
instance_uuid=instance_uuid, console_port=console_port,
|
||||
console_type=console_type)
|
||||
self.assertEqual('fake-response', response)
|
||||
|
||||
def test_bdm_update_or_create_at_top(self):
|
||||
self.mox.StubOutWithMock(self.msg_runner,
|
||||
'bdm_update_or_create_at_top')
|
||||
self.msg_runner.bdm_update_or_create_at_top(self.ctxt,
|
||||
'fake-bdm',
|
||||
create='foo')
|
||||
self.mox.ReplayAll()
|
||||
self.cells_manager.bdm_update_or_create_at_top(self.ctxt,
|
||||
'fake-bdm',
|
||||
create='foo')
|
||||
|
||||
def test_bdm_destroy_at_top(self):
|
||||
self.mox.StubOutWithMock(self.msg_runner, 'bdm_destroy_at_top')
|
||||
self.msg_runner.bdm_destroy_at_top(self.ctxt,
|
||||
'fake_instance_uuid',
|
||||
device_name='fake_device_name',
|
||||
volume_id='fake_volume_id')
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.cells_manager.bdm_destroy_at_top(self.ctxt,
|
||||
'fake_instance_uuid',
|
||||
device_name='fake_device_name',
|
||||
volume_id='fake_volume_id')
|
||||
|
|
|
@ -1425,3 +1425,173 @@ class CellsBroadcastMethodsTestCase(test.TestCase):
|
|||
self.mox.ReplayAll()
|
||||
|
||||
self.src_msg_runner.consoleauth_delete_tokens(self.ctxt, fake_uuid)
|
||||
|
||||
def test_bdm_update_or_create_with_none_create(self):
|
||||
fake_bdm = {'id': 'fake_id',
|
||||
'volume_id': 'fake_volume_id'}
|
||||
expected_bdm = fake_bdm.copy()
|
||||
expected_bdm.pop('id')
|
||||
|
||||
# Shouldn't be called for these 2 cells
|
||||
self.mox.StubOutWithMock(self.src_db_inst,
|
||||
'block_device_mapping_update_or_create')
|
||||
self.mox.StubOutWithMock(self.mid_db_inst,
|
||||
'block_device_mapping_update_or_create')
|
||||
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_update_or_create')
|
||||
self.tgt_db_inst.block_device_mapping_update_or_create(
|
||||
self.ctxt, expected_bdm, legacy=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
|
||||
fake_bdm,
|
||||
create=None)
|
||||
|
||||
def test_bdm_update_or_create_with_true_create(self):
|
||||
fake_bdm = {'id': 'fake_id',
|
||||
'volume_id': 'fake_volume_id'}
|
||||
expected_bdm = fake_bdm.copy()
|
||||
expected_bdm.pop('id')
|
||||
|
||||
# Shouldn't be called for these 2 cells
|
||||
self.mox.StubOutWithMock(self.src_db_inst,
|
||||
'block_device_mapping_create')
|
||||
self.mox.StubOutWithMock(self.mid_db_inst,
|
||||
'block_device_mapping_create')
|
||||
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_create')
|
||||
self.tgt_db_inst.block_device_mapping_create(
|
||||
self.ctxt, fake_bdm, legacy=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
|
||||
fake_bdm,
|
||||
create=True)
|
||||
|
||||
def test_bdm_update_or_create_with_false_create_vol_id(self):
|
||||
fake_bdm = {'id': 'fake_id',
|
||||
'instance_uuid': 'fake_instance_uuid',
|
||||
'device_name': 'fake_device_name',
|
||||
'volume_id': 'fake_volume_id'}
|
||||
expected_bdm = fake_bdm.copy()
|
||||
expected_bdm.pop('id')
|
||||
|
||||
fake_inst_bdms = [{'id': 1,
|
||||
'volume_id': 'not-a-match',
|
||||
'device_name': 'not-a-match'},
|
||||
{'id': 2,
|
||||
'volume_id': 'fake_volume_id',
|
||||
'device_name': 'not-a-match'},
|
||||
{'id': 3,
|
||||
'volume_id': 'not-a-match',
|
||||
'device_name': 'not-a-match'}]
|
||||
|
||||
# Shouldn't be called for these 2 cells
|
||||
self.mox.StubOutWithMock(self.src_db_inst,
|
||||
'block_device_mapping_update')
|
||||
self.mox.StubOutWithMock(self.mid_db_inst,
|
||||
'block_device_mapping_update')
|
||||
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_get_all_by_instance')
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_update')
|
||||
|
||||
self.tgt_db_inst.block_device_mapping_get_all_by_instance(
|
||||
self.ctxt, 'fake_instance_uuid').AndReturn(
|
||||
fake_inst_bdms)
|
||||
# Should try to update ID 2.
|
||||
self.tgt_db_inst.block_device_mapping_update(
|
||||
self.ctxt, 2, expected_bdm, legacy=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
|
||||
fake_bdm,
|
||||
create=False)
|
||||
|
||||
def test_bdm_update_or_create_with_false_create_dev_name(self):
|
||||
fake_bdm = {'id': 'fake_id',
|
||||
'instance_uuid': 'fake_instance_uuid',
|
||||
'device_name': 'fake_device_name',
|
||||
'volume_id': 'fake_volume_id'}
|
||||
expected_bdm = fake_bdm.copy()
|
||||
expected_bdm.pop('id')
|
||||
|
||||
fake_inst_bdms = [{'id': 1,
|
||||
'volume_id': 'not-a-match',
|
||||
'device_name': 'not-a-match'},
|
||||
{'id': 2,
|
||||
'volume_id': 'not-a-match',
|
||||
'device_name': 'fake_device_name'},
|
||||
{'id': 3,
|
||||
'volume_id': 'not-a-match',
|
||||
'device_name': 'not-a-match'}]
|
||||
|
||||
# Shouldn't be called for these 2 cells
|
||||
self.mox.StubOutWithMock(self.src_db_inst,
|
||||
'block_device_mapping_update')
|
||||
self.mox.StubOutWithMock(self.mid_db_inst,
|
||||
'block_device_mapping_update')
|
||||
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_get_all_by_instance')
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_update')
|
||||
|
||||
self.tgt_db_inst.block_device_mapping_get_all_by_instance(
|
||||
self.ctxt, 'fake_instance_uuid').AndReturn(
|
||||
fake_inst_bdms)
|
||||
# Should try to update ID 2.
|
||||
self.tgt_db_inst.block_device_mapping_update(
|
||||
self.ctxt, 2, expected_bdm, legacy=False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.src_msg_runner.bdm_update_or_create_at_top(self.ctxt,
|
||||
fake_bdm,
|
||||
create=False)
|
||||
|
||||
def test_bdm_destroy_by_volume(self):
|
||||
fake_instance_uuid = 'fake-instance-uuid'
|
||||
fake_volume_id = 'fake-volume-name'
|
||||
|
||||
# Shouldn't be called for these 2 cells
|
||||
self.mox.StubOutWithMock(self.src_db_inst,
|
||||
'block_device_mapping_destroy_by_instance_and_volume')
|
||||
self.mox.StubOutWithMock(self.mid_db_inst,
|
||||
'block_device_mapping_destroy_by_instance_and_volume')
|
||||
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_destroy_by_instance_and_volume')
|
||||
self.tgt_db_inst.block_device_mapping_destroy_by_instance_and_volume(
|
||||
self.ctxt, fake_instance_uuid, fake_volume_id)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.src_msg_runner.bdm_destroy_at_top(self.ctxt, fake_instance_uuid,
|
||||
volume_id=fake_volume_id)
|
||||
|
||||
def test_bdm_destroy_by_device(self):
|
||||
fake_instance_uuid = 'fake-instance-uuid'
|
||||
fake_device_name = 'fake-device-name'
|
||||
|
||||
# Shouldn't be called for these 2 cells
|
||||
self.mox.StubOutWithMock(self.src_db_inst,
|
||||
'block_device_mapping_destroy_by_instance_and_device')
|
||||
self.mox.StubOutWithMock(self.mid_db_inst,
|
||||
'block_device_mapping_destroy_by_instance_and_device')
|
||||
|
||||
self.mox.StubOutWithMock(self.tgt_db_inst,
|
||||
'block_device_mapping_destroy_by_instance_and_device')
|
||||
self.tgt_db_inst.block_device_mapping_destroy_by_instance_and_device(
|
||||
self.ctxt, fake_instance_uuid, fake_device_name)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self.src_msg_runner.bdm_destroy_at_top(self.ctxt, fake_instance_uuid,
|
||||
device_name=fake_device_name)
|
||||
|
|
|
@ -422,3 +422,29 @@ class CellsAPITestCase(test.TestCase):
|
|||
self._check_result(call_info, 'validate_console_port',
|
||||
expected_args, version='1.6')
|
||||
self.assertEqual(result, 'fake_response')
|
||||
|
||||
def test_bdm_update_or_create_at_top(self):
|
||||
fake_bdm = {'id': 2, 'other': 'meow'}
|
||||
|
||||
call_info = self._stub_rpc_method('cast', None)
|
||||
|
||||
self.cells_rpcapi.bdm_update_or_create_at_top(
|
||||
self.fake_context, fake_bdm, create='fake-create')
|
||||
|
||||
expected_args = {'bdm': fake_bdm, 'create': 'fake-create'}
|
||||
self._check_result(call_info, 'bdm_update_or_create_at_top',
|
||||
expected_args, version='1.10')
|
||||
|
||||
def test_bdm_destroy_at_top(self):
|
||||
call_info = self._stub_rpc_method('cast', None)
|
||||
|
||||
self.cells_rpcapi.bdm_destroy_at_top(self.fake_context,
|
||||
'fake-uuid',
|
||||
device_name='fake-device',
|
||||
volume_id='fake-vol')
|
||||
|
||||
expected_args = {'instance_uuid': 'fake-uuid',
|
||||
'device_name': 'fake-device',
|
||||
'volume_id': 'fake-vol'}
|
||||
self._check_result(call_info, 'bdm_destroy_at_top',
|
||||
expected_args, version='1.10')
|
||||
|
|
|
@ -632,13 +632,28 @@ class ConductorTestCase(_BaseTestCase, test.TestCase):
|
|||
self.conductor_manager = self.conductor
|
||||
|
||||
def test_block_device_mapping_update_or_create(self):
|
||||
fake_bdm = {'id': 'fake-id'}
|
||||
fake_bdm = {'id': 'fake-id', 'device_name': 'foo'}
|
||||
fake_bdm2 = {'id': 'fake-id', 'device_name': 'foo2'}
|
||||
cells_rpcapi = self.conductor.cells_rpcapi
|
||||
self.mox.StubOutWithMock(db, 'block_device_mapping_create')
|
||||
self.mox.StubOutWithMock(db, 'block_device_mapping_update')
|
||||
self.mox.StubOutWithMock(db, 'block_device_mapping_update_or_create')
|
||||
db.block_device_mapping_create(self.context, fake_bdm)
|
||||
db.block_device_mapping_update(self.context, fake_bdm['id'], fake_bdm)
|
||||
db.block_device_mapping_update_or_create(self.context, fake_bdm)
|
||||
self.mox.StubOutWithMock(cells_rpcapi,
|
||||
'bdm_update_or_create_at_top')
|
||||
db.block_device_mapping_create(self.context,
|
||||
fake_bdm).AndReturn(fake_bdm2)
|
||||
cells_rpcapi.bdm_update_or_create_at_top(self.context, fake_bdm2,
|
||||
create=True)
|
||||
db.block_device_mapping_update(self.context, fake_bdm['id'],
|
||||
fake_bdm).AndReturn(fake_bdm2)
|
||||
cells_rpcapi.bdm_update_or_create_at_top(self.context,
|
||||
fake_bdm2,
|
||||
create=False)
|
||||
db.block_device_mapping_update_or_create(
|
||||
self.context, fake_bdm).AndReturn(fake_bdm2)
|
||||
cells_rpcapi.bdm_update_or_create_at_top(self.context,
|
||||
fake_bdm2,
|
||||
create=None)
|
||||
self.mox.ReplayAll()
|
||||
self.conductor.block_device_mapping_update_or_create(self.context,
|
||||
fake_bdm,
|
||||
|
@ -650,22 +665,44 @@ class ConductorTestCase(_BaseTestCase, test.TestCase):
|
|||
fake_bdm)
|
||||
|
||||
def test_block_device_mapping_destroy(self):
|
||||
fake_bdm = {'id': 'fake-bdm'}
|
||||
fake_bdm2 = {'id': 'fake-bdm-2'}
|
||||
fake_bdm = {'id': 'fake-bdm',
|
||||
'instance_uuid': 'fake-uuid',
|
||||
'device_name': 'fake-device1',
|
||||
'volume_id': 'fake-vol-id1'}
|
||||
fake_bdm2 = {'id': 'fake-bdm-2',
|
||||
'instance_uuid': 'fake-uuid2',
|
||||
'device_name': '',
|
||||
'volume_id': 'fake-vol-id2'}
|
||||
fake_inst = {'uuid': 'fake-uuid'}
|
||||
|
||||
cells_rpcapi = self.conductor.cells_rpcapi
|
||||
|
||||
self.mox.StubOutWithMock(db, 'block_device_mapping_destroy')
|
||||
self.mox.StubOutWithMock(
|
||||
db, 'block_device_mapping_destroy_by_instance_and_device')
|
||||
self.mox.StubOutWithMock(
|
||||
db, 'block_device_mapping_destroy_by_instance_and_volume')
|
||||
self.mox.StubOutWithMock(cells_rpcapi, 'bdm_destroy_at_top')
|
||||
|
||||
db.block_device_mapping_destroy(self.context, 'fake-bdm')
|
||||
cells_rpcapi.bdm_destroy_at_top(self.context,
|
||||
fake_bdm['instance_uuid'],
|
||||
device_name=fake_bdm['device_name'])
|
||||
db.block_device_mapping_destroy(self.context, 'fake-bdm-2')
|
||||
cells_rpcapi.bdm_destroy_at_top(self.context,
|
||||
fake_bdm2['instance_uuid'],
|
||||
volume_id=fake_bdm2['volume_id'])
|
||||
db.block_device_mapping_destroy_by_instance_and_device(self.context,
|
||||
'fake-uuid',
|
||||
'fake-device')
|
||||
cells_rpcapi.bdm_destroy_at_top(self.context, fake_inst['uuid'],
|
||||
device_name='fake-device')
|
||||
db.block_device_mapping_destroy_by_instance_and_volume(self.context,
|
||||
'fake-uuid',
|
||||
'fake-volume')
|
||||
cells_rpcapi.bdm_destroy_at_top(self.context, fake_inst['uuid'],
|
||||
volume_id='fake-volume')
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.conductor.block_device_mapping_destroy(self.context,
|
||||
[fake_bdm,
|
||||
|
@ -810,8 +847,12 @@ class ConductorRPCAPITestCase(_BaseTestCase, test.TestCase):
|
|||
fake_bdm)
|
||||
|
||||
def test_block_device_mapping_destroy(self):
|
||||
fake_bdm = {'id': 'fake-bdm'}
|
||||
fake_bdm = {'id': 'fake-bdm',
|
||||
'instance_uuid': 'fake-uuid',
|
||||
'device_name': 'fake-device1',
|
||||
'volume_id': 'fake-vol-id1'}
|
||||
fake_inst = {'uuid': 'fake-uuid'}
|
||||
|
||||
self.mox.StubOutWithMock(db, 'block_device_mapping_destroy')
|
||||
self.mox.StubOutWithMock(
|
||||
db, 'block_device_mapping_destroy_by_instance_and_device')
|
||||
|
@ -961,8 +1002,12 @@ class ConductorAPITestCase(_BaseTestCase, test.TestCase):
|
|||
'fake-bdm')
|
||||
|
||||
def test_block_device_mapping_destroy(self):
|
||||
fake_bdm = {'id': 'fake-bdm'}
|
||||
fake_bdm = {'id': 'fake-bdm',
|
||||
'instance_uuid': 'fake-uuid',
|
||||
'device_name': 'fake-device1',
|
||||
'volume_id': 'fake-vol-id1'}
|
||||
fake_inst = {'uuid': 'fake-uuid'}
|
||||
|
||||
self.mox.StubOutWithMock(db, 'block_device_mapping_destroy')
|
||||
self.mox.StubOutWithMock(
|
||||
db, 'block_device_mapping_destroy_by_instance_and_device')
|
||||
|
|
|
@ -4039,12 +4039,15 @@ class BlockDeviceMappingTestCase(test.TestCase):
|
|||
|
||||
def test_block_device_mapping_update(self):
|
||||
bdm = self._create_bdm({})
|
||||
db.block_device_mapping_update(self.ctxt, bdm['id'],
|
||||
{'destination_type': 'moon'},
|
||||
legacy=False)
|
||||
result = db.block_device_mapping_update(
|
||||
self.ctxt, bdm['id'], {'destination_type': 'moon'},
|
||||
legacy=False)
|
||||
uuid = bdm['instance_uuid']
|
||||
bdm_real = db.block_device_mapping_get_all_by_instance(self.ctxt, uuid)
|
||||
self.assertEqual(bdm_real[0]['destination_type'], 'moon')
|
||||
# Also make sure the update call returned correct data
|
||||
self.assertEqual(dict(bdm_real[0].iteritems()),
|
||||
dict(result.iteritems()))
|
||||
|
||||
def test_block_device_mapping_update_or_create(self):
|
||||
values = {
|
||||
|
|
Loading…
Reference in New Issue