Beispiel #1
0
def replication_compare(options, args):
    """%(prog)s compare <fromserver:port> <toserver:port>

    Compare the contents of fromserver with those of toserver.

    fromserver:port: the location of the master glance instance.
    toserver:port:   the location of the slave glance instance.
    """

    # Make sure from-server and to-server are provided
    if len(args) < 2:
        raise TypeError(_("Too few arguments."))

    imageservice = get_image_service()

    slave_server, slave_port = utils.parse_valid_host_port(args.pop())
    slave_conn = http.HTTPConnection(slave_server, slave_port)
    slave_client = imageservice(slave_conn, options.slavetoken)

    master_server, master_port = utils.parse_valid_host_port(args.pop())
    master_conn = http.HTTPConnection(master_server, master_port)
    master_client = imageservice(master_conn, options.mastertoken)

    differences = {}

    for image in master_client.get_images():
        if _image_present(slave_client, image['id']):
            headers = slave_client.get_image_meta(image['id'])
            for key in options.dontreplicate.split(' '):
                if key in image:
                    LOG.debug('Stripping %(header)s from master metadata',
                              {'header': key})
                    del image[key]
                if key in headers:
                    LOG.debug('Stripping %(header)s from slave metadata',
                              {'header': key})
                    del headers[key]

            for key in image:
                if image[key] != headers.get(key, None):
                    LOG.warn(_LW('%(image_id)s: field %(key)s differs '
                                 '(source is %(master_value)s, destination '
                                 'is %(slave_value)s)')
                             % {'image_id': image['id'],
                                'key': key,
                                'master_value': image[key],
                                'slave_value': headers.get(key, 'undefined')})
                    differences[image['id']] = 'diff'
                else:
                    LOG.debug('%(image_id)s is identical',
                              {'image_id': image['id']})

        elif image['status'] == 'active':
            LOG.warn(_LW('Image %(image_id)s ("%(image_name)s") '
                     'entirely missing from the destination')
                     % {'image_id': image['id'],
                        'image_name': image.get('name', '--unnamed')})
            differences[image['id']] = 'missing'

    return differences
Beispiel #2
0
 def _foreach_store_type_preference():
     store_types = CONF.store_type_location_strategy.store_type_preference
     for preferred_store in store_types:
         preferred_store = str(preferred_store).strip()
         if not preferred_store:
             continue
         # NOTE(dharinic): The following conversion of ``filesystem`` and
         # ``vmware_datastore`` to ``file`` and ``vmware`` respectively
         # are to make store names consistent in Glance and glance_store
         # and also be backward compatible.
         # Reference: Bug 1615852
         if preferred_store == 'filesystem':
             preferred_store = 'file'
             msg = _LW('The value ``filesystem`` is DEPRECATED for use '
                       'with ``store_type_preference``. It will be '
                       'removed in the Pike release. Please use ``file`` '
                       'instead. Please see the Glance Newton release '
                       'notes for more information.')
             LOG.warn(msg)
         if preferred_store == 'vmware_datastore':
             preferred_store = 'vmware'
             msg = _LW('The value ``vmware_datastore`` is DEPRECATED for '
                       'use with ``store_type_preference``. It will be '
                       'removed in the Pike release. Please use ``vmware`` '
                       'instead. Please see the Glance Newton release '
                       'notes for more information.')
             LOG.warn(msg)
         yield preferred_store
Beispiel #3
0
def _get(context, artifact_id, session, type_name=None, type_version=None,
         show_level=ga.Showlevel.BASIC):
    values = dict(id=artifact_id)
    if type_name is not None:
        values['type_name'] = type_name
    if type_version is not None:
        values['type_version'] = type_version
    _set_version_fields(values)
    try:
        if show_level == ga.Showlevel.NONE:
            query = (
                session.query(models.Artifact).
                options(joinedload(models.Artifact.tags)).
                filter_by(**values))
        else:
            query = (
                session.query(models.Artifact).
                options(joinedload(models.Artifact.properties)).
                options(joinedload(models.Artifact.tags)).
                options(joinedload(models.Artifact.blobs).
                        joinedload(models.ArtifactBlob.locations)).
                filter_by(**values))

        artifact = query.one()
    except orm.exc.NoResultFound:
        LOG.warn(_LW("Artifact with id=%s not found") % artifact_id)
        raise exception.ArtifactNotFound(id=artifact_id)
    if not _check_visibility(context, artifact):
        LOG.warn(_LW("Artifact with id=%s is not accessible") % artifact_id)
        raise exception.ArtifactForbidden(id=artifact_id)
    return artifact
Beispiel #4
0
def _update_cinder_location_and_store_id(context, loc):
    """Update store location of legacy images

    While upgrading from single cinder store to multiple stores,
    the images having a store configured with a volume type matching
    the image-volume's type will be migrated/associated to that store
    and their location url will be updated respectively to the new format
    i.e. cinder://store-id/volume-id
    If there is no store configured for the image, the location url will
    not be updated.
    """
    uri = loc['url']
    volume_id = loc['url'].split("/")[-1]
    scheme = urlparse.urlparse(uri).scheme
    location_map = store_api.location.SCHEME_TO_CLS_BACKEND_MAP
    if scheme not in location_map:
        LOG.warning(_LW("Unknown scheme '%(scheme)s' found in uri '%(uri)s'"),
                    {'scheme': scheme, 'uri': uri})
        return

    for store in location_map[scheme]:
        store_instance = location_map[scheme][store]['store']
        if store_instance.is_image_associated_with_store(context, volume_id):
            url_prefix = store_instance.url_prefix
            loc['url'] = "%s/%s" % (url_prefix, volume_id)
            loc['metadata']['store'] = "%s" % store
            return

    LOG.warning(_LW("Not able to update location url '%s' of legacy image "
                    "due to unknown issues."), uri)
