summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/compute/contrib/virtual_storage_arrays.py701
1 files changed, 0 insertions, 701 deletions
diff --git a/nova/api/openstack/compute/contrib/virtual_storage_arrays.py b/nova/api/openstack/compute/contrib/virtual_storage_arrays.py
deleted file mode 100644
index 9c413e76f..000000000
--- a/nova/api/openstack/compute/contrib/virtual_storage_arrays.py
+++ /dev/null
@@ -1,701 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright (c) 2011 Zadara Storage Inc.
-# Copyright (c) 2011 OpenStack LLC.
-#
-# 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 virtul storage array extension"""
-
-
-import webob
-from webob import exc
-
-from nova.api.openstack import common
-from nova.api.openstack.compute.contrib import volumes
-from nova.api.openstack import extensions
-from nova.api.openstack.compute import servers
-from nova.api.openstack import wsgi
-from nova.api.openstack import xmlutil
-from nova import compute
-from nova.compute import instance_types
-from nova import network
-from nova import exception
-from nova import flags
-from nova import log as logging
-from nova.vsa import api as vsa_api
-from nova import volume
-
-
-FLAGS = flags.FLAGS
-LOG = logging.getLogger(__name__)
-authorize = extensions.extension_authorizer('compute',
- 'virtual_storage_arrays')
-
-
-def _vsa_view(context, vsa, details=False, instances=None):
- """Map keys for vsa summary/detailed view."""
- d = {}
-
- d['id'] = vsa.get('id')
- d['name'] = vsa.get('name')
- d['displayName'] = vsa.get('display_name')
- d['displayDescription'] = vsa.get('display_description')
-
- d['createTime'] = vsa.get('created_at')
- d['status'] = vsa.get('status')
-
- if 'vsa_instance_type' in vsa:
- d['vcType'] = vsa['vsa_instance_type'].get('name', None)
- else:
- d['vcType'] = vsa['instance_type_id']
-
- d['vcCount'] = vsa.get('vc_count')
- d['driveCount'] = vsa.get('vol_count')
-
- d['ipAddress'] = None
- for instance in instances:
- fixed_addr = None
- floating_addr = None
- if instance['fixed_ips']:
- fixed = instance['fixed_ips'][0]
- fixed_addr = fixed['address']
- if fixed['floating_ips']:
- floating_addr = fixed['floating_ips'][0]['address']
-
- if floating_addr:
- d['ipAddress'] = floating_addr
- break
- else:
- d['ipAddress'] = d['ipAddress'] or fixed_addr
-
- return d
-
-
-def make_vsa(elem):
- elem.set('id')
- elem.set('name')
- elem.set('displayName')
- elem.set('displayDescription')
- elem.set('createTime')
- elem.set('status')
- elem.set('vcType')
- elem.set('vcCount')
- elem.set('driveCount')
- elem.set('ipAddress')
-
-
-class VsaTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('vsa', selector='vsa')
- make_vsa(root)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaSetTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('vsaSet')
- elem = xmlutil.SubTemplateElement(root, 'vsa', selector='vsaSet')
- make_vsa(elem)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaController(object):
- """The Virtual Storage Array API controller for the OpenStack API."""
-
- def __init__(self):
- self.vsa_api = vsa_api.API()
- self.compute_api = compute.API()
- self.network_api = network.API()
- super(VsaController, self).__init__()
-
- def _get_instances_by_vsa_id(self, context, id):
- return self.compute_api.get_all(context,
- search_opts={'metadata': dict(vsa_id=str(id))})
-
- def _items(self, req, details):
- """Return summary or detailed list of VSAs."""
- context = req.environ['nova.context']
- authorize(context)
- vsas = self.vsa_api.get_all(context)
- limited_list = common.limited(vsas, req)
-
- vsa_list = []
- for vsa in limited_list:
- instances = self._get_instances_by_vsa_id(context, vsa.get('id'))
- vsa_list.append(_vsa_view(context, vsa, details, instances))
- return {'vsaSet': vsa_list}
-
- @wsgi.serializers(xml=VsaSetTemplate)
- def index(self, req):
- """Return a short list of VSAs."""
- return self._items(req, details=False)
-
- @wsgi.serializers(xml=VsaSetTemplate)
- def detail(self, req):
- """Return a detailed list of VSAs."""
- return self._items(req, details=True)
-
- @wsgi.serializers(xml=VsaTemplate)
- def show(self, req, id):
- """Return data about the given VSA."""
- context = req.environ['nova.context']
- authorize(context)
-
- try:
- vsa = self.vsa_api.get(context, vsa_id=id)
- except exception.NotFound:
- raise exc.HTTPNotFound()
-
- instances = self._get_instances_by_vsa_id(context, vsa.get('id'))
- return {'vsa': _vsa_view(context, vsa, True, instances)}
-
- @wsgi.serializers(xml=VsaTemplate)
- def create(self, req, body):
- """Create a new VSA."""
- context = req.environ['nova.context']
- authorize(context)
-
- if not body or 'vsa' not in body:
- LOG.debug(_("No body provided"), context=context)
- raise exc.HTTPUnprocessableEntity()
-
- vsa = body['vsa']
-
- display_name = vsa.get('displayName')
- vc_type = vsa.get('vcType', FLAGS.default_vsa_instance_type)
- try:
- instance_type = instance_types.get_instance_type_by_name(vc_type)
- except exception.NotFound:
- raise exc.HTTPNotFound()
-
- LOG.audit(_("Create VSA %(display_name)s of type %(vc_type)s"),
- locals(), context=context)
-
- _vsa_placement = vsa.get('placement', {})
- args = dict(display_name=display_name,
- display_description=vsa.get('displayDescription'),
- instance_type=instance_type,
- storage=vsa.get('storage'),
- shared=vsa.get('shared'),
- availability_zone=_vsa_placement.get('AvailabilityZone'))
-
- vsa = self.vsa_api.create(context, **args)
-
- instances = self._get_instances_by_vsa_id(context, vsa.get('id'))
- return {'vsa': _vsa_view(context, vsa, True, instances)}
-
- def delete(self, req, id):
- """Delete a VSA."""
- context = req.environ['nova.context']
- authorize(context)
-
- LOG.audit(_("Delete VSA with id: %s"), id, context=context)
-
- try:
- self.vsa_api.delete(context, vsa_id=id)
- except exception.NotFound:
- raise exc.HTTPNotFound()
-
- def associate_address(self, req, id, body):
- """ /zadr-vsa/{vsa_id}/associate_address
- auto or manually associate an IP to VSA
- """
- context = req.environ['nova.context']
- authorize(context)
-
- # FIXME(comstud): Seems like this always assigns 'auto' right
- # now despite what the docstring says this should support.
- if body is None:
- ip = 'auto'
- else:
- ip = body.get('ipAddress', 'auto')
-
- LOG.audit(_("Associate address %(ip)s to VSA %(id)s"),
- locals(), context=context)
-
- try:
- instances = self._get_instances_by_vsa_id(context, id)
- if instances is None or len(instances) == 0:
- raise exc.HTTPNotFound()
-
- for instance in instances:
- self.network_api.allocate_for_instance(context, instance,
- vpn=False)
- # Placeholder
- return
-
- except exception.NotFound:
- raise exc.HTTPNotFound()
-
- def disassociate_address(self, req, id, body):
- """ /zadr-vsa/{vsa_id}/disassociate_address
- auto or manually associate an IP to VSA
- """
- context = req.environ['nova.context']
- authorize(context)
-
- if body is None:
- ip = 'auto'
- else:
- ip = body.get('ipAddress', 'auto')
-
- LOG.audit(_("Disassociate address from VSA %(id)s"),
- locals(), context=context)
- # Placeholder
-
-
-def make_volume(elem):
- volumes.make_volume(elem)
- elem.set('name')
- elem.set('vsaId')
-
-
-class VsaVolumeDriveController(volumes.VolumeController):
- """The base class for VSA volumes & drives.
-
- A child resource of the VSA object. Allows operations with
- volumes and drives created to/from particular VSA
-
- """
-
- def __init__(self):
- self.volume_api = volume.API()
- self.vsa_api = vsa_api.API()
- super(VsaVolumeDriveController, self).__init__()
-
- def _translation(self, context, vol, vsa_id, details):
- if details:
- translation = volumes._translate_volume_detail_view
- else:
- translation = volumes._translate_volume_summary_view
-
- d = translation(context, vol)
- d['vsaId'] = vsa_id
- d['name'] = vol['name']
- return d
-
- def _check_volume_ownership(self, context, vsa_id, id):
- obj = self.object
- try:
- volume_ref = self.volume_api.get(context, id)
- except exception.NotFound:
- LOG.error(_("%(obj)s with ID %(id)s not found"), locals())
- raise
-
- own_vsa_id = self.volume_api.get_volume_metadata_value(volume_ref,
- self.direction)
- if own_vsa_id != vsa_id:
- LOG.error(_("%(obj)s with ID %(id)s belongs to VSA %(own_vsa_id)s"
- " and not to VSA %(vsa_id)s."), locals())
- raise exception.Invalid()
-
- def _items(self, req, vsa_id, details):
- """Return summary or detailed list of volumes for particular VSA."""
- context = req.environ['nova.context']
- authorize(context)
-
- vols = self.volume_api.get_all(context,
- search_opts={'metadata': {self.direction: str(vsa_id)}})
- limited_list = common.limited(vols, req)
-
- res = [self._translation(context, vol, vsa_id, details)
- for vol in limited_list]
-
- return {self.objects: res}
-
- def index(self, req, vsa_id):
- """Return a short list of volumes created from particular VSA."""
- LOG.audit(_("Index. vsa_id=%(vsa_id)s"), locals())
- return self._items(req, vsa_id, details=False)
-
- def detail(self, req, vsa_id):
- """Return a detailed list of volumes created from particular VSA."""
- LOG.audit(_("Detail. vsa_id=%(vsa_id)s"), locals())
- return self._items(req, vsa_id, details=True)
-
- def create(self, req, vsa_id, body):
- """Create a new volume from VSA."""
- LOG.audit(_("Create. vsa_id=%(vsa_id)s, body=%(body)s"), locals())
- context = req.environ['nova.context']
- authorize(context)
-
- if not body:
- raise exc.HTTPUnprocessableEntity()
-
- vol = body[self.object]
- size = vol['size']
- LOG.audit(_("Create volume of %(size)s GB from VSA ID %(vsa_id)s"),
- locals(), context=context)
- try:
- # create is supported for volumes only (drives created through VSA)
- volume_type = self.vsa_api.get_vsa_volume_type(context)
- except exception.NotFound:
- raise exc.HTTPNotFound()
-
- new_volume = self.volume_api.create(context,
- size,
- vol.get('displayName'),
- vol.get('displayDescription'),
- None,
- volume_type=volume_type,
- metadata=dict(from_vsa_id=str(vsa_id)))
-
- return {self.object: self._translation(context, new_volume,
- vsa_id, True)}
-
- def update(self, req, vsa_id, id, body):
- """Update a volume."""
- context = req.environ['nova.context']
- authorize(context)
-
- try:
- self._check_volume_ownership(context, vsa_id, id)
- except exception.NotFound:
- raise exc.HTTPNotFound()
- except exception.Invalid:
- raise exc.HTTPBadRequest()
-
- vol = body[self.object]
- updatable_fields = [{'displayName': 'display_name'},
- {'displayDescription': 'display_description'},
- {'status': 'status'},
- {'providerLocation': 'provider_location'},
- {'providerAuth': 'provider_auth'}]
- changes = {}
- for field in updatable_fields:
- key = field.keys()[0]
- val = field[key]
- if key in vol:
- changes[val] = vol[key]
-
- obj = self.object
- LOG.audit(_("Update %(obj)s with id: %(id)s, changes: %(changes)s"),
- locals(), context=context)
-
- try:
- volume = self.volume_api.get(context, id)
- self.volume_api.update(context, volume, fields=changes)
- except exception.NotFound:
- raise exc.HTTPNotFound()
- return webob.Response(status_int=202)
-
- def delete(self, req, vsa_id, id):
- """Delete a volume."""
- context = req.environ['nova.context']
- authorize(context)
-
- LOG.audit(_("Delete. vsa_id=%(vsa_id)s, id=%(id)s"), locals())
-
- try:
- self._check_volume_ownership(context, vsa_id, id)
- except exception.NotFound:
- raise exc.HTTPNotFound()
- except exception.Invalid:
- raise exc.HTTPBadRequest()
-
- return super(VsaVolumeDriveController, self).delete(req, id)
-
- def show(self, req, vsa_id, id):
- """Return data about the given volume."""
- context = req.environ['nova.context']
- authorize(context)
-
- LOG.audit(_("Show. vsa_id=%(vsa_id)s, id=%(id)s"), locals())
-
- try:
- self._check_volume_ownership(context, vsa_id, id)
- except exception.NotFound:
- raise exc.HTTPNotFound()
- except exception.Invalid:
- raise exc.HTTPBadRequest()
-
- return super(VsaVolumeDriveController, self).show(req, id)
-
-
-class VsaVolumeTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('volume', selector='volume')
- make_volume(root)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaVolumesTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('volumes')
- elem = xmlutil.SubTemplateElement(root, 'volume', selector='volumes')
- make_volume(elem)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaVolumeController(VsaVolumeDriveController):
- """The VSA volume API controller for the OpenStack API.
-
- A child resource of the VSA object. Allows operations with volumes created
- by particular VSA
-
- """
-
- def __init__(self):
- self.direction = 'from_vsa_id'
- self.objects = 'volumes'
- self.object = 'volume'
- super(VsaVolumeController, self).__init__()
-
- @wsgi.serializers(xml=VsaVolumesTemplate)
- def index(self, req, vsa_id):
- return super(VsaVolumeController, self).index(req, vsa_id)
-
- @wsgi.serializers(xml=VsaVolumesTemplate)
- def detail(self, req, vsa_id):
- return super(VsaVolumeController, self).detail(req, vsa_id)
-
- @wsgi.serializers(xml=VsaVolumeTemplate)
- def create(self, req, vsa_id, body):
- return super(VsaVolumeController, self).create(req, vsa_id, body)
-
- @wsgi.serializers(xml=VsaVolumeTemplate)
- def update(self, req, vsa_id, id, body):
- return super(VsaVolumeController, self).update(req, vsa_id, id, body)
-
- @wsgi.serializers(xml=VsaVolumeTemplate)
- def show(self, req, vsa_id, id):
- return super(VsaVolumeController, self).show(req, vsa_id, id)
-
-
-class VsaDriveTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('drive', selector='drive')
- make_volume(root)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaDrivesTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('drives')
- elem = xmlutil.SubTemplateElement(root, 'drive', selector='drives')
- make_volume(elem)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaDriveController(VsaVolumeDriveController):
- """The VSA Drive API controller for the OpenStack API.
-
- A child resource of the VSA object. Allows operations with drives created
- for particular VSA
-
- """
-
- def __init__(self):
- self.direction = 'to_vsa_id'
- self.objects = 'drives'
- self.object = 'drive'
- super(VsaDriveController, self).__init__()
-
- def create(self, req, vsa_id, body):
- """Create a new drive for VSA. Should be done through VSA APIs"""
- raise exc.HTTPBadRequest()
-
- def update(self, req, vsa_id, id, body):
- """Update a drive. Should be done through VSA APIs"""
- raise exc.HTTPBadRequest()
-
- def delete(self, req, vsa_id, id):
- """Delete a volume. Should be done through VSA APIs"""
- raise exc.HTTPBadRequest()
-
- @wsgi.serializers(xml=VsaDrivesTemplate)
- def index(self, req, vsa_id):
- return super(VsaDriveController, self).index(req, vsa_id)
-
- @wsgi.serializers(xml=VsaDrivesTemplate)
- def detail(self, req, vsa_id):
- return super(VsaDriveController, self).detail(req, vsa_id)
-
- @wsgi.serializers(xml=VsaDriveTemplate)
- def show(self, req, vsa_id, id):
- return super(VsaDriveController, self).show(req, vsa_id, id)
-
-
-def make_vpool(elem):
- elem.set('id')
- elem.set('vsaId')
- elem.set('name')
- elem.set('displayName')
- elem.set('displayDescription')
- elem.set('driveCount')
- elem.set('protection')
- elem.set('stripeSize')
- elem.set('stripeWidth')
- elem.set('createTime')
- elem.set('status')
-
- drive_ids = xmlutil.SubTemplateElement(elem, 'driveIds')
- drive_id = xmlutil.SubTemplateElement(drive_ids, 'driveId',
- selector='driveIds')
- drive_id.text = xmlutil.Selector()
-
-
-class VsaVPoolTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('vpool', selector='vpool')
- make_vpool(root)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaVPoolsTemplate(xmlutil.TemplateBuilder):
- def construct(self):
- root = xmlutil.TemplateElement('vpools')
- elem = xmlutil.SubTemplateElement(root, 'vpool', selector='vpools')
- make_vpool(elem)
- return xmlutil.MasterTemplate(root, 1)
-
-
-class VsaVPoolController(object):
- """The vPool VSA API controller for the OpenStack API."""
-
- def __init__(self):
- self.vsa_api = vsa_api.API()
- super(VsaVPoolController, self).__init__()
-
- @wsgi.serializers(xml=VsaVPoolsTemplate)
- def index(self, req, vsa_id):
- """Return a short list of vpools created from particular VSA."""
- return {'vpools': []}
-
- def create(self, req, vsa_id, body):
- """Create a new vPool for VSA."""
- raise exc.HTTPBadRequest()
-
- def update(self, req, vsa_id, id, body):
- """Update vPool parameters."""
- raise exc.HTTPBadRequest()
-
- def delete(self, req, vsa_id, id):
- """Delete a vPool."""
- raise exc.HTTPBadRequest()
-
- def show(self, req, vsa_id, id):
- """Return data about the given vPool."""
- raise exc.HTTPBadRequest()
-
-
-class VsaVCController(servers.Controller):
- """The VSA Virtual Controller API controller for the OpenStack API."""
-
- def __init__(self):
- self.vsa_api = vsa_api.API()
- self.compute_api = compute.API()
- self.vsa_id = None # VP-TODO(vladimir.p): temporary ugly hack
- super(VsaVCController, self).__init__()
-
- def _get_servers(self, req, is_detail):
- """Returns a list of servers, taking into account any search
- options specified.
- """
-
- if self.vsa_id is None:
- super(VsaVCController, self)._get_servers(req, is_detail)
-
- context = req.environ['nova.context']
-
- search_opts = {'metadata': dict(vsa_id=str(self.vsa_id))}
- instance_list = self.compute_api.get_all(
- context, search_opts=search_opts)
-
- limited_list = self._limit_items(instance_list, req)
- servers = [self._build_view(req, inst, is_detail)['server']
- for inst in limited_list]
- return dict(servers=servers)
-
- @wsgi.serializers(xml=servers.MinimalServersTemplate)
- def index(self, req, vsa_id):
- """Return list of instances for particular VSA."""
-
- LOG.audit(_("Index instances for VSA %s"), vsa_id)
-
- self.vsa_id = vsa_id # VP-TODO(vladimir.p): temporary ugly hack
- result = super(VsaVCController, self).detail(req)
- self.vsa_id = None
- return result
-
- def create(self, req, vsa_id, body):
- """Create a new instance for VSA."""
- raise exc.HTTPBadRequest()
-
- def update(self, req, vsa_id, id, body):
- """Update VSA instance."""
- raise exc.HTTPBadRequest()
-
- def delete(self, req, vsa_id, id):
- """Delete VSA instance."""
- raise exc.HTTPBadRequest()
-
- @wsgi.serializers(xml=servers.ServerTemplate)
- def show(self, req, vsa_id, id):
- """Return data about the given instance."""
- return super(VsaVCController, self).show(req, id)
-
-
-class Virtual_storage_arrays(extensions.ExtensionDescriptor):
- """Virtual Storage Arrays support"""
-
- name = "VSAs"
- alias = "zadr-vsa"
- namespace = "http://docs.openstack.org/compute/ext/vsa/api/v1.1"
- updated = "2011-08-25T00:00:00+00:00"
-
- def get_resources(self):
- resources = []
-
- res = extensions.ResourceExtension(
- 'zadr-vsa',
- VsaController(),
- collection_actions={'detail': 'GET'},
- member_actions={'add_capacity': 'POST',
- 'remove_capacity': 'POST',
- 'associate_address': 'POST',
- 'disassociate_address': 'POST'})
- resources.append(res)
-
- res = extensions.ResourceExtension('volumes',
- VsaVolumeController(),
- collection_actions={'detail': 'GET'},
- parent=dict(
- member_name='vsa',
- collection_name='zadr-vsa'))
- resources.append(res)
-
- res = extensions.ResourceExtension('drives',
- VsaDriveController(),
- collection_actions={'detail': 'GET'},
- parent=dict(
- member_name='vsa',
- collection_name='zadr-vsa'))
- resources.append(res)
-
- res = extensions.ResourceExtension('vpools',
- VsaVPoolController(),
- parent=dict(
- member_name='vsa',
- collection_name='zadr-vsa'))
- resources.append(res)
-
- res = extensions.ResourceExtension('instances',
- VsaVCController(),
- parent=dict(
- member_name='vsa',
- collection_name='zadr-vsa'))
- resources.append(res)
-
- return resources