def image_to_raw(image_href, path, path_tmp): with fileutils.remove_path_on_error(path_tmp): data = qemu_img_info(path_tmp) fmt = data.file_format if fmt is None: raise exception.ImageUnacceptable( reason=_("'qemu-img info' parsing failed."), image_id=image_href) backing_file = data.backing_file if backing_file is not None: raise exception.ImageUnacceptable(image_id=image_href, reason=_("fmt=%(fmt)s backed by: %(backing_file)s") % {'fmt': fmt, 'backing_file': backing_file}) if fmt != "raw": staged = "%s.converted" % path LOG.debug("%(image)s was %(format)s, converting to raw" % {'image': image_href, 'format': fmt}) with fileutils.remove_path_on_error(staged): convert_image(path_tmp, staged, 'raw') os.unlink(path_tmp) data = qemu_img_info(staged) if data.file_format != "raw": raise exception.ImageConvertFailed(image_id=image_href, reason=_("Converted to raw, but format is now %s") % data.file_format) os.rename(staged, path) else: os.rename(path_tmp, path)
def _show(self, image_href, method='get'): """Returns a dict with image data for the given opaque image id. :param image_href: The opaque image identifier. :returns: A dict containing image metadata. :raises: ImageNotFound :raises: ImageUnacceptable if the image status is not active """ LOG.debug("Getting image metadata from glance. Image: %s", image_href) image_id = service_utils.parse_image_id(image_href) image = self.call(method, image_id) if not service_utils.is_image_active(image): raise exception.ImageUnacceptable( image_id=image_id, reason=_("The image is required to be in an active state.")) if not service_utils.is_image_available(self.context, image): raise exception.ImageNotFound(image_id=image_id) base_image_meta = service_utils.translate_from_glance(image) return base_image_meta
def get_source_format(image_href, path): data = disk_utils.qemu_img_info(path) fmt = data.file_format if fmt is None: raise exception.ImageUnacceptable( reason=_("'qemu-img info' parsing failed."), image_id=image_href) backing_file = data.backing_file if backing_file is not None: raise exception.ImageUnacceptable( image_id=image_href, reason=_("fmt=%(fmt)s backed by: %(backing_file)s") % {'fmt': fmt, 'backing_file': backing_file}) return fmt
def swift_temp_url(self, image_info): """Generate a no-auth Swift temporary URL. This function will generate the temporary Swift URL using the image id from Glance and the config options: 'swift_endpoint_url', 'swift_api_version', 'swift_account' and 'swift_container'. The temporary URL will be valid for 'swift_temp_url_duration' seconds. This allows Ironic to download a Glance image without passing around an auth_token. :param image_info: The return from a GET request to Glance for a certain image_id. Should be a dictionary, with keys like 'name' and 'checksum'. See http://docs.openstack.org/developer/glance/glanceapi.html for examples. :returns: A signed Swift URL from which an image can be downloaded, without authentication. :raises: InvalidParameterValue if Swift config options are not set correctly. :raises: MissingParameterValue if a required parameter is not set. :raises: ImageUnacceptable if the image info from Glance does not have a image ID. """ self._validate_temp_url_config() if ('id' not in image_info or not utils.is_uuid_like(image_info['id'])): raise exc.ImageUnacceptable(_( 'The given image info does not have a valid image id: %s') % image_info) url_fragments = { 'endpoint_url': CONF.glance.swift_endpoint_url, 'api_version': CONF.glance.swift_api_version, 'account': CONF.glance.swift_account, 'container': self._get_swift_container(image_info['id']), 'object_id': image_info['id'] } template = '/{api_version}/{account}/{container}/{object_id}' url_path = template.format(**url_fragments) path = swift_utils.generate_temp_url( path=url_path, seconds=CONF.glance.swift_temp_url_duration, key=CONF.glance.swift_temp_url_key, method='GET') return '{endpoint_url}{url_path}'.format( endpoint_url=url_fragments['endpoint_url'], url_path=path)
def swift_temp_url(self, image_info): """Generate a no-auth Swift temporary URL. This function will generate (or return the cached one if temp URL cache is enabled) the temporary Swift URL using the image id from Glance and the config options: 'swift_endpoint_url', 'swift_api_version', 'swift_account' and 'swift_container'. The temporary URL will be valid for 'swift_temp_url_duration' seconds. This allows Ironic to download a Glance image without passing around an auth_token. :param image_info: The return from a GET request to Glance for a certain image_id. Should be a dictionary, with keys like 'name' and 'checksum'. See https://docs.openstack.org/glance/latest/user/glanceapi.html for examples. :returns: A signed Swift URL from which an image can be downloaded, without authentication. :raises: InvalidParameterValue if Swift config options are not set correctly. :raises: MissingParameterValue if a required parameter is not set. :raises: ImageUnacceptable if the image info from Glance does not have an image ID. """ self._validate_temp_url_config() if ('id' not in image_info or not uuidutils.is_uuid_like(image_info['id'])): raise exception.ImageUnacceptable( _('The given image info does not have a valid image id: %s') % image_info) image_id = image_info['id'] url_fragments = { 'api_version': CONF.glance.swift_api_version, 'container': self._get_swift_container(image_id), 'object_id': image_id } endpoint_url = CONF.glance.swift_endpoint_url if not endpoint_url: swift_session = swift.get_swift_session() try: endpoint_url = keystone.get_endpoint('swift', session=swift_session) except exception.CatalogNotFound: raise exception.MissingParameterValue( _('Swift temporary URLs require a Swift endpoint URL, ' 'but it was not found in the service catalog. You must ' 'provide "swift_endpoint_url" as a config option.')) # Strip /v1/AUTH_%(tenant_id)s, if present endpoint_url = re.sub('/v1/AUTH_[^/]+/?$', '', endpoint_url) key = CONF.glance.swift_temp_url_key account = CONF.glance.swift_account if not account: swift_session = swift.get_swift_session() auth_ref = swift_session.auth.get_auth_ref(swift_session) account = 'AUTH_%s' % auth_ref.project_id if not key: swift_api = swift.SwiftAPI() key_header = 'x-account-meta-temp-url-key' key = swift_api.connection.head_account().get(key_header) if not key: raise exception.MissingParameterValue( _('Swift temporary URLs require a shared secret to be ' 'created. You must provide "swift_temp_url_key" as a ' 'config option or pre-generate the key on the project ' 'used to access Swift.')) url_fragments['account'] = account template = '/{api_version}/{account}/{container}/{object_id}' url_path = template.format(**url_fragments) return self._generate_temp_url( path=url_path, seconds=CONF.glance.swift_temp_url_duration, key=key, method='GET', endpoint=endpoint_url, image_id=image_id)
def swift_temp_url(self, image_info): """Generate a no-auth Swift temporary URL. This function will generate (or return the cached one if temp URL cache is enabled) the temporary Swift URL using the image id from Glance and the config options: 'swift_endpoint_url', 'swift_api_version', 'swift_account' and 'swift_container'. The temporary URL will be valid for 'swift_temp_url_duration' seconds. This allows Ironic to download a Glance image without passing around an auth_token. :param image_info: The return from a GET request to Glance for a certain image_id. Should be a dictionary, with keys like 'name' and 'checksum'. See http://docs.openstack.org/developer/glance/glanceapi.html for examples. :returns: A signed Swift URL from which an image can be downloaded, without authentication. :raises: InvalidParameterValue if Swift config options are not set correctly. :raises: MissingParameterValue if a required parameter is not set. :raises: ImageUnacceptable if the image info from Glance does not have a image ID. """ self._validate_temp_url_config() if ('id' not in image_info or not uuidutils.is_uuid_like(image_info['id'])): raise exc.ImageUnacceptable( _('The given image info does not have a valid image id: %s') % image_info) image_id = image_info['id'] url_fragments = { 'api_version': CONF.glance.swift_api_version, 'account': CONF.glance.swift_account, 'container': self._get_swift_container(image_id), 'object_id': image_id } endpoint_url = CONF.glance.swift_endpoint_url if CONF.glance.temp_url_endpoint_type == 'radosgw': chunks = urlparse.urlsplit(CONF.glance.swift_endpoint_url) if not chunks.path: endpoint_url = urlparse.urljoin(endpoint_url, 'swift') elif chunks.path != '/swift': raise exc.InvalidParameterValue( _('Swift endpoint URL should only contain scheme, ' 'hostname, optional port and optional /swift path ' 'without trailing slash; provided value is: %s') % endpoint_url) template = '/{api_version}/{container}/{object_id}' else: template = '/{api_version}/{account}/{container}/{object_id}' url_path = template.format(**url_fragments) return self._generate_temp_url( path=url_path, seconds=CONF.glance.swift_temp_url_duration, key=CONF.glance.swift_temp_url_key, method='GET', endpoint=endpoint_url, image_id=image_id)