¡@

Home 

OpenStack Study: volume_type_encryption.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright (c) 2013 The Johns Hopkins University/Applied Physics Laboratory

# 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.

"""The volume types encryption extension."""

import webob

from cinder.api import extensions

from cinder.api.openstack import wsgi

from cinder.api import xmlutil

from cinder import db

from cinder import exception

from cinder import rpc

from cinder.volume import volume_types

authorize = extensions.extension_authorizer('volume',

'volume_type_encryption')

CONTROL_LOCATION = ['front-end', 'back-end']

**** CubicPower OpenStack Study ****

class VolumeTypeEncryptionTemplate(xmlutil.TemplateBuilder):

**** CubicPower OpenStack Study ****

    def construct(self):

        root = xmlutil.make_flat_dict('encryption', selector='encryption')

        return xmlutil.MasterTemplate(root, 1)

**** CubicPower OpenStack Study ****

class VolumeTypeEncryptionController(wsgi.Controller):

"""The volume type encryption API controller for the OpenStack API."""

**** CubicPower OpenStack Study ****

    def _get_volume_type_encryption(self, context, type_id):

        encryption_ref = db.volume_type_encryption_get(context, type_id)

        encryption_specs = {}

        if not encryption_ref:

            return encryption_specs

        for key, value in encryption_ref.iteritems():

            encryption_specs[key] = value

        return encryption_specs

**** CubicPower OpenStack Study ****

    def _check_type(self, context, type_id):

        try:

            volume_types.get_volume_type(context, type_id)

        except exception.NotFound as ex:

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

**** CubicPower OpenStack Study ****

    def _check_encryption_input(self, encryption, create=True):

        if 'key_size' in encryption.keys():

            key_size = encryption['key_size']

            if key_size is not None:

                if isinstance(key_size, (int, long)):

                    if key_size < 0:

                        msg = _('key_size must be non-negative')

                        raise exception.InvalidInput(reason=msg)

                else:

                    msg = _('key_size must be an integer')

                    raise exception.InvalidInput(reason=msg)

        if create:

            msg = None

            if 'provider' not in encryption.keys():

                msg = _('provider must be defined')

            elif 'control_location' not in encryption.keys():

                msg = _('control_location must be defined')

            if msg is not None:

                raise exception.InvalidInput(reason=msg)

        # Check control location

        if 'control_location' in encryption.keys():

            if encryption['control_location'] not in CONTROL_LOCATION:

                msg = _("Valid control location are: %s") % CONTROL_LOCATION

                raise exception.InvalidInput(reason=msg)

**** CubicPower OpenStack Study ****

    def _encrypted_type_in_use(self, context, volume_type_id):

        volume_list = db.volume_type_encryption_volume_get(context,

                                                           volume_type_id)

        # If there is at least one volume in the list

        # returned, this type is in use by a volume.

        if len(volume_list) > 0:

            return True

        else:

            return False

    @wsgi.serializers(xml=VolumeTypeEncryptionTemplate)

**** CubicPower OpenStack Study ****

    def index(self, req, type_id):

        """Returns the encryption specs for a given volume type."""

        context = req.environ['cinder.context']

        authorize(context)

        self._check_type(context, type_id)

        return self._get_volume_type_encryption(context, type_id)

    @wsgi.serializers(xml=VolumeTypeEncryptionTemplate)

**** CubicPower OpenStack Study ****

    def create(self, req, type_id, body=None):

        """Create encryption specs for an existing volume type."""

        context = req.environ['cinder.context']

        authorize(context)

        if self._encrypted_type_in_use(context, type_id):

            expl = _('Cannot create encryption specs. Volume type in use.')

            raise webob.exc.HTTPBadRequest(explanation=expl)

        if not self.is_valid_body(body, 'encryption'):

            expl = _('Create body is not valid.')

            raise webob.exc.HTTPBadRequest(explanation=expl)

        self._check_type(context, type_id)

        encryption_specs = self._get_volume_type_encryption(context, type_id)

        if encryption_specs:

            raise exception.VolumeTypeEncryptionExists(type_id=type_id)

        encryption_specs = body['encryption']

        self._check_encryption_input(encryption_specs)

        db.volume_type_encryption_create(context, type_id, encryption_specs)

        notifier_info = dict(type_id=type_id, specs=encryption_specs)

        notifier = rpc.get_notifier('volumeTypeEncryption')

        notifier.info(context, 'volume_type_encryption.create', notifier_info)

        return body

    @wsgi.serializers(xml=VolumeTypeEncryptionTemplate)

**** CubicPower OpenStack Study ****

    def update(self, req, type_id, id, body=None):

        """Update encryption specs for a given volume type."""

        context = req.environ['cinder.context']

        authorize(context)

        if not body:

            expl = _('Request body empty.')

            raise webob.exc.HTTPBadRequest(explanation=expl)

        if not self.is_valid_body(body, 'encryption'):

            expl = _('Update body is not valid. It must contain "encryption."')

            raise webob.exc.HTTPBadRequest(explanation=expl)

        if len(body) > 1:

            expl = _('Request body contains too many items.')

            raise webob.exc.HTTPBadRequest(explanation=expl)

        self._check_type(context, type_id)

        if self._encrypted_type_in_use(context, type_id):

            expl = _('Cannot update encryption specs. Volume type in use.')

            raise webob.exc.HTTPBadRequest(explanation=expl)

        encryption_specs = body['encryption']

        self._check_encryption_input(encryption_specs, create=False)

        db.volume_type_encryption_update(context, type_id, encryption_specs)

        notifier_info = dict(type_id=type_id, id=id)

        notifier = rpc.get_notifier('volumeTypeEncryption')

        notifier.info(context, 'volume_type_encryption.update', notifier_info)

        return body

    @wsgi.serializers(xml=VolumeTypeEncryptionTemplate)

**** CubicPower OpenStack Study ****

    def show(self, req, type_id, id):

        """Return a single encryption item."""

        context = req.environ['cinder.context']

        authorize(context)

        self._check_type(context, type_id)

        encryption_specs = self._get_volume_type_encryption(context, type_id)

        if id not in encryption_specs:

            raise webob.exc.HTTPNotFound()

        return {id: encryption_specs[id]}

**** CubicPower OpenStack Study ****

    def delete(self, req, type_id, id):

        """Delete encryption specs for a given volume type."""

        context = req.environ['cinder.context']

        authorize(context)

        if self._encrypted_type_in_use(context, type_id):

            expl = _('Cannot delete encryption specs. Volume type in use.')

            raise webob.exc.HTTPBadRequest(explanation=expl)

        else:

            db.volume_type_encryption_delete(context, type_id)

        return webob.Response(status_int=202)

**** CubicPower OpenStack Study ****

class Volume_type_encryption(extensions.ExtensionDescriptor):

"""Encryption support for volume types."""

name = "VolumeTypeEncryption"

alias = "encryption"

namespace = ("http://docs.openstack.org/volume/ext/"

"volume-type-encryption/api/v1")

updated = "2013-07-01T00:00:00+00:00"

**** CubicPower OpenStack Study ****

    def get_resources(self):

        resources = []

        res = extensions.ResourceExtension(

            Volume_type_encryption.alias,

            VolumeTypeEncryptionController(),

            parent=dict(member_name='type', collection_name='types'))

        resources.append(res)

        return resources

**** CubicPower OpenStack Study ****

    def get_controller_extensions(self):

        controller = VolumeTypeEncryptionController()

        extension = extensions.ControllerExtension(self, 'types', controller)

        return [extension]