Beispiel #5
0
def replication_compare(options, args):
    """%(prog)s compare <fromserver:port> <toserver:port>

    Compare the contents of fromserver with those of toserver.

    fromserver:port: the location of the master glance instance.
    toserver:port:   the location of the slave glance instance.
    """

    # Make sure from-server and to-server are provided
    if len(args) < 2:
        raise TypeError(_("Too few arguments."))

    imageservice = get_image_service()

    slave_server, slave_port = utils.parse_valid_host_port(args.pop())
    slave_conn = http.HTTPConnection(slave_server, slave_port)
    slave_client = imageservice(slave_conn, options.slavetoken)

    master_server, master_port = utils.parse_valid_host_port(args.pop())
    master_conn = http.HTTPConnection(master_server, master_port)
    master_client = imageservice(master_conn, options.mastertoken)

    differences = {}

    for image in master_client.get_images():
        if _image_present(slave_client, image['id']):
            headers = slave_client.get_image_meta(image['id'])
            for key in options.dontreplicate.split(' '):
                if key in image:
                    LOG.debug('Stripping %(header)s from master metadata',
                              {'header': key})
                    del image[key]
                if key in headers:
                    LOG.debug('Stripping %(header)s from slave metadata',
                              {'header': key})
                    del headers[key]

            for key in image:
                if image[key] != headers.get(key, None):
                    LOG.warn(_LW('%(image_id)s: field %(key)s differs '
                                 '(source is %(master_value)s, destination '
                                 'is %(slave_value)s)')
                             % {'image_id': image['id'],
                                'key': key,
                                'master_value': image[key],
                                'slave_value': headers.get(key, 'undefined')})
                    differences[image['id']] = 'diff'
                else:
                    LOG.debug('%(image_id)s is identical',
                              {'image_id': image['id']})

        elif image['status'] == 'active':
            LOG.warn(_LW('Image %(image_id)s ("%(image_name)s") '
                     'entirely missing from the destination')
                     % {'image_id': image['id'],
                        'image_name': image.get('name', '--unnamed')})
            differences[image['id']] = 'missing'

    return differences
Beispiel #6
0
 def _get_images(self, context, filters, **params):
     """Get images, wrapping in exception if necessary."""
     # NOTE(markwash): for backwards compatibility, is_public=True for
     # admins actually means "treat me as if I'm not an admin and show me
     # all my images"
     if context.is_admin and params.get('is_public') is True:
         params['admin_as_user'] = True
         del params['is_public']
     try:
         return self.db_api.image_get_all(context,
                                          filters=filters,
                                          **params)
     except exception.ImageNotFound:
         LOG.warn(
             _LW("Invalid marker. Image %(id)s could not be "
                 "found.") % {'id': params.get('marker')})
         msg = _("Invalid marker. Image could not be found.")
         raise exc.HTTPBadRequest(explanation=msg)
     except exception.Forbidden:
         LOG.warn(
             _LW("Access denied to image %(id)s but returning "
                 "'not found'") % {'id': params.get('marker')})
         msg = _("Invalid marker. Image could not be found.")
         raise exc.HTTPBadRequest(explanation=msg)
     except Exception:
         LOG.exception(_LE("Unable to get images"))
         raise
Beispiel #7
0
    def fetch_image_into_cache(self, image_id):
        ctx = context.RequestContext(is_admin=True, show_deleted=True)

        try:
            image_repo = self.gateway.get_repo(ctx)
            image = image_repo.get(image_id)
        except exception.NotFound:
            LOG.warning(_LW("Image '%s' not found"), image_id)
            return False

        if image.status != 'active':
            LOG.warn(_LW("Image '%s' is not active. Not caching.") % image_id)
            return False

        for loc in image.locations:
            if CONF.enabled_backends:
                image_data, image_size = glance_store.get(loc['url'],
                                                          None,
                                                          context=ctx)
            else:
                image_data, image_size = glance_store.get_from_backend(
                    loc['url'], context=ctx)

            LOG.debug("Caching image '%s'", image_id)
            cache_tee_iter = self.cache.cache_tee_iter(image_id, image_data,
                                                       image.checksum)
            # Image is tee'd into cache and checksum verified
            # as we iterate
            list(cache_tee_iter)
            return True
Beispiel #8
0
    def delete(self, req, image_id, id):
        """
        Removes a membership from the image.
        """
        self._check_can_access_image_members(req.context)

        # Make sure the image exists
        try:
            image = self.db_api.image_get(req.context, image_id)
        except exception.NotFound:
            msg = _("Image %(id)s not found") % {'id': image_id}
            LOG.warn(msg)
            raise webob.exc.HTTPNotFound(msg)
        except exception.Forbidden:
            # If it's private and doesn't belong to them, don't let on
            # that it exists
            msg = _LW("Access denied to image %(id)s but returning"
                      " 'not found'") % {
                          'id': image_id
                      }
            LOG.warn(msg)
            raise webob.exc.HTTPNotFound()

        # Can they manipulate the membership?
        if not self.is_image_sharable(req.context, image):
            msg = (_LW("User lacks permission to share image %(id)s") % {
                'id': image_id
            })
            LOG.warn(msg)
            msg = _("No permission to share that image")
            raise webob.exc.HTTPForbidden(msg)

        # Look up an existing membership
        members = self.db_api.image_member_find(req.context,
                                                image_id=image_id,
                                                member=id)
        if members:
            self.db_api.image_member_delete(req.context, members[0]['id'])
        else:
            LOG.debug("%(id)s is not a member of image %(image_id)s", {
                'id': id,
                'image_id': image_id
            })
            msg = _("Membership could not be found.")
            raise webob.exc.HTTPNotFound(explanation=msg)

        # Make an appropriate result
        LOG.info(_LI("Successfully deleted a membership from image %(id)s"),
                 {'id': image_id})
        return webob.exc.HTTPNoContent()
Beispiel #9
0
def check_quota(context, image_size, db_api, image_id=None):
    """Method called to see if the user is allowed to store an image.

    Checks if it is allowed based on the given size in glance based on their
    quota and current usage.

    :param context:
    :param image_size:  The size of the image we hope to store
    :param db_api:  The db_api in use for this configuration
    :param image_id: The image that will be replaced with this new data size
    :returns:
    """

    remaining = get_remaining_quota(context, db_api, image_id=image_id)

    if remaining is None:
        return

    user = getattr(context, 'user_id', '<unknown>')

    if image_size is None:
        # NOTE(jbresnah) When the image size is None it means that it is
        # not known.  In this case the only time we will raise an
        # exception is when there is no room left at all, thus we know
        # it will not fit
        if remaining <= 0:
            LOG.warn(
                _LW("User %(user)s attempted to upload an image of"
                    " unknown size that will exceed the quota."
                    " %(remaining)d bytes remaining.") % {
                        'user': user,
                        'remaining': remaining
                    })
            raise exception.StorageQuotaFull(image_size=image_size,
                                             remaining=remaining)
        return

    if image_size > remaining:
        LOG.warn(
            _LW("User %(user)s attempted to upload an image of size"
                " %(size)d that will exceed the quota. %(remaining)d"
                " bytes remaining.") % {
                    'user': user,
                    'size': image_size,
                    'remaining': remaining
                })
        raise exception.StorageQuotaFull(image_size=image_size,
                                         remaining=remaining)

    return remaining
