summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikola Dipanov <ndipanov@redhat.com>2013-05-15 16:00:05 +0200
committerChris Behrens <cbehrens@codestud.com>2013-06-10 23:10:39 +0000
commit41eb083d228f159e8d4e566148db5994ad49143c (patch)
tree41f8828730de39290c2b03f5fe1e08e691580caa
parent0d5fb06b39e8244429be72f05e2066d24572dc2e (diff)
downloadnova-41eb083d228f159e8d4e566148db5994ad49143c.tar.gz
nova-41eb083d228f159e8d4e566148db5994ad49143c.tar.xz
nova-41eb083d228f159e8d4e566148db5994ad49143c.zip
Create an image BDM for every instance
This patch makes every boot create a block device mapping if the instance was started with an image. These block devices are not used anywhere at the moment but will be used in the future as part of a more flexible block device API. This patch also makes sure they are deleted once the instance is deleted as well. Change-Id: Ia89d531be71c460f1f82fcfce34b270639a23061 blueprint: improve-block-device-handling
-rw-r--r--nova/block_device.py15
-rw-r--r--nova/compute/api.py10
-rwxr-xr-xnova/compute/manager.py10
-rw-r--r--nova/tests/compute/test_compute.py50
4 files changed, 85 insertions, 0 deletions
diff --git a/nova/block_device.py b/nova/block_device.py
index 1094ef3ae..746fd6bb4 100644
--- a/nova/block_device.py
+++ b/nova/block_device.py
@@ -166,6 +166,21 @@ def is_safe_for_update(block_device_dict):
bdm_db_only_fields)
+def create_image_bdm(image_ref, boot_index=0):
+ """Create a block device dict based on the image_ref.
+
+ This is useful in the API layer to keep the compatibility
+ with having an image_ref as a field in the instance requests
+ """
+ return BlockDeviceDict(
+ {'source_type': 'image',
+ 'image_id': image_ref,
+ 'delete_on_termination': True,
+ 'boot_index': boot_index,
+ 'device_type': 'disk',
+ 'destination_type': 'local'})
+
+
def legacy_mapping(block_device_mapping):
"""Transform a list of block devices of an instance back to the
legacy data format."""
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 0674cff5f..65142aef0 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -898,6 +898,16 @@ class API(base.Base):
continue
self._update_block_device_mapping(context,
instance_type, instance_uuid, mapping)
+ # NOTE(ndipanov): Create an image bdm - at the moment
+ # this is not used but is done for easier transition
+ # in the future.
+ if (instance['image_ref'] and not
+ self.is_volume_backed_instance(context, instance, None)):
+ image_bdm = block_device.create_image_bdm(instance['image_ref'])
+ image_bdm['instance_uuid'] = instance_uuid
+ self.db.block_device_mapping_update_or_create(context,
+ image_bdm,
+ legacy=False)
def _populate_instance_shutdown_terminate(self, instance, image,
block_device_mapping):
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 998be6f76..42f8029a5 100755
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -1376,6 +1376,7 @@ class ComputeManager(manager.SchedulerDependentManager):
as necessary.
"""
instance_uuid = instance['uuid']
+ image = instance['image_ref']
if context.is_admin and context.project_id != instance['project_id']:
project_id = instance['project_id']
@@ -1429,6 +1430,15 @@ class ComputeManager(manager.SchedulerDependentManager):
self._quota_commit(context, reservations, project_id=project_id)
# ensure block device mappings are not leaked
self.conductor_api.block_device_mapping_destroy(context, bdms)
+ # NOTE(ndipanov): Delete the dummy image BDM as well. This will not
+ # be needed once the manager code is using the image
+ if image:
+ # Do not convert to legacy here - we want them all
+ leftover_bdm = \
+ self.conductor_api.block_device_mapping_get_all_by_instance(
+ context, instance)
+ self.conductor_api.block_device_mapping_destroy(context,
+ leftover_bdm)
self._notify_about_instance_usage(context, instance, "delete.end",
system_metadata=system_meta)
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index 3e0fbe63e..4dea52dfb 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -7263,6 +7263,56 @@ class ComputeAPITestCase(BaseTestCase):
instance = db.instance_get_by_uuid(self.context, instance['uuid'])
self.compute.terminate_instance(self.context, instance)
+ def test_populate_instance_for_bdm(self):
+ # Test that the image bdm is created
+ instance_type = {'swap': 1}
+ instance = self._create_fake_instance(
+ {'root_device_name': 'vda'}
+ )
+ image = {'uuid': FAKE_IMAGE_REF}
+ fake_bdms = [{'device_name': '/dev/vda',
+ 'snapshot_id': '33333333-aaaa-bbbb-cccc-333333333333',
+ 'delete_on_termination': False}]
+
+ # Has an image but no bdms
+ self.compute_api._populate_instance_for_bdm(self.context,
+ instance,
+ instance_type,
+ image, [])
+ bdms = db.block_device_mapping_get_all_by_instance(
+ self.context, instance['uuid'])
+ self.assertEqual(len(bdms), 1)
+ self.assertEqual(bdms[0]['image_id'], FAKE_IMAGE_REF)
+ for bdm in bdms:
+ db.block_device_mapping_destroy(self.context, bdm['id'])
+
+ # Has an image and is volume backed - legacy style
+ self.compute_api._populate_instance_for_bdm(self.context,
+ instance,
+ instance_type,
+ image, fake_bdms)
+ bdms = db.block_device_mapping_get_all_by_instance(
+ self.context, instance['uuid'])
+ self.assertEqual(len(bdms), 1)
+ self.assertEqual(bdms[0]['snapshot_id'],
+ '33333333-aaaa-bbbb-cccc-333333333333')
+ for bdm in bdms:
+ db.block_device_mapping_destroy(self.context, bdm['id'])
+
+ # Is volume backed and has no image
+ instance['image_ref'] = ''
+ self.compute_api._populate_instance_for_bdm(self.context,
+ instance,
+ instance_type,
+ image, fake_bdms)
+ bdms = db.block_device_mapping_get_all_by_instance(
+ self.context, instance['uuid'])
+ self.assertEqual(len(bdms), 1)
+ self.assertEqual(bdms[0]['snapshot_id'],
+ '33333333-aaaa-bbbb-cccc-333333333333')
+ for bdm in bdms:
+ db.block_device_mapping_destroy(self.context, bdm['id'])
+
def test_volume_size(self):
ephemeral_size = 2
swap_size = 3