def test_get_os_image(self, db_api, glance): glance = glance.return_value fake_context = base.create_context() os_image = fakes.OSImage(fakes.OS_IMAGE_1) glance.images.get.return_value = os_image # check normal flow db_api.get_items_ids.return_value = [ (fakes.ID_EC2_IMAGE_1, fakes.ID_OS_IMAGE_1)] self.assertEqual( os_image, ec2utils.get_os_image(fake_context, fakes.ID_EC2_IMAGE_1)) db_api.get_items_ids.assert_called_with( mock.ANY, 'ami', item_ids=(fakes.ID_EC2_IMAGE_1,), item_os_ids=None) glance.images.get.assert_called_with(fakes.ID_OS_IMAGE_1) # check case of absence of an image in OS glance.images.get.side_effect = glance_exception.HTTPNotFound() self.assertRaises( exception.InvalidAMIIDNotFound, ec2utils.get_os_image, fake_context, fakes.ID_EC2_IMAGE_1) # check case of an unknown image id db_api.get_items_ids.return_value = [] self.assertRaises( exception.InvalidAMIIDNotFound, ec2utils.get_os_image, fake_context, fakes.random_ec2_id('ami')) # check case of creating image db_api.get_items_ids.return_value = [(fakes.ID_EC2_IMAGE_1, None)] self.assertIsNone(ec2utils.get_os_image(fake_context, fakes.ID_EC2_IMAGE_1))
def test_get_os_image(self, db_api, glance): glance = glance.return_value fake_context = base.create_context() os_image = fakes.OSImage(fakes.OS_IMAGE_1) glance.images.get.return_value = os_image # check normal flow db_api.get_items_ids.return_value = [(fakes.ID_EC2_IMAGE_1, fakes.ID_OS_IMAGE_1)] self.assertEqual( os_image, ec2utils.get_os_image(fake_context, fakes.ID_EC2_IMAGE_1)) db_api.get_items_ids.assert_called_with( mock.ANY, 'ami', item_ids=(fakes.ID_EC2_IMAGE_1, ), item_os_ids=None) glance.images.get.assert_called_with(fakes.ID_OS_IMAGE_1) # check case of absence of an image in OS glance.images.get.side_effect = glance_exception.HTTPNotFound() self.assertRaises(exception.InvalidAMIIDNotFound, ec2utils.get_os_image, fake_context, fakes.ID_EC2_IMAGE_1) # check case of an unknown image id db_api.get_items_ids.return_value = [] self.assertRaises(exception.InvalidAMIIDNotFound, ec2utils.get_os_image, fake_context, fakes.random_ec2_id('ami')) # check case of creating image db_api.get_items_ids.return_value = [(fakes.ID_EC2_IMAGE_1, None)] self.assertIsNone( ec2utils.get_os_image(fake_context, fakes.ID_EC2_IMAGE_1))
def describe_image_attribute(context, image_id, attribute): def _block_device_mapping_attribute(os_image, image, result): properties = ec2utils.deserialize_os_image_properties(os_image) mappings = _format_mappings(context, properties) if mappings: result['blockDeviceMapping'] = mappings def _description_attribute(os_image, image, result): result['description'] = {'value': image.get('description')} def _launch_permission_attribute(os_image, image, result): result['launchPermission'] = [] if os_image.is_public: result['launchPermission'].append({'group': 'all'}) def _kernel_attribute(os_image, image, result): kernel_id = os_image.properties.get('kernel_id') if kernel_id: result['kernel'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'aki', kernel_id) } def _ramdisk_attribute(os_image, image, result): ramdisk_id = os_image.properties.get('ramdisk_id') if ramdisk_id: result['ramdisk'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'ari', ramdisk_id) } # NOTE(ft): Openstack extension, AWS-incompability def _root_device_name_attribute(os_image, image, result): properties = ec2utils.deserialize_os_image_properties(os_image) result['rootDeviceName'] = ( ec2utils.block_device_properties_root_device_name(properties)) supported_attributes = { 'blockDeviceMapping': _block_device_mapping_attribute, 'description': _description_attribute, 'launchPermission': _launch_permission_attribute, 'kernel': _kernel_attribute, 'ramdisk': _ramdisk_attribute, # NOTE(ft): Openstack extension, AWS-incompability 'rootDeviceName': _root_device_name_attribute, } fn = supported_attributes.get(attribute) if fn is None: raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) if not os_image: # TODO(ft): figure out corresponding AWS error raise exception.IncorrectState( reason='Image is still being created or failed') _check_owner(context, os_image) image = ec2utils.get_db_item(context, image_id) result = {'imageId': image_id} fn(os_image, image, result) return result
def reset_image_attribute(context, image_id, attribute): if attribute != 'launchPermission': raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) _check_owner(context, os_image) glance = clients.glance(context) glance.images.update(os_image.id, visibility='private') return True
def reset_image_attribute(context, image_id, attribute): if attribute != 'launchPermission': raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) _check_owner(context, os_image) os_image.update(is_public=False) return True
def set_dependent_image_id(image_key): try: image_key_path = ('machine_configuration/%(image_key)s' % {'image_key': image_key}) image_id = manifest.find(image_key_path).text except Exception: return if image_id == 'true': return True os_image = ec2utils.get_os_image(context, image_id) properties[image_key] = os_image.id
def deregister_image(context, image_id): os_image = ec2utils.get_os_image(context, image_id) _check_owner(context, os_image) glance = clients.glance(context) try: glance.images.delete(os_image.id) except glance_exception.HTTPNotFound: pass db_api.delete_item(context, image_id) return True
def describe_image_attribute(context, image_id, attribute): def _block_device_mapping_attribute(os_image, image, result): _cloud_format_mappings(context, os_image.properties, result) def _description_attribute(os_image, image, result): result['description'] = {'value': image.get('description')} def _launch_permission_attribute(os_image, image, result): result['launchPermission'] = [] if os_image.is_public: result['launchPermission'].append({'group': 'all'}) def _kernel_attribute(os_image, image, result): kernel_id = os_image.properties.get('kernel_id') if kernel_id: result['kernel'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'jki', kernel_id) } def _ramdisk_attribute(os_image, image, result): ramdisk_id = os_image.properties.get('ramdisk_id') if ramdisk_id: result['ramdisk'] = { 'value': ec2utils.os_id_to_ec2_id(context, 'jri', ramdisk_id) } # NOTE(ft): Openstack extension, AWS-incompability def _root_device_name_attribute(os_image, image, result): result['rootDeviceName'] = (_block_device_properties_root_device_name( os_image.properties)) supported_attributes = { 'blockDeviceMapping': _block_device_mapping_attribute, 'description': _description_attribute, 'launchPermission': _launch_permission_attribute, 'kernel': _kernel_attribute, 'ramdisk': _ramdisk_attribute, # NOTE(ft): Openstack extension, AWS-incompability 'rootDeviceName': _root_device_name_attribute, } fn = supported_attributes.get(attribute) if fn is None: raise exception.InvalidRequest() os_image = ec2utils.get_os_image(context, image_id) _check_owner(context, os_image) _prepare_mappings(os_image) image = ec2utils.get_db_item(context, image_id) result = {'imageId': image_id} fn(os_image, image, result) return result
def test_get_os_image(self, db_api, glance): glance = glance.return_value fake_context = mock.Mock(service_catalog=[{'type': 'fake'}]) os_image = fakes.OSImage(fakes.OS_IMAGE_1) glance.images.get.return_value = os_image # NOTE(ft): check normal flow for an user owned image db_api.get_public_items.return_value = [] db_api.get_item_by_id.return_value = fakes.DB_IMAGE_1 self.assertEqual( os_image, ec2utils.get_os_image(fake_context, fakes.ID_EC2_IMAGE_1)) db_api.get_item_by_id.assert_called_with( mock.ANY, fakes.ID_EC2_IMAGE_1) glance.images.get.assert_called_with(fakes.ID_OS_IMAGE_1) # NOTE(ft): check normal flow for a public image db_api.get_public_items.return_value = [fakes.DB_IMAGE_1] db_api.get_item_by_id.return_value = None self.assertEqual( os_image, ec2utils.get_os_image(fake_context, fakes.ID_EC2_IMAGE_1)) db_api.get_public_items.assert_called_with( mock.ANY, 'ami', (fakes.ID_EC2_IMAGE_1,)) glance.images.get.assert_called_with(fakes.ID_OS_IMAGE_1) # NOTE(ft): check case of absence of an image in OS glance.images.get.side_effect = glance_exception.HTTPNotFound() self.assertRaises( exception.InvalidAMIIDNotFound, ec2utils.get_os_image, fake_context, fakes.ID_EC2_IMAGE_1) # NOTE(ft): check case of an unknown image id db_api.get_public_items.return_value = [] db_api.get_item_by_id.return_value = None self.assertRaises( exception.InvalidAMIIDNotFound, ec2utils.get_os_image, fake_context, fakes.random_ec2_id('ami'))
def deregister_image(context, image_id): os_image = ec2utils.get_os_image(context, image_id) if not os_image: image = db_api.get_item_by_id(context, image_id) if image.get('state') != 'failed': # TODO(ft): figure out corresponding AWS error raise exception.IncorrectState( reason='Image is still being created') else: _check_owner(context, os_image) glance = clients.glance(context) try: glance.images.delete(os_image.id) except glance_exception.HTTPNotFound: pass db_api.delete_item(context, image_id) return True
def modify_image_attribute(context, image_id, attribute=None, user_group=None, operation_type=None, description=None, launch_permission=None, product_code=None, user_id=None, value=None): os_image = ec2utils.get_os_image(context, image_id) if not os_image: # TODO(ft): figure out corresponding AWS error raise exception.IncorrectState( reason='Image is still being created or failed') attributes = set() # NOTE(andrey-mp): launchPermission structure is converted here # to plain parameters: attribute, user_group, operation_type, user_id if launch_permission is not None: attributes.add('launchPermission') user_group = list() user_id = list() if len(launch_permission) == 0: msg = _('No operation specified for launchPermission attribute.') raise exception.InvalidParameterCombination(msg) if len(launch_permission) > 1: msg = _('Only one operation can be specified.') raise exception.InvalidParameterCombination(msg) operation_type, permissions = launch_permission.popitem() for index_key in permissions: permission = permissions[index_key] if 'group' in permission: user_group.append(permission['group']) if 'user_id' in permission: user_id.append(permission['user_id']) if attribute == 'launchPermission': attributes.add('launchPermission') if description is not None: attributes.add('description') value = description if attribute == 'description': attributes.add('description') # check attributes if len(attributes) == 0: if product_code is not None: attribute = 'productCodes' if attribute in [ 'kernel', 'ramdisk', 'productCodes', 'blockDeviceMapping' ]: raise exception.InvalidParameter( _('Parameter %s is invalid. ' 'The attribute is not supported.') % attribute) raise exception.InvalidParameterCombination('No attributes specified.') if len(attributes) > 1: raise exception.InvalidParameterCombination( _('Fields for multiple attribute types specified: %s') % str(attributes)) if 'launchPermission' in attributes: if not user_group: msg = _('No operation specified for launchPermission attribute.') raise exception.InvalidParameterCombination(msg) if len(user_group) != 1 and user_group[0] != 'all': msg = _('only group "all" is supported') raise exception.InvalidParameterValue(parameter='UserGroup', value=user_group, reason=msg) if operation_type not in ['add', 'remove']: msg = _('operation_type must be add or remove') raise exception.InvalidParameterValue(parameter='OperationType', value='operation_type', reason=msg) _check_owner(context, os_image) os_image.update(is_public=(operation_type == 'add')) return True if 'description' in attributes: if not value: raise exception.MissingParameter( 'The request must contain the parameter description') _check_owner(context, os_image) image = ec2utils.get_db_item(context, image_id) image['description'] = value db_api.update_item(context, image) return True
def register_image(context, name=None, image_location=None, description=None, architecture=None, root_device_name=None, block_device_mapping=None, virtualization_type=None, kernel_id=None, ramdisk_id=None, sriov_net_support=None): if not image_location and not root_device_name: # NOTE(ft): for backward compatibility with a hypothetical code # which uses name as image_location image_location = name if not image_location and not root_device_name: msg = _("Either imageLocation or rootDeviceName must be set.") raise exception.InvalidParameterCombination(msg) if not image_location and not name: msg = _('The request must contain the parameter name') raise exception.MissingParameter(msg) # TODO(ft): check parameters properties = {} metadata = {'properties': properties} if name: # TODO(ft): check the name is unique (at least for EBS image case) metadata['name'] = name if image_location: properties['image_location'] = image_location if 'name' not in metadata: # NOTE(ft): it's needed for backward compatibility metadata['name'] = image_location if root_device_name: properties['root_device_name'] = root_device_name cinder = clients.cinder(context) if block_device_mapping: mappings = instance_api._parse_block_device_mapping( context, block_device_mapping) # TODO(ft): merge with image manifets's virtual device mappings short_root_device_name = ( ec2utils.block_device_strip_dev(root_device_name)) for bdm in mappings: instance_api._populate_parsed_bdm_parameter( bdm, short_root_device_name) if 'volume_size' in bdm: continue try: if bdm['source_type'] == 'snapshot': snapshot = cinder.volume_snapshots.get(bdm['snapshot_id']) bdm['volume_size'] = snapshot.size elif bdm['source_type'] == 'volume': volume = cinder.volumes.get(bdm['volume_id']) bdm['volume_size'] = volume.size except cinder_exception.NotFound: pass properties['bdm_v2'] = True properties['block_device_mapping'] = json.dumps(mappings) if architecture is not None: properties['architecture'] = architecture if kernel_id: properties['kernel_id'] = ec2utils.get_os_image(context, kernel_id).id if ramdisk_id: properties['ramdisk_id'] = ec2utils.get_os_image(context, ramdisk_id).id with common.OnCrashCleaner() as cleaner: if 'image_location' in properties: os_image = _s3_create(context, metadata) else: metadata.update({'size': 0, 'is_public': False}) # TODO(ft): set default values of image properties glance = clients.glance(context) os_image = glance.images.create(**metadata) cleaner.addCleanup(os_image.delete) kind = _get_os_image_kind(os_image) image = db_api.add_item(context, kind, { 'os_id': os_image.id, 'is_public': False, 'description': description }) return {'imageId': image['id']}
def register_image(context, name=None, image_location=None, description=None, architecture=None, root_device_name=None, block_device_mapping=None, virtualization_type=None, kernel_id=None, ramdisk_id=None, sriov_net_support=None): # Setup default flags is_s3_import = False is_url_import = False # Process the input arguments if not image_location and not root_device_name: # NOTE(ft): for backward compatibility with a hypothetical code # which uses name as image_location image_location = name if not image_location and not root_device_name: msg = _("Either imageLocation or rootDeviceName must be set.") raise exception.InvalidParameterCombination(msg) if not image_location and not name: msg = _('The request must contain the parameter name') raise exception.MissingParameter(msg) # TODO(ft): check parameters metadata = {} if name: # TODO(ft): check the name is unique (at least for EBS image case) metadata['name'] = name if image_location: # Resolve the import type metadata['image_location'] = image_location parsed_url = six.moves.urllib.parse.urlparse(image_location) is_s3_import = (parsed_url.scheme == '') or (parsed_url.scheme == 's3') is_url_import = not is_s3_import # Check if the name is in the metadata if 'name' not in metadata: # NOTE(ft): it's needed for backward compatibility metadata['name'] = image_location if root_device_name: metadata['root_device_name'] = root_device_name cinder = clients.cinder(context) if block_device_mapping: mappings = instance_api._parse_block_device_mapping( context, block_device_mapping) # TODO(ft): merge with image manifets's virtual device mappings short_root_device_name = ( ec2utils.block_device_strip_dev(root_device_name)) for bdm in mappings: instance_api._populate_parsed_bdm_parameter( bdm, short_root_device_name) if 'volume_size' in bdm: continue try: if bdm['source_type'] == 'snapshot': snapshot = cinder.volume_snapshots.get(bdm['snapshot_id']) bdm['volume_size'] = snapshot.size elif bdm['source_type'] == 'volume': volume = cinder.volumes.get(bdm['volume_id']) bdm['volume_size'] = volume.size except cinder_exception.NotFound: pass metadata['bdm_v2'] = 'True' metadata['block_device_mapping'] = json.dumps(mappings) if architecture is not None: metadata['architecture'] = architecture if kernel_id: metadata['kernel_id'] = ec2utils.get_os_image(context, kernel_id).id if ramdisk_id: metadata['ramdisk_id'] = ec2utils.get_os_image(context, ramdisk_id).id # Begin the import/registration process with common.OnCrashCleaner() as cleaner: # Setup the glance client glance = clients.glance(context) # Check if this is an S3 import if is_s3_import: os_image = _s3_create(context, metadata) # Condition for all non-S3 imports else: # Create the image in glance metadata.update({ 'visibility': 'private', 'container_format': 'bare', 'disk_format': 'raw' }) os_image = glance.images.create(**metadata) # Kick-off the URL image import if from URL if is_url_import: glance.images.image_import(os_image.id, method='web-download', uri=metadata['image_location']) # Otherwise, use the default method else: glance.images.upload(os_image.id, '', image_size=0) # Add cleanups and complete the registration process cleaner.addCleanup(glance.images.delete, os_image.id) kind = _get_os_image_kind(os_image) image = db_api.add_item(context, kind, { 'os_id': os_image.id, 'is_public': False, 'description': description }) # Return the image ID for the registration process return {'imageId': image['id']}
def modify_image_attribute(context, image_id, attribute=None, user_group=None, operation_type=None, description=None, launch_permission=None, product_code=None, user_id=None, value=None): os_image = ec2utils.get_os_image(context, image_id) if not os_image: # TODO(ft): figure out corresponding AWS error raise exception.IncorrectState( reason='Image is still being created or failed') attributes = set() # NOTE(andrey-mp): launchPermission structure is converted here # to plain parameters: attribute, user_group, operation_type, user_id if launch_permission is not None: attributes.add('launchPermission') user_group = list() user_id = list() if len(launch_permission) == 0: msg = _('No operation specified for launchPermission attribute.') raise exception.InvalidParameterCombination(msg) if len(launch_permission) > 1: msg = _('Only one operation can be specified.') raise exception.InvalidParameterCombination(msg) operation_type, permissions = launch_permission.popitem() for index_key in permissions: permission = permissions[index_key] if 'group' in permission: user_group.append(permission['group']) if 'user_id' in permission: user_id.append(permission['user_id']) if attribute == 'launchPermission': attributes.add('launchPermission') if description is not None: attributes.add('description') value = description if attribute == 'description': attributes.add('description') # check attributes if len(attributes) == 0: if product_code is not None: attribute = 'productCodes' if attribute in ['kernel', 'ramdisk', 'productCodes', 'blockDeviceMapping']: raise exception.InvalidParameter( _('Parameter %s is invalid. ' 'The attribute is not supported.') % attribute) raise exception.InvalidParameterCombination('No attributes specified.') if len(attributes) > 1: raise exception.InvalidParameterCombination( _('Fields for multiple attribute types specified: %s') % str(attributes)) if 'launchPermission' in attributes: if not user_group: msg = _('No operation specified for launchPermission attribute.') raise exception.InvalidParameterCombination(msg) if len(user_group) != 1 and user_group[0] != 'all': msg = _('only group "all" is supported') raise exception.InvalidParameterValue(parameter='UserGroup', value=user_group, reason=msg) if operation_type not in ['add', 'remove']: msg = _('operation_type must be add or remove') raise exception.InvalidParameterValue(parameter='OperationType', value='operation_type', reason=msg) _check_owner(context, os_image) os_image.update(is_public=(operation_type == 'add')) return True if 'description' in attributes: if not value: raise exception.MissingParameter( 'The request must contain the parameter description') _check_owner(context, os_image) image = ec2utils.get_db_item(context, image_id) image['description'] = value db_api.update_item(context, image) return True
def register_image(context, name=None, image_location=None, description=None, architecture=None, root_device_name=None, block_device_mapping=None, virtualization_type=None, kernel_id=None, ramdisk_id=None, sriov_net_support=None): # Setup default flags is_s3_import = False is_url_import = False # Process the input arguments if not image_location and not root_device_name: # NOTE(ft): for backward compatibility with a hypothetical code # which uses name as image_location image_location = name if not image_location and not root_device_name: msg = _("Either imageLocation or rootDeviceName must be set.") raise exception.InvalidParameterCombination(msg) if not image_location and not name: msg = _('The request must contain the parameter name') raise exception.MissingParameter(msg) # TODO(ft): check parameters metadata = {} if name: # TODO(ft): check the name is unique (at least for EBS image case) metadata['name'] = name if image_location: # Resolve the import type metadata['image_location'] = image_location parsed_url = six.moves.urllib.parse.urlparse(image_location) is_s3_import = (parsed_url.scheme == '') or (parsed_url.scheme == 's3') is_url_import = not is_s3_import # Check if the name is in the metadata if 'name' not in metadata: # NOTE(ft): it's needed for backward compatibility metadata['name'] = image_location if root_device_name: metadata['root_device_name'] = root_device_name cinder = clients.cinder(context) if block_device_mapping: mappings = instance_api._parse_block_device_mapping( context, block_device_mapping) # TODO(ft): merge with image manifets's virtual device mappings short_root_device_name = ( ec2utils.block_device_strip_dev(root_device_name)) for bdm in mappings: instance_api._populate_parsed_bdm_parameter( bdm, short_root_device_name) if 'volume_size' in bdm: continue try: if bdm['source_type'] == 'snapshot': snapshot = cinder.volume_snapshots.get(bdm['snapshot_id']) bdm['volume_size'] = snapshot.size elif bdm['source_type'] == 'volume': volume = cinder.volumes.get(bdm['volume_id']) bdm['volume_size'] = volume.size except cinder_exception.NotFound: pass metadata['bdm_v2'] = 'True' metadata['block_device_mapping'] = json.dumps(mappings) if architecture is not None: metadata['architecture'] = architecture if kernel_id: metadata['kernel_id'] = ec2utils.get_os_image(context, kernel_id).id if ramdisk_id: metadata['ramdisk_id'] = ec2utils.get_os_image(context, ramdisk_id).id # Begin the import/registration process with common.OnCrashCleaner() as cleaner: # Setup the glance client glance = clients.glance(context) # Check if this is an S3 import if is_s3_import: os_image = _s3_create(context, metadata) # Condition for all non-S3 imports else: # Create the image in glance metadata.update({'visibility': 'private', 'container_format': 'bare', 'disk_format': 'raw'}) os_image = glance.images.create(**metadata) # Kick-off the URL image import if from URL if is_url_import: glance.images.image_import(os_image.id, method='web-download', uri=metadata['image_location']) # Otherwise, use the default method else: glance.images.upload(os_image.id, '', image_size=0) # Add cleanups and complete the registration process cleaner.addCleanup(glance.images.delete, os_image.id) kind = _get_os_image_kind(os_image) image = db_api.add_item(context, kind, {'os_id': os_image.id, 'is_public': False, 'description': description}) # Return the image ID for the registration process return {'imageId': image['id']}
def register_image(context, name=None, image_location=None, description=None, architecture=None, root_device_name=None, block_device_mapping=None, virtualization_type=None, kernel_id=None, ramdisk_id=None, sriov_net_support=None): if not image_location and not root_device_name: # NOTE(ft): for backward compatibility with a hypothetical code # which uses name as image_location image_location = name if not image_location and not root_device_name: msg = _("Either imageLocation or rootDeviceName must be set.") raise exception.InvalidParameterCombination(msg) if not image_location and not name: msg = _('The request must contain the parameter name') raise exception.MissingParameter(msg) # TODO(ft): check parameters properties = {} metadata = {'properties': properties} if name: # TODO(ft): check the name is unique (at least for EBS image case) metadata['name'] = name if image_location: properties['image_location'] = image_location if 'name' not in metadata: # NOTE(ft): it's needed for backward compatibility metadata['name'] = image_location if root_device_name: properties['root_device_name'] = root_device_name cinder = clients.cinder(context) if block_device_mapping: mappings = instance_api._parse_block_device_mapping( context, block_device_mapping) # TODO(ft): merge with image manifets's virtual device mappings short_root_device_name = ( ec2utils.block_device_strip_dev(root_device_name)) for bdm in mappings: instance_api._populate_parsed_bdm_parameter( bdm, short_root_device_name) if 'volume_size' in bdm: continue try: if bdm['source_type'] == 'snapshot': snapshot = cinder.volume_snapshots.get(bdm['snapshot_id']) bdm['volume_size'] = snapshot.size elif bdm['source_type'] == 'volume': volume = cinder.volumes.get(bdm['volume_id']) bdm['volume_size'] = volume.size except cinder_exception.NotFound: pass properties['bdm_v2'] = True properties['block_device_mapping'] = json.dumps(mappings) if architecture is not None: properties['architecture'] = architecture if kernel_id: properties['kernel_id'] = ec2utils.get_os_image(context, kernel_id).id if ramdisk_id: properties['ramdisk_id'] = ec2utils.get_os_image(context, ramdisk_id).id with common.OnCrashCleaner() as cleaner: if 'image_location' in properties: os_image = _s3_create(context, metadata) else: metadata.update({'size': 0, 'is_public': False}) # TODO(ft): set default values of image properties glance = clients.glance(context) os_image = glance.images.create(**metadata) cleaner.addCleanup(os_image.delete) kind = _get_os_image_kind(os_image) image = db_api.add_item(context, kind, {'os_id': os_image.id, 'is_public': False, 'description': description}) return {'imageId': image['id']}