Beispiel #10
0
    def get_data(self, offset=0, chunk_size=None):
        if not self.image.locations:
            # NOTE(mclaren): This is the only set of arguments
            # which work with this exception currently, see:
            # https://bugs.launchpad.net/glance-store/+bug/1501443
            # When the above glance_store bug is fixed we can
            # add a msg as usual.
            raise store.NotFound(image=None)
        err = None

        # If glance cache is enabled, we overwrite the location
        # to a remote glance one.
        if CONF.remote_registry_region_name:
            try:
                data, size = self.store_api.get_from_backend(
                    "glance://%s/%s" % (CONF.remote_registry_region_name,
                                        self.image.image_id),
                    offset=offset,
                    chunk_size=chunk_size,
                    context=self.context)

                return data
            except Exception as e:
                LOG.warn(_LW('Get image %(id)s from remote glance server '
                             'failed: %(err)s.')
                         % {'id': self.image.image_id,
                            'err': encodeutils.exception_to_unicode(e)})
                err = e

        for loc in self.image.locations:
            try:
                data, size = self.store_api.get_from_backend(
                    loc['url'],
                    offset=offset,
                    chunk_size=chunk_size,
                    context=self.context)

                return data
            except Exception as e:
                LOG.warn(_LW('Get image %(id)s data failed: '
                             '%(err)s.')
                         % {'id': self.image.image_id,
                            'err': encodeutils.exception_to_unicode(e)})
                err = e
        # tried all locations
        LOG.error(_LE('Glance tried all active locations to get data for '
                      'image %s but all have failed.') % self.image.image_id)
        raise err
Beispiel #11
0
def _do_dependencies(artifact, new_dependencies, session):
    deps_to_update = []
    # small check that all dependencies are new
    if artifact.dependencies is not None:
        for db_dep in artifact.dependencies:
            for dep in new_dependencies.keys():
                if db_dep.name == dep:
                    msg = _LW("Artifact with the specified type, name "
                              "and versions already has the direct "
                              "dependency=%s") % dep
                    LOG.warn(msg)
        # change values of former dependency
        for dep in artifact.dependencies:
            session.delete(dep)
        artifact.dependencies = []
    for depname, depvalues in new_dependencies.items():
        for pos, depvalue in enumerate(depvalues):
            db_dep = models.ArtifactDependency()
            db_dep.name = depname
            db_dep.artifact_source = artifact.id
            db_dep.artifact_dest = depvalue
            db_dep.artifact_origin = artifact.id
            db_dep.is_direct = True
            db_dep.position = pos
            deps_to_update.append(db_dep)
    artifact.dependencies = deps_to_update
Beispiel #12
0
    def execute(self, image_id, file_path):

        # NOTE(flaper87): A format must be explicitly
        # specified. There's no "sane" default for this
        # because the dest format may work differently depending
        # on the environment OpenStack is running in.
        conversion_format = CONF.taskflow_executor.conversion_format
        if conversion_format is None:
            if not _Convert.conversion_missing_warned:
                msg = (_LW('The conversion format is None, please add a value '
                           'for it in the config file for this task to '
                           'work: %s') % self.task_id)
                LOG.warn(msg)
                _Convert.conversion_missing_warned = True
            return

        # TODO(flaper87): Check whether the image is in the desired
        # format already. Probably using `qemu-img` just like the
        # `Introspection` task.
        dest_path = os.path.join(CONF.task.work_dir, "%s.converted" % image_id)
        stdout, stderr = putils.trycmd('qemu-img',
                                       'convert',
                                       '-O',
                                       conversion_format,
                                       file_path,
                                       dest_path,
                                       log_errors=putils.LOG_ALL_ERRORS)

        if stderr:
            raise RuntimeError(stderr)

        os.rename(dest_path, file_path.split("file://")[-1])
        return file_path
Beispiel #13
0
    def get_data(self, offset=0, chunk_size=None):
        if not self.image.locations:
            # NOTE(mclaren): This is the only set of arguments
            # which work with this exception currently, see:
            # https://bugs.launchpad.net/glance-store/+bug/1501443
            # When the above glance_store bug is fixed we can
            # add a msg as usual.
            raise store.NotFound(image=None)
        err = None
        for loc in self.image.locations:
            try:
                data, size = self.store_api.get_from_backend(
                    loc['url'],
                    offset=offset,
                    chunk_size=chunk_size,
                    context=self.context)

                return data
            except Exception as e:
                LOG.warn(_LW('Get image %(id)s data failed: '
                             '%(err)s.')
                         % {'id': self.image.image_id,
                            'err': encodeutils.exception_to_unicode(e)})
                err = e
        # tried all locations
        LOG.error(_LE('Glance tried all active locations to get data for '
                      'image %s but all have failed.') % self.image.image_id)
        raise err
Beispiel #14
0
def _do_transitive_dependencies(artifact, session):
    deps_to_update = []
    for dependency in artifact.dependencies:
        depvalue = dependency.artifact_dest
        transitdeps = session.query(models.ArtifactDependency).filter_by(
            artifact_source=depvalue).all()
        for transitdep in transitdeps:
            if not transitdep.is_direct:
                # transitive dependencies are already created
                msg = _LW("Artifact with the specified type, "
                          "name and version already has the "
                          "direct dependency=%d") % transitdep.id
                LOG.warn(msg)
                raise exception.ArtifactDuplicateTransitiveDependency(
                    dep=transitdep.id)

            db_dep = models.ArtifactDependency()
            db_dep.name = transitdep['name']
            db_dep.artifact_source = artifact.id
            db_dep.artifact_dest = transitdep.artifact_dest
            db_dep.artifact_origin = transitdep.artifact_source
            db_dep.is_direct = False
            db_dep.position = transitdep.position
            deps_to_update.append(db_dep)
    return deps_to_update
Beispiel #15
0
    def _scrub_image(self, image_id, delete_jobs):
        if len(delete_jobs) == 0:
            return

        LOG.info(_LI("Scrubbing image %(id)s from %(count)d locations."),
                 {'id': image_id, 'count': len(delete_jobs)})

        success = True
        if CONF.enabled_backends:
            for img_id, loc_id, uri, backend in delete_jobs:
                try:
                    self._delete_image_location_from_backend(img_id, loc_id,
                                                             uri,
                                                             backend=backend)
                except Exception:
                    success = False
        else:
            for img_id, loc_id, uri in delete_jobs:
                try:
                    self._delete_image_location_from_backend(img_id, loc_id,
                                                             uri)
                except Exception:
                    success = False

        if success:
            image = db_api.get_api().image_get(self.admin_context, image_id)
            if image['status'] == 'pending_delete':
                db_api.get_api().image_update(self.admin_context, image_id,
                                              {'status': 'deleted'})
            LOG.info(_LI("Image %s has been scrubbed successfully"), image_id)
        else:
            LOG.warn(_LW("One or more image locations couldn't be scrubbed "
                         "from backend. Leaving image '%s' in 'pending_delete'"
                         " status") % image_id)
