# 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 copy api.""" from oslo_config import cfg from oslo_log import log as logging from oslo_utils import uuidutils from webob import exc from karbor.api import common from karbor.api.openstack import wsgi from karbor import exception from karbor.i18n import _ from karbor import objects from karbor.policies import copies as copy_policy from karbor.services.protection import api as protection_api CONF = cfg.CONF LOG = logging.getLogger(__name__) class CopiesViewBuilder(common.ViewBuilder): """Model a server API response as a python dictionary.""" def detail(self, request, copy): """Detailed view of a single copy.""" copy_ref = { 'copy': { 'project_id': copy.get('project_id'), 'provider_id': copy.get('provider_id'), 'plan_id': copy.get('plan_id'), 'checkpoint_id': copy.get('checkpoint_id'), 'parameters': copy.get('parameters'), } } return copy_ref class CopiesController(wsgi.Controller): """The copy API controller for the OpenStack API.""" _view_builder_class = CopiesViewBuilder def __init__(self): self.protection_api = protection_api.API() super(CopiesController, self).__init__() def create(self, req, provider_id, body): """Creates a new copy.""" if not self.is_valid_body(body, 'copy'): raise exc.HTTPUnprocessableEntity() LOG.debug('Create copy request body: %s', body) context = req.environ['karbor.context'] context.can(copy_policy.CREATE_POLICY) copy = body['copy'] plan_id = copy.get("plan_id", None) if not uuidutils.is_uuid_like(plan_id): msg = _("Invalid plan id provided.") raise exception.InvalidInput(reason=msg) if not uuidutils.is_uuid_like(provider_id): msg = _("Invalid provider id provided.") raise exception.InvalidInput(reason=msg) parameters = copy.get("parameters", None) if parameters: if not isinstance(parameters, dict): msg = _("The parameters must be a dict when creating" " a copy.") raise exception.InvalidInput(reason=msg) try: plan = objects.Plan.get_by_id(context, plan_id) except exception.PlanNotFound as error: raise exc.HTTPNotFound(explanation=error.msg) if provider_id != plan.provider_id: msg = _("The provider id is not the same as the value " "in the plan.") raise exception.InvalidInput(reason=msg) filters = {'plan_id': plan_id} checkpoints = self.protection_api.list_checkpoints( context, provider_id, marker=None, limit=None, sort_keys=None, sort_dirs=None, filters=filters, offset=None) if not checkpoints: msg = _("The plan has not been protected.") raise exception.InvalidInput(reason=msg) plan.parameters.update(parameters) try: checkpoint_copy = self.protection_api.copy(context, plan) except Exception: LOG.exception("Failed to create checkpoint copies.") raise copy = { 'project_id': context.project_id, 'provider_id': plan.provider_id, 'plan_id': plan.id, 'checkpoint_id': checkpoint_copy, 'parameters': parameters } retval = self._view_builder.detail(req, copy) return retval def create_resource(): return wsgi.Resource(CopiesController())