# Copyright 2019 NetApp, Inc. # 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. from oslo_log import log from six.moves import http_client import webob from webob import exc from manila.api.openstack import wsgi from manila.api.v1 import share_servers from manila.common import constants from manila.db import api as db_api from manila import exception from manila.i18n import _ from manila.share import utils as share_utils from manila import utils LOG = log.getLogger(__name__) class ShareServerController(share_servers.ShareServerController, wsgi.Controller, wsgi.AdminActionsMixin): """The Share Server API V2 controller for the OpenStack API.""" valid_statuses = { 'status': { constants.STATUS_ACTIVE, constants.STATUS_ERROR, constants.STATUS_DELETING, constants.STATUS_CREATING, constants.STATUS_MANAGING, constants.STATUS_UNMANAGING, constants.STATUS_UNMANAGE_ERROR, constants.STATUS_MANAGE_ERROR, } } def _update(self, context, id, update): db_api.share_server_update(context, id, update) @wsgi.Controller.api_version('2.49') @wsgi.action('reset_status') def share_server_reset_status(self, req, id, body): return self._reset_status(req, id, body) @wsgi.Controller.authorize('manage_share_server') def _manage(self, req, body): """Manage a share server.""" LOG.debug("Manage Share Server with id: %s", id) context = req.environ['manila.context'] identifier, host, share_network, driver_opts, network_subnet = ( self._validate_manage_share_server_parameters(context, body)) try: result = self.share_api.manage_share_server( context, identifier, host, network_subnet, driver_opts) except exception.InvalidInput as e: raise exc.HTTPBadRequest(explanation=e.msg) except exception.PolicyNotAuthorized as e: raise exc.HTTPForbidden(explanation=e.msg) result.project_id = share_network["project_id"] result.share_network_id = share_network["id"] if share_network['name']: result.share_network_name = share_network['name'] else: result.share_network_name = share_network['id'] return self._view_builder.build_share_server(req, result) @wsgi.Controller.api_version('2.51') @wsgi.response(202) def manage(self, req, body): return self._manage(req, body) @wsgi.Controller.api_version('2.49') # noqa @wsgi.response(202) def manage(self, req, body): # pylint: disable=function-redefined # noqa F811 body.get('share_server', {}).pop('share_network_subnet_id', None) return self._manage(req, body) @wsgi.Controller.authorize('unmanage_share_server') def _unmanage(self, req, id, body=None): context = req.environ['manila.context'] LOG.debug("Unmanage Share Server with id: %s", id) # force's default value is False # force will be True if body is {'unmanage': {'force': True}} force = (body.get('unmanage') or {}).get('force', False) or False try: share_server = db_api.share_server_get( context, id) except exception.ShareServerNotFound as e: raise exc.HTTPNotFound(explanation=e.msg) allowed_statuses = [constants.STATUS_ERROR, constants.STATUS_ACTIVE, constants.STATUS_MANAGE_ERROR, constants.STATUS_UNMANAGE_ERROR] if share_server['status'] not in allowed_statuses: data = { 'status': share_server['status'], 'allowed_statuses': ', '.join(allowed_statuses), } msg = _("Share server's actual status is %(status)s, allowed " "statuses for unmanaging are " "%(allowed_statuses)s.") % data raise exc.HTTPBadRequest(explanation=msg) try: self.share_api.unmanage_share_server( context, share_server, force=force) except (exception.ShareServerInUse, exception.PolicyNotAuthorized) as e: raise exc.HTTPBadRequest(explanation=e.msg) return webob.Response(status_int=http_client.ACCEPTED) @wsgi.Controller.api_version("2.49") @wsgi.action('unmanage') def unmanage(self, req, id, body=None): """Unmanage a share server.""" return self._unmanage(req, id, body) def _validate_manage_share_server_parameters(self, context, body): if not (body and self.is_valid_body(body, 'share_server')): msg = _("Share Server entity not found in request body") raise exc.HTTPUnprocessableEntity(explanation=msg) required_parameters = ('host', 'share_network_id', 'identifier') data = body['share_server'] for parameter in required_parameters: if parameter not in data: msg = _("Required parameter %s not found") % parameter raise exc.HTTPBadRequest(explanation=msg) if not data.get(parameter): msg = _("Required parameter %s is empty") % parameter raise exc.HTTPBadRequest(explanation=msg) identifier = data['identifier'] host, share_network_id = data['host'], data['share_network_id'] network_subnet_id = data.get('share_network_subnet_id') if network_subnet_id: try: network_subnet = db_api.share_network_subnet_get( context, network_subnet_id) except exception.ShareNetworkSubnetNotFound: msg = _("The share network subnet %s does not " "exist.") % network_subnet_id raise exc.HTTPBadRequest(explanation=msg) else: network_subnet = db_api.share_network_subnet_get_default_subnet( context, share_network_id) if network_subnet is None: msg = _("The share network %s does have a default subnet. Create " "one or use a specific subnet to manage this share server " "with API version >= 2.51.") % share_network_id raise exc.HTTPBadRequest(explanation=msg) if share_utils.extract_host(host, 'pool'): msg = _("Host parameter should not contain pool.") raise exc.HTTPBadRequest(explanation=msg) try: utils.validate_service_host( context, share_utils.extract_host(host)) except exception.ServiceNotFound as e: raise exc.HTTPBadRequest(explanation=e) except exception.PolicyNotAuthorized as e: raise exc.HTTPForbidden(explanation=e) except exception.AdminRequired as e: raise exc.HTTPForbidden(explanation=e) except exception.ServiceIsDown as e: raise exc.HTTPBadRequest(explanation=e) try: share_network = db_api.share_network_get( context, share_network_id) except exception.ShareNetworkNotFound as e: raise exc.HTTPBadRequest(explanation=e) driver_opts = data.get('driver_options') if driver_opts is not None and not isinstance(driver_opts, dict): msg = _("Driver options must be in dictionary format.") raise exc.HTTPBadRequest(explanation=msg) return identifier, host, share_network, driver_opts, network_subnet def create_resource(): return wsgi.Resource(ShareServerController())