Beispiel #16
0
    def get_data(self, offset=0, chunk_size=None):
        if not self.image.locations:
            # NOTE(mclaren): This is the only set of arguments
            # which work with this exception currently, see:
            # https://bugs.launchpad.net/glance-store/+bug/1501443
            # When the above glance_store bug is fixed we can
            # add a msg as usual.
            raise store.NotFound(image=None)
        err = None
        for loc in self.image.locations:
            try:
                backend = loc['metadata'].get('store')
                if CONF.enabled_backends:
                    data, size = self.store_api.get(
                        loc['url'], backend, offset=offset,
                        chunk_size=chunk_size, context=self.context
                    )
                else:
                    data, size = self.store_api.get_from_backend(
                        loc['url'],
                        offset=offset,
                        chunk_size=chunk_size,
                        context=self.context)

                return data
            except Exception as e:
                LOG.warn(_LW('Get image %(id)s data failed: '
                             '%(err)s.'),
                         {'id': self.image.image_id,
                          'err': encodeutils.exception_to_unicode(e)})
                err = e
        # tried all locations
        LOG.error(_LE('Glance tried all active locations to get data for '
                      'image %s but all have failed.'), self.image.image_id)
        raise err
Beispiel #17
0
def set_image_data(image, uri, task_id):
    data_iter = None
    try:
        LOG.info(
            _LI("Task %(task_id)s: Got image data uri %(data_uri)s to be "
                "imported"), {
                    "data_uri": uri,
                    "task_id": task_id
                })
        data_iter = script_utils.get_image_data_iter(uri)
        image.set_data(data_iter)
    except Exception as e:
        with excutils.save_and_reraise_exception():
            LOG.warn(
                _LW("Task %(task_id)s failed with exception %(error)s") % {
                    "error": encodeutils.exception_to_unicode(e),
                    "task_id": task_id
                })
            LOG.info(
                _LI("Task %(task_id)s: Could not import image file"
                    " %(image_data)s"), {
                        "image_data": uri,
                        "task_id": task_id
                    })
    finally:
        if hasattr(data_iter, 'close'):
            data_iter.close()
Beispiel #18
0
def _update_rt_association(table, values, rt_id, namespace_id):
    try:
        (table.update(values=values).
         where(and_(table.c.resource_type_id == rt_id,
                    table.c.namespace_id == namespace_id)).execute())
    except sqlalchemy.exc.IntegrityError:
        LOG.warning(_LW("Duplicate entry for values: %s"), values)
Beispiel #19
0
    def reload(self):
        """
        Reload and re-apply configuration settings

        Existing child processes are sent a SIGHUP signal
        and will exit after completing existing requests.
        New child processes, which will have the updated
        configuration, are spawned. This allows preventing
        interruption to the service.
        """
        def _has_changed(old, new, param):
            old = old.get(param)
            new = getattr(new, param)
            return (new != old)

        old_conf = utils.stash_conf_values()
        has_changed = functools.partial(_has_changed, old_conf, CONF)
        CONF.reload_config_files()
        os.killpg(self.pgid, signal.SIGHUP)
        self.stale_children = self.children
        self.children = set()

        if self.raw_caching_pid:
            LOG.warn(_LW('RAW Caching does not support configuration reload'))

        # Ensure any logging config changes are picked up
        logging.setup(CONF, 'glance')
        config.set_config_defaults()

        self.configure(old_conf, has_changed)
        self.start_wsgi()
Beispiel #20
0
 def wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         msg = (_LW("An optional task has failed, "
                    "the failure was: %s") % six.text_type(exc))
         LOG.warn(msg)
Beispiel #21
0
def safe_delete_from_backend(context, image_id, location):
    """
    Given a location, delete an image from the store and
    update location status to db.

    This function try to handle all known exceptions which might be raised
    by those calls on store and DB modules in its implementation.

    :param context: The request context
    :param image_id: The image identifier
    :param location: The image location entry
    """

    try:
        ret = store_api.delete_from_backend(location['url'], context=context)
        location['status'] = 'deleted'
        if 'id' in location:
            db_api.get_api().image_location_delete(context, image_id,
                                                   location['id'], 'deleted')
        return ret
    except store_api.NotFound:
        msg = _LW('Failed to delete image %s in store from URI') % image_id
        LOG.warn(msg)
    except store_api.StoreDeleteNotSupported as e:
        LOG.warn(encodeutils.exception_to_unicode(e))
    except store_api.UnsupportedBackend:
        exc_type = sys.exc_info()[0].__name__
        msg = (_LE('Failed to delete image %(image_id)s from store: %(exc)s') %
               dict(image_id=image_id, exc=exc_type))
        LOG.error(msg)
Beispiel #22
0
def delete_cached_file(path):
    if os.path.exists(path):
        LOG.debug("Deleting image cache file '%s'", path)
        os.unlink(path)
    else:
        LOG.warn(_LW("Cached image file '%s' doesn't exist, unable to"
                     " delete") % path)
Beispiel #23
0
    def create(self, req, task):
        # NOTE(rosmaita): access to this call is enforced in the deserializer

        ctxt = req.context
        task_factory = self.gateway.get_task_factory(ctxt)
        executor_factory = self.gateway.get_task_executor_factory(ctxt)
        task_repo = self.gateway.get_task_repo(ctxt)
        try:
            new_task = task_factory.new_task(
                task_type=task['type'],
                owner=ctxt.owner,
                task_input=task['input'],
                image_id=task['input'].get('image_id'),
                user_id=ctxt.user_id,
                request_id=ctxt.request_id)
            task_repo.add(new_task)
            task_executor = executor_factory.new_task_executor(ctxt)
            pool = common.get_thread_pool("tasks_pool")
            pool.spawn(new_task.run, task_executor)
        except exception.Forbidden as e:
            msg = (_LW("Forbidden to create task. Reason: %(reason)s") % {
                'reason': encodeutils.exception_to_unicode(e)
            })
            LOG.warn(msg)
            raise webob.exc.HTTPForbidden(explanation=e.msg)
        return new_task
