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
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)
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)
def fake_save_conflict(self): raise exception.Conflict()
def fake_save_conflict(self, from_state=None): raise exception.Conflict()
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)
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