summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/compute/manager.py12
-rw-r--r--nova/conductor/api.py31
-rw-r--r--nova/conductor/manager.py19
-rw-r--r--nova/conductor/rpcapi.py12
-rw-r--r--nova/tests/conductor/test_conductor.py75
5 files changed, 142 insertions, 7 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index d472418f3..564b2aa02 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -1058,8 +1058,7 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_uuid)
# ensure block device mappings are not leaked
- for bdm in bdms:
- self.db.block_device_mapping_destroy(context, bdm['id'])
+ self.conductor_api.block_device_mapping_destroy(context, bdms)
self._notify_about_instance_usage(context, instance, "delete.end",
system_metadata=system_meta)
@@ -2323,8 +2322,9 @@ class ComputeManager(manager.SchedulerDependentManager):
mountpoint, instance)
except Exception:
with excutils.save_and_reraise_exception():
- self.db.block_device_mapping_destroy_by_instance_and_device(
- context, instance.get('uuid'), mountpoint)
+ capi = self.conductor_api
+ capi.block_device_mapping_destroy_by_instance_and_device(
+ context, instance, mountpoint)
def _attach_volume(self, context, volume_id, mountpoint, instance):
volume = self.volume_api.get(context, volume_id)
@@ -2435,8 +2435,8 @@ class ComputeManager(manager.SchedulerDependentManager):
connector = self.driver.get_volume_connector(instance)
self.volume_api.terminate_connection(context, volume, connector)
self.volume_api.detach(context.elevated(), volume)
- self.db.block_device_mapping_destroy_by_instance_and_volume(
- context, instance['uuid'], volume_id)
+ self.conductor_api.block_device_mapping_destroy_by_instance_and_volume(
+ context, instance, volume_id)
@exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
def remove_volume_connection(self, context, volume_id, instance):
diff --git a/nova/conductor/api.py b/nova/conductor/api.py
index 1fe78d4ab..888bdfa9f 100644
--- a/nova/conductor/api.py
+++ b/nova/conductor/api.py
@@ -154,6 +154,21 @@ class LocalAPI(object):
return self._manager.block_device_mapping_get_all_by_instance(
context, instance)
+ def block_device_mapping_destroy(self, context, bdms):
+ return self._manager.block_device_mapping_destroy(context, bdms=bdms)
+
+ def block_device_mapping_destroy_by_instance_and_device(self, context,
+ instance,
+ device_name):
+ return self._manager.block_device_mapping_destroy(
+ context, instance=instance, device_name=device_name)
+
+ def block_device_mapping_destroy_by_instance_and_volume(self, context,
+ instance,
+ volume_id):
+ return self._manager.block_device_mapping_destroy(
+ context, instance=instance, volume_id=volume_id)
+
class API(object):
"""Conductor API that does updates via RPC to the ConductorManager"""
@@ -257,3 +272,19 @@ class API(object):
def block_device_mapping_get_all_by_instance(self, context, instance):
return self.conductor_rpcapi.block_device_mapping_get_all_by_instance(
context, instance)
+
+ def block_device_mapping_destroy(self, context, bdms):
+ return self.conductor_rpcapi.block_device_mapping_destroy(context,
+ bdms=bdms)
+
+ def block_device_mapping_destroy_by_instance_and_device(self, context,
+ instance,
+ device_name):
+ return self.conductor_rpcapi.block_device_mapping_destroy(
+ context, instance=instance, device_name=device_name)
+
+ def block_device_mapping_destroy_by_instance_and_volume(self, context,
+ instance,
+ volume_id):
+ return self.conductor_rpcapi.block_device_mapping_destroy(
+ context, instance=instance, volume_id=volume_id)
diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py
index bac8207d4..6b7344ed2 100644
--- a/nova/conductor/manager.py
+++ b/nova/conductor/manager.py
@@ -43,7 +43,7 @@ datetime_fields = ['launched_at', 'terminated_at']
class ConductorManager(manager.SchedulerDependentManager):
"""Mission: TBD"""
- RPC_API_VERSION = '1.13'
+ RPC_API_VERSION = '1.14'
def __init__(self, *args, **kwargs):
super(ConductorManager, self).__init__(service_name='conductor',
@@ -169,3 +169,20 @@ class ConductorManager(manager.SchedulerDependentManager):
bdms = self.db.block_device_mapping_get_all_by_instance(
context, instance['uuid'])
return jsonutils.to_primitive(bdms)
+
+ def block_device_mapping_destroy(self, context, bdms=None,
+ instance=None, volume_id=None,
+ device_name=None):
+ if bdms is not None:
+ for bdm in bdms:
+ self.db.block_device_mapping_destroy(context, bdm['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)
+ 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)
+ else:
+ # NOTE(danms): This shouldn't happen
+ raise exception.Invalid(_("Invalid block_device_mapping_destroy"
+ " invocation"))
diff --git a/nova/conductor/rpcapi.py b/nova/conductor/rpcapi.py
index fea461d26..ceb38a425 100644
--- a/nova/conductor/rpcapi.py
+++ b/nova/conductor/rpcapi.py
@@ -42,6 +42,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
1.11 - Added aggregate_get
1.12 - Added block_device_mapping_update_or_create
1.13 - Added block_device_mapping_get_all_by_instance
+ 1.14 - Added block_device_mapping_destroy
"""
BASE_RPC_API_VERSION = '1.0'
@@ -159,3 +160,14 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
msg = self.make_msg('block_device_mapping_get_all_by_instance',
instance=instance_p)
return self.call(context, msg, version='1.13')
+
+ def block_device_mapping_destroy(self, context, bdms=None,
+ instance=None, volume_id=None,
+ device_name=None):
+ bdms_p = jsonutils.to_primitive(bdms)
+ instance_p = jsonutils.to_primitive(instance)
+ msg = self.make_msg('block_device_mapping_destroy',
+ bdms=bdms_p,
+ instance=instance_p, volume_id=volume_id,
+ device_name=device_name)
+ return self.call(context, msg, version='1.14')
diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py
index 4aa552cc7..23930770a 100644
--- a/nova/tests/conductor/test_conductor.py
+++ b/nova/tests/conductor/test_conductor.py
@@ -305,6 +305,34 @@ class ConductorTestCase(_BaseTestCase, test.TestCase):
self.conductor.block_device_mapping_update_or_create(self.context,
fake_bdm)
+ def test_block_device_mapping_destroy(self):
+ fake_bdm = {'id': 'fake-bdm'}
+ fake_bdm2 = {'id': 'fake-bdm-2'}
+ 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')
+ self.mox.StubOutWithMock(
+ db, 'block_device_mapping_destroy_by_instance_and_volume')
+ db.block_device_mapping_destroy(self.context, 'fake-bdm')
+ db.block_device_mapping_destroy(self.context, 'fake-bdm-2')
+ db.block_device_mapping_destroy_by_instance_and_device(self.context,
+ 'fake-uuid',
+ 'fake-device')
+ db.block_device_mapping_destroy_by_instance_and_volume(self.context,
+ 'fake-uuid',
+ 'fake-volume')
+ self.mox.ReplayAll()
+ self.conductor.block_device_mapping_destroy(self.context,
+ [fake_bdm,
+ fake_bdm2])
+ self.conductor.block_device_mapping_destroy(self.context,
+ instance=fake_inst,
+ device_name='fake-device')
+ self.conductor.block_device_mapping_destroy(self.context,
+ instance=fake_inst,
+ volume_id='fake-volume')
+
class ConductorRPCAPITestCase(_BaseTestCase, test.TestCase):
"""Conductor RPC API Tests"""
@@ -332,6 +360,31 @@ class ConductorRPCAPITestCase(_BaseTestCase, test.TestCase):
self.conductor.block_device_mapping_update_or_create(self.context,
fake_bdm)
+ def test_block_device_mapping_destroy(self):
+ fake_bdm = {'id': 'fake-bdm'}
+ 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')
+ self.mox.StubOutWithMock(
+ db, 'block_device_mapping_destroy_by_instance_and_volume')
+ db.block_device_mapping_destroy(self.context, 'fake-bdm')
+ db.block_device_mapping_destroy_by_instance_and_device(self.context,
+ 'fake-uuid',
+ 'fake-device')
+ db.block_device_mapping_destroy_by_instance_and_volume(self.context,
+ 'fake-uuid',
+ 'fake-volume')
+ self.mox.ReplayAll()
+ self.conductor.block_device_mapping_destroy(self.context,
+ bdms=[fake_bdm])
+ self.conductor.block_device_mapping_destroy(self.context,
+ instance=fake_inst,
+ device_name='fake-device')
+ self.conductor.block_device_mapping_destroy(self.context,
+ instance=fake_inst,
+ volume_id='fake-volume')
+
class ConductorAPITestCase(_BaseTestCase, test.TestCase):
"""Conductor API Tests"""
@@ -375,6 +428,28 @@ class ConductorAPITestCase(_BaseTestCase, test.TestCase):
self.conductor.block_device_mapping_update_or_create(self.context,
'fake-bdm')
+ def test_block_device_mapping_destroy(self):
+ fake_bdm = {'id': 'fake-bdm'}
+ 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')
+ self.mox.StubOutWithMock(
+ db, 'block_device_mapping_destroy_by_instance_and_volume')
+ db.block_device_mapping_destroy(self.context, 'fake-bdm')
+ db.block_device_mapping_destroy_by_instance_and_device(self.context,
+ 'fake-uuid',
+ 'fake-device')
+ db.block_device_mapping_destroy_by_instance_and_volume(self.context,
+ 'fake-uuid',
+ 'fake-volume')
+ self.mox.ReplayAll()
+ self.conductor.block_device_mapping_destroy(self.context, [fake_bdm])
+ self.conductor.block_device_mapping_destroy_by_instance_and_device(
+ self.context, fake_inst, 'fake-device')
+ self.conductor.block_device_mapping_destroy_by_instance_and_volume(
+ self.context, fake_inst, 'fake-volume')
+
class ConductorLocalAPITestCase(ConductorAPITestCase):
"""Conductor LocalAPI Tests"""