Beispiel #24
0
    def execute(self, image_id, file_path):

        # NOTE(flaper87): A format must be explicitly
        # specified. There's no "sane" default for this
        # because the dest format may work differently depending
        # on the environment OpenStack is running in.
        conversion_format = CONF.taskflow_executor.conversion_format
        if conversion_format is None:
            if not _Convert.conversion_missing_warned:
                msg = _LW('The conversion format is None, please add a value '
                          'for it in the config file for this task to '
                          'work: %s')
                LOG.warn(msg, self.task_id)
                _Convert.conversion_missing_warned = True
            return

        # TODO(flaper87): Check whether the image is in the desired
        # format already. Probably using `qemu-img` just like the
        # `Introspection` task.
        dest_path = os.path.join(CONF.task.work_dir, "%s.converted" % image_id)
        stdout, stderr = putils.trycmd('qemu-img', 'convert', '-O',
                                       conversion_format, file_path, dest_path,
                                       log_errors=putils.LOG_ALL_ERRORS)

        if stderr:
            raise RuntimeError(stderr)

        os.rename(dest_path, file_path.split("file://")[-1])
        return file_path
Beispiel #25
0
def safe_delete_from_backend(context, image_id, location):
    """
    Given a location, delete an image from the store and
    update location status to db.

    This function try to handle all known exceptions which might be raised
    by those calls on store and DB modules in its implementation.

    :param context: The request context
    :param image_id: The image identifier
    :param location: The image location entry
    """

    try:
        ret = store_api.delete_from_backend(location['url'], context=context)
        location['status'] = 'deleted'
        if 'id' in location:
            db_api.get_api().image_location_delete(context, image_id,
                                                   location['id'], 'deleted')
        return ret
    except store_api.NotFound:
        msg = _LW('Failed to delete image %s in store from URI') % image_id
        LOG.warn(msg)
    except store_api.StoreDeleteNotSupported as e:
        LOG.warn(encodeutils.exception_to_unicode(e))
    except store_api.UnsupportedBackend:
        exc_type = sys.exc_info()[0].__name__
        msg = (_LE('Failed to delete image %(image_id)s from store: %(exc)s') %
               dict(image_id=image_id, exc=exc_type))
        LOG.error(msg)
Beispiel #26
0
    def _scrub_image(self, image_id, delete_jobs):
        if len(delete_jobs) == 0:
            return

        LOG.info(_LI("Scrubbing image %(id)s from %(count)d locations."), {
            'id': image_id,
            'count': len(delete_jobs)
        })

        success = True
        for img_id, loc_id, uri in delete_jobs:
            try:
                self._delete_image_location_from_backend(img_id, loc_id, uri)
            except Exception:
                success = False

        if success:
            image = self.registry.get_image(image_id)
            if image['status'] == 'pending_delete':
                self.registry.update_image(image_id, {'status': 'deleted'})
            LOG.info(_LI("Image %s has been scrubbed successfully"), image_id)
        else:
            LOG.warn(
                _LW("One or more image locations couldn't be scrubbed "
                    "from backend. Leaving image '%s' in 'pending_delete'"
                    " status") % image_id)
Beispiel #27
0
def validate_key_cert(key_file, cert_file):
    try:
        error_key_name = "private key"
        error_filename = key_file
        with open(key_file, 'r') as keyfile:
            key_str = keyfile.read()
        key = crypto.load_privatekey(crypto.FILETYPE_PEM, key_str)

        error_key_name = "certificate"
        error_filename = cert_file
        with open(cert_file, 'r') as certfile:
            cert_str = certfile.read()
        cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_str)
    except IOError as ioe:
        raise RuntimeError(
            _("There is a problem with your %(error_key_name)s "
              "%(error_filename)s.  Please verify it."
              "  Error: %(ioe)s") % {
                  'error_key_name': error_key_name,
                  'error_filename': error_filename,
                  'ioe': ioe
              })
    except crypto.Error as ce:
        raise RuntimeError(
            _("There is a problem with your %(error_key_name)s "
              "%(error_filename)s.  Please verify it. OpenSSL"
              " error: %(ce)s") % {
                  'error_key_name': error_key_name,
                  'error_filename': error_filename,
                  'ce': ce
              })

    try:
        data = str(uuid.uuid4())
        # On Python 3, explicitly encode to UTF-8 to call crypto.sign() which
        # requires bytes. Otherwise, it raises a deprecation warning (and
        # will raise an error later).
        data = encodeutils.to_utf8(data)
        digest = CONF.digest_algorithm
        if digest == 'sha1':
            LOG.warn(
                _LW('The FIPS (FEDERAL INFORMATION PROCESSING STANDARDS)'
                    ' state that the SHA-1 is not suitable for'
                    ' general-purpose digital signature applications (as'
                    ' specified in FIPS 186-3) that require 112 bits of'
                    ' security. The default value is sha1 in Kilo for a'
                    ' smooth upgrade process, and it will be updated'
                    ' with sha256 in next release(L).'))
        out = crypto.sign(key, data, digest)
        crypto.verify(cert, out, data, digest)
    except crypto.Error as ce:
        raise RuntimeError(
            _("There is a problem with your key pair.  "
              "Please verify that cert %(cert_file)s and "
              "key %(key_file)s belong together.  OpenSSL "
              "error %(ce)s") % {
                  'cert_file': cert_file,
                  'key_file': key_file,
                  'ce': ce
              })
    def new_task_executor(self, context):
        try:
            # NOTE(flaper87): Backwards compatibility layer.
            # It'll allow us to provide a deprecation path to
            # users that are currently consuming the `eventlet`
            # executor.
            task_executor = CONF.task.task_executor
            if task_executor == 'eventlet':
                # NOTE(jokke): Making sure we do not log the deprecation
                # warning 1000 times or anything crazy like that.
                if not TaskExecutorFactory.eventlet_deprecation_warned:
                    msg = _LW("The `eventlet` executor has been deprecated. "
                              "Use `taskflow` instead.")
                    LOG.warn(msg)
                    TaskExecutorFactory.eventlet_deprecation_warned = True
                task_executor = 'taskflow'

            executor_cls = ('glance.async.%s_executor.'
                            'TaskExecutor' % task_executor)
            LOG.debug("Loading %s executor", task_executor)
            executor = importutils.import_class(executor_cls)
            return executor(context,
                            self.task_repo,
                            self.image_repo,
                            self.image_factory)
        except ImportError:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Failed to load the %s executor provided "
                                  "in the config.") % CONF.task.task_executor)
