Source code for glance.glare.location

# Copyright (c) 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import sys
import uuid

from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import encodeutils

from glance.common.glare import definitions
from glance.common import utils
from glance.glare.domain import proxy
from glance.i18n import _LE, _LW

CONF = cfg.CONF
LOG = logging.getLogger(__name__)


[docs]class ArtifactFactoryProxy(proxy.ArtifactFactory): def __init__(self, factory, context, store_api, store_utils): self.context = context self.store_api = store_api self.store_utils = store_utils proxy_kwargs = {'store_api': store_api, 'store_utils': store_utils, 'context': self.context} super(ArtifactFactoryProxy, self).__init__( factory, artifact_proxy_class=ArtifactProxy, artifact_proxy_kwargs=proxy_kwargs)
[docs]class ArtifactProxy(proxy.Artifact): def __init__(self, artifact, context, store_api, store_utils): self.artifact = artifact self.context = context self.store_api = store_api self.store_utils = store_utils super(ArtifactProxy, self).__init__(artifact, proxy_class=ArtifactBlobProxy, proxy_kwargs={"context": self.context, "store_api": self.store_api})
[docs] def set_type_specific_property(self, prop_name, value): if prop_name not in self.artifact.metadata.attributes.blobs: super(ArtifactProxy, self).set_type_specific_property(prop_name, value) return item_key = "%s.%s" % (self.artifact.id, prop_name) # XXX FIXME have to add support for BinaryObjectList properties blob = definitions.Blob(item_key=item_key) blob_proxy = self.helper.proxy(blob) if value is None: for location in blob_proxy.locations: blob_proxy.delete_from_store(location) else: data = value[0] size = value[1] blob_proxy.upload_to_store(data, size) setattr(self.artifact, prop_name, blob)
[docs] def get_type_specific_property(self, prop_name): base = super(ArtifactProxy, self).get_type_specific_property(prop_name) if base is None: return None if prop_name in self.artifact.metadata.attributes.blobs: if isinstance(self.artifact.metadata.attributes.blobs[prop_name], list): return ArtifactBlobProxyList(self.artifact.id, prop_name, base, self.context, self.store_api) else: return self.helper.proxy(base) else: return base
[docs]class ArtifactRepoProxy(proxy.ArtifactRepo): def __init__(self, artifact_repo, context, store_api, store_utils): self.context = context self.store_api = store_api proxy_kwargs = {'context': context, 'store_api': store_api, 'store_utils': store_utils} super(ArtifactRepoProxy, self).__init__( artifact_repo, proxy_helper=proxy.ArtifactHelper(ArtifactProxy, proxy_kwargs))
[docs] def get(self, *args, **kwargs): return self.helper.proxy(self.base.get(*args, **kwargs))
[docs]class ArtifactBlobProxy(proxy.ArtifactBlob): def __init__(self, blob, context, store_api): self.context = context self.store_api = store_api self.blob = blob super(ArtifactBlobProxy, self).__init__(blob)
[docs] def delete_from_store(self, location): try: ret = self.store_api.delete_from_backend(location['value'], context=self.context) location['status'] = 'deleted' return ret except self.store_api.NotFound: msg = _LW('Failed to delete blob' ' %s in store from URI') % self.blob.id LOG.warn(msg) except self.store_api.StoreDeleteNotSupported as e: LOG.warn(encodeutils.exception_to_unicode(e)) except self.store_api.UnsupportedBackend: exc_type = sys.exc_info()[0].__name__ msg = (_LE('Failed to delete blob' ' %(blob_id)s from store: %(exc)s') % dict(blob_id=self.blob.id, exc=exc_type)) LOG.error(msg)
[docs] def upload_to_store(self, data, size): if size is None: # NOTE(ativelkov): None is "unknown size" size = 0 location, ret_size, checksum, loc_meta = self.store_api.add_to_backend( CONF, self.blob.item_key, utils.LimitingReader(utils.CooperativeReader(data), CONF.image_size_cap), size, context=self.context) self.blob.size = ret_size self.blob.locations = [{'status': 'active', 'value': location}] self.blob.checksum = checksum
@property def data_stream(self): if len(self.locations) > 0: err = None try: for location in self.locations: data, size = self.store_api.get_from_backend( location['value'], context=self.context) return data except Exception as e: LOG.warn(_LW('Get blob %(name)s data failed: ' '%(err)s.') % {'name': self.blob.item_key, 'err': encodeutils.exception_to_unicode(e)}) err = e # tried all locations LOG.error(_LE('Glance tried all active locations to get data ' 'for blob %s ' 'but all have failed.') % self.blob.item_key) raise err
[docs]class ArtifactBlobProxyList(proxy.List): def __init__(self, artifact_id, prop_name, bloblist, context, store_api): self.artifact_id = artifact_id self.prop_name = prop_name self.context = context self.store_api = store_api super(ArtifactBlobProxyList, self).__init__(bloblist, item_proxy_class=ArtifactBlobProxy, item_proxy_kwargs={'context': context, 'store_api': store_api})
[docs] def insert(self, index, value): data = value[0] size = value[1] item_key = "%s.%s.%s" % (self.artifact_id, self.prop_name, uuid.uuid4()) blob = definitions.Blob(item_key=item_key) blob_proxy = self.helper.proxy(blob) blob_proxy.upload_to_store(data, size) super(ArtifactBlobProxyList, self).insert(index, blob_proxy)
def __setitem__(self, index, value): blob = self[index] data = value[0] size = value[1] blob.upload_to_store(data, size)