¡@

Home 

OpenStack Study: image_members.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2013 OpenStack Foundation

# 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

import webob

from glance.api import policy

from glance.common import exception

from glance.common import utils

from glance.common import wsgi

import glance.db

import glance.gateway

import glance.notifier

from glance.openstack.common import jsonutils

from glance.openstack.common import timeutils

import glance.schema

import glance.store

**** CubicPower OpenStack Study ****

class ImageMembersController(object):

**** CubicPower OpenStack Study ****

    def __init__(self, db_api=None, policy_enforcer=None, notifier=None,

                 store_api=None):

        self.db_api = db_api or glance.db.get_api()

        self.policy = policy_enforcer or policy.Enforcer()

        self.notifier = notifier or glance.notifier.Notifier()

        self.store_api = store_api or glance.store

        self.gateway = glance.gateway.Gateway(self.db_api, self.store_api,

                                              self.notifier, self.policy)

    @utils.mutating

**** CubicPower OpenStack Study ****

    def create(self, req, image_id, member_id):

        """

        Adds a membership to the image.

        :param req: the Request object coming from the wsgi layer

        :param image_id: the image identifier

        :param member_id: the member identifier

        :retval The response body is a mapping of the following form::

            {'member_id': ,

             'image_id': ,

             'status': 

             'created_at': ..,

             'updated_at': ..}

        """

        image_repo = self.gateway.get_repo(req.context)

        image_member_factory = self.gateway\

                                   .get_image_member_factory(req.context)

        try:

            image = image_repo.get(image_id)

            member_repo = image.get_member_repo()

            new_member = image_member_factory.new_image_member(image,

                                                               member_id)

            member_repo.add(new_member)

            return new_member

        except exception.NotFound as e:

            raise webob.exc.HTTPNotFound(explanation=e.msg)

        except exception.Forbidden as e:

            raise webob.exc.HTTPForbidden(explanation=e.msg)

        except exception.Duplicate as e:

            raise webob.exc.HTTPConflict(explanation=e.msg)

        except exception.ImageMemberLimitExceeded as e:

            raise webob.exc.HTTPRequestEntityTooLarge(explanation=e.msg)

    @utils.mutating

**** CubicPower OpenStack Study ****

    def update(self, req, image_id, member_id, status):

        """

        Adds a membership to the image.

        :param req: the Request object coming from the wsgi layer

        :param image_id: the image identifier

        :param member_id: the member identifier

        :retval The response body is a mapping of the following form::

            {'member_id': ,

             'image_id': ,

             'status': 

             'created_at': ..,

             'updated_at': ..}

        """

        image_repo = self.gateway.get_repo(req.context)

        try:

            image = image_repo.get(image_id)

            member_repo = image.get_member_repo()

            member = member_repo.get(member_id)

            member.status = status

            member_repo.save(member)

            return member

        except exception.NotFound as e:

            raise webob.exc.HTTPNotFound(explanation=e.msg)

        except exception.Forbidden as e:

            raise webob.exc.HTTPForbidden(explanation=e.msg)

        except ValueError as e:

            raise webob.exc.HTTPBadRequest(explanation=unicode(e))

**** CubicPower OpenStack Study ****

    def index(self, req, image_id):

        """

        Return a list of dictionaries indicating the members of the

        image, i.e., those tenants the image is shared with.

        :param req: the Request object coming from the wsgi layer

        :param image_id: The image identifier

        :retval The response body is a mapping of the following form::

            {'members': [

                {'member_id': ,

                 'image_id': ,

                 'status': 

                 'created_at': ..,

                 'updated_at': ..}, ..

            ]}

        """

        image_repo = self.gateway.get_repo(req.context)

        try:

            image = image_repo.get(image_id)

            member_repo = image.get_member_repo()

            members = []

            for member in member_repo.list():

                members.append(member)

            return dict(members=members)

        except exception.NotFound as e:

            raise webob.exc.HTTPNotFound(explanation=e.msg)

        except exception.Forbidden as e:

            raise webob.exc.HTTPForbidden(explanation=e.msg)

**** CubicPower OpenStack Study ****

    def show(self, req, image_id, member_id):

        """

        Returns the membership of the tenant wrt to the image_id specified.

        :param req: the Request object coming from the wsgi layer

        :param image_id: The image identifier

        :retval The response body is a mapping of the following form::

            {'member_id': ,

             'image_id': ,

             'status': 

             'created_at': ..,

             'updated_at': ..}

        """

        image_repo = self.gateway.get_repo(req.context)

        try:

            image = image_repo.get(image_id)

            member_repo = image.get_member_repo()

            member = member_repo.get(member_id)

            return member

        except (exception.NotFound, exception.Forbidden) as e:

            raise webob.exc.HTTPNotFound(explanation=e.msg)

    @utils.mutating

**** CubicPower OpenStack Study ****

    def delete(self, req, image_id, member_id):

        """

        Removes a membership from the image.

        """

        image_repo = self.gateway.get_repo(req.context)

        try:

            image = image_repo.get(image_id)

            member_repo = image.get_member_repo()

            member = member_repo.get(member_id)

            member_repo.remove(member)

            return webob.Response(body='', status=204)

        except exception.NotFound as e:

            raise webob.exc.HTTPNotFound(explanation=e.msg)

        except exception.Forbidden as e:

            raise webob.exc.HTTPForbidden(explanation=e.msg)