Beispiel #29
0
def _update_rt_association(table, values, rt_id, namespace_id):
    try:
        (table.update(values=values).where(
            and_(table.c.resource_type_id == rt_id,
                 table.c.namespace_id == namespace_id)).execute())
    except sqlalchemy.exc.IntegrityError:
        LOG.warning(_LW("Duplicate entry for values: %s"), values)
Beispiel #30
0
    def new_task_executor(self, context):
        try:
            # NOTE(flaper87): Backwards compatibility layer.
            # It'll allow us to provide a deprecation path to
            # users that are currently consuming the `eventlet`
            # executor.
            task_executor = CONF.task.task_executor
            if task_executor == 'eventlet':
                # NOTE(jokke): Making sure we do not log the deprecation
                # warning 1000 times or anything crazy like that.
                if not TaskExecutorFactory.eventlet_deprecation_warned:
                    msg = _LW("The `eventlet` executor has been deprecated. "
                              "Use `taskflow` instead.")
                    LOG.warn(msg)
                    TaskExecutorFactory.eventlet_deprecation_warned = True
                task_executor = 'taskflow'

            executor_cls = ('glance.async_.%s_executor.'
                            'TaskExecutor' % task_executor)
            LOG.debug("Loading %s executor", task_executor)
            executor = importutils.import_class(executor_cls)
            return executor(context,
                            self.task_repo,
                            self.image_repo,
                            self.image_factory)
        except ImportError:
            with excutils.save_and_reraise_exception():
                LOG.exception(_LE("Failed to load the %s executor provided "
                                  "in the config.") % CONF.task.task_executor)
Beispiel #31
0
def _create_or_update(context, values, artifact_id, session, type_name,
                      type_version=None):
    values = copy.deepcopy(values)
    with session.begin():
        _set_version_fields(values)
        _validate_values(values)
        _drop_protected_attrs(models.Artifact, values)
        if artifact_id:
            # update existing artifact
            state = values.get('state')
            show_level = ga.Showlevel.BASIC
            if state is not None:
                if state == 'active':
                    show_level = ga.Showlevel.DIRECT
                    values['published_at'] = timeutils.utcnow()
                if state == 'deleted':
                    values['deleted_at'] = timeutils.utcnow()

            artifact = _get(context, artifact_id, session, type_name,
                            type_version, show_level=show_level)
            _validate_transition(artifact.state,
                                 values.get('state') or artifact.state)
        else:
            # create new artifact
            artifact = models.Artifact()
            if 'id' not in values:
                artifact.id = str(uuid.uuid4())
            else:
                artifact.id = values['id']

        if 'tags' in values:
            tags = values.pop('tags')
            artifact.tags = _do_tags(artifact, tags)

        if 'properties' in values:
            properties = values.pop('properties', {})
            artifact.properties = _do_properties(artifact, properties)

        if 'blobs' in values:
            blobs = values.pop('blobs')
            artifact.blobs = _do_blobs(artifact, blobs)

        if 'dependencies' in values:
            dependencies = values.pop('dependencies')
            _do_dependencies(artifact, dependencies, session)

        if values.get('state', None) == 'publish':
            artifact.dependencies.extend(
                _do_transitive_dependencies(artifact, session))

        artifact.update(values)
        try:
            artifact.save(session=session)
        except db_exc.DBDuplicateEntry:
            LOG.warn(_LW("Artifact with the specified type, name and version "
                         "already exists"))
            raise exception.ArtifactDuplicateNameTypeVersion()

    return artifact
Beispiel #32
0
 def wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         msg = (_LW("An optional task has failed, "
                    "the failure was: %s") %
                encodeutils.exception_to_unicode(exc))
         LOG.warn(msg)
 def wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         msg = (_LW("An optional task has failed, "
                    "the failure was: %s") %
                six.text_type(exc))
         LOG.warn(msg)
Beispiel #34
0
 def wrapper(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except Exception as exc:
         msg = (_LW("An optional task has failed, "
                    "the failure was: %s") %
                encodeutils.exception_to_unicode(exc))
         LOG.warn(msg)
Beispiel #35
0
    def delete(self, req, image_id, id):
        """
        Removes a membership from the image.
        """
        self._check_can_access_image_members(req.context)

        # Make sure the image exists
        try:
            image = self.db_api.image_get(req.context, image_id)
        except exception.NotFound:
            msg = _("Image %(id)s not found") % {'id': image_id}
            LOG.warn(msg)
            raise webob.exc.HTTPNotFound(msg)
        except exception.Forbidden:
            # If it's private and doesn't belong to them, don't let on
            # that it exists
            msg = _LW("Access denied to image %(id)s but returning"
                      " 'not found'") % {'id': image_id}
            LOG.warn(msg)
            raise webob.exc.HTTPNotFound()

        # Can they manipulate the membership?
        if not self.is_image_sharable(req.context, image):
            msg = (_LW("User lacks permission to share image %(id)s") %
                   {'id': image_id})
            LOG.warn(msg)
            msg = _("No permission to share that image")
            raise webob.exc.HTTPForbidden(msg)

        # Look up an existing membership
        members = self.db_api.image_member_find(req.context,
                                                image_id=image_id,
                                                member=id)
        if members:
            self.db_api.image_member_delete(req.context, members[0]['id'])
        else:
            LOG.debug("%(id)s is not a member of image %(image_id)s",
                      {'id': id, 'image_id': image_id})
            msg = _("Membership could not be found.")
            raise webob.exc.HTTPNotFound(explanation=msg)

        # Make an appropriate result
        LOG.info(_LI("Successfully deleted a membership from image %(id)s"),
                 {'id': image_id})
        return webob.exc.HTTPNoContent()
Beispiel #36
0
 def get(self, req, task_id):
     try:
         task_repo = self.gateway.get_task_repo(req.context)
         task = task_repo.get(task_id)
     except exception.NotFound as e:
         msg = (_LW("Failed to find task %(task_id)s. Reason: %(reason)s")
                % {'task_id': task_id,
                   'reason': encodeutils.exception_to_unicode(e)})
         LOG.warn(msg)
         raise webob.exc.HTTPNotFound(explanation=e.msg)
     except exception.Forbidden as e:
         msg = (_LW("Forbidden to get task %(task_id)s. Reason:"
                    " %(reason)s")
                % {'task_id': task_id,
                   'reason': encodeutils.exception_to_unicode(e)})
         LOG.warn(msg)
         raise webob.exc.HTTPForbidden(explanation=e.msg)
     return task
Beispiel #37
0
def _get(context, id, session):
    try:
        query = (session.query(models.MetadefTag).filter_by(id=id))
        metadef_tag = query.one()
    except sa_orm.exc.NoResultFound:
        msg = (_LW("Metadata tag not found for id %s") % id)
        LOG.warn(msg)
        raise exc.MetadefTagNotFound(message=msg)
    return metadef_tag
Beispiel #38
0
 def _remove_children(self, pid):
     if pid in self.children:
         self.children.remove(pid)
         LOG.info(_LI('Removed dead child %s'), pid)
     elif pid in self.stale_children:
         self.stale_children.remove(pid)
         LOG.info(_LI('Removed stale child %s'), pid)
     else:
         LOG.warn(_LW('Unrecognised child %s') % pid)
Beispiel #39
0
 def _remove_children(self, pid):
     if pid in self.children:
         self.children.remove(pid)
         LOG.info(_LI('Removed dead child %s'), pid)
     elif pid in self.stale_children:
         self.stale_children.remove(pid)
         LOG.info(_LI('Removed stale child %s'), pid)
     else:
         LOG.warn(_LW('Unrecognised child %s') % pid)
Beispiel #40
0
 def get(self, req, task_id):
     try:
         task_repo = self.gateway.get_task_repo(req.context)
         task = task_repo.get(task_id)
     except exception.NotFound as e:
         msg = (_LW("Failed to find task %(task_id)s. Reason: %(reason)s")
                % {'task_id': task_id,
                   'reason': encodeutils.exception_to_unicode(e)})
         LOG.warn(msg)
         raise webob.exc.HTTPNotFound(explanation=e.msg)
     except exception.Forbidden as e:
         msg = (_LW("Forbidden to get task %(task_id)s. Reason:"
                    " %(reason)s")
                % {'task_id': task_id,
                   'reason': encodeutils.exception_to_unicode(e)})
         LOG.warn(msg)
         raise webob.exc.HTTPForbidden(explanation=e.msg)
     return task
Beispiel #41
0
def check_quota(context, image_size, db_api, image_id=None):
    """Method called to see if the user is allowed to store an image.

    Checks if it is allowed based on the given size in glance based on their
    quota and current usage.

    :param context:
    :param image_size:  The size of the image we hope to store
    :param db_api:  The db_api in use for this configuration
    :param image_id: The image that will be replaced with this new data size
    :returns:
    """

    remaining = get_remaining_quota(context, db_api, image_id=image_id)

    if remaining is None:
        return

    user = getattr(context, 'user', '<unknown>')

    if image_size is None:
        # NOTE(jbresnah) When the image size is None it means that it is
        # not known.  In this case the only time we will raise an
        # exception is when there is no room left at all, thus we know
        # it will not fit
        if remaining <= 0:
            LOG.warn(_LW("User %(user)s attempted to upload an image of"
                         " unknown size that will exceed the quota."
                         " %(remaining)d bytes remaining.")
                     % {'user': user, 'remaining': remaining})
            raise exception.StorageQuotaFull(image_size=image_size,
                                             remaining=remaining)
        return

    if image_size > remaining:
        LOG.warn(_LW("User %(user)s attempted to upload an image of size"
                     " %(size)d that will exceed the quota. %(remaining)d"
                     " bytes remaining.")
                 % {'user': user, 'size': image_size, 'remaining': remaining})
        raise exception.StorageQuotaFull(image_size=image_size,
                                         remaining=remaining)

    return remaining
Beispiel #42
0
 def __init__(self):
     super(Enforcer, self).__init__(CONF, use_conf=True, overwrite=False)
     self.register_defaults(policies.list_rules())
     if CONF.enforce_secure_rbac and CONF.oslo_policy.enforce_new_defaults:
         LOG.warning(
             _LW("Deploying glance with secure RBAC personas enabled via "
                 "`glance-api.conf [DEFAULT] enforce_secure_rbac=True` and "
                 "`glance-api.conf [oslo_policy] enforce_new_defaults=True` "
                 "is marked as EXPERIMENTAL in Wallaby. The status of this "
                 "feature will graduate to SUPPORTED as glance adopts more "
                 "personas, specifically for system-scope."))
Beispiel #43
0
 def _check_ext(ext):
     try:
         next(n for n, v in available
              if n == ext.plugin.metadata.type_name and
              (v is None or v == ext.plugin.metadata.type_version))
     except StopIteration:
         LOG.warn(_LW("Can't load artifact %s: not in"
                      " available_plugins list") % ext.name)
         raise exception.ArtifactLoadError(name=ext.name)
     LOG.info(
         _LI("Artifact %s has been successfully loaded"), ext.name)
     return True
Beispiel #44
0
def validate_key_cert(key_file, cert_file):
    try:
        error_key_name = "private key"
        error_filename = key_file
        with open(key_file, 'r') as keyfile:
            key_str = keyfile.read()
        key = crypto.load_privatekey(crypto.FILETYPE_PEM, key_str)

        error_key_name = "certificate"
        error_filename = cert_file
        with open(cert_file, 'r') as certfile:
            cert_str = certfile.read()
        cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_str)
    except IOError as ioe:
        raise RuntimeError(_("There is a problem with your %(error_key_name)s "
                             "%(error_filename)s.  Please verify it."
                             "  Error: %(ioe)s") %
                           {'error_key_name': error_key_name,
                            'error_filename': error_filename,
                            'ioe': ioe})
    except crypto.Error as ce:
        raise RuntimeError(_("There is a problem with your %(error_key_name)s "
                             "%(error_filename)s.  Please verify it. OpenSSL"
                             " error: %(ce)s") %
                           {'error_key_name': error_key_name,
                            'error_filename': error_filename,
                            'ce': ce})

    try:
        data = str(uuid.uuid4())
        # On Python 3, explicitly encode to UTF-8 to call crypto.sign() which
        # requires bytes. Otherwise, it raises a deprecation warning (and
        # will raise an error later).
        data = encodeutils.to_utf8(data)
        digest = CONF.digest_algorithm
        if digest == 'sha1':
            LOG.warn(
                _LW('The FIPS (FEDERAL INFORMATION PROCESSING STANDARDS)'
                    ' state that the SHA-1 is not suitable for'
                    ' general-purpose digital signature applications (as'
                    ' specified in FIPS 186-3) that require 112 bits of'
                    ' security. The default value is sha1 in Kilo for a'
                    ' smooth upgrade process, and it will be updated'
                    ' with sha256 in next release(L).'))
        out = crypto.sign(key, data, digest)
        crypto.verify(cert, out, data, digest)
    except crypto.Error as ce:
        raise RuntimeError(_("There is a problem with your key pair.  "
                             "Please verify that cert %(cert_file)s and "
                             "key %(key_file)s belong together.  OpenSSL "
                             "error %(ce)s") % {'cert_file': cert_file,
                                                'key_file': key_file,
                                                'ce': ce})
 def _check_ext(ext):
     try:
         next(n for n, v in available
              if n == ext.plugin.metadata.type_name and
              (v is None or v == ext.plugin.metadata.type_version))
     except StopIteration:
         LOG.warn(_LW("Can't load artifact %s: not in"
                      " available_plugins list") % ext.name)
         raise exception.ArtifactLoadError(name=ext.name)
     LOG.info(
         _LI("Artifact %s has been successfully loaded"), ext.name)
     return True
Beispiel #46
0
def load_custom_properties():
    """Find the schema properties files and load them into a dict."""
    filename = "schema-image.json"
    match = CONF.find_file(filename)
    if match:
        with open(match, "r") as schema_file:
            schema_data = schema_file.read()
        return json.loads(schema_data)
    else:
        msg = _LW("Could not find schema properties file %s. Continuing " "without custom properties") % filename
        LOG.warn(msg)
        return {}
Beispiel #47
0
 def _get_images(self, context, filters, **params):
     """Get images, wrapping in exception if necessary."""
     # NOTE(markwash): for backwards compatibility, is_public=True for
     # admins actually means "treat me as if I'm not an admin and show me
     # all my images"
     if context.is_admin and params.get("is_public") is True:
         params["admin_as_user"] = True
         del params["is_public"]
     try:
         return self.db_api.image_get_all(context, filters=filters, **params)
     except exception.ImageNotFound:
         LOG.warn(_LW("Invalid marker. Image %(id)s could not be " "found.") % {"id": params.get("marker")})
         msg = _("Invalid marker. Image could not be found.")
         raise exc.HTTPBadRequest(explanation=msg)
     except exception.Forbidden:
         LOG.warn(_LW("Access denied to image %(id)s but returning " "'not found'") % {"id": params.get("marker")})
         msg = _("Invalid marker. Image could not be found.")
         raise exc.HTTPBadRequest(explanation=msg)
     except Exception:
         LOG.exception(_LE("Unable to get images"))
         raise
Beispiel #48
0
 def __init__(self, mapper):
     versionutils.report_deprecated_feature(
         LOG,
         _LW('/v3 controller is deprecated and will be removed from '
             'glance-api soon. Remove the reference to it from '
             'glance-api-paste.ini configuration file and use Glance '
             'Artifact Service API instead'))
     redirector = self._get_redirector()
     mapper.connect(None, "/artifacts",
                    controller=redirector, action='redirect')
     mapper.connect(None, "/artifacts/{path:.*}",
                    controller=redirector, action='redirect')
     super(API, self).__init__(mapper)
Beispiel #49
0
    def _load_interested_properties(self):
        """Find the OVF properties config file and load it.

        OVF properties config file specifies which metadata of interest to
        extract. Reads in a JSON file named 'ovf-metadata.json' if available.
        See example file at etc/ovf-metadata.json.sample.
        """
        filename = 'ovf-metadata.json'
        match = CONF.find_file(filename)
        if match:
            with open(match, 'r') as properties_file:
                properties = json.loads(properties_file.read())
                self.interested_properties = properties.get(
                    'cim_pasd', [])
                if not self.interested_properties:
                    LOG.warn(_LW('OVF metadata of interest was not specified '
                                 'in ovf-metadata.json config file. Please '
                                 'set "cim_pasd" to a list of interested '
                                 'CIM_ProcessorAllocationSettingData '
                                 'properties.'))
        else:
            LOG.warn(_LW('OVF properties config file "ovf-metadata.json" was '
                         'not found.'))
Beispiel #50
0
    def process_response(self, resp):
        try:
            request_id = resp.request.context.request_id
        except AttributeError:
            LOG.warn(_LW('Unable to retrieve request id from context'))
        else:
            # For python 3 compatibility need to use bytes type
            prefix = b'req-' if isinstance(request_id, bytes) else 'req-'

            if not request_id.startswith(prefix):
                request_id = prefix + request_id

            resp.headers['x-openstack-request-id'] = request_id

        return resp
Beispiel #51
0
    def fetch_image_into_cache(self, image_id):
        ctx = context.RequestContext(is_admin=True, show_deleted=True)

        try:
            image_meta = registry.get_image_metadata(ctx, image_id)
            if image_meta['status'] != 'active':
                LOG.warn(_LW("Image '%s' is not active. Not caching.") %
                         image_id)
                return False

        except exception.NotFound:
            LOG.warn(_LW("No metadata found for image '%s'") % image_id)
            return False

        location = image_meta['location']
        image_data, image_size = glance_store.get_from_backend(location,
                                                               context=ctx)
        LOG.debug("Caching image '%s'", image_id)
        cache_tee_iter = self.cache.cache_tee_iter(image_id, image_data,
                                                   image_meta['checksum'])
        # Image is tee'd into cache and checksum verified
        # as we iterate
        list(cache_tee_iter)
        return True
Beispiel #52
0
        def rollback(e):
            with self.get_db() as db:
                if os.path.exists(incomplete_path):
                    invalid_path = self.get_image_filepath(image_id, 'invalid')

                    LOG.warn(_LW("Fetch of cache file failed (%(e)s), rolling "
                                 "back by moving '%(incomplete_path)s' to "
                                 "'%(invalid_path)s'") %
                             {'e': e,
                              'incomplete_path': incomplete_path,
                              'invalid_path': invalid_path})
                    os.rename(incomplete_path, invalid_path)

                db.execute("""DELETE FROM cached_images
                           WHERE image_id = ?""", (image_id, ))
                db.commit()
Beispiel #53
0
    def index_shared_images(self, req, id):
        """
        Retrieves images shared with the given member.
        """
        try:
            members = self.db_api.image_member_find(req.context, member=id)
        except exception.NotFound:
            msg = _LW("Member %(id)s not found") % {'id': id}
            LOG.warn(msg)
            msg = _("Membership could not be found.")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        LOG.debug("Returning list of images shared with member %(id)s",
                  {'id': id})
        return dict(shared_images=make_member_list(members,
                                                   image_id='image_id',
                                                   can_share='can_share'))