glance/glance/api/property_protections.py

127 lines
5.0 KiB
Python

# Copyright 2013 Rackspace
#
# 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.
from glance.common import exception
import glance.domain.proxy
class ProtectedImageFactoryProxy(glance.domain.proxy.ImageFactory):
def __init__(self, image_factory, context, property_rules):
self.image_factory = image_factory
self.context = context
self.property_rules = property_rules
kwargs = {'context': self.context,
'property_rules': self.property_rules}
super(ProtectedImageFactoryProxy, self).__init__(
image_factory,
proxy_class=ProtectedImageProxy,
proxy_kwargs=kwargs)
def new_image(self, **kwargs):
extra_props = kwargs.pop('extra_properties', {})
extra_properties = {}
for key in extra_props.keys():
if self.property_rules.check_property_rules(key, 'create',
self.context):
extra_properties[key] = extra_props[key]
else:
raise exception.ReservedProperty(property=key)
return super(ProtectedImageFactoryProxy, self).\
new_image(extra_properties=extra_properties, **kwargs)
class ProtectedImageRepoProxy(glance.domain.proxy.Repo):
def __init__(self, image_repo, context, property_rules):
self.context = context
self.image_repo = image_repo
self.property_rules = property_rules
proxy_kwargs = {'context': self.context}
super(ProtectedImageRepoProxy, self).__init__(
image_repo, item_proxy_class=ProtectedImageProxy,
item_proxy_kwargs=proxy_kwargs)
def get(self, image_id):
return ProtectedImageProxy(self.image_repo.get(image_id),
self.context, self.property_rules)
def list(self, *args, **kwargs):
images = self.image_repo.list(*args, **kwargs)
return [ProtectedImageProxy(image, self.context, self.property_rules)
for image in images]
class ProtectedImageProxy(glance.domain.proxy.Image):
def __init__(self, image, context, property_rules):
self.image = image
self.context = context
self.property_rules = property_rules
self.image.extra_properties = ExtraPropertiesProxy(
self.context,
self.image.extra_properties,
self.property_rules)
super(ProtectedImageProxy, self).__init__(self.image)
class ExtraPropertiesProxy(glance.domain.ExtraProperties):
def __init__(self, context, extra_props, property_rules):
self.context = context
self.property_rules = property_rules
extra_properties = {}
for key in extra_props.keys():
if self.property_rules.check_property_rules(key, 'read',
self.context):
extra_properties[key] = extra_props[key]
super(ExtraPropertiesProxy, self).__init__(extra_properties)
def __getitem__(self, key):
if self.property_rules.check_property_rules(key, 'read', self.context):
return dict.__getitem__(self, key)
else:
raise KeyError
def __setitem__(self, key, value):
# NOTE(isethi): Exceptions are raised only for actions update, delete
# and create, where the user proactively interacts with the properties.
# A user cannot request to read a specific property, hence reads do
# raise an exception
try:
if self.__getitem__(key):
if self.property_rules.check_property_rules(key, 'update',
self.context):
return dict.__setitem__(self, key, value)
else:
raise exception.ReservedProperty(property=key)
except KeyError:
if self.property_rules.check_property_rules(key, 'create',
self.context):
return dict.__setitem__(self, key, value)
else:
raise exception.ReservedProperty(property=key)
def __delitem__(self, key):
if not super(ExtraPropertiesProxy, self).__getitem__(key):
raise KeyError
if self.property_rules.check_property_rules(key, 'delete',
self.context):
return dict.__delitem__(self, key)
else:
raise exception.ReservedProperty(property=key)