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"))
Exemple #3
0
    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)
Exemple #4
0
    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()
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
    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
Exemple #10
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)
Exemple #11
0
    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
Exemple #12
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)
Exemple #13
0
    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)
Exemple #15
0
    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
Exemple #16
0
    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)
Exemple #17
0
 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]
Exemple #18
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)
Exemple #20
0
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
Exemple #21
0
    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)
Exemple #22
0
    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()
Exemple #23
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 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())
Exemple #24
0
    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()
Exemple #25
0
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)
Exemple #27
0
 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)
Exemple #28
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()
        :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()
Exemple #30
0
    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")