Beispiel #1
0
def check_string_length(value, name, min_length=0, max_length=None):
    """Check the length of specified string.

    :param value: the value of the string
    :param name: the name of the string
    :param min_length: the min_length of the string
    :param max_length: the max_length of the string
    """
    if not isinstance(value, six.string_types):
        msg = _("%s is not a string or unicode") % name
        raise exception.InvalidInput(message=msg)

    if len(value) < min_length:
        msg = _("%(name)s has a minimum character requirement of "
                "%(min_length)s.") % {
                    'name': name,
                    'min_length': min_length
                }
        raise exception.InvalidInput(message=msg)

    if max_length and len(value) > max_length:
        msg = _("%(name)s has more than %(max_length)s "
                "characters.") % {
                    'name': name,
                    'max_length': max_length
                }
        raise exception.InvalidInput(message=msg)
Beispiel #2
0
    def validate_integer(value, name, min_value=None, max_value=None):
        """Make sure that value is a valid integer, potentially within range.

        :param value: the value of the integer
        :param name: the name of the integer
        :param min_length: the min_length of the integer
        :param max_length: the max_length of the integer
        :returns: integer
        """
        try:
            value = int(value)
        except (TypeError, ValueError, UnicodeEncodeError):
            raise webob.exc.HTTPBadRequest(
                explanation=(_('%s must be an integer.') % name))

        if min_value is not None and value < min_value:
            raise webob.exc.HTTPBadRequest(
                explanation=(_('%(value_name)s must be >= %(min_value)d') % {
                    'value_name': name,
                    'min_value': min_value
                }))
        if max_value is not None and value > max_value:
            raise webob.exc.HTTPBadRequest(
                explanation=(_('%(value_name)s must be <= %(max_value)d') % {
                    'value_name': name,
                    'max_value': max_value
                }))

        return value
Beispiel #3
0
    def create(self, req, body):
        """Creates a new restore."""
        if not self.is_valid_body(body, 'restore'):
            raise exc.HTTPUnprocessableEntity()

        LOG.debug('Create restore request body: %s', body)
        context = req.environ['smaug.context']
        check_policy(context, 'create')
        restore = body['restore']
        LOG.debug('Create restore request : %s', restore)

        if not restore.get("provider_id"):
            msg = _("provider_id must be provided when creating "
                    "a restore.")
            raise exception.InvalidInput(reason=msg)

        if not restore.get("checkpoint_id"):
            msg = _("checkpoint_id must be provided when creating "
                    "a restore.")
            raise exception.InvalidInput(reason=msg)

        parameters = restore.get("parameters")
        if not isinstance(parameters, dict):
            msg = _("parameters must be a dict when creating"
                    " a restore.")
            raise exception.InvalidInput(reason=msg)

        restore_properties = {
            'project_id': context.project_id,
            'provider_id': restore.get('provider_id'),
            'checkpoint_id': restore.get('checkpoint_id'),
            'restore_target': restore.get('restore_target'),
            'parameters': jsonutils.dumps(parameters),
            'status': 'started',
        }

        restoreobj = objects.Restore(context=context,
                                     **restore_properties)
        restoreobj.create()
        LOG.debug('call restore RPC  : restoreobj:%s', restoreobj)

        # call restore rpc API of protection service
        result = self.protection_api.restore(context, restoreobj)
        if result is True:
            status_update = "success"
        else:
            status_update = "failed"
        # update the status of restore
        update_dict = {
            "status": status_update
        }

        check_policy(context, 'update', restoreobj)
        self._restore_update(context,
                             restoreobj.get("id"), update_dict)

        restoreobj.update(update_dict)
        retval = self._view_builder.detail(req, restoreobj)

        return retval
Beispiel #4
0
    def validate_integer(value, name, min_value=None, max_value=None):
        """Make sure that value is a valid integer, potentially within range.

        :param value: the value of the integer
        :param name: the name of the integer
        :param min_length: the min_length of the integer
        :param max_length: the max_length of the integer
        :returns: integer
        """
        try:
            value = int(value)
        except (TypeError, ValueError, UnicodeEncodeError):
            raise webob.exc.HTTPBadRequest(explanation=(
                _('%s must be an integer.') % name))

        if min_value is not None and value < min_value:
            raise webob.exc.HTTPBadRequest(
                explanation=(_('%(value_name)s must be >= %(min_value)d') %
                             {'value_name': name, 'min_value': min_value}))
        if max_value is not None and value > max_value:
            raise webob.exc.HTTPBadRequest(
                explanation=(_('%(value_name)s must be <= %(max_value)d') %
                             {'value_name': name, 'max_value': max_value}))

        return value
Beispiel #5
0
    def _checkpoints_get_all(self, context, provider_id, marker=None,
                             limit=None, sort_keys=None, sort_dirs=None,
                             filters=None, offset=None):
        check_policy(context, 'checkpoint_get_all')

        if filters is None:
            filters = {}

        try:
            if limit is not None:
                limit = int(limit)
                if limit <= 0:
                    msg = _('limit param must be positive')
                    raise exception.InvalidInput(reason=msg)
        except ValueError:
            msg = _('limit param must be an integer')
            raise exception.InvalidInput(reason=msg)

        if filters:
            LOG.debug("Searching by: %s.", six.text_type(filters))

        checkpoints = self.protection_api.list_checkpoints(
            context, provider_id, marker, limit,
            sort_keys=sort_keys,
            sort_dirs=sort_dirs,
            filters=filters,
            offset=offset)

        LOG.info(_LI("Get all checkpoints completed successfully."))
        return checkpoints
Beispiel #6
0
    def create_trigger(self, context, trigger):
        if trigger.type not in ['time']:
            msg = (_("Invalid trigger type:%s") % trigger.type)
            raise exception.InvalidInput(msg)

        if trigger.properties['format'] not in ['crontab']:
            msg = (_("Invalid trigger time format type"))
            raise exception.InvalidInput(msg)
Beispiel #7
0
    def create_trigger(self, context, trigger):
        if trigger.type not in ['time']:
            msg = (_("Invalid trigger type:%s") % trigger.type)
            raise exception.InvalidInput(msg)

        if trigger.properties['format'] not in ['crontab']:
            msg = (_("Invalid trigger time format type"))
            raise exception.InvalidInput(msg)
Beispiel #8
0
    def check_time_format(cls, pattern):
        if not pattern:
            msg = (_("The trigger pattern is None"))
            raise exception.InvalidInput(msg)

        try:
            croniter(pattern)
        except Exception:
            msg = (_("The trigger pattern(%s) is invalid") % pattern)
            raise exception.InvalidInput(msg)
Beispiel #9
0
    def checkpoints_create(self, req, provider_id, body):
        """Creates a new checkpoint."""
        if not self.is_valid_body(body, 'checkpoint'):
            raise exc.HTTPUnprocessableEntity()

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

        LOG.debug('Create checkpoint request '
                  'body: %s provider_id:%s', body, provider_id)

        check_policy(context, 'checkpoint_create')
        checkpoint = body['checkpoint']
        LOG.debug('Create checkpoint request checkpoint: %s',
                  checkpoint)

        if not provider_id:
            msg = _("provider_id must be provided when creating "
                    "a checkpoint.")
            raise exception.InvalidInput(reason=msg)

        plan_id = checkpoint.get("plan_id")

        if not plan_id:
            msg = _("plan_id must be provided when creating "
                    "a checkpoint.")
            raise exception.InvalidInput(reason=msg)

        if not uuidutils.is_uuid_like(plan_id):
            msg = _("Invalid plan id provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        plan = objects.Plan.get_by_id(context, plan_id)
        if not plan:
            raise exception.PlanNotFound(plan_id=plan_id)

        checkpoint_properties = {
            'project_id': context.project_id,
            'status': 'protecting',
            'provider_id': provider_id,
            "protection_plan": {
                "id": plan.get("id"),
                "name": plan.get("name"),
                "resources": plan.get("resources"),
            }
        }
        checkpoint = self.protection_api.protect(context, plan)
        if checkpoint is not None:
            checkpoint_properties['id'] = checkpoint.get('checkpoint_id')
        else:
            msg = _("Get checkpoint failed.")
            raise exc.HTTPNotFound(explanation=msg)

        returnval = self._checkpoint_view_builder.detail(
            req, checkpoint_properties)
        return returnval
Beispiel #10
0
    def create(self, req, body):
        """Creates a new restore."""
        if not self.is_valid_body(body, 'restore'):
            raise exc.HTTPUnprocessableEntity()

        LOG.debug('Create restore request body: %s', body)
        context = req.environ['smaug.context']
        check_policy(context, 'create')
        restore = body['restore']
        LOG.debug('Create restore request : %s', restore)

        if not restore.get("provider_id"):
            msg = _("provider_id must be provided when creating " "a restore.")
            raise exception.InvalidInput(reason=msg)

        if not restore.get("checkpoint_id"):
            msg = _("checkpoint_id must be provided when creating "
                    "a restore.")
            raise exception.InvalidInput(reason=msg)

        parameters = restore.get("parameters")
        if not isinstance(parameters, dict):
            msg = _("parameters must be a dict when creating" " a restore.")
            raise exception.InvalidInput(reason=msg)

        restore_properties = {
            'project_id': context.project_id,
            'provider_id': restore.get('provider_id'),
            'checkpoint_id': restore.get('checkpoint_id'),
            'restore_target': restore.get('restore_target'),
            'parameters': parameters,
            'status': 'started',
        }

        restoreobj = objects.Restore(context=context, **restore_properties)
        restoreobj.create()
        LOG.debug('call restore RPC  : restoreobj:%s', restoreobj)

        # call restore rpc API of protection service
        result = self.protection_api.restore(context, restoreobj)
        if result is True:
            status_update = "success"
        else:
            status_update = "failed"
        # update the status of restore
        update_dict = {"status": status_update}

        check_policy(context, 'update', restoreobj)
        self._restore_update(context, restoreobj.get("id"), update_dict)

        restoreobj.update(update_dict)
        retval = self._view_builder.detail(req, restoreobj)

        return retval
Beispiel #11
0
    def checkpoints_create(self, req, provider_id, body):
        """Creates a new checkpoint."""
        if not self.is_valid_body(body, 'checkpoint'):
            raise exc.HTTPUnprocessableEntity()

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

        LOG.debug('Create checkpoint request '
                  'body: %s provider_id:%s', body, provider_id)

        check_policy(context, 'checkpoint_create')
        checkpoint = body['checkpoint']
        LOG.debug('Create checkpoint request checkpoint: %s', checkpoint)

        if not provider_id:
            msg = _("provider_id must be provided when creating "
                    "a checkpoint.")
            raise exception.InvalidInput(reason=msg)

        plan_id = checkpoint.get("plan_id")

        if not plan_id:
            msg = _("plan_id must be provided when creating " "a checkpoint.")
            raise exception.InvalidInput(reason=msg)

        if not uuidutils.is_uuid_like(plan_id):
            msg = _("Invalid plan id provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        plan = objects.Plan.get_by_id(context, plan_id)
        if not plan:
            raise exception.PlanNotFound(plan_id=plan_id)

        checkpoint_properties = {
            'project_id': context.project_id,
            'status': 'protecting',
            'provider_id': provider_id,
            "protection_plan": {
                "id": plan.get("id"),
                "name": plan.get("name"),
                "resources": plan.get("resources"),
            }
        }
        checkpoint = self.protection_api.protect(context, plan)
        if checkpoint is not None:
            checkpoint_properties['id'] = checkpoint.get('checkpoint_id')
        else:
            msg = _("Get checkpoint failed.")
            raise exc.HTTPNotFound(explanation=msg)

        returnval = self._checkpoint_view_builder.detail(
            req, checkpoint_properties)
        return returnval
Beispiel #12
0
def _get_offset_param(params):
    """Extract offset id from request's dictionary (defaults to 0) or fail."""
    try:
        offset = int(params.pop('offset', 0))
    except ValueError:
        msg = _('offset param must be an integer')
        raise webob.exc.HTTPBadRequest(explanation=msg)

    if offset < 0:
        msg = _('offset param must be positive')
        raise webob.exc.HTTPBadRequest(explanation=msg)

    return offset
Beispiel #13
0
    def _get_all(self,
                 context,
                 marker=None,
                 limit=None,
                 sort_keys=None,
                 sort_dirs=None,
                 filters=None,
                 offset=None):
        check_policy(context, 'get_all')

        if filters is None:
            filters = {}

        all_tenants = utils.get_bool_param('all_tenants', filters)

        try:
            if limit is not None:
                limit = int(limit)
                if limit <= 0:
                    msg = _('limit param must be positive')
                    raise exception.InvalidInput(reason=msg)
        except ValueError:
            msg = _('limit param must be an integer')
            raise exception.InvalidInput(reason=msg)

        if filters:
            LOG.debug("Searching by: %s.", six.text_type(filters))

        if context.is_admin and all_tenants:
            # Need to remove all_tenants to pass the filtering below.
            del filters['all_tenants']
            restores = objects.RestoreList.get_all(context,
                                                   marker,
                                                   limit,
                                                   sort_keys=sort_keys,
                                                   sort_dirs=sort_dirs,
                                                   filters=filters,
                                                   offset=offset)
        else:
            restores = objects.RestoreList.get_all_by_project(
                context,
                context.project_id,
                marker,
                limit,
                sort_keys=sort_keys,
                sort_dirs=sort_dirs,
                filters=filters,
                offset=offset)

        LOG.info(_LI("Get all restores completed successfully."))
        return restores
Beispiel #14
0
 def validate_plan_resources(self, plan):
     resources_list = plan["resources"]
     if (isinstance(resources_list, list)) and (len(resources_list) > 0):
         for resource in resources_list:
             if (isinstance(resource, dict) and (len(resource) == 3)
                     and {"id", "type", 'name'}.issubset(resource)):
                 pass
             else:
                 msg = _("Resource in list must be a dict when creating a "
                         "plan.The keys of resource are id,type and name.")
                 raise exception.InvalidInput(reason=msg)
     else:
         msg = _("list resources must be provided when creating " "a plan.")
         raise exception.InvalidInput(reason=msg)
Beispiel #15
0
    def _get_trigger_class(self, trigger_type):
        cls = self._trigger_cls_map.get(trigger_type, None)
        if not cls:
            msg = (_("Invalid trigger type:%s") % trigger_type)
            raise exception.InvalidInput(msg)

        return cls
Beispiel #16
0
 def create(self):
     if self.obj_attr_is_set('id'):
         raise exception.ObjectActionError(action='create',
                                           reason=_('already created'))
     updates = self.smaug_obj_get_changes()
     db_service = db.service_create(self._context, updates)
     self._from_db_object(self._context, self, db_service)
 def sync_status(self):
     for resource_id, resource_info in self.protection_resource_map.items():
         backup_id = resource_info["backup_id"]
         bank_section = resource_info["bank_section"]
         cinder_client = resource_info["cinder_client"]
         operation = resource_info["operation"]
         try:
             backup = cinder_client.backups.get(backup_id)
             if backup.status == "available":
                 bank_section.update_object(
                     "status", constants.RESOURCE_STATUS_AVAILABLE)
                 self.protection_resource_map.pop(resource_id)
             elif backup.status in ["error", "error-deleting"]:
                 bank_section.update_object(
                     "status", constants.RESOURCE_STATUS_ERROR)
                 self.protection_resource_map.pop(resource_id)
             else:
                 continue
         except Exception as exc:
             if operation == "delete" and type(exc) == NotFound:
                 bank_section.update_object(
                     "status",
                     constants.RESOURCE_STATUS_DELETED)
                 LOG.info(_("deleting volume backup finished."
                            "backup id: %s"), backup_id)
             else:
                 LOG.error(_LE("deleting volume backup error.exc:%s."),
                           six.text_type(exc))
             self.protection_resource_map.pop(resource_id)
Beispiel #18
0
    def __init__(self, name, loader=None):
        """Initialize, but do not start the WSGI server.

        :param name: The name of the WSGI server given to the loader.
        :param loader: Loads the WSGI application using the given name.
        :returns: None

        """
        self.name = name
        self.manager = self._get_manager()
        self.loader = loader or wsgi_common.Loader()
        self.app = self.loader.load_app(name)
        self.host = getattr(CONF, '%s_listen' % name, "0.0.0.0")
        self.port = getattr(CONF, '%s_listen_port' % name, 0)
        self.workers = (getattr(CONF, '%s_workers' % name, None) or
                        processutils.get_worker_count())
        if self.workers and self.workers < 1:
            worker_name = '%s_workers' % name
            msg = (_("%(worker_name)s value of %(workers)d is invalid, "
                     "must be greater than 0.") %
                   {'worker_name': worker_name,
                    'workers': self.workers})
            raise exception.InvalidInput(msg)

        self.server = wsgi.Server(name,
                                  self.app,
                                  host=self.host,
                                  port=self.port)
Beispiel #19
0
 def _sync_status(self, checkpoint, status_getters):
     status = {}
     for s in status_getters:
         resource_id = s.get('resource_id')
         get_resource_stats = s.get('get_resource_stats')
         status[resource_id] = get_resource_stats(checkpoint,
                                                  resource_id)
     if constants.RESOURCE_STATUS_ERROR in status.values():
         checkpoint.status = constants.CHECKPOINT_STATUS_ERROR
         checkpoint.commit()
     elif constants.RESOURCE_STATUS_PROTECTING in status.values():
         checkpoint.status = constants.CHECKPOINT_STATUS_PROTECTING
         checkpoint.commit()
     elif constants.RESOURCE_STATUS_UNDEFINED in status.values():
         checkpoint.status = constants.CHECKPOINT_STATUS_PROTECTING
         checkpoint.commit()
     else:
         checkpoint.status = constants.CHECKPOINT_STATUS_AVAILABLE
         checkpoint.commit()
         LOG.info(_("Stop sync checkpoint status,checkpoint_id:"
                    "%(checkpoint_id)s,checkpoint status:"
                    "%(checkpoint_status)s") %
                  {"checkpoint_id": checkpoint.id,
                   "checkpoint_status": checkpoint.status})
         raise loopingcall.LoopingCallDone()
Beispiel #20
0
    def instances_show(self, req, protectable_type, protectable_id):
        """Return a instance about the given protectable_type and id."""

        context = req.environ['smaug.context']
        LOG.info(_LI("Show the instance of a given protectable"
                     " type: %s"), protectable_type)

        protectable_types = self._get_all(context)

        if protectable_type not in protectable_types:
            msg = _("Invalid protectable type provided.")
            raise exception.InvalidInput(reason=msg)

        instance = self.protection_api.\
            show_protectable_instance(context, protectable_type,
                                      protectable_id)
        if instance is None:
            raise exception.InvalidProtectableInstance(
                protectable_id=instance.get('id'))

        dependents = self.protection_api.\
            list_protectable_dependents(context, protectable_id,
                                        protectable_type)
        instance["dependent_resources"] = dependents

        retval_instance = self._view_builder.detail(req, instance)
        return retval_instance
Beispiel #21
0
    def create_backup(self, cntxt, checkpoint, **kwargs):
        resource_node = kwargs.get("node")
        image_id = resource_node.value.id
        bank_section = checkpoint.get_resource_bank_section(image_id)

        resource_definition = {"resource_id": image_id}
        glance_client = self._glance_client(cntxt)

        LOG.info(_("creating image backup, image_id: %s."), image_id)
        try:
            bank_section.create_object("status",
                                       constants.RESOURCE_STATUS_PROTECTING)
            image_info = glance_client.images.get(image_id)
            image_metadata = {
                "disk_format": image_info.disk_format,
                "container_format": image_info.container_format
            }
            resource_definition["image_metadata"] = image_metadata
            resource_definition["backup_id"] = image_id

            bank_section.create_object("metadata", resource_definition)
        except Exception as err:
            LOG.error(_LE("create image backup failed, image_id: %s."),
                      image_id)
            bank_section.update_object("status",
                                       constants.RESOURCE_STATUS_ERROR)
            raise exception.CreateBackupFailed(
                reason=err,
                resource_id=image_id,
                resource_type=constants.IMAGE_RESOURCE_TYPE)

        self._add_to_threadpool(self._create_backup, glance_client,
                                bank_section, image_id)
    def _get_trigger_class(self, trigger_type):
        cls = self._trigger_cls_map.get(trigger_type, None)
        if not cls:
            msg = (_("Invalid trigger type:%s") % trigger_type)
            raise exception.InvalidInput(msg)

        return cls
Beispiel #23
0
    def __call__(self, environ, start_response):
        """Subclasses will probably want to implement __call__ like this:

        @webob.dec.wsgify(RequestClass=Request)
        def __call__(self, req):
          # Any of the following objects work as responses:

          # Option 1: simple string
          res = 'message\n'

          # Option 2: a nicely formatted HTTP exception page
          res = exc.HTTPForbidden(explanation='Nice try')

          # Option 3: a webob Response object (in case you need to play with
          # headers, or you want to be treated like an iterable)
          res = Response();
          res.app_iter = open('somefile')

          # Option 4: any wsgi app to be run next
          res = self.application

          # Option 5: you can get a Response object for a wsgi app, too, to
          # play with headers etc
          res = req.get_response(self.application)

          # You can then just return your response...
          return res
          # ... or set req.response and return None.
          req.response = res

        See the end of http://pythonpaste.org/webob/modules/dec.html
        for more info.

        """
        raise NotImplementedError(_('You must implement __call__'))
Beispiel #24
0
    def __call__(self, environ, start_response):
        """Subclasses will probably want to implement __call__ like this:

        @webob.dec.wsgify(RequestClass=Request)
        def __call__(self, req):
          # Any of the following objects work as responses:

          # Option 1: simple string
          res = 'message\n'

          # Option 2: a nicely formatted HTTP exception page
          res = exc.HTTPForbidden(explanation='Nice try')

          # Option 3: a webob Response object (in case you need to play with
          # headers, or you want to be treated like an iterable)
          res = Response();
          res.app_iter = open('somefile')

          # Option 4: any wsgi app to be run next
          res = self.application

          # Option 5: you can get a Response object for a wsgi app, too, to
          # play with headers etc
          res = req.get_response(self.application)

          # You can then just return your response...
          return res
          # ... or set req.response and return None.
          req.response = res

        See the end of http://pythonpaste.org/webob/modules/dec.html
        for more info.

        """
        raise NotImplementedError(_('You must implement __call__'))
Beispiel #25
0
 def _sync_status(self, checkpoint, status_getters):
     status = {}
     for s in status_getters:
         resource_id = s.get('resource_id')
         get_resource_stats = s.get('get_resource_stats')
         status[resource_id] = get_resource_stats(checkpoint, resource_id)
     if constants.RESOURCE_STATUS_ERROR in status.values():
         checkpoint.status = constants.CHECKPOINT_STATUS_ERROR
         checkpoint.commit()
     elif constants.RESOURCE_STATUS_PROTECTING in status.values():
         checkpoint.status = constants.CHECKPOINT_STATUS_PROTECTING
         checkpoint.commit()
     elif constants.RESOURCE_STATUS_UNDEFINED in status.values():
         checkpoint.status = constants.CHECKPOINT_STATUS_PROTECTING
         checkpoint.commit()
     else:
         checkpoint.status = constants.CHECKPOINT_STATUS_AVAILABLE
         checkpoint.commit()
         LOG.info(
             _("Stop sync checkpoint status,checkpoint_id:"
               "%(checkpoint_id)s,checkpoint status:"
               "%(checkpoint_status)s") % {
                   "checkpoint_id": checkpoint.id,
                   "checkpoint_status": checkpoint.status
               })
         raise loopingcall.LoopingCallDone()
Beispiel #26
0
def action_peek_json(body):
    """Determine action to invoke."""

    try:
        decoded = jsonutils.loads(body)
    except ValueError:
        msg = _("cannot understand JSON")
        raise exception.MalformedRequestBody(reason=msg)

    # Make sure there's exactly one key...
    if len(decoded) != 1:
        msg = _("too many body keys")
        raise exception.MalformedRequestBody(reason=msg)

    # Return the action and the decoded body...
    return list(decoded.keys())[0]
Beispiel #27
0
    def instances_show(self, req, protectable_type, protectable_id):
        """Return a instance about the given protectable_type and id."""

        context = req.environ['smaug.context']
        LOG.info(_LI("Show the instance of a given protectable"
                     " type: %s"), protectable_type)

        protectable_types = self._get_all(context)

        if protectable_type not in protectable_types:
            msg = _("Invalid protectable type provided.")
            raise exception.InvalidInput(reason=msg)

        instance = self.protection_api.\
            show_protectable_instance(context, protectable_type,
                                      protectable_id)
        if instance is None:
            raise exception.InvalidProtectableInstance(
                protectable_id=instance.get('id'))

        dependents = self.protection_api.\
            list_protectable_dependents(context, protectable_id,
                                        protectable_type)
        instance["dependent_resources"] = dependents

        retval_instance = self._view_builder.detail(req, instance)
        return retval_instance
Beispiel #28
0
    def delete(self, req, id):
        """Delete a trigger."""

        LOG.debug('Delete trigger(%s) start', id)

        context = req.environ['smaug.context']
        trigger = self._get_trigger_by_id(context, id)

        check_policy(context, 'delete', trigger)

        try:
            operations = objects.ScheduledOperationList.get_by_filters(
                context, {"trigger_id": id}, limit=1)
        except Exception as ex:
            self._raise_unknown_exception(ex)

        if operations:
            msg = _("There are more than one scheduled operations binded "
                    "with this trigger, please delete them first")
            raise exc.HTTPMethodNotAllowed(explanation=msg)

        try:
            self.operationengine_api.delete_trigger(context, id)
        except exception.TriggerNotFound as ex:
            pass
        except (exception.DeleteTriggerNotAllowed,
                Exception) as ex:
            self._raise_unknown_exception(ex)

        trigger.destroy()
Beispiel #29
0
def _parse_service_catalog_info(config, context):
    try:
        service_type, service_name, endpoint_type = config.split(':')
    except ValueError:
        msg = _("Failed to parse the catalog info option %s, "
                "must be in the form: "
                "<service_type>:<service_name>:<endpoint_type>") % config
        raise exception.SmaugException(msg)

    for entry in context.service_catalog:
        if entry.get('type') == service_type:
            return entry.get('endpoints')[0].get(endpoint_type)

    raise exception.SmaugException(
        _("Couldn't find the endpoint of service type %s "
          "from service catalog") % service_type)
Beispiel #30
0
def action_peek_json(body):
    """Determine action to invoke."""

    try:
        decoded = jsonutils.loads(body)
    except ValueError:
        msg = _("cannot understand JSON")
        raise exception.MalformedRequestBody(reason=msg)

    # Make sure there's exactly one key...
    if len(decoded) != 1:
        msg = _("too many body keys")
        raise exception.MalformedRequestBody(reason=msg)

    # Return the action and the decoded body...
    return list(decoded.keys())[0]
Beispiel #31
0
 def create(self):
     if self.obj_attr_is_set('id'):
         raise exception.ObjectActionError(action='create',
                                           reason=_('already created'))
     updates = self.smaug_obj_get_changes()
     db_operation_log = db.operation_log_create(self._context, updates)
     self._from_db_object(self._context, self, db_operation_log)
Beispiel #32
0
    def show(self, req, id):
        """Return data about the given protectable_type."""
        context = req.environ['smaug.context']
        protectable_type = id
        LOG.info(
            _LI("Show the information of a given"
                " protectable type: %s"), protectable_type)

        protectable_types = self._get_all(context)

        if protectable_type not in protectable_types:
            msg = _("Invalid protectable type provided.")
            raise exception.InvalidInput(reason=msg)

        check_policy(context, 'get')
        try:
            retval_protectable_type = self.protection_api.\
                show_protectable_type(context, protectable_type)
        except exception.ProtectableTypeNotFound as error:
            raise exc.HTTPNotFound(explanation=error.msg)

        LOG.info(
            _LI("Show the protectable type information"
                " issued successfully."))
        return self._view_builder.show(req, retval_protectable_type)
    def delete_backup(self, cntxt, checkpoint, **kwargs):
        resource_node = kwargs.get("node")
        resource_id = resource_node.value.id

        bank_section = checkpoint.get_resource_bank_section(resource_id)
        cinder_client = self._cinder_client(cntxt)

        LOG.info(_("deleting volume backup, volume_id: %s."), resource_id)
        try:
            bank_section.update_object("status",
                                       constants.RESOURCE_STATUS_DELETING)
            resource_definition = bank_section.get_object("metadata")
            backup_id = resource_definition["backup_id"]
            cinder_client.backups.delete(backup_id)
            bank_section.delete_object("metadata", resource_definition)
            self.protection_resource_map[resource_id] = {
                "bank_section": bank_section,
                "backup_id": backup_id,
                "cinder_client": cinder_client,
                "operation": "delete"
            }
        except Exception as e:
            LOG.error(_LE("delete volume backup failed, volume_id: %s."),
                      resource_id)
            bank_section.update_object("status",
                                       constants.CHECKPOINT_STATUS_ERROR)

            raise exception.DeleteBackupFailed(
                reason=six.text_type(e),
                resource_id=resource_id,
                resource_type=constants.VOLUME_RESOURCE_TYPE)
    def delete_backup(self, cntxt, checkpoint, **kwargs):
        resource_node = kwargs.get("node")
        resource_id = resource_node.value.id

        bank_section = checkpoint.get_resource_bank_section(resource_id)
        cinder_client = self._cinder_client(cntxt)

        LOG.info(_("deleting volume backup, volume_id: %s."), resource_id)
        try:
            bank_section.update_object("status",
                                       constants.RESOURCE_STATUS_DELETING)
            resource_definition = bank_section.get_object("metadata")
            backup_id = resource_definition["backup_id"]
            cinder_client.backups.delete(backup_id)
            bank_section.delete_object("metadata", resource_definition)
            self.protection_resource_map[resource_id] = {
                "bank_section": bank_section,
                "backup_id": backup_id,
                "cinder_client": cinder_client,
                "operation": "delete"
            }
        except Exception as e:
            LOG.error(_LE("delete volume backup failed, volume_id: %s."),
                      resource_id)
            bank_section.update_object("status",
                                       constants.CHECKPOINT_STATUS_ERROR)

            raise exception.DeleteBackupFailed(
                reason=six.text_type(e),
                resource_id=resource_id,
                resource_type=constants.VOLUME_RESOURCE_TYPE
            )
Beispiel #35
0
def model_query(context, *args, **kwargs):
    """Query helper that accounts for context's `read_deleted` field.

    :param context: context to query under
    :param session: if present, the session to use
    :param read_deleted: if present, overrides context's read_deleted field.
    :param project_only: if present and context is user-type, then restrict
            query to match the context's project_id.
    """
    session = kwargs.get('session') or get_session()
    read_deleted = kwargs.get('read_deleted') or context.read_deleted
    project_only = kwargs.get('project_only')

    query = session.query(*args)
    if read_deleted == 'no':
        query = query.filter_by(deleted=False)
    elif read_deleted == 'yes':
        pass  # omit the filter to include deleted and active
    elif read_deleted == 'only':
        query = query.filter_by(deleted=True)
    else:
        raise Exception(
            _("Unrecognized read_deleted value '%s'") % read_deleted)

    if project_only and is_user_context(context):
        query = query.filter_by(project_id=context.project_id)

    return query
Beispiel #36
0
def model_query(context, *args, **kwargs):
    """Query helper that accounts for context's `read_deleted` field.

    :param context: context to query under
    :param session: if present, the session to use
    :param read_deleted: if present, overrides context's read_deleted field.
    :param project_only: if present and context is user-type, then restrict
            query to match the context's project_id.
    """
    session = kwargs.get('session') or get_session()
    read_deleted = kwargs.get('read_deleted') or context.read_deleted
    project_only = kwargs.get('project_only')

    query = session.query(*args)
    if read_deleted == 'no':
        query = query.filter_by(deleted=False)
    elif read_deleted == 'yes':
        pass  # omit the filter to include deleted and active
    elif read_deleted == 'only':
        query = query.filter_by(deleted=True)
    else:
        raise Exception(
            _("Unrecognized read_deleted value '%s'") % read_deleted)

    if project_only and is_user_context(context):
        query = query.filter_by(project_id=context.project_id)

    return query
    def create_backup(self, cntxt, checkpoint, **kwargs):
        resource_node = kwargs.get("node")
        image_id = resource_node.value.id
        bank_section = checkpoint.get_resource_bank_section(image_id)

        resource_definition = {"resource_id": image_id}
        glance_client = self._glance_client(cntxt)

        LOG.info(_("creating image backup, image_id: %s."), image_id)
        try:
            bank_section.create_object("status",
                                       constants.RESOURCE_STATUS_PROTECTING)
            image_info = glance_client.images.get(image_id)
            image_metadata = {
                "disk_format": image_info.disk_format,
                "container_format": image_info.container_format
            }
            resource_definition["image_metadata"] = image_metadata
            resource_definition["backup_id"] = image_id

            bank_section.create_object("metadata", resource_definition)
        except Exception as err:
            LOG.error(_LE("create image backup failed, image_id: %s."),
                      image_id)
            bank_section.update_object("status",
                                       constants.RESOURCE_STATUS_ERROR)
            raise exception.CreateBackupFailed(
                reason=err,
                resource_id=image_id,
                resource_type=constants.IMAGE_RESOURCE_TYPE)

        self._add_to_threadpool(self._create_backup, glance_client,
                                bank_section, image_id)
Beispiel #38
0
    def protect(self, context, plan):
        """create protection for the given plan

        :param plan: Define that protection plan should be done
        """

        LOG.info(_LI("Starting protection service:protect action"))
        LOG.debug('protecting  :%s tpye:%s', plan, type(plan))

        if not plan:
            raise exception.InvalidPlan(reason='the protection plan is None')
        provider_id = plan.get('provider_id', None)
        plan_id = plan.get('id', None)
        provider = self.provider_registry.show_provider(provider_id)
        if not provider:
            raise exception.ProviderNotFound(provider_id=provider_id)
        try:
            protection_flow = self.worker.get_flow(context,
                                                   constants.OPERATION_PROTECT,
                                                   plan=plan,
                                                   provider=provider)
        except Exception:
            LOG.exception(_LE("Failed to create protection flow,plan:%s"),
                          plan_id)
            raise exception.SmaugException(
                _("Failed to create protection flow"))
        try:
            self.worker.run_flow(protection_flow)
        except Exception:
            LOG.exception(_LE("Failed to run protection flow"))
            raise
        finally:
            checkpoint = self.worker.flow_outputs(protection_flow,
                                                  target='checkpoint')
            return {'checkpoint_id': checkpoint.id}
Beispiel #39
0
    def update(self, req, id, body):
        """Update a plan."""
        context = req.environ['smaug.context']

        if not body:
            msg = _("Missing request body")
            raise exc.HTTPBadRequest(explanation=msg)

        if 'plan' not in body:
            msg = _("Missing required element '%s' in request body") % 'plan'
            raise exc.HTTPBadRequest(explanation=msg)

        if not uuidutils.is_uuid_like(id):
            msg = _("Invalid plan id provided.")
            raise exc.HTTPBadRequest(explanation=msg)

        plan = body['plan']
        update_dict = {}

        valid_update_keys = {
            'name',
            'resources',
            'status',
        }
        for key in valid_update_keys.intersection(plan):
            update_dict[key] = plan[key]

        if update_dict is None:
            msg = _("Missing updated parameters in request body.")
            raise exc.HTTPBadRequest(explanation=msg)

        self.validate_name_and_description(update_dict)
        if update_dict.get("resources"):
            self.validate_plan_resources(update_dict)

        try:
            plan = self._plan_get(context, id)
        except exception.PlanNotFound as error:
            raise exc.HTTPNotFound(explanation=error.msg)

        check_policy(context, 'update', plan)
        self._plan_update(context, plan, update_dict)

        plan.update(update_dict)

        retval = self._view_builder.detail(req, plan)
        return retval
Beispiel #40
0
def get_bool_param(param_string, params):
    param = params.get(param_string, False)
    if not is_valid_boolstr(param):
        msg = _('Value %(param)s for %(param_string)s is not a '
                'boolean.') % {'param': param, 'param_string': param_string}
        raise exception.InvalidParameterValue(err=msg)

    return strutils.bool_from_string(param, strict=True)
Beispiel #41
0
 def _raise_unknown_exception(self, exception_instance):
     value = exception_instance.msg if isinstance(
         exception_instance, exception.SmaugException) else type(
         exception_instance)
     msg = (_('Unexpected API Error. Please report this at '
              'http://bugs.launchpad.net/smaug/ and attach the '
              'Smaug API log if possible.\n%s') % value)
     raise exc.HTTPInternalServerError(explanation=msg)
Beispiel #42
0
 def _plan_update(self, context, plan, fields):
     if plan['status'] != 'suspended':
         LOG.info(
             _LI("Unable to update plan, "
                 "because it is in %s state."), plan['status'])
         msg = _("The plan can be only updated in suspended status.")
         raise exception.InvalidPlan(reason=msg)
     # TODO(chenying) replication scene: need call rpc API when
     # the status of the plan is changed.
     if isinstance(plan, objects_base.SmaugObject):
         plan.update(fields)
         plan.save()
         LOG.info(_LI("Plan updated successfully."), resource=plan)
     else:
         msg = _("The parameter plan must be a object of "
                 "SmaugObject class.")
         raise exception.InvalidInput(reason=msg)
Beispiel #43
0
    def _prepend_prefix(self, key):
        if not key:
            raise RuntimeError(_("No key specified"))

        if not key.startswith("/"):
            key = "/" + key

        return "%s%s" % (self._prefix, key)
Beispiel #44
0
    def add_trigger(self, trigger_id, trigger_type, trigger_property):
        if trigger_id in self._trigger_obj_map:
            msg = (_("Trigger id  %s is exist") % trigger_id)
            raise exception.InvalidInput(msg)

        trigger_cls = self._get_trigger_class(trigger_type)
        trigger = trigger_cls(trigger_id, trigger_property, self._executor)
        self._trigger_obj_map[trigger_id] = trigger
Beispiel #45
0
    def check_trigger_definition(cls, trigger_definition):
        """Check trigger definition

        All the time instances of trigger_definition are in UTC,
        including start_time, end_time
        """

        trigger_format = trigger_definition.get("format", None)
        pattern = trigger_definition.get("pattern", None)
        cls.TIME_FORMAT_MANAGER.check_time_format(trigger_format, pattern)

        interval = int(
            cls.TIME_FORMAT_MANAGER.get_interval(trigger_format, pattern))
        if interval < CONF.min_interval:
            msg = (_("The interval of two adjacent time points "
                     "is less than %d") % CONF.min_interval)
            raise exception.InvalidInput(msg)

        window = trigger_definition.get("window", CONF.window_time)
        if not isinstance(window, int):
            try:
                window = int(window)
            except Exception:
                msg = (_("The trigger windows(%s) is not integer") % window)
                raise exception.InvalidInput(msg)
        if window <= 0:
            msg = (_("The trigger windows(%d) must be positive") % window)
            raise exception.InvalidInput(msg)
        if (window * 2) > interval:
            msg = (_("The trigger windows%(window)d must be less "
                     "than %(interval)d") % {
                         "window": window,
                         "interval": interval / 2
                     })
            raise exception.InvalidInput(msg)

        end_time = trigger_definition.get("end_time", None)
        end_time = cls._check_and_get_datetime(end_time, "end_time")

        start_time = trigger_definition.get("start_time", None)
        start_time = cls._check_and_get_datetime(start_time, "start_time")

        valid_trigger_property = trigger_definition.copy()
        valid_trigger_property['start_time'] = start_time
        valid_trigger_property['end_time'] = end_time
        return valid_trigger_property
Beispiel #46
0
def get_bool_param(param_string, params):
    param = params.get(param_string, False)
    if not is_valid_boolstr(param):
        msg = _('Value %(param)s for %(param_string)s is not a '
                'boolean.') % {'param': param, 'param_string': param_string}
        raise exception.InvalidParameterValue(err=msg)

    return strutils.bool_from_string(param, strict=True)
Beispiel #47
0
def _get_limit_param(params, max_limit=None):
    """Extract integer limit from request's dictionary or fail.

   Defaults to max_limit if not present and returns max_limit if present
   'limit' is greater than max_limit.
    """
    max_limit = max_limit or CONF.osapi_max_limit
    try:
        limit = int(params.pop('limit', max_limit))
    except ValueError:
        msg = _('limit param must be an integer')
        raise webob.exc.HTTPBadRequest(explanation=msg)
    if limit <= 0:
        msg = _('limit param must be positive')
        raise webob.exc.HTTPBadRequest(explanation=msg)
    limit = min(limit, max_limit)
    return limit
    def add_trigger(self, trigger_id, trigger_type, trigger_property):
        if trigger_id in self._trigger_obj_map:
            msg = (_("Trigger id  %s is exist") % trigger_id)
            raise exception.InvalidInput(msg)

        trigger_cls = self._get_trigger_class(trigger_type)
        trigger = trigger_cls(trigger_id, trigger_property, self._executor)
        self._trigger_obj_map[trigger_id] = trigger
Beispiel #49
0
    def _check_and_get_datetime(cls, time, time_name):
        if not time or isinstance(time, datetime):
            return time

        if not isinstance(time, six.string_types):
            msg = (_("The trigger %(name)s(type = %(vtype)s) is not an "
                     "instance of string") %
                   {"name": time_name, "vtype": type(time)})
            raise exception.InvalidInput(msg)

        try:
            time = timeutils.parse_strtime(time, fmt='%Y-%m-%d %H:%M:%S')
        except Exception:
            msg = (_("The format of trigger %s is not correct") % time_name)
            raise exception.InvalidInput(msg)

        return time
Beispiel #50
0
def _parse_service_catalog_info(config, context):
    try:
        service_type, service_name, endpoint_type = config.split(':')
    except ValueError:
        msg = _("Failed to parse the catalog info option %s, "
                "must be in the form: "
                "<service_type>:<service_name>:<endpoint_type>"
                ) % config
        raise exception.SmaugException(msg)

    for entry in context.service_catalog:
        if entry.get('type') == service_type:
            return entry.get('endpoints')[0].get(endpoint_type)

    raise exception.SmaugException(_(
        "Couldn't find the endpoint of service type %s "
        "from service catalog") % service_type)
Beispiel #51
0
    def check_trigger_definition(cls, trigger_definition):
        """Check trigger definition

        All the time instances of trigger_definition are in UTC,
        including start_time, end_time
        """

        trigger_format = trigger_definition.get("format", None)
        pattern = trigger_definition.get("pattern", None)
        cls.TIME_FORMAT_MANAGER.check_time_format(
            trigger_format, pattern)

        interval = int(cls.TIME_FORMAT_MANAGER.get_interval(
            trigger_format, pattern))
        if interval < CONF.min_interval:
            msg = (_("The interval of two adjacent time points "
                     "is less than %d") % CONF.min_interval)
            raise exception.InvalidInput(msg)

        window = trigger_definition.get("window", CONF.window_time)
        if not isinstance(window, int):
            try:
                window = int(window)
            except Exception:
                msg = (_("The trigger windows(%s) is not integer") % window)
                raise exception.InvalidInput(msg)
        if window <= 0:
            msg = (_("The trigger windows(%d) must be positive") % window)
            raise exception.InvalidInput(msg)
        if (window * 2) > interval:
            msg = (_("The trigger windows%(window)d must be less "
                     "than %(interval)d") % {"window": window,
                                             "interval": interval / 2})
            raise exception.InvalidInput(msg)

        end_time = trigger_definition.get("end_time", None)
        end_time = cls._check_and_get_datetime(end_time, "end_time")

        start_time = trigger_definition.get("start_time", None)
        start_time = cls._check_and_get_datetime(start_time, "start_time")

        valid_trigger_property = trigger_definition.copy()
        valid_trigger_property['start_time'] = start_time
        valid_trigger_property['end_time'] = end_time
        return valid_trigger_property
Beispiel #52
0
    def create(self):
        if self.obj_attr_is_set('id'):
            raise exception.ObjectActionError(action='create',
                                              reason=_('already created'))

        updates = self.smaug_obj_get_changes()
        self._convert_operation_definition_to_db_format(updates)
        db_op = db.scheduled_operation_create(self._context, updates)
        self._from_db_object(self._context, self, db_op)
Beispiel #53
0
    def create(self):
        if self.obj_attr_is_set('id'):
            raise exception.ObjectActionError(action='create',
                                              reason=_('already created'))

        updates = self.smaug_obj_get_changes()
        self._convert_operation_definition_to_db_format(updates)
        db_op = db.scheduled_operation_create(self._context, updates)
        self._from_db_object(self._context, self, db_op)
Beispiel #54
0
    def on_node_exit(self, node):
        resource = node.value
        resource_type = resource.type
        LOG.info(_("on_node_exit, node resource_type:%s"), resource_type)
        protection_plugin = self._get_protection_plugin(resource_type)

        # get node context
        context = self.context.get_node_context(node)
        # do something in protection_plugin
        protection_plugin.on_resource_end(context)
Beispiel #55
0
    def restore(self, context, restore=None):
        LOG.info(_LI("Starting restore service:restore action"))

        checkpoint_id = restore["checkpoint_id"]
        provider_id = restore["provider_id"]
        provider = self.provider_registry.show_provider(provider_id)
        try:
            checkpoint_collection = provider.get_checkpoint_collection()
            checkpoint = checkpoint_collection.get(checkpoint_id)
        except Exception:
            LOG.error(_LE("Invalid checkpoint id: %s"), checkpoint_id)
            raise exception.InvalidInput(
                reason=_("Invalid checkpoint id"))

        if checkpoint.status in [constants.CHECKPOINT_STATUS_ERROR,
                                 constants.CHECKPOINT_STATUS_PROTECTING]:
            raise exception.CheckpointNotAvailable(
                checkpoint_id=checkpoint_id)

        try:
            restoration_flow = self.worker.get_restoration_flow(
                context,
                constants.OPERATION_RESTORE,
                checkpoint,
                provider,
                restore)
        except Exception:
            LOG.exception(
                _LE("Failed to create restoration flow checkpoint: %s"),
                checkpoint_id)
            raise exception.FlowError(
                flow="restore",
                error=_("Failed to create flow"))
        try:
            self.worker.run_flow(restoration_flow)
            return True
        except Exception:
            LOG.exception(
                _LE("Failed to run restoration flow checkpoint: %s"),
                checkpoint_id)
            raise exception.FlowError(
                flow="restore",
                error=_("Failed to run flow"))
Beispiel #56
0
    def _check_and_get_datetime(cls, time, time_name):
        if not time or isinstance(time, datetime):
            return time

        if not isinstance(time, six.string_types):
            msg = (_("The trigger %(name)s(type = %(vtype)s) is not an "
                     "instance of string") % {
                         "name": time_name,
                         "vtype": type(time)
                     })
            raise exception.InvalidInput(msg)

        try:
            time = timeutils.parse_strtime(time, fmt='%Y-%m-%d %H:%M:%S')
        except Exception:
            msg = (_("The format of trigger %s is not correct") % time_name)
            raise exception.InvalidInput(msg)

        return time