manila/manila/api/v1/share_networks.py

295 lines
11 KiB
Python

# Copyright 2014 NetApp
# 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 shares api."""
import six
import webob
from webob import exc
from manila.api.openstack import wsgi
from manila.api.views import share_networks as share_networks_views
from manila.api import xmlutil
from manila.common import constants
from manila.db import api as db_api
from manila import exception
from manila import network
from manila.openstack.common import importutils
from manila.openstack.common import log as logging
from manila import policy
from manila import quota
from manila.share import rpcapi as share_rpcapi
RESOURCE_NAME = 'share_network'
RESOURCES_NAME = 'share_networks'
LOG = logging.getLogger(__name__)
QUOTAS = quota.QUOTAS
SHARE_NETWORK_ATTRS = (
'id',
'project_id',
'user_id',
'created_at',
'updated_at',
'neutron_net_id',
'neutron_subnet_id',
'network_type',
'segmentation_id',
'cidr',
'ip_version',
'name',
'description',
)
def _make_share_network(elem):
for attr in SHARE_NETWORK_ATTRS:
elem.set(attr)
class ShareNetworkTemplate(xmlutil.TemplateBuilder):
def construct(self):
root = xmlutil.TemplateElement(RESOURCE_NAME, selector=RESOURCE_NAME)
_make_share_network(root)
return xmlutil.MasterTemplate(root, 1)
class ShareNetworksTemplate(xmlutil.TemplateBuilder):
def construct(self):
root = xmlutil.TemplateElement(RESOURCES_NAME)
elem = xmlutil.SubTemplateElement(root, RESOURCE_NAME,
selector=RESOURCES_NAME)
_make_share_network(elem)
return xmlutil.MasterTemplate(root, 1)
class ShareNetworkController(wsgi.Controller):
"""The Share Network API controller for the OpenStack API."""
_view_builder_class = share_networks_views.ViewBuilder
def __init__(self):
super(ShareNetworkController, self).__init__()
self.share_rpcapi = share_rpcapi.ShareAPI()
@wsgi.serializers(xml=ShareNetworkTemplate)
def show(self, req, id):
"""Return data about the requested network info."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'show')
try:
share_network = db_api.share_network_get(context, id)
except exception.ShareNetworkNotFound as e:
msg = "%s" % e
raise exc.HTTPNotFound(explanation=msg)
return self._view_builder.build_share_network(share_network)
def delete(self, req, id):
"""Delete specified share network."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'delete')
try:
share_network = db_api.share_network_get(context, id)
except exception.ShareNetworkNotFound as e:
msg = "%s" % e
raise exc.HTTPNotFound(explanation=msg)
if share_network['share_servers']:
msg = _("Cannot delete share network %s. "
"There are share servers using it") % id
raise exc.HTTPForbidden(explanation=msg)
db_api.share_network_delete(context, id)
try:
reservations = QUOTAS.reserve(
context, project_id=share_network['project_id'],
share_networks=-1)
except Exception:
msg = _("Failed to update usages deleting share-network.")
LOG.exception(msg)
else:
QUOTAS.commit(context, reservations,
project_id=share_network['project_id'])
return webob.Response(status_int=202)
@wsgi.serializers(xml=ShareNetworksTemplate)
def _get_share_networks(self, req, is_detail=True):
"""Returns a list of share networks."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'index')
search_opts = {}
search_opts.update(req.GET)
if search_opts.pop('all_tenants', None):
networks = db_api.share_network_get_all(context)
else:
networks = db_api.share_network_get_all_by_project(
context,
context.project_id)
if search_opts:
for key, value in six.iteritems(search_opts):
networks = [network for network in networks
if network[key] == value]
return self._view_builder.build_share_networks(networks, is_detail)
@wsgi.serializers(xml=ShareNetworksTemplate)
def index(self, req):
"""Returns a summary list of share networks."""
return self._get_share_networks(req, is_detail=False)
@wsgi.serializers(xml=ShareNetworksTemplate)
def detail(self, req):
"""Returns a detailed list of share networks."""
return self._get_share_networks(req)
@wsgi.serializers(xml=ShareNetworkTemplate)
def update(self, req, id, body):
"""Update specified share network."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'update')
if not body or RESOURCE_NAME not in body:
raise exc.HTTPUnprocessableEntity()
try:
share_network = db_api.share_network_get(context, id)
except exception.ShareNetworkNotFound as e:
msg = "%s" % e
raise exc.HTTPNotFound(explanation=msg)
if share_network['share_servers']:
msg = _("Cannot update share network %s."
" It is used by share servers") % share_network['id']
raise exc.HTTPForbidden(explanation=msg)
update_values = body[RESOURCE_NAME]
try:
share_network = db_api.share_network_update(context,
id,
update_values)
except exception.DBError:
msg = "Could not save supplied data due to database error"
raise exc.HTTPBadRequest(explanation=msg)
return self._view_builder.build_share_network(share_network)
@wsgi.serializers(xml=ShareNetworkTemplate)
def create(self, req, body):
"""Creates a new share network."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'create')
if not body or RESOURCE_NAME not in body:
raise exc.HTTPUnprocessableEntity()
values = body[RESOURCE_NAME]
values['project_id'] = context.project_id
try:
reservations = QUOTAS.reserve(context, share_networks=1)
except exception.OverQuota as e:
overs = e.kwargs['overs']
usages = e.kwargs['usages']
quotas = e.kwargs['quotas']
def _consumed(name):
return (usages[name]['reserved'] + usages[name]['in_use'])
if 'share_networks' in overs:
msg = _("Quota exceeded for %(s_pid)s, tried to create"
" share-network (%(d_consumed)d of %(d_quota)d "
"already consumed)")
LOG.warn(msg % {'s_pid': context.project_id,
'd_consumed': _consumed('share_networks'),
'd_quota': quotas['share_networks']})
raise exception.ShareNetworksLimitExceeded(
allowed=quotas['share_networks'])
else:
try:
share_network = db_api.share_network_create(context, values)
except exception.DBError:
msg = "Could not save supplied data due to database error"
raise exc.HTTPBadRequest(explanation=msg)
QUOTAS.commit(context, reservations)
return self._view_builder.build_share_network(share_network)
@wsgi.serializers(xml=ShareNetworkTemplate)
def action(self, req, id, body):
_actions = {
'add_security_service': self._add_security_service,
'remove_security_service': self._remove_security_service
}
for action, data in six.iteritems(body):
try:
return _actions[action](req, id, data)
except KeyError:
msg = _("Share networks does not have %s action") % action
raise exc.HTTPBadRequest(explanation=msg)
def _add_security_service(self, req, id, data):
"""Associate share network with a given security service."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'add_security_service')
share_network = db_api.share_network_get(context, id)
if share_network['share_servers']:
msg = _("Cannot add security services. Share network is used.")
raise exc.HTTPForbidden(explanation=msg)
try:
share_network = db_api.share_network_add_security_service(
context,
id,
data['security_service_id'])
except KeyError:
msg = "Malformed request body"
raise exc.HTTPBadRequest(explanation=msg)
except exception.NotFound as e:
msg = "%s" % e
raise exc.HTTPNotFound(explanation=msg)
except exception.ShareNetworkSecurityServiceAssociationError as e:
msg = "%s" % e
raise exc.HTTPBadRequest(explanation=msg)
return self._view_builder.build_share_network(share_network)
def _remove_security_service(self, req, id, data):
"""Dissociate share network from a given security service."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'remove_security_service')
try:
share_network = db_api.share_network_remove_security_service(
context,
id,
data['security_service_id'])
except KeyError:
msg = "Malformed request body"
raise exc.HTTPBadRequest(explanation=msg)
except exception.NotFound as e:
msg = "%s" % e
raise exc.HTTPNotFound(explanation=msg)
except exception.ShareNetworkSecurityServiceDissociationError as e:
msg = "%s" % e
raise exc.HTTPBadRequest(explanation=msg)
return self._view_builder.build_share_network(share_network)
def create_resource():
return wsgi.Resource(ShareNetworkController())