**** CubicPower OpenStack Study ****

class RequestDeserializer(wsgi.JSONRequestDeserializer):

**** CubicPower OpenStack Study ****

    def __init__(self):

        super(RequestDeserializer, self).__init__()

**** CubicPower OpenStack Study ****

    def _get_request_body(self, request):

        output = super(RequestDeserializer, self).default(request)

        if 'body' not in output:

            msg = _('Body expected in request.')

            raise webob.exc.HTTPBadRequest(explanation=msg)

        return output['body']

**** CubicPower OpenStack Study ****

    def create(self, request):

        body = self._get_request_body(request)

        try:

            member_id = body['member']

            if not member_id:

                raise ValueError()

        except KeyError:

            msg = _("Member to be added not specified")

            raise webob.exc.HTTPBadRequest(explanation=msg)

        except ValueError:

            msg = _("Member can't be empty")

            raise webob.exc.HTTPBadRequest(explanation=msg)

        return dict(member_id=member_id)

**** CubicPower OpenStack Study ****

    def update(self, request):

        body = self._get_request_body(request)

        try:

            status = body['status']

        except KeyError:

            msg = _("Status not specified")

            raise webob.exc.HTTPBadRequest(explanation=msg)

        return dict(status=status)

**** CubicPower OpenStack Study ****

class ResponseSerializer(wsgi.JSONResponseSerializer):

**** CubicPower OpenStack Study ****

    def __init__(self, schema=None):

        super(ResponseSerializer, self).__init__()

        self.schema = schema or get_schema()

**** CubicPower OpenStack Study ****

    def _format_image_member(self, member):

        member_view = {}

        attributes = ['member_id', 'image_id', 'status']

        for key in attributes:

            member_view[key] = getattr(member, key)

        member_view['created_at'] = timeutils.isotime(member.created_at)

        member_view['updated_at'] = timeutils.isotime(member.updated_at)

        member_view['schema'] = '/v2/schemas/member'

        member_view = self.schema.filter(member_view)

        return member_view

**** CubicPower OpenStack Study ****

    def create(self, response, image_member):

        image_member_view = self._format_image_member(image_member)

        body = jsonutils.dumps(image_member_view, ensure_ascii=False)

        response.unicode_body = unicode(body)

        response.content_type = 'application/json'

**** CubicPower OpenStack Study ****

    def update(self, response, image_member):

        image_member_view = self._format_image_member(image_member)

        body = jsonutils.dumps(image_member_view, ensure_ascii=False)

        response.unicode_body = unicode(body)

        response.content_type = 'application/json'

**** CubicPower OpenStack Study ****

    def index(self, response, image_members):

        image_members = image_members['members']

        image_members_view = []

        for image_member in image_members:

            image_member_view = self._format_image_member(image_member)

            image_members_view.append(image_member_view)

        totalview = dict(members=image_members_view)

        totalview['schema'] = '/v2/schemas/members'

        body = jsonutils.dumps(totalview, ensure_ascii=False)

        response.unicode_body = unicode(body)

        response.content_type = 'application/json'

**** CubicPower OpenStack Study ****

    def show(self, response, image_member):

        image_member_view = self._format_image_member(image_member)

        body = jsonutils.dumps(image_member_view, ensure_ascii=False)

        response.unicode_body = unicode(body)

        response.content_type = 'application/json'

_MEMBER_SCHEMA = {

    'member_id': {

        'type': 'string',

        'description': _('An identifier for the image member (tenantId)')

    },

    'image_id': {

        'type': 'string',

        'description': _('An identifier for the image'),

        'pattern': ('^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}'

                    '-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$'),

    },

    'created_at': {

        'type': 'string',

        'description': _('Date and time of image member creation'),

        #TODO(brian-rosmaita): our jsonschema library doesn't seem to like the

        # format attribute, figure out why (and also fix in images.py)

        #'format': 'date-time',

    },

    'updated_at': {

        'type': 'string',

        'description': _('Date and time of last modification of image member'),

        #'format': 'date-time',

    },

    'status': {

        'type': 'string',

        'description': _('The status of this image member'),

        'enum': [

            'pending',

            'accepted',

            'rejected'

        ]

    },

    'schema': {'type': 'string'}

}

def get_schema():

    properties = copy.deepcopy(_MEMBER_SCHEMA)

    schema = glance.schema.Schema('member', properties)

    return schema

def get_collection_schema():

    member_schema = get_schema()

    return glance.schema.CollectionSchema('members', member_schema)

def create_resource():

    """Image Members resource factory method"""

    deserializer = RequestDeserializer()

    serializer = ResponseSerializer()

    controller = ImageMembersController()

    return wsgi.Resource(controller, deserializer, serializer)

**** CubicPower OpenStack Study ****

def get_schema():

    properties = copy.deepcopy(_MEMBER_SCHEMA)

    schema = glance.schema.Schema('member', properties)

    return schema

**** CubicPower OpenStack Study ****

def get_collection_schema():

    member_schema = get_schema()

    return glance.schema.CollectionSchema('members', member_schema)

**** CubicPower OpenStack Study ****

def create_resource():

    """Image Members resource factory method"""

    deserializer = RequestDeserializer()

    serializer = ResponseSerializer()

    controller = ImageMembersController()

    return wsgi.Resource(controller, deserializer, serializer)