Skip to content

Commit 7e229ba

Browse files
committed
Extract compute API _create_image to compute.utils
This refactors the _create_image and related _initialize_instance_snapshot_metadata methods to nova.compute.utils and makes them public utilities so that code outside the API can re-use it. Change-Id: I08630bbbd1df9b758ff5088f9b48183a503ecc09
1 parent d883a1b commit 7e229ba

File tree

4 files changed

+72
-69
lines changed

4 files changed

+72
-69
lines changed

nova/compute/api.py

Lines changed: 9 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,9 +2902,9 @@ def backup(self, context, instance, name, backup_type, rotation,
29022902
raise exception.InvalidRequest(
29032903
_('Backup is not supported for volume-backed instances.'))
29042904
else:
2905-
image_meta = self._create_image(context, instance,
2906-
name, 'backup',
2907-
extra_properties=props_copy)
2905+
image_meta = compute_utils.create_image(
2906+
context, instance, name, 'backup', self.image_api,
2907+
extra_properties=props_copy)
29082908

29092909
# NOTE(comstud): Any changes to this method should also be made
29102910
# to the backup_instance() method in nova/cells/messaging.py
@@ -2935,9 +2935,9 @@ def snapshot(self, context, instance, name, extra_properties=None):
29352935
when creating the image.
29362936
:returns: A dict containing image metadata
29372937
"""
2938-
image_meta = self._create_image(context, instance, name,
2939-
'snapshot',
2940-
extra_properties=extra_properties)
2938+
image_meta = compute_utils.create_image(
2939+
context, instance, name, 'snapshot', self.image_api,
2940+
extra_properties=extra_properties)
29412941

29422942
# NOTE(comstud): Any changes to this method should also be made
29432943
# to the snapshot_instance() method in nova/cells/messaging.py
@@ -2981,62 +2981,6 @@ def snapshot(self, context, instance, name, extra_properties=None):
29812981

29822982
return image_meta
29832983

2984-
def _create_image(self, context, instance, name, image_type,
2985-
extra_properties=None):
2986-
"""Create new image entry in the image service. This new image
2987-
will be reserved for the compute manager to upload a snapshot
2988-
or backup.
2989-
2990-
:param context: security context
2991-
:param instance: nova.objects.instance.Instance object
2992-
:param name: string for name of the snapshot
2993-
:param image_type: snapshot | backup
2994-
:param extra_properties: dict of extra image properties to include
2995-
2996-
"""
2997-
properties = {
2998-
'instance_uuid': instance.uuid,
2999-
'user_id': str(context.user_id),
3000-
'image_type': image_type,
3001-
}
3002-
properties.update(extra_properties or {})
3003-
3004-
image_meta = self._initialize_instance_snapshot_metadata(
3005-
instance, name, properties)
3006-
# if we're making a snapshot, omit the disk and container formats,
3007-
# since the image may have been converted to another format, and the
3008-
# original values won't be accurate. The driver will populate these
3009-
# with the correct values later, on image upload.
3010-
if image_type == 'snapshot':
3011-
image_meta.pop('disk_format', None)
3012-
image_meta.pop('container_format', None)
3013-
return self.image_api.create(context, image_meta)
3014-
3015-
def _initialize_instance_snapshot_metadata(self, instance, name,
3016-
extra_properties=None):
3017-
"""Initialize new metadata for a snapshot of the given instance.
3018-
3019-
:param instance: nova.objects.instance.Instance object
3020-
:param name: string for name of the snapshot
3021-
:param extra_properties: dict of extra metadata properties to include
3022-
3023-
:returns: the new instance snapshot metadata
3024-
"""
3025-
image_meta = utils.get_image_from_system_metadata(
3026-
instance.system_metadata)
3027-
image_meta.update({'name': name,
3028-
'is_public': False})
3029-
3030-
# Delete properties that are non-inheritable
3031-
properties = image_meta['properties']
3032-
for key in CONF.non_inheritable_image_properties:
3033-
properties.pop(key, None)
3034-
3035-
# The properties in extra_properties have precedence
3036-
properties.update(extra_properties or {})
3037-
3038-
return image_meta
3039-
30402984
# NOTE(melwitt): We don't check instance lock for snapshot because lock is
30412985
# intended to prevent accidental change/delete of instances
30422986
@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED,
@@ -3051,7 +2995,7 @@ def snapshot_volume_backed(self, context, instance, name,
30512995
30522996
:returns: the new image metadata
30532997
"""
3054-
image_meta = self._initialize_instance_snapshot_metadata(
2998+
image_meta = compute_utils.initialize_instance_snapshot_metadata(
30552999
instance, name, extra_properties)
30563000
# the new image is simply a bucket of properties (particularly the
30573001
# block device mapping, kernel and ramdisk IDs) with no image data,
@@ -3654,8 +3598,8 @@ def shelve(self, context, instance, clean_shutdown=True):
36543598

36553599
if not compute_utils.is_volume_backed_instance(context, instance):
36563600
name = '%s-shelved' % instance.display_name
3657-
image_meta = self._create_image(context, instance, name,
3658-
'snapshot')
3601+
image_meta = compute_utils.create_image(
3602+
context, instance, name, 'snapshot', self.image_api)
36593603
image_id = image_meta['id']
36603604
self.compute_rpcapi.shelve_instance(context, instance=instance,
36613605
image_id=image_id, clean_shutdown=clean_shutdown)

nova/compute/utils.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,65 @@ def remove_shelved_keys_from_system_metadata(instance):
11421142
del (instance.system_metadata[key])
11431143

11441144

1145+
def create_image(context, instance, name, image_type, image_api,
1146+
extra_properties=None):
1147+
"""Create new image entry in the image service. This new image
1148+
will be reserved for the compute manager to upload a snapshot
1149+
or backup.
1150+
1151+
:param context: security context
1152+
:param instance: nova.objects.instance.Instance object
1153+
:param name: string for name of the snapshot
1154+
:param image_type: snapshot | backup
1155+
:param image_api: instance of nova.image.API
1156+
:param extra_properties: dict of extra image properties to include
1157+
1158+
"""
1159+
properties = {
1160+
'instance_uuid': instance.uuid,
1161+
'user_id': str(context.user_id),
1162+
'image_type': image_type,
1163+
}
1164+
properties.update(extra_properties or {})
1165+
1166+
image_meta = initialize_instance_snapshot_metadata(
1167+
instance, name, properties)
1168+
# if we're making a snapshot, omit the disk and container formats,
1169+
# since the image may have been converted to another format, and the
1170+
# original values won't be accurate. The driver will populate these
1171+
# with the correct values later, on image upload.
1172+
if image_type == 'snapshot':
1173+
image_meta.pop('disk_format', None)
1174+
image_meta.pop('container_format', None)
1175+
return image_api.create(context, image_meta)
1176+
1177+
1178+
def initialize_instance_snapshot_metadata(instance, name,
1179+
extra_properties=None):
1180+
"""Initialize new metadata for a snapshot of the given instance.
1181+
1182+
:param instance: nova.objects.instance.Instance object
1183+
:param name: string for name of the snapshot
1184+
:param extra_properties: dict of extra metadata properties to include
1185+
1186+
:returns: the new instance snapshot metadata
1187+
"""
1188+
image_meta = utils.get_image_from_system_metadata(
1189+
instance.system_metadata)
1190+
image_meta.update({'name': name,
1191+
'is_public': False})
1192+
1193+
# Delete properties that are non-inheritable
1194+
properties = image_meta['properties']
1195+
for key in CONF.non_inheritable_image_properties:
1196+
properties.pop(key, None)
1197+
1198+
# The properties in extra_properties have precedence
1199+
properties.update(extra_properties or {})
1200+
1201+
return image_meta
1202+
1203+
11451204
def may_have_ports_or_volumes(instance):
11461205
"""Checks to see if an instance may have ports or volumes based on vm_state
11471206

nova/tests/unit/compute/test_compute_api.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,7 +2997,7 @@ def test_snapshot_invalid_state(self):
29972997
self.context, instance, 'fake-name')
29982998

29992999
@mock.patch.object(objects.Instance, 'save')
3000-
@mock.patch.object(compute_api.API, '_create_image')
3000+
@mock.patch.object(compute_utils, 'create_image')
30013001
@mock.patch.object(compute_rpcapi.ComputeAPI,
30023002
'snapshot_instance')
30033003
def test_vm_deleting_while_creating_snapshot(self,
@@ -3017,7 +3017,7 @@ def test_vm_deleting_while_creating_snapshot(self,
30173017
'fake-image-id')
30183018

30193019
@mock.patch.object(objects.Instance, 'save')
3020-
@mock.patch.object(compute_api.API, '_create_image')
3020+
@mock.patch.object(compute_utils, 'create_image')
30213021
@mock.patch.object(compute_rpcapi.ComputeAPI,
30223022
'snapshot_instance')
30233023
def test_vm_deleted_while_creating_snapshot(self,
@@ -3037,7 +3037,7 @@ def test_vm_deleted_while_creating_snapshot(self,
30373037
'fake-image-id')
30383038

30393039
@mock.patch.object(objects.Instance, 'save')
3040-
@mock.patch.object(compute_api.API, '_create_image')
3040+
@mock.patch.object(compute_utils, 'create_image')
30413041
@mock.patch.object(compute_rpcapi.ComputeAPI,
30423042
'snapshot_instance')
30433043
def test_vm_deleted_while_snapshot_and_snapshot_delete_failed(self,

nova/tests/unit/compute/test_shelve.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ def _test_shelve(self, vm_state=vm_states.ACTIVE, boot_from_volume=False,
696696
with test.nested(
697697
mock.patch.object(compute_utils, 'is_volume_backed_instance',
698698
return_value=boot_from_volume),
699-
mock.patch.object(self.compute_api, '_create_image',
699+
mock.patch.object(compute_utils, 'create_image',
700700
return_value=dict(id='fake-image-id')),
701701
mock.patch.object(instance, 'save'),
702702
mock.patch.object(self.compute_api, '_record_action_start'),

0 commit comments

Comments
 (0)