예제 #1
0
def import_image(image_repo, image_factory, task_input, task_id, uri):
    original_image = create_image(image_repo, image_factory,
                                  task_input.get('image_properties'), task_id)
    # NOTE: set image status to saving just before setting data
    original_image.status = 'saving'
    image_repo.save(original_image)
    set_image_data(original_image, uri, None)

    # NOTE: Check if the Image is not deleted after setting the data
    # before setting it's status to active. We need to set the status
    # explicitly here using the Image object returned from image_repo .The
    # Image object returned from create_image method does not have appropriate
    # factories wrapped around it.
    image_id = original_image.image_id
    new_image = image_repo.get(image_id)
    if new_image.status in ['saving']:
        new_image.status = 'active'
        new_image.size = original_image.size
        new_image.virtual_size = original_image.virtual_size
        new_image.checksum = original_image.checksum
    else:
        msg = _LE("The Image %(image_id)s object being created by this task "
                  "%(task_id)s, is no longer in valid status for further "
                  "processing." % {"image_id": new_image.image_id,
                                   "task_id": task_id})
        raise exception.Conflict(msg)
    image_repo.save(new_image)

    return image_id
예제 #2
0
def import_image(image_repo, image_factory, task_input, task_id, uri):
    original_image = v2_api.create_image(image_repo, image_factory,
                                         task_input.get('image_properties'),
                                         task_id)
    # NOTE: set image status to saving just before setting data
    original_image.status = 'saving'
    image_repo.save(original_image)
    image_id = original_image.image_id

    # NOTE: Retrieving image from the database because the Image object
    # returned from create_image method does not have appropriate factories
    # wrapped around it.
    new_image = image_repo.get(image_id)
    set_image_data(new_image, uri, task_id)

    try:
        # NOTE: Check if the Image is not deleted after setting the data
        # before saving the active image. Here if image status is
        # saving, then new_image is saved as it contains updated location,
        # size, virtual_size and checksum information and the status of
        # new_image is already set to active in set_image_data() call.
        image = image_repo.get(image_id)
        if image.status == 'saving':
            image_repo.save(new_image)
            return image_id
        else:
            msg = _("The Image %(image_id)s object being created by this task "
                    "%(task_id)s, is no longer in valid status for further "
                    "processing.") % {
                        "image_id": image_id,
                        "task_id": task_id
                    }
            raise exception.Conflict(msg)
    except (exception.Conflict, exception.NotFound,
            exception.NotAuthenticated):
        with excutils.save_and_reraise_exception():
            if new_image.locations:
                for location in new_image.locations:
                    store_utils.delete_image_location_from_backend(
                        new_image.context, image_id, location)
예제 #3
0
def import_image(image_repo, image_factory, task_input, task_id, uri):
    original_image = create_image(image_repo, image_factory,
                                  task_input.get('image_properties'), task_id)
    # NOTE: set image status to saving just before setting data
    original_image.status = 'saving'
    image_repo.save(original_image)
    set_image_data(original_image, uri, None)

    # NOTE: Check if the Image is not deleted after setting the data
    # before setting it's status to active. We need to set the status
    # explicitly here using the Image object returned from image_repo .The
    # Image object returned from create_image method does not have appropriate
    # factories wrapped around it.
    image_id = original_image.image_id
    try:
        new_image = image_repo.get(image_id)
        if new_image.status == 'saving':
            new_image.status = 'active'
            new_image.size = original_image.size
            new_image.virtual_size = original_image.virtual_size
            new_image.checksum = original_image.checksum
        else:
            msg = _("The Image %(image_id)s object being created by this task "
                    "%(task_id)s, is no longer in valid status for further "
                    "processing.") % {
                        "image_id": new_image.image_id,
                        "task_id": task_id
                    }
            raise exception.Conflict(msg)
        image_repo.save(new_image)

        return image_id
    except (exception.Conflict, exception.NotFound):
        with excutils.save_and_reraise_exception():
            if original_image.locations:
                for location in original_image.locations:
                    store_utils.delete_image_location_from_backend(
                        original_image.context, original_image.image_id,
                        location)
예제 #4
0
 def fake_save_conflict(self):
     raise exception.Conflict()
 def fake_save_conflict(self, from_state=None):
     raise exception.Conflict()
예제 #6
0
파일: api.py 프로젝트: wputra/MOS-centos
def _image_update(context,
                  values,
                  image_id,
                  purge_props=False,
                  from_state=None):
    """
    Used internally by image_create and image_update

    :param context: Request context
    :param values: A dict of attributes to set
    :param image_id: If None, create the image, otherwise, find and update it
    """

    #NOTE(jbresnah) values is altered in this so a copy is needed
    values = values.copy()

    session = get_session()
    with session.begin():

        # Remove the properties passed in the values mapping. We
        # handle properties separately from base image attributes,
        # and leaving properties in the values mapping will cause
        # a SQLAlchemy model error because SQLAlchemy expects the
        # properties attribute of an Image model to be a list and
        # not a dict.
        properties = values.pop('properties', {})

        location_data = values.pop('locations', None)

        new_status = values.get('status', None)
        if image_id:
            image_ref = _image_get(context, image_id, session=session)
            current = image_ref.status
            # Perform authorization check
            _check_mutate_authorization(context, image_ref)
        else:
            if values.get('size') is not None:
                values['size'] = int(values['size'])

            if 'min_ram' in values:
                values['min_ram'] = int(values['min_ram'] or 0)

            if 'min_disk' in values:
                values['min_disk'] = int(values['min_disk'] or 0)

            values['is_public'] = bool(values.get('is_public', False))
            values['protected'] = bool(values.get('protected', False))
            image_ref = models.Image()

        # Need to canonicalize ownership
        if 'owner' in values and not values['owner']:
            values['owner'] = None

        if image_id:
            # Don't drop created_at if we're passing it in...
            _drop_protected_attrs(models.Image, values)
            #NOTE(iccha-sethi): updated_at must be explicitly set in case
            #                   only ImageProperty table was modifited
            values['updated_at'] = timeutils.utcnow()

        if image_id:
            query = session.query(models.Image).filter_by(id=image_id)
            if from_state:
                query = query.filter_by(status=from_state)

            if new_status:
                _validate_image(values)

            # Validate fields for Images table. This is similar to what is done
            # for the query result update except that we need to do it prior
            # in this case.
            # TODO(dosaboy): replace this with a dict comprehension once py26
            #                support is deprecated.
            keys = values.keys()
            for k in keys:
                if k not in image_ref.to_dict():
                    del values[k]
            updated = query.update(values, synchronize_session='fetch')

            if not updated:
                msg = (_('cannot transition from %(current)s to '
                         '%(next)s in update (wanted '
                         'from_state=%(from)s)') % {
                             'current': current,
                             'next': new_status,
                             'from': from_state
                         })
                raise exception.Conflict(msg)

            image_ref = _image_get(context, image_id, session=session)
        else:
            image_ref.update(values)
            # Validate the attributes before we go any further. From my
            # investigation, the @validates decorator does not validate
            # on new records, only on existing records, which is, well,
            # idiotic.
            values = _validate_image(image_ref.to_dict())
            _update_values(image_ref, values)

            try:
                image_ref.save(session=session)
            except db_exception.DBDuplicateEntry:
                raise exception.Duplicate("Image ID %s already exists!" %
                                          values['id'])

        _set_properties_for_image(context, image_ref, properties, purge_props,
                                  session)

    if location_data is not None:
        _image_locations_set(image_ref.id, location_data, session)

    return image_get(context, image_ref.id)
예제 #7
0
    def import_image(self, req, image_id, body):
        image_repo = self.gateway.get_repo(req.context)
        task_factory = self.gateway.get_task_factory(req.context)
        executor_factory = self.gateway.get_task_executor_factory(req.context)
        task_repo = self.gateway.get_task_repo(req.context)
        import_method = body.get('method').get('name')
        uri = body.get('method').get('uri')

        try:
            image = image_repo.get(image_id)
            if image.status == 'active':
                msg = _("Image with status active cannot be target for import")
                raise exception.Conflict(msg)
            if image.status != 'queued' and import_method == 'web-download':
                msg = _("Image needs to be in 'queued' state to use "
                        "'web-download' method")
                raise exception.Conflict(msg)
            if (image.status != 'uploading'
                    and import_method == 'glance-direct'):
                msg = _("Image needs to be staged before 'glance-direct' "
                        "method can be used")
                raise exception.Conflict(msg)
            if not getattr(image, 'container_format', None):
                msg = _("'container_format' needs to be set before import")
                raise exception.Conflict(msg)
            if not getattr(image, 'disk_format', None):
                msg = _("'disk_format' needs to be set before import")
                raise exception.Conflict(msg)

            backend = None
            if CONF.enabled_backends:
                backend = req.headers.get('x-image-meta-store',
                                          CONF.glance_store.default_backend)
                try:
                    glance_store.get_store_from_store_identifier(backend)
                except glance_store.UnknownScheme:
                    msg = _("Store for scheme %s not found") % backend
                    LOG.warn(msg)
                    raise exception.Conflict(msg)
        except exception.Conflict as e:
            raise webob.exc.HTTPConflict(explanation=e.msg)
        except exception.NotFound as e:
            raise webob.exc.HTTPNotFound(explanation=e.msg)

        task_input = {
            'image_id': image_id,
            'import_req': body,
            'backend': backend
        }

        if (import_method == 'web-download'
                and not utils.validate_import_uri(uri)):
            LOG.debug("URI for web-download does not pass filtering: %s", uri)
            msg = (_("URI for web-download does not pass filtering: %s") % uri)
            raise webob.exc.HTTPBadRequest(explanation=msg)

        try:
            import_task = task_factory.new_task(task_type='api_image_import',
                                                owner=req.context.owner,
                                                task_input=task_input)
            task_repo.add(import_task)
            task_executor = executor_factory.new_task_executor(req.context)
            pool = common.get_thread_pool("tasks_eventlet_pool")
            pool.spawn_n(import_task.run, task_executor)
        except exception.Forbidden as e:
            LOG.debug("User not permitted to create image import task.")
            raise webob.exc.HTTPForbidden(explanation=e.msg)
        except exception.Conflict as e:
            raise webob.exc.HTTPConflict(explanation=e.msg)
        except exception.InvalidImageStatusTransition as e:
            raise webob.exc.HTTPConflict(explanation=e.msg)
        except ValueError as e:
            LOG.debug("Cannot import data for image %(id)s: %(e)s", {
                'id': image_id,
                'e': encodeutils.exception_to_unicode(e)
            })
            raise webob.exc.HTTPBadRequest(
                explanation=encodeutils.exception_to_unicode(e))

        return image_id