c27c25f779
Import i18n functions from module directly and do not use global module variables like _ = i18n._. It makes code shorter and cleaner. It also to detect cases when these functions are not used in module. Change-Id: Iaa593ac1f2dd15cbcad049bef6ba68f1cfa610da
905 lines
30 KiB
Python
905 lines
30 KiB
Python
# Copyright 2012 OpenStack Foundation
|
|
# Copyright 2013 IBM Corp.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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 copy
|
|
|
|
from glance.common import exception
|
|
import glance.domain.proxy
|
|
from glance.i18n import _
|
|
|
|
|
|
def is_image_mutable(context, image):
|
|
"""Return True if the image is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if image.owner is None or context.owner is None:
|
|
return False
|
|
|
|
return image.owner == context.owner
|
|
|
|
|
|
def proxy_image(context, image):
|
|
if is_image_mutable(context, image):
|
|
return ImageProxy(image, context)
|
|
else:
|
|
return ImmutableImageProxy(image, context)
|
|
|
|
|
|
def is_member_mutable(context, member):
|
|
"""Return True if the image is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
return member.member_id == context.owner
|
|
|
|
|
|
def proxy_member(context, member):
|
|
if is_member_mutable(context, member):
|
|
return member
|
|
else:
|
|
return ImmutableMemberProxy(member)
|
|
|
|
|
|
def is_task_mutable(context, task):
|
|
"""Return True if the task is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
return task.owner == context.owner
|
|
|
|
|
|
def is_task_stub_mutable(context, task_stub):
|
|
"""Return True if the task stub is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
return task_stub.owner == context.owner
|
|
|
|
|
|
def proxy_task(context, task):
|
|
if is_task_mutable(context, task):
|
|
return task
|
|
else:
|
|
return ImmutableTaskProxy(task)
|
|
|
|
|
|
def proxy_task_stub(context, task_stub):
|
|
if is_task_stub_mutable(context, task_stub):
|
|
return task_stub
|
|
else:
|
|
return ImmutableTaskStubProxy(task_stub)
|
|
|
|
|
|
class ImageRepoProxy(glance.domain.proxy.Repo):
|
|
|
|
def __init__(self, image_repo, context):
|
|
self.context = context
|
|
self.image_repo = image_repo
|
|
proxy_kwargs = {'context': self.context}
|
|
super(ImageRepoProxy, self).__init__(image_repo,
|
|
item_proxy_class=ImageProxy,
|
|
item_proxy_kwargs=proxy_kwargs)
|
|
|
|
def get(self, image_id):
|
|
image = self.image_repo.get(image_id)
|
|
return proxy_image(self.context, image)
|
|
|
|
def list(self, *args, **kwargs):
|
|
images = self.image_repo.list(*args, **kwargs)
|
|
return [proxy_image(self.context, i) for i in images]
|
|
|
|
|
|
class ImageMemberRepoProxy(glance.domain.proxy.Repo):
|
|
|
|
def __init__(self, member_repo, image, context):
|
|
self.member_repo = member_repo
|
|
self.image = image
|
|
self.context = context
|
|
super(ImageMemberRepoProxy, self).__init__(member_repo)
|
|
|
|
def get(self, member_id):
|
|
if (self.context.is_admin or
|
|
self.context.owner in (self.image.owner, member_id)):
|
|
member = self.member_repo.get(member_id)
|
|
return proxy_member(self.context, member)
|
|
else:
|
|
message = _("You cannot get image member for %s")
|
|
raise exception.Forbidden(message % member_id)
|
|
|
|
def list(self, *args, **kwargs):
|
|
members = self.member_repo.list(*args, **kwargs)
|
|
if (self.context.is_admin or
|
|
self.context.owner == self.image.owner):
|
|
return [proxy_member(self.context, m) for m in members]
|
|
for member in members:
|
|
if member.member_id == self.context.owner:
|
|
return [proxy_member(self.context, member)]
|
|
message = _("You cannot get image member for %s")
|
|
raise exception.Forbidden(message % self.image.image_id)
|
|
|
|
def remove(self, image_member):
|
|
if (self.image.owner == self.context.owner or
|
|
self.context.is_admin):
|
|
self.member_repo.remove(image_member)
|
|
else:
|
|
message = _("You cannot delete image member for %s")
|
|
raise exception.Forbidden(message
|
|
% self.image.image_id)
|
|
|
|
def add(self, image_member):
|
|
if (self.image.owner == self.context.owner or
|
|
self.context.is_admin):
|
|
self.member_repo.add(image_member)
|
|
else:
|
|
message = _("You cannot add image member for %s")
|
|
raise exception.Forbidden(message
|
|
% self.image.image_id)
|
|
|
|
def save(self, image_member, from_state=None):
|
|
if (self.context.is_admin or
|
|
self.context.owner == image_member.member_id):
|
|
self.member_repo.save(image_member, from_state=from_state)
|
|
else:
|
|
message = _("You cannot update image member %s")
|
|
raise exception.Forbidden(message % image_member.member_id)
|
|
|
|
|
|
class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
|
|
|
|
def __init__(self, image_factory, context):
|
|
self.image_factory = image_factory
|
|
self.context = context
|
|
kwargs = {'context': self.context}
|
|
super(ImageFactoryProxy, self).__init__(image_factory,
|
|
proxy_class=ImageProxy,
|
|
proxy_kwargs=kwargs)
|
|
|
|
def new_image(self, **kwargs):
|
|
owner = kwargs.pop('owner', self.context.owner)
|
|
|
|
if not self.context.is_admin:
|
|
if owner is None or owner != self.context.owner:
|
|
message = _("You are not permitted to create images "
|
|
"owned by '%s'.")
|
|
raise exception.Forbidden(message % owner)
|
|
|
|
return super(ImageFactoryProxy, self).new_image(owner=owner, **kwargs)
|
|
|
|
|
|
class ImageMemberFactoryProxy(object):
|
|
|
|
def __init__(self, image_member_factory, context):
|
|
self.image_member_factory = image_member_factory
|
|
self.context = context
|
|
|
|
def new_image_member(self, image, member_id):
|
|
owner = image.owner
|
|
|
|
if not self.context.is_admin:
|
|
if owner is None or owner != self.context.owner:
|
|
message = _("You are not permitted to create image members "
|
|
"for the image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
if image.visibility == 'public':
|
|
message = _("Public images do not have members.")
|
|
raise exception.Forbidden(message)
|
|
|
|
return self.image_member_factory.new_image_member(image, member_id)
|
|
|
|
|
|
def _immutable_attr(target, attr, proxy=None):
|
|
|
|
def get_attr(self):
|
|
value = getattr(getattr(self, target), attr)
|
|
if proxy is not None:
|
|
value = proxy(value)
|
|
return value
|
|
|
|
def forbidden(self, *args, **kwargs):
|
|
resource = getattr(self, 'resource_name', 'resource')
|
|
message = _("You are not permitted to modify '%(attr)s' on this "
|
|
"%(resource)s.")
|
|
raise exception.Forbidden(message % {'attr': attr,
|
|
'resource': resource})
|
|
|
|
return property(get_attr, forbidden, forbidden)
|
|
|
|
|
|
class ImmutableLocations(list):
|
|
def forbidden(self, *args, **kwargs):
|
|
message = _("You are not permitted to modify locations "
|
|
"for this image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def __deepcopy__(self, memo):
|
|
return ImmutableLocations(copy.deepcopy(list(self), memo))
|
|
|
|
append = forbidden
|
|
extend = forbidden
|
|
insert = forbidden
|
|
pop = forbidden
|
|
remove = forbidden
|
|
reverse = forbidden
|
|
sort = forbidden
|
|
__delitem__ = forbidden
|
|
__delslice__ = forbidden
|
|
__iadd__ = forbidden
|
|
__imul__ = forbidden
|
|
__setitem__ = forbidden
|
|
__setslice__ = forbidden
|
|
|
|
|
|
class ImmutableProperties(dict):
|
|
def forbidden_key(self, key, *args, **kwargs):
|
|
message = _("You are not permitted to modify '%s' on this image.")
|
|
raise exception.Forbidden(message % key)
|
|
|
|
def forbidden(self, *args, **kwargs):
|
|
message = _("You are not permitted to modify this image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
__delitem__ = forbidden_key
|
|
__setitem__ = forbidden_key
|
|
pop = forbidden
|
|
popitem = forbidden
|
|
setdefault = forbidden
|
|
update = forbidden
|
|
|
|
|
|
class ImmutableTags(set):
|
|
def forbidden(self, *args, **kwargs):
|
|
message = _("You are not permitted to modify tags on this image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
add = forbidden
|
|
clear = forbidden
|
|
difference_update = forbidden
|
|
intersection_update = forbidden
|
|
pop = forbidden
|
|
remove = forbidden
|
|
symmetric_difference_update = forbidden
|
|
update = forbidden
|
|
|
|
|
|
class ImmutableImageProxy(object):
|
|
def __init__(self, base, context):
|
|
self.base = base
|
|
self.context = context
|
|
self.resource_name = 'image'
|
|
|
|
name = _immutable_attr('base', 'name')
|
|
image_id = _immutable_attr('base', 'image_id')
|
|
status = _immutable_attr('base', 'status')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
visibility = _immutable_attr('base', 'visibility')
|
|
min_disk = _immutable_attr('base', 'min_disk')
|
|
min_ram = _immutable_attr('base', 'min_ram')
|
|
protected = _immutable_attr('base', 'protected')
|
|
locations = _immutable_attr('base', 'locations', proxy=ImmutableLocations)
|
|
checksum = _immutable_attr('base', 'checksum')
|
|
owner = _immutable_attr('base', 'owner')
|
|
disk_format = _immutable_attr('base', 'disk_format')
|
|
container_format = _immutable_attr('base', 'container_format')
|
|
size = _immutable_attr('base', 'size')
|
|
virtual_size = _immutable_attr('base', 'virtual_size')
|
|
extra_properties = _immutable_attr('base', 'extra_properties',
|
|
proxy=ImmutableProperties)
|
|
tags = _immutable_attr('base', 'tags', proxy=ImmutableTags)
|
|
|
|
def delete(self):
|
|
message = _("You are not permitted to delete this image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def get_member_repo(self):
|
|
member_repo = self.base.get_member_repo()
|
|
return ImageMemberRepoProxy(member_repo, self, self.context)
|
|
|
|
def get_data(self, *args, **kwargs):
|
|
return self.base.get_data(*args, **kwargs)
|
|
|
|
def set_data(self, *args, **kwargs):
|
|
message = _("You are not permitted to upload data for this image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def deactivate(self, *args, **kwargs):
|
|
message = _("You are not permitted to deactivate this image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def reactivate(self, *args, **kwargs):
|
|
message = _("You are not permitted to reactivate this image.")
|
|
raise exception.Forbidden(message)
|
|
|
|
|
|
class ImmutableMemberProxy(object):
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'image member'
|
|
|
|
id = _immutable_attr('base', 'id')
|
|
image_id = _immutable_attr('base', 'image_id')
|
|
member_id = _immutable_attr('base', 'member_id')
|
|
status = _immutable_attr('base', 'status')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
|
|
|
|
class ImmutableTaskProxy(object):
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'task'
|
|
|
|
task_id = _immutable_attr('base', 'task_id')
|
|
type = _immutable_attr('base', 'type')
|
|
status = _immutable_attr('base', 'status')
|
|
owner = _immutable_attr('base', 'owner')
|
|
expires_at = _immutable_attr('base', 'expires_at')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
input = _immutable_attr('base', 'input')
|
|
message = _immutable_attr('base', 'message')
|
|
result = _immutable_attr('base', 'result')
|
|
|
|
def run(self, executor):
|
|
self.base.run(executor)
|
|
|
|
def begin_processing(self):
|
|
message = _("You are not permitted to set status on this task.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def succeed(self, result):
|
|
message = _("You are not permitted to set status on this task.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def fail(self, message):
|
|
message = _("You are not permitted to set status on this task.")
|
|
raise exception.Forbidden(message)
|
|
|
|
|
|
class ImmutableTaskStubProxy(object):
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'task stub'
|
|
|
|
task_id = _immutable_attr('base', 'task_id')
|
|
type = _immutable_attr('base', 'type')
|
|
status = _immutable_attr('base', 'status')
|
|
owner = _immutable_attr('base', 'owner')
|
|
expires_at = _immutable_attr('base', 'expires_at')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
|
|
|
|
class ImageProxy(glance.domain.proxy.Image):
|
|
|
|
def __init__(self, image, context):
|
|
self.image = image
|
|
self.context = context
|
|
super(ImageProxy, self).__init__(image)
|
|
|
|
def get_member_repo(self, **kwargs):
|
|
if self.image.visibility == 'public':
|
|
message = _("Public images do not have members.")
|
|
raise exception.Forbidden(message)
|
|
else:
|
|
member_repo = self.image.get_member_repo(**kwargs)
|
|
return ImageMemberRepoProxy(member_repo, self, self.context)
|
|
|
|
|
|
class TaskProxy(glance.domain.proxy.Task):
|
|
|
|
def __init__(self, task):
|
|
self.task = task
|
|
super(TaskProxy, self).__init__(task)
|
|
|
|
|
|
class TaskFactoryProxy(glance.domain.proxy.TaskFactory):
|
|
|
|
def __init__(self, task_factory, context):
|
|
self.task_factory = task_factory
|
|
self.context = context
|
|
super(TaskFactoryProxy, self).__init__(
|
|
task_factory,
|
|
task_proxy_class=TaskProxy)
|
|
|
|
def new_task(self, **kwargs):
|
|
owner = kwargs.get('owner', self.context.owner)
|
|
|
|
# NOTE(nikhil): Unlike Images, Tasks are expected to have owner.
|
|
# We currently do not allow even admins to set the owner to None.
|
|
if owner is not None and (owner == self.context.owner
|
|
or self.context.is_admin):
|
|
return super(TaskFactoryProxy, self).new_task(**kwargs)
|
|
else:
|
|
message = _("You are not permitted to create this task with "
|
|
"owner as: %s")
|
|
raise exception.Forbidden(message % owner)
|
|
|
|
|
|
class TaskRepoProxy(glance.domain.proxy.TaskRepo):
|
|
|
|
def __init__(self, task_repo, context):
|
|
self.task_repo = task_repo
|
|
self.context = context
|
|
super(TaskRepoProxy, self).__init__(task_repo)
|
|
|
|
def get(self, task_id):
|
|
task = self.task_repo.get(task_id)
|
|
return proxy_task(self.context, task)
|
|
|
|
|
|
class TaskStubRepoProxy(glance.domain.proxy.TaskStubRepo):
|
|
|
|
def __init__(self, task_stub_repo, context):
|
|
self.task_stub_repo = task_stub_repo
|
|
self.context = context
|
|
super(TaskStubRepoProxy, self).__init__(task_stub_repo)
|
|
|
|
def list(self, *args, **kwargs):
|
|
task_stubs = self.task_stub_repo.list(*args, **kwargs)
|
|
return [proxy_task_stub(self.context, t) for t in task_stubs]
|
|
|
|
|
|
# Metadef Namespace classes
|
|
def is_namespace_mutable(context, namespace):
|
|
"""Return True if the namespace is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
return namespace.owner == context.owner
|
|
|
|
|
|
def proxy_namespace(context, namespace):
|
|
if is_namespace_mutable(context, namespace):
|
|
return namespace
|
|
else:
|
|
return ImmutableMetadefNamespaceProxy(namespace)
|
|
|
|
|
|
class ImmutableMetadefNamespaceProxy(object):
|
|
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'namespace'
|
|
|
|
namespace_id = _immutable_attr('base', 'namespace_id')
|
|
namespace = _immutable_attr('base', 'namespace')
|
|
display_name = _immutable_attr('base', 'display_name')
|
|
description = _immutable_attr('base', 'description')
|
|
owner = _immutable_attr('base', 'owner')
|
|
visibility = _immutable_attr('base', 'visibility')
|
|
protected = _immutable_attr('base', 'protected')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
|
|
def delete(self):
|
|
message = _("You are not permitted to delete this namespace.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def save(self):
|
|
message = _("You are not permitted to update this namespace.")
|
|
raise exception.Forbidden(message)
|
|
|
|
|
|
class MetadefNamespaceProxy(glance.domain.proxy.MetadefNamespace):
|
|
|
|
def __init__(self, namespace):
|
|
self.namespace_input = namespace
|
|
super(MetadefNamespaceProxy, self).__init__(namespace)
|
|
|
|
|
|
class MetadefNamespaceFactoryProxy(
|
|
glance.domain.proxy.MetadefNamespaceFactory):
|
|
|
|
def __init__(self, meta_namespace_factory, context):
|
|
self.meta_namespace_factory = meta_namespace_factory
|
|
self.context = context
|
|
super(MetadefNamespaceFactoryProxy, self).__init__(
|
|
meta_namespace_factory,
|
|
meta_namespace_proxy_class=MetadefNamespaceProxy)
|
|
|
|
def new_namespace(self, **kwargs):
|
|
owner = kwargs.pop('owner', self.context.owner)
|
|
|
|
if not self.context.is_admin:
|
|
if owner is None or owner != self.context.owner:
|
|
message = _("You are not permitted to create namespace "
|
|
"owned by '%s'")
|
|
raise exception.Forbidden(message % (owner))
|
|
|
|
return super(MetadefNamespaceFactoryProxy, self).new_namespace(
|
|
owner=owner, **kwargs)
|
|
|
|
|
|
class MetadefNamespaceRepoProxy(glance.domain.proxy.MetadefNamespaceRepo):
|
|
|
|
def __init__(self, namespace_repo, context):
|
|
self.namespace_repo = namespace_repo
|
|
self.context = context
|
|
super(MetadefNamespaceRepoProxy, self).__init__(namespace_repo)
|
|
|
|
def get(self, namespace):
|
|
namespace_obj = self.namespace_repo.get(namespace)
|
|
return proxy_namespace(self.context, namespace_obj)
|
|
|
|
def list(self, *args, **kwargs):
|
|
namespaces = self.namespace_repo.list(*args, **kwargs)
|
|
return [proxy_namespace(self.context, namespace) for
|
|
namespace in namespaces]
|
|
|
|
|
|
# Metadef Object classes
|
|
def is_object_mutable(context, object):
|
|
"""Return True if the object is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
return object.namespace.owner == context.owner
|
|
|
|
|
|
def proxy_object(context, object):
|
|
if is_object_mutable(context, object):
|
|
return object
|
|
else:
|
|
return ImmutableMetadefObjectProxy(object)
|
|
|
|
|
|
class ImmutableMetadefObjectProxy(object):
|
|
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'object'
|
|
|
|
object_id = _immutable_attr('base', 'object_id')
|
|
name = _immutable_attr('base', 'name')
|
|
required = _immutable_attr('base', 'required')
|
|
description = _immutable_attr('base', 'description')
|
|
properties = _immutable_attr('base', 'properties')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
|
|
def delete(self):
|
|
message = _("You are not permitted to delete this object.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def save(self):
|
|
message = _("You are not permitted to update this object.")
|
|
raise exception.Forbidden(message)
|
|
|
|
|
|
class MetadefObjectProxy(glance.domain.proxy.MetadefObject):
|
|
|
|
def __init__(self, meta_object):
|
|
self.meta_object = meta_object
|
|
super(MetadefObjectProxy, self).__init__(meta_object)
|
|
|
|
|
|
class MetadefObjectFactoryProxy(glance.domain.proxy.MetadefObjectFactory):
|
|
|
|
def __init__(self, meta_object_factory, context):
|
|
self.meta_object_factory = meta_object_factory
|
|
self.context = context
|
|
super(MetadefObjectFactoryProxy, self).__init__(
|
|
meta_object_factory,
|
|
meta_object_proxy_class=MetadefObjectProxy)
|
|
|
|
def new_object(self, **kwargs):
|
|
owner = kwargs.pop('owner', self.context.owner)
|
|
|
|
if not self.context.is_admin:
|
|
if owner is None or owner != self.context.owner:
|
|
message = _("You are not permitted to create object "
|
|
"owned by '%s'")
|
|
raise exception.Forbidden(message % (owner))
|
|
|
|
return super(MetadefObjectFactoryProxy, self).new_object(**kwargs)
|
|
|
|
|
|
class MetadefObjectRepoProxy(glance.domain.proxy.MetadefObjectRepo):
|
|
|
|
def __init__(self, object_repo, context):
|
|
self.object_repo = object_repo
|
|
self.context = context
|
|
super(MetadefObjectRepoProxy, self).__init__(object_repo)
|
|
|
|
def get(self, namespace, object_name):
|
|
meta_object = self.object_repo.get(namespace, object_name)
|
|
return proxy_object(self.context, meta_object)
|
|
|
|
def list(self, *args, **kwargs):
|
|
objects = self.object_repo.list(*args, **kwargs)
|
|
return [proxy_object(self.context, meta_object) for
|
|
meta_object in objects]
|
|
|
|
|
|
# Metadef ResourceType classes
|
|
def is_meta_resource_type_mutable(context, meta_resource_type):
|
|
"""Return True if the meta_resource_type is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
# (lakshmiS): resource type can exist without an association with
|
|
# namespace and resource type cannot be created/update/deleted directly(
|
|
# they have to be associated/de-associated from namespace)
|
|
if meta_resource_type.namespace:
|
|
return meta_resource_type.namespace.owner == context.owner
|
|
else:
|
|
return False
|
|
|
|
|
|
def proxy_meta_resource_type(context, meta_resource_type):
|
|
if is_meta_resource_type_mutable(context, meta_resource_type):
|
|
return meta_resource_type
|
|
else:
|
|
return ImmutableMetadefResourceTypeProxy(meta_resource_type)
|
|
|
|
|
|
class ImmutableMetadefResourceTypeProxy(object):
|
|
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'meta_resource_type'
|
|
|
|
namespace = _immutable_attr('base', 'namespace')
|
|
name = _immutable_attr('base', 'name')
|
|
prefix = _immutable_attr('base', 'prefix')
|
|
properties_target = _immutable_attr('base', 'properties_target')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
|
|
def delete(self):
|
|
message = _("You are not permitted to delete this meta_resource_type.")
|
|
raise exception.Forbidden(message)
|
|
|
|
|
|
class MetadefResourceTypeProxy(glance.domain.proxy.MetadefResourceType):
|
|
|
|
def __init__(self, meta_resource_type):
|
|
self.meta_resource_type = meta_resource_type
|
|
super(MetadefResourceTypeProxy, self).__init__(meta_resource_type)
|
|
|
|
|
|
class MetadefResourceTypeFactoryProxy(
|
|
glance.domain.proxy.MetadefResourceTypeFactory):
|
|
|
|
def __init__(self, resource_type_factory, context):
|
|
self.meta_resource_type_factory = resource_type_factory
|
|
self.context = context
|
|
super(MetadefResourceTypeFactoryProxy, self).__init__(
|
|
resource_type_factory,
|
|
resource_type_proxy_class=MetadefResourceTypeProxy)
|
|
|
|
def new_resource_type(self, **kwargs):
|
|
owner = kwargs.pop('owner', self.context.owner)
|
|
|
|
if not self.context.is_admin:
|
|
if owner is None or owner != self.context.owner:
|
|
message = _("You are not permitted to create resource_type "
|
|
"owned by '%s'")
|
|
raise exception.Forbidden(message % (owner))
|
|
|
|
return super(MetadefResourceTypeFactoryProxy, self).new_resource_type(
|
|
**kwargs)
|
|
|
|
|
|
class MetadefResourceTypeRepoProxy(
|
|
glance.domain.proxy.MetadefResourceTypeRepo):
|
|
|
|
def __init__(self, meta_resource_type_repo, context):
|
|
self.meta_resource_type_repo = meta_resource_type_repo
|
|
self.context = context
|
|
super(MetadefResourceTypeRepoProxy, self).__init__(
|
|
meta_resource_type_repo)
|
|
|
|
def list(self, *args, **kwargs):
|
|
meta_resource_types = self.meta_resource_type_repo.list(
|
|
*args, **kwargs)
|
|
return [proxy_meta_resource_type(self.context, meta_resource_type) for
|
|
meta_resource_type in meta_resource_types]
|
|
|
|
def get(self, *args, **kwargs):
|
|
meta_resource_type = self.meta_resource_type_repo.get(*args, **kwargs)
|
|
return proxy_meta_resource_type(self.context, meta_resource_type)
|
|
|
|
|
|
# Metadef namespace properties classes
|
|
def is_namespace_property_mutable(context, namespace_property):
|
|
"""Return True if the object is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
return namespace_property.namespace.owner == context.owner
|
|
|
|
|
|
def proxy_namespace_property(context, namespace_property):
|
|
if is_namespace_property_mutable(context, namespace_property):
|
|
return namespace_property
|
|
else:
|
|
return ImmutableMetadefPropertyProxy(namespace_property)
|
|
|
|
|
|
class ImmutableMetadefPropertyProxy(object):
|
|
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'namespace_property'
|
|
|
|
property_id = _immutable_attr('base', 'property_id')
|
|
name = _immutable_attr('base', 'name')
|
|
schema = _immutable_attr('base', 'schema')
|
|
|
|
def delete(self):
|
|
message = _("You are not permitted to delete this property.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def save(self):
|
|
message = _("You are not permitted to update this property.")
|
|
raise exception.Forbidden(message)
|
|
|
|
|
|
class MetadefPropertyProxy(glance.domain.proxy.MetadefProperty):
|
|
|
|
def __init__(self, namespace_property):
|
|
self.meta_object = namespace_property
|
|
super(MetadefPropertyProxy, self).__init__(namespace_property)
|
|
|
|
|
|
class MetadefPropertyFactoryProxy(glance.domain.proxy.MetadefPropertyFactory):
|
|
|
|
def __init__(self, namespace_property_factory, context):
|
|
self.meta_object_factory = namespace_property_factory
|
|
self.context = context
|
|
super(MetadefPropertyFactoryProxy, self).__init__(
|
|
namespace_property_factory,
|
|
property_proxy_class=MetadefPropertyProxy)
|
|
|
|
def new_namespace_property(self, **kwargs):
|
|
owner = kwargs.pop('owner', self.context.owner)
|
|
|
|
if not self.context.is_admin:
|
|
if owner is None or owner != self.context.owner:
|
|
message = _("You are not permitted to create property "
|
|
"owned by '%s'")
|
|
raise exception.Forbidden(message % (owner))
|
|
|
|
return super(MetadefPropertyFactoryProxy, self).new_namespace_property(
|
|
**kwargs)
|
|
|
|
|
|
class MetadefPropertyRepoProxy(glance.domain.proxy.MetadefPropertyRepo):
|
|
|
|
def __init__(self, namespace_property_repo, context):
|
|
self.namespace_property_repo = namespace_property_repo
|
|
self.context = context
|
|
super(MetadefPropertyRepoProxy, self).__init__(namespace_property_repo)
|
|
|
|
def get(self, namespace, object_name):
|
|
namespace_property = self.namespace_property_repo.get(namespace,
|
|
object_name)
|
|
return proxy_namespace_property(self.context, namespace_property)
|
|
|
|
def list(self, *args, **kwargs):
|
|
namespace_properties = self.namespace_property_repo.list(
|
|
*args, **kwargs)
|
|
return [proxy_namespace_property(self.context, namespace_property) for
|
|
namespace_property in namespace_properties]
|
|
|
|
|
|
# Metadef Tag classes
|
|
def is_tag_mutable(context, tag):
|
|
"""Return True if the tag is mutable in this context."""
|
|
if context.is_admin:
|
|
return True
|
|
|
|
if context.owner is None:
|
|
return False
|
|
|
|
return tag.namespace.owner == context.owner
|
|
|
|
|
|
def proxy_tag(context, tag):
|
|
if is_tag_mutable(context, tag):
|
|
return tag
|
|
else:
|
|
return ImmutableMetadefTagProxy(tag)
|
|
|
|
|
|
class ImmutableMetadefTagProxy(object):
|
|
|
|
def __init__(self, base):
|
|
self.base = base
|
|
self.resource_name = 'tag'
|
|
|
|
tag_id = _immutable_attr('base', 'tag_id')
|
|
name = _immutable_attr('base', 'name')
|
|
created_at = _immutable_attr('base', 'created_at')
|
|
updated_at = _immutable_attr('base', 'updated_at')
|
|
|
|
def delete(self):
|
|
message = _("You are not permitted to delete this tag.")
|
|
raise exception.Forbidden(message)
|
|
|
|
def save(self):
|
|
message = _("You are not permitted to update this tag.")
|
|
raise exception.Forbidden(message)
|
|
|
|
|
|
class MetadefTagProxy(glance.domain.proxy.MetadefTag):
|
|
pass
|
|
|
|
|
|
class MetadefTagFactoryProxy(glance.domain.proxy.MetadefTagFactory):
|
|
|
|
def __init__(self, meta_tag_factory, context):
|
|
self.meta_tag_factory = meta_tag_factory
|
|
self.context = context
|
|
super(MetadefTagFactoryProxy, self).__init__(
|
|
meta_tag_factory,
|
|
meta_tag_proxy_class=MetadefTagProxy)
|
|
|
|
def new_tag(self, **kwargs):
|
|
owner = kwargs.pop('owner', self.context.owner)
|
|
if not self.context.is_admin:
|
|
if owner is None:
|
|
message = _("Owner must be specified to create a tag.")
|
|
raise exception.Forbidden(message)
|
|
elif owner != self.context.owner:
|
|
message = _("You are not permitted to create a tag"
|
|
" in the namespace owned by '%s'")
|
|
raise exception.Forbidden(message % (owner))
|
|
|
|
return super(MetadefTagFactoryProxy, self).new_tag(**kwargs)
|
|
|
|
|
|
class MetadefTagRepoProxy(glance.domain.proxy.MetadefTagRepo):
|
|
|
|
def __init__(self, tag_repo, context):
|
|
self.tag_repo = tag_repo
|
|
self.context = context
|
|
super(MetadefTagRepoProxy, self).__init__(tag_repo)
|
|
|
|
def get(self, namespace, tag_name):
|
|
meta_tag = self.tag_repo.get(namespace, tag_name)
|
|
return proxy_tag(self.context, meta_tag)
|
|
|
|
def list(self, *args, **kwargs):
|
|
tags = self.tag_repo.list(*args, **kwargs)
|
|
return [proxy_tag(self.context, meta_tag) for
|
|
meta_tag in tags]
|