def _retry_request(self, session, method, location): loc = location.store_location # NOTE(arnaud): use a decorator when the config is not tied to self for i in range(self.api_retry_count + 1): cookie = self._build_vim_cookie_header() headers = {'Cookie': cookie} conn = session.request(method, loc.https_url, headers=headers, stream=True) resp = conn.raw if resp.status >= 400: if resp.status == requests.codes.unauthorized: self.reset_session() continue if resp.status == requests.codes.not_found: reason = _('VMware datastore could not find image at URI.') LOG.info(reason) raise exceptions.NotFound(message=reason) msg = ('HTTP request returned a %(status)s status code.' % { 'status': resp.status }) LOG.debug(msg) raise exceptions.BadStoreUri(msg) break return conn, resp
def delete(uri, backend, context=None): """Removes chunks of data from backend specified by uri.""" if backend: loc = location.get_location_from_uri_and_backend(uri, backend, conf=CONF) store = get_store_from_store_identifier(backend) return store.delete(loc, context=context) LOG.warning('Backend is not set to image, searching all backends based on ' 'location URI.') backends = CONF.enabled_backends for backend in backends: try: if not uri.startswith(backends[backend]): continue loc = location.get_location_from_uri_and_backend(uri, backend, conf=CONF) store = get_store_from_store_identifier(backend) return store.delete(loc, context=context) except (exceptions.NotFound, exceptions.UnknownScheme): continue raise exceptions.NotFound(_("Image not found in any configured backend"))
def delete(self, location, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file to delete :location `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises NotFound if image does not exist :raises Forbidden if cannot delete because of permissions """ loc = location.store_location self._check_context(context) try: volume = get_cinderclient(self.conf, context).volumes.get(loc.volume_id) volume.delete() except cinder_exception.NotFound: raise exceptions.NotFound(image=loc.volume_id) except cinder_exception.ClientException as e: msg = (_('Failed to delete volume %(volume_id)s: %(error)s') % { 'volume_id': loc.volume_id, 'error': e }) raise exceptions.BackendException(msg)
def get_size(self, location, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file, and returns the size :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises: `glance_store.exceptions.NotFound` if image does not exist """ loc = location.store_location # if there is a pool specific in the location, use it; otherwise # we fall back to the default pool specified in the config target_pool = loc.pool or self.pool with self.get_connection(conffile=self.conf_file, rados_id=self.user) as conn: with conn.open_ioctx(target_pool) as ioctx: try: with rbd.Image(ioctx, loc.image, snapshot=loc.snapshot) as image: img_info = image.stat() return img_info['size'] except rbd.ImageNotFound: msg = _('RBD image %s does not exist') % loc.get_uri() LOG.debug(msg) raise exceptions.NotFound(msg)
def delete(self, location, context=None): """Takes a `glance_store.location.Location` object that indicates where to find the image file to delete :location `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises NotFound if image does not exist """ file_path = '[%s] %s' % ( location.store_location.datastore_name, location.store_location.path[len(DS_URL_PREFIX):]) dc_obj = self._get_datacenter(location.store_location.datacenter_path) delete_task = self.session.invoke_api( self.session.vim, 'DeleteDatastoreFile_Task', self.session.vim.service_content.fileManager, name=file_path, datacenter=dc_obj.ref) try: self.session.wait_for_task(delete_task) except vexc.FileNotFoundException: msg = _('Image file %s not found') % file_path LOG.warn(msg) raise exceptions.NotFound(message=msg) except Exception: with excutils.save_and_reraise_exception(): LOG.exception( _LE('Failed to delete image %(image)s ' 'content.') % {'image': location.image_id})
def test_remove_location_for_store_pop_failures(self, mock_log): class TestList(list): def pop(self): pass self.image.locations = TestList([{'metadata': {'store': 'foo'}}]) with mock.patch.object(self.image.locations, 'pop', new_callable=mock.PropertyMock) as mock_pop: mock_pop.side_effect = store_exceptions.NotFound(image='image') self.actions.remove_location_for_store('foo') mock_log.warning.assert_called_once_with( _('Error deleting from store foo when reverting.')) mock_log.warning.reset_mock() mock_pop.side_effect = store_exceptions.Forbidden() self.actions.remove_location_for_store('foo') mock_log.warning.assert_called_once_with( _('Error deleting from store foo when reverting.')) mock_log.warning.reset_mock() mock_pop.side_effect = Exception self.actions.remove_location_for_store('foo') mock_log.warning.assert_called_once_with( _('Unexpected exception when deleting from store foo.')) mock_log.warning.reset_mock()
def _check_store_uri(conn, loc): # TODO(sigmavirus24): Make this a staticmethod # Check for bad status codes if conn.status_code >= 400: if conn.status_code == requests.codes.not_found: reason = _("HTTP datastore could not find image at URI.") LOG.debug(reason) raise exceptions.NotFound(message=reason) reason = (_("HTTP URL %(url)s returned a " "%(status)s status code. \nThe response body:\n" "%(body)s") % { 'url': loc.path, 'status': conn.status_code, 'body': conn.text }) LOG.debug(reason) raise exceptions.BadStoreUri(message=reason) if conn.is_redirect and conn.status_code not in (301, 302): reason = (_("The HTTP URL %(url)s attempted to redirect " "with an invalid %(status)s status code.") % { 'url': loc.path, 'status': conn.status_code }) LOG.info(reason) raise exceptions.BadStoreUri(message=reason)
def delete(self, location, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file to delete. :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises: NotFound if image does not exist; InUseByStore if image is in use or snapshot unprotect failed """ loc = location.store_location s3_client, bucket, key = self._operation_set(loc) if not self._object_exists(s3_client, bucket, key): LOG.warning("Could not find key %(key)s in bucket %(bucket)s", { 'key': key, 'bucket': bucket }) raise exceptions.NotFound(image=key) LOG.debug( "Deleting image object from S3 using s3_host=%(s3_host)s, " "accesskey=%(accesskey)s, bucket=%(bucket)s, key=%(key)s)", { 's3_host': loc.s3serviceurl, 'accesskey': loc.accesskey, 'bucket': bucket, 'key': key }) return s3_client.delete_object(Bucket=bucket, Key=key)
def get_size(self, location, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file and returns the image size :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises: `glance_store.exceptions.NotFound` if image does not exist :rtype: int """ loc = location.store_location try: self._check_context(context) volume = self.get_cinderclient(context).volumes.get(loc.volume_id) return int( volume.metadata.get('image_size', volume.size * units.Gi)) except cinder_exception.NotFound: raise exceptions.NotFound(image=loc.volume_id) except Exception: LOG.exception( _LE("Failed to get image size due to " "internal error.")) return 0
def get(self, location, offset=0, chunk_size=None, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file, and returns a tuple of generator (for reading the image file) and image_size :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :param offset: offset to start reading :param chunk_size: size to read, or None to get all the image :param context: Request context :raises: `glance_store.exceptions.NotFound` if image does not exist """ loc = location.store_location self._check_context(context) try: client = self.get_cinderclient(context) volume = client.volumes.get(loc.volume_id) size = int(volume.metadata.get('image_size', volume.size * units.Gi)) iterator = self._cinder_volume_data_iterator( client, volume, size, offset=offset, chunk_size=self.READ_CHUNKSIZE, partial_length=chunk_size) return (iterator, chunk_size or size) except cinder_exception.NotFound: reason = _("Failed to get image size due to " "volume can not be found: %s") % loc.volume_id LOG.error(reason) raise exceptions.NotFound(reason) except cinder_exception.ClientException as e: msg = (_('Failed to get image volume %(volume_id)s: %(error)s') % {'volume_id': loc.volume_id, 'error': e}) LOG.error(msg) raise exceptions.BackendException(msg)
def get_size(self, location, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file and returns the image size :param location `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises `glance_store.exceptions.NotFound` if image does not exist :rtype int """ loc = location.store_location try: self._check_context(context) volume = get_cinderclient(self.conf, context).volumes.get(loc.volume_id) # GB unit convert to byte return volume.size * (1024**3) except cinder_exception.NotFound as e: reason = _("Failed to get image size due to " "volume can not be found: %s") % self.volume_id LOG.error(reason) raise exceptions.NotFound(reason) except Exception as e: LOG.exception( _("Failed to get image size due to " "internal error: %s") % e) return 0
def _delete_image(self, target_pool, image_name, snapshot_name=None, context=None): """ Delete RBD image and snapshot. :param image_name: Image's name :param snapshot_name: Image snapshot's name :raises: NotFound if image does not exist; InUseByStore if image is in use or snapshot unprotect failed """ with self.get_connection(conffile=self.conf_file, rados_id=self.user) as conn: with conn.open_ioctx(target_pool) as ioctx: try: # First remove snapshot. if snapshot_name is not None: with rbd.Image(ioctx, image_name) as image: try: self._unprotect_snapshot(image, snapshot_name) image.remove_snap(snapshot_name) except rbd.ImageNotFound as exc: msg = (_("Snap Operating Exception " "%(snap_exc)s " "Snapshot does not exist.") % { 'snap_exc': exc }) LOG.debug(msg) except rbd.ImageBusy as exc: log_msg = (_LE("Snap Operating Exception " "%(snap_exc)s " "Snapshot is in use.") % { 'snap_exc': exc }) LOG.error(log_msg) raise exceptions.InUseByStore() # Then delete image. rbd.RBD().remove(ioctx, image_name) except rbd.ImageHasSnapshots: log_msg = (_LE("Remove image %(img_name)s failed. " "It has snapshot(s) left.") % { 'img_name': image_name }) LOG.error(log_msg) raise exceptions.HasSnapshot() except rbd.ImageBusy: log_msg = (_LE("Remove image %(img_name)s failed. " "It is in use.") % { 'img_name': image_name }) LOG.error(log_msg) raise exceptions.InUseByStore() except rbd.ImageNotFound: msg = _("RBD image %s does not exist") % image_name raise exceptions.NotFound(message=msg)
def _resolve_location(location): filepath = location.store_location.path if not os.path.exists(filepath): raise exceptions.NotFound(image=filepath) filesize = os.path.getsize(filepath) return filepath, filesize
def _query(self, location, method, depth=0): if depth > MAX_REDIRECTS: msg = ("The HTTP URL exceeded %(max_redirects)s maximum " "redirects.", { 'max_redirects': MAX_REDIRECTS }) LOG.debug(msg) raise exceptions.MaxRedirectsExceeded(redirects=MAX_REDIRECTS) loc = location.store_location # NOTE(arnaud): use a decorator when the config is not tied to self for i in range(self.api_retry_count + 1): cookie = self._build_vim_cookie_header( self._session.vim.client.options.transport.cookiejar) headers = {'Cookie': cookie} try: conn = self._get_http_conn(method, loc, headers) resp = conn.getresponse() except Exception: with excutils.save_and_reraise_exception(): LOG.exception( _LE('Failed to access image %(image)s ' 'content.') % {'image': location.image_id}) if resp.status >= 400: if resp.status == httplib.UNAUTHORIZED: self._create_session() continue if resp.status == httplib.NOT_FOUND: reason = _('VMware datastore could not find image at URI.') LOG.info(reason) raise exceptions.NotFound(message=reason) msg = ('HTTP request returned a %(status)s status code.' % { 'status': resp.status }) LOG.debug(msg) raise exceptions.BadStoreUri(msg) break location_header = resp.getheader('location') if location_header: if resp.status not in (301, 302): reason = (_("The HTTP URL %(path)s attempted to redirect " "with an invalid %(status)s status code.") % { 'path': loc.path, 'status': resp.status }) LOG.info(reason) raise exceptions.BadStoreUri(message=reason) location_class = glance_store.location.Location new_loc = location_class(location.store_name, location.store_location.__class__, uri=location_header, image_id=location.image_id, store_specs=location.store_specs) return self._query(new_loc, method, depth + 1) content_length = int(resp.getheader('content-length', 0)) return (conn, resp, content_length)
def delete(self, location, connection=None, context=None): location = location.store_location if not connection: connection = self.get_connection(location, context=context) try: # We request the manifest for the object. If one exists, # that means the object was uploaded in chunks/segments, # and we need to delete all the chunks as well as the # manifest. dlo_manifest = None slo_manifest = None try: headers = connection.head_object(location.container, location.obj) dlo_manifest = headers.get('x-object-manifest') slo_manifest = headers.get('x-static-large-object') except swiftclient.ClientException as e: if e.http_status != http_client.NOT_FOUND: raise if _is_slo(slo_manifest): # Delete the manifest as well as the segments query_string = 'multipart-manifest=delete' connection.delete_object(location.container, location.obj, query_string=query_string) return if dlo_manifest: # Delete all the chunks before the object manifest itself obj_container, obj_prefix = dlo_manifest.split('/', 1) segments = connection.get_container(obj_container, prefix=obj_prefix)[1] for segment in segments: # TODO(jaypipes): This would be an easy area to parallelize # since we're simply sending off parallelizable requests # to Swift to delete stuff. It's not like we're going to # be hogging up network or file I/O here... try: connection.delete_object(obj_container, segment['name']) except swiftclient.ClientException as e: msg = _('Unable to delete segment %(segment_name)s') msg = msg % {'segment_name': segment['name']} LOG.exception(msg) # Delete object (or, in segmented case, the manifest) connection.delete_object(location.container, location.obj) except swiftclient.ClientException as e: if e.http_status == http_client.NOT_FOUND: msg = _("Swift could not find image at URI.") raise exceptions.NotFound(message=msg) else: raise
def _query(self, location, verb, depth=0): if depth > MAX_REDIRECTS: reason = (_("The HTTP URL exceeded %s maximum " "redirects.") % MAX_REDIRECTS) LOG.debug(reason) raise exceptions.MaxRedirectsExceeded(message=reason) loc = location.store_location conn_class = self._get_conn_class(loc) conn = conn_class(loc.netloc) hearders = {} if loc.token: hearders.setdefault('x-auth-token', loc.token) verb = 'GET' conn.request(verb, loc.path, "", hearders) resp = conn.getresponse() try: size = jsonutils.loads(resp.read())['size'] except Exception: size = 0 raise exception.BadStoreUri(loc.path, reason) return (conn, resp, size) conn.request(verb, loc.path, "", {}) resp = conn.getresponse() # Check for bad status codes if resp.status >= 400: if resp.status == httplib.NOT_FOUND: reason = _("HTTP datastore could not find image at URI.") LOG.debug(reason) raise exceptions.NotFound(message=reason) reason = (_("HTTP URL %(url)s returned a " "%(status)s status code.") % dict(url=loc.path, status=resp.status)) LOG.debug(reason) raise exceptions.BadStoreUri(message=reason) location_header = resp.getheader("location") if location_header: if resp.status not in (301, 302): reason = (_("The HTTP URL %(url)s attempted to redirect " "with an invalid %(status)s status code.") % dict(url=loc.path, status=resp.status)) LOG.info(reason) raise exceptions.BadStoreUri(message=reason) location_class = glance_store.location.Location new_loc = location_class(location.store_name, location.store_location.__class__, uri=location_header, image_id=location.image_id, store_specs=location.store_specs) return self._query(new_loc, verb, depth + 1) content_length = int(resp.getheader('content-length', 0)) return (conn, resp, content_length)
def _name_to_ai(self, name): tenant = self._get_tenant() try: # api.tenants.get needs a non '/'-prefixed tenant id self.api.tenants.get(tenant.strip('/')) except dfs_sdk.exceptions.ApiNotFoundError: self._create_tenant() ais = self.api.app_instances.list( filter='match(name,.*{}.*)'.format(name), tenant=tenant) if not ais: raise exceptions.NotFound(image=name) return ais[0]
def _get_file(self, location): store_location = location if isinstance(location, glance_store.location.Location): store_location = location.store_location try: parsed = urllib.parse.urlparse(store_location.get_uri()) return self.fs.get(parsed.netloc) except gridfs.errors.NoFile: msg = _("Could not find %s image in GridFS") % \ store_location.get_uri() LOG.debug(msg) raise exceptions.NotFound(msg)
def test_delete_with_backends_delete_fails(self): self.config(enabled_backends='file:foo') task = import_flow._DeleteFromFS(TASK_ID1, TASK_TYPE) with mock.patch.object(import_flow.store_api, 'delete') as mock_del: mock_del.side_effect = store_exceptions.NotFound(image=IMAGE_ID1, message='Testing') # If we didn't swallow this we would explode here task.execute(mock.sentinel.path) mock_del.assert_called_once_with(mock.sentinel.path, 'os_glance_staging_store') # Raise something unexpected and make sure it bubbles up mock_del.side_effect = RuntimeError self.assertRaises(RuntimeError, task.execute, mock.sentinel.path)
def get_bucket(conn, bucket_id): """ Get a bucket from an s3 connection :param conn: The ``boto.s3.connection.S3Connection`` :param bucket_id: ID of the bucket to fetch :raises ``glance_store.exceptions.NotFound`` if bucket is not found. """ bucket = conn.get_bucket(bucket_id) if not bucket: msg = _("Could not find bucket with ID %s") % bucket_id LOG.debug(msg) raise exceptions.NotFound(msg) return bucket
def _query(self, location, method, headers, depth=0): if depth > MAX_REDIRECTS: msg = ("The HTTP URL exceeded %(max_redirects)s maximum " "redirects." % { 'max_redirects': MAX_REDIRECTS }) LOG.debug(msg) raise exceptions.MaxRedirectsExceeded(redirects=MAX_REDIRECTS) loc = location.store_location try: conn = self._get_http_conn(method, loc, headers) resp = conn.getresponse() except Exception: with excutils.save_and_reraise_exception(): LOG.exception( _('Failed to access image %(image)s content.') % {'image': location.image_id}) if resp.status >= 400: if resp.status == httplib.NOT_FOUND: reason = _('VMware datastore could not find image at URI.') LOG.info(reason) raise exceptions.NotFound(message=reason) msg = ('HTTP request returned a %(status)s status code.' % { 'status': resp.status }) LOG.debug(msg) raise exceptions.BadStoreUri(msg) location_header = resp.getheader('location') if location_header: if resp.status not in (301, 302): reason = (_("The HTTP URL %(path)s attempted to redirect " "with an invalid %(status)s status code.") % { 'path': loc.path, 'status': resp.status }) LOG.info(reason) raise exceptions.BadStoreUri(message=reason) location_class = glance_store.location.Location new_loc = location_class(location.store_name, location.store_location.__class__, uri=location_header, image_id=location.image_id, store_specs=location.store_specs) return self._query(new_loc, method, depth + 1) content_length = int(resp.getheader('content-length', 0)) return (conn, resp, content_length)
def delete(self, location, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file to delete :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises: NotFound if image does not exist """ loc = location.store_location image = SheepdogImage(loc.addr, loc.port, loc.image, self.WRITE_CHUNKSIZE) if not image.exist(): raise exceptions.NotFound( _("Sheepdog image %s does not exist") % loc.image) image.delete()
def get(self, location, offset=0, chunk_size=None, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file, and returns a generator for reading the image file :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises: `glance_store.exceptions.NotFound` if image does not exist """ loc = location.store_location image = SheepdogImage(loc.addr, loc.port, loc.image, self.READ_CHUNKSIZE) if not image.exist(): raise exceptions.NotFound( _("Sheepdog image %s does not exist") % image.name) return (ImageIterator(image), image.get_size())
def get_size(self, location, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file and returns the image size :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises: `glance_store.exceptions.NotFound` if image does not exist :rtype: int """ loc = location.store_location image = SheepdogImage(loc.addr, loc.port, loc.image, self.READ_CHUNKSIZE) if not image.exist(): raise exceptions.NotFound( _("Sheepdog image %s does not exist") % image.name) return image.get_size()
def get_key(bucket, obj): """ Get a key from a bucket :param bucket: The ``boto.s3.Bucket`` :param obj: Object to get the key for :raises ``glance_store.exceptions.NotFound`` if key is not found. """ key = bucket.get_key(obj) if not key or not key.exists(): msg = (_("Could not find key %(obj)s in bucket %(bucket)s") % { 'obj': obj, 'bucket': bucket }) LOG.debug(msg) raise exceptions.NotFound(message=msg) return key
def __iter__(self): try: with rados.Rados(conffile=self.conf_file, rados_id=self.user) as conn: with conn.open_ioctx(self.pool) as ioctx: with rbd.Image(ioctx, self.name) as image: img_info = image.stat() size = img_info['size'] bytes_left = size while bytes_left > 0: length = min(self.chunk_size, bytes_left) data = image.read(size - bytes_left, length) bytes_left -= len(data) yield data raise StopIteration() except rbd.ImageNotFound: raise exceptions.NotFound( _('RBD image %s does not exist') % self.name)
def __iter__(self): try: with self.store.get_connection(conffile=self.conf_file, rados_id=self.user) as conn: with conn.open_ioctx(self.pool) as ioctx: with rbd.Image(ioctx, self.name, snapshot=self.snapshot) as image: size = image.size() bytes_left = size while bytes_left > 0: length = min(self.chunk_size, bytes_left) data = image.read(size - bytes_left, length) bytes_left -= len(data) yield data raise StopIteration() except rbd.ImageNotFound: raise exceptions.NotFound( _('RBD image %s does not exist') % self.name)
def get(self, location, offset=0, chunk_size=None, context=None): """ Takes a `glance_store.location.Location` object that indicates where to find the image file, and returns a tuple of generator (for reading the image file) and image_size :param location: `glance_store.location.Location` object, supplied from glance_store.location.get_location_from_uri() :raises: `glance_store.exceptions.NotFound` if image does not exist """ loc = location.store_location s3_client, bucket, key = self._operation_set(loc) if not self._object_exists(s3_client, bucket, key): LOG.warning("Could not find key %(key)s in " "bucket %(bucket)s", { 'key': key, 'bucket': bucket }) raise exceptions.NotFound(image=key) key = s3_client.get_object(Bucket=bucket, Key=key) LOG.debug( "Retrieved image object from S3 using s3_host=%(s3_host)s, " "access_key=%(accesskey)s, bucket=%(bucket)s, " "key=%(key)s)", { 's3_host': loc.s3serviceurl, 'accesskey': loc.accesskey, 'bucket': bucket, 'key': key }) cs = self.READ_CHUNKSIZE class ResponseIndexable(glance_store.Indexable): def another(self): try: return next(self.wrapped) except StopIteration: return b'' return (ResponseIndexable(utils.chunkiter(key['Body'], cs), key['ContentLength']), key['ContentLength'])
def _delete_image(self, target_pool, image_name, snapshot_name=None, context=None): """ Delete RBD image and snapshot. :param image_name Image's name :param snapshot_name Image snapshot's name :raises NotFound if image does not exist; InUseByStore if image is in use or snapshot unprotect failed """ with self.get_connection(conffile=self.conf_file, rados_id=self.user) as conn: with conn.open_ioctx(target_pool) as ioctx: try: # First remove snapshot. if snapshot_name is not None: with rbd.Image(ioctx, image_name) as image: try: image.unprotect_snap(snapshot_name) except rbd.ImageBusy: log_msg = _("snapshot %(image)s@%(snap)s " "could not be unprotected because " "it is in use") LOG.debug(log_msg % { 'image': image_name, 'snap': snapshot_name }) raise exceptions.InUseByStore() image.remove_snap(snapshot_name) # Then delete image. rbd.RBD().remove(ioctx, image_name) except rbd.ImageNotFound: msg = _("RBD image %s does not exist") % image_name raise exceptions.NotFound(message=msg) except rbd.ImageBusy: log_msg = _("image %s could not be removed " "because it is in use") LOG.debug(log_msg % image_name) raise exceptions.InUseByStore()
def delete_image_file(self, full_data_path): """ Deletes image file or returns Exception """ try: LOG.debug("opening file %s" % full_data_path) file_object = self.irods_conn_object.data_objects.get( full_data_path) except: LOG.error("file not found") raise exceptions.NotFound(msg) try: file_object.unlink() self.irods_conn_object.cleanup() except: LOG.error("cannot delete file") raise exceptions.Forbidden(store_name="irods", reason=reason) LOG.debug("delete success")