b54d3d17ef
Add in missing log hints for warnings TrivialFix Change-Id: I70888f9e59744acace08d4ec7afd3eb297d27b95
199 lines
7.6 KiB
Python
199 lines
7.6 KiB
Python
# 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__)
|
|
|
|
|
|
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)
|
|
|
|
|
|
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})
|
|
|
|
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)
|
|
|
|
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
|
|
|
|
|
|
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))
|
|
|
|
def get(self, *args, **kwargs):
|
|
return self.helper.proxy(self.base.get(*args, **kwargs))
|
|
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
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
|
|
|
|
|
|
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})
|
|
|
|
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)
|