def get_bdm_image_metadata(context, image_api, volume_api, block_device_mapping, legacy_bdm=True): """Attempt to retrive image metadata from a given block_device_mapping. If we are booting from a volume, we need to get the volume details from Cinder and make sure we pass the metadata back accordingly. :param context: request context :param image_api: Image API :param volume_api: Volume API :param block_device_mapping: :param legacy_bdm: """ if not block_device_mapping: return {} for bdm in block_device_mapping: if (legacy_bdm and get_device_letter(bdm.get('device_name', '')) != 'a'): continue elif not legacy_bdm and bdm.get('boot_index') != 0: continue volume_id = bdm.get('volume_id') snapshot_id = bdm.get('snapshot_id') if snapshot_id: # NOTE(alaski): A volume snapshot inherits metadata from the # originating volume, but the API does not expose metadata # on the snapshot itself. So we query the volume for it below. snapshot = volume_api.get_snapshot(context, snapshot_id) volume_id = snapshot['volume_id'] if bdm.get('image_id'): try: image_id = bdm['image_id'] image_meta = image_api.get(context, image_id) return image_meta except Exception: raise exception.InvalidBDMImage(id=image_id) elif volume_id: try: volume = volume_api.get(context, volume_id) except exception.CinderConnectionFailed: raise except Exception: raise exception.InvalidBDMVolume(id=volume_id) if not volume.get('bootable', True): raise exception.InvalidBDMVolumeNotBootable(id=volume_id) return get_image_metadata_from_volume(volume) return {}
def root_metadata(self, context, image_api, volume_api): root_bdm = self.root_bdm() if not root_bdm: return {} if root_bdm.is_volume: try: volume = volume_api.get(context, root_bdm.volume_id) return volume.get('volume_image_metadata', {}) except Exception: raise exception.InvalidBDMVolume(id=root_bdm.id) elif root_bdm.is_image: try: image_meta = image_api.show(context, root_bdm.image_id) return image_meta.get('properties', {}) except Exception: raise exception.InvalidBDMImage(id=root_bdm.id) else: return {}