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
def _instances_get_all(self, context, protectable_type, marker=None, limit=None, sort_keys=None, sort_dirs=None, filters=None, offset=None, parameters=None): check_policy(context, '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)) instances = self.protection_api.list_protectable_instances( context, protectable_type, marker, limit, sort_keys=sort_keys, sort_dirs=sort_dirs, filters=filters, offset=offset, parameters=parameters) LOG.info(_LI("Get all instances completed successfully.")) return instances
def update_trigger_property(self, trigger_property): valid_trigger_property = self.check_trigger_definition( trigger_property) if valid_trigger_property == self._trigger_property: return timer, first_run_time = self._get_timer_and_first_run_time( valid_trigger_property) if not first_run_time: msg = (_("The new trigger property is invalid, " "Can not find the first run time")) raise exception.InvalidInput(msg) if self._greenthread is not None: pre_run_time = self._greenthread.pre_run_time if pre_run_time: end_time = pre_run_time + timedelta( seconds=self._trigger_property['window']) if first_run_time <= end_time: msg = (_("The new trigger property is invalid, " "First run time%(t1)s must be after %(t2)s") % {'t1': first_run_time, 't2': end_time}) raise exception.InvalidInput(msg) self._trigger_property = valid_trigger_property if len(self._operation_ids) > 0: # Restart greenthread to take the change of trigger property # effect immediately self._kill_greenthread() self._create_green_thread(first_run_time, timer)
def __init__(self, provider_config): super(PluggableProtectionProvider, self).__init__() self._config = provider_config self._id = self._config.provider.id self._name = self._config.provider.name self._description = self._config.provider.description self._extended_info_schema = {'options_schema': {}, 'restore_schema': {}, 'saved_info_schema': {}} self.checkpoint_collection = None self._bank_plugin = None self._plugin_map = {} if hasattr(self._config.provider, 'bank') \ and not self._config.provider.bank: raise ImportError(_("Empty bank")) self._load_bank(self._config.provider.bank) self._bank = bank_plugin.Bank(self._bank_plugin) self.checkpoint_collection = CheckpointCollection( self._bank) if hasattr(self._config.provider, 'plugin'): for plugin_name in self._config.provider.plugin: if not plugin_name: raise ImportError(_("Empty protection plugin")) self._register_plugin(plugin_name)
def instances_show(self, req, protectable_type, protectable_id): """Return a instance about the given protectable_type and id.""" context = req.environ['karbor.context'] params = req.params.copy() utils.check_filters(params) parameters = params.get("parameters", None) LOG.info(_LI("Show the instance of a given protectable" " type: %s"), protectable_type) if parameters is not None: if not isinstance(parameters, dict): msg = _("The parameters must be a dict.") raise exception.InvalidInput(reason=msg) 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, parameters=parameters) if instance is None: raise exception.InvalidProtectableInstance() 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
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)
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)
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['karbor.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': constants.CHECKPOINT_STATUS_PROTECTING, 'provider_id': provider_id, "protection_plan": { "id": plan.get("id"), "name": plan.get("name"), "resources": plan.get("resources"), } } try: checkpoint_id = self.protection_api.protect(context, plan) except Exception as error: msg = _("Create checkpoint failed: %s") % error.msg raise exc.HTTPBadRequest(explanation=msg) checkpoint_properties['id'] = checkpoint_id returnval = self._checkpoint_view_builder.detail( req, checkpoint_properties) return returnval
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
def purge(self, age_in_days): """Purge deleted rows older than a given age from karbor tables.""" age_in_days = int(age_in_days) if age_in_days <= 0: print(_("Must supply a positive, non-zero value for age")) sys.exit(1) ctxt = context.get_admin_context() try: db.purge_deleted_rows(ctxt, age_in_days) except Exception as e: print(_("Purge command failed, check karbor-manage " "logs for more details. %s") % e) sys.exit(1)
def check_operation_definition(cls, operation_definition): provider_id = operation_definition.get("provider_id") if not provider_id or not uuidutils.is_uuid_like(provider_id): reason = _("Provider_id is invalid") raise exception.InvalidOperationDefinition(reason=reason) plan_id = operation_definition.get("plan_id") if not plan_id or not uuidutils.is_uuid_like(plan_id): reason = _("Plan_id is invalid") raise exception.InvalidOperationDefinition(reason=reason) plan = objects.Plan.get_by_id(context.get_admin_context(), plan_id) if provider_id != plan.provider_id: reason = _("Provider_id is invalid") raise exception.InvalidOperationDefinition(reason=reason)
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)
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]
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
def restore(self, context, restore, restore_auth): 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) if not provider: raise exception.ProviderNotFound(provider_id=provider_id) checkpoint_collection = provider.get_checkpoint_collection() checkpoint = checkpoint_collection.get(checkpoint_id) if checkpoint.status != constants.CHECKPOINT_STATUS_AVAILABLE: raise exception.CheckpointNotAvailable( checkpoint_id=checkpoint_id) try: restoration_flow = self.worker.get_restoration_flow( context, constants.OPERATION_RESTORE, checkpoint, provider, restore, restore_auth) except Exception: LOG.exception( _LE("Failed to create restoration flow checkpoint: %s"), checkpoint_id) raise exception.FlowError( flow="restore", error=_("Failed to create flow")) self._spawn(self.worker.run_flow, restoration_flow)
def link_task(self, flow, u, v): if flow is None: LOG.error(_LE("The flow is None, build it first")) raise exception.InvalidTaskFlowObject( reason=_("The flow is None")) if u and v: flow.link(u, v)
def build_flow(self, flow_name, flow_type='graph'): if flow_type == 'linear': return linear_flow.Flow(flow_name) elif flow_type == 'graph': return graph_flow.Flow(flow_name) else: raise ValueError(_("unsupported flow type: %s") % flow_type)
def unpack_graph(packed_graph): """Return a list of GraphNodes from a PackedGraph Unpacks a PackedGraph, which must have the property: each parent node in the adjacency list appears after its children. """ (nodes, adjacency_list) = packed_graph nodes_dict = dict(nodes) graph_nodes_dict = {} for (parent_sid, children_sids) in adjacency_list: if parent_sid in graph_nodes_dict: raise exception.InvalidInput( reason=_("PackedGraph adjacency list must be topologically " "ordered")) children = [] for child_sid in children_sids: if child_sid not in graph_nodes_dict: graph_nodes_dict[child_sid] = GraphNode( nodes_dict[child_sid], ()) children.append(graph_nodes_dict[child_sid]) nodes_dict.pop(child_sid, None) graph_nodes_dict[parent_sid] = GraphNode(nodes_dict[parent_sid], tuple(children)) result_nodes = [] for sid in nodes_dict: if sid not in graph_nodes_dict: graph_nodes_dict[sid] = GraphNode(nodes_dict[sid], ()) result_nodes.append(graph_nodes_dict[sid]) return result_nodes
def _assert_supported_version(self, new_md): if new_md["version"] not in self.SUPPORTED_VERSIONS: # Something bad happened invalidate the object self._md_cache = None self._checkpoint_section = None raise RuntimeError( _("Checkpoint was created in an unsupported version"))
def delete(self, req, id): """Delete a trigger.""" LOG.debug('Delete trigger(%s) start', id) context = req.environ['karbor.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 = _("Trigger is being used by one or more operations") raise exc.HTTPFailedDependency(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()
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)
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__'))
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason=_('already created')) updates = self.karbor_obj_get_changes() db_operation_log = db.operation_log_create(self._context, updates) self._from_db_object(self._context, self, db_operation_log)
def _plan_update(self, context, plan, fields): if plan['status'] != constants.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.KarborObject): plan.update(fields) plan.save() LOG.info(_LI("Plan updated successfully."), resource=plan) else: msg = _("The parameter plan must be a object of " "KarborObject class.") raise exception.InvalidInput(reason=msg)
def update(self, req, id, body): """Update a plan.""" context = req.environ['karbor.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
def instances_index(self, req, protectable_type): """Return data about the given protectable_type.""" context = req.environ['karbor.context'] LOG.info(_LI("Show the instances of a given" " protectable type: %s"), protectable_type) params = req.params.copy() marker, limit, offset = common.get_pagination_params(params) sort_keys, sort_dirs = common.get_sort_params(params) filters = params utils.check_filters(filters) parameters = filters.get("parameters", None) if parameters is not None: if not isinstance(parameters, dict): msg = _("The parameters must be a dict.") raise exception.InvalidInput(reason=msg) utils.remove_invalid_filter_options( context, filters, self._get_instance_filter_options()) protectable_types = self._get_all(context) if protectable_type not in protectable_types: msg = _("Invalid protectable type provided.") raise exception.InvalidInput(reason=msg) instances = self._instances_get_all( context, protectable_type, marker, limit, sort_keys=sort_keys, sort_dirs=sort_dirs, filters=filters, offset=offset, parameters=parameters) for instance in instances: protectable_id = instance.get("id") instance["type"] = protectable_type if protectable_id is None: raise exception.InvalidProtectableInstance() dependents = self.protection_api.\ list_protectable_dependents(context, protectable_id, protectable_type) instance["dependent_resources"] = dependents retval_instances = self._view_builder.detail_list(req, instances) return retval_instances
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 """ tf_cls = cls._get_time_format_class() pattern = trigger_definition.get("pattern", None) tf_cls.check_time_format(pattern) start_time = trigger_definition.get("start_time", None) if not start_time: msg = _("The trigger\'s start time is unknown") raise exception.InvalidInput(msg) start_time = cls._check_and_get_datetime(start_time, "start_time") interval = tf_cls(start_time, pattern).get_min_interval() if interval is not None and 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.min_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 < CONF.min_window_time or window > CONF.max_window_time: msg = (_("The trigger windows %(window)d must be between " "%(min_window)d and %(max_window)d") % {"window": window, "min_window": CONF.min_window_time, "max_window": CONF.max_window_time}) raise exception.InvalidInput(msg) end_time = trigger_definition.get("end_time", None) end_time = cls._check_and_get_datetime(end_time, "end_time") valid_trigger_property = trigger_definition.copy() valid_trigger_property['window'] = window valid_trigger_property['start_time'] = start_time valid_trigger_property['end_time'] = end_time return valid_trigger_property
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.KarborException(msg) for entry in context.service_catalog: if entry.get('type') == service_type: return entry.get('endpoints')[0].get(endpoint_type) raise exception.KarborException(_( "Couldn't find the endpoint of service type %s " "from service catalog") % service_type)
def check_configuration(cls): min_window = CONF.min_window_time max_window = CONF.max_window_time min_interval = CONF.min_interval if not (min_window < max_window and (max_window * 2 <= min_interval)): msg = (_('Configurations of time trigger are invalid')) raise exception.InvalidInput(msg)
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
class InvalidReservationExpiration(Invalid): message = _("Invalid reservation expiration %(expire)s.")
class QuotaError(KarborException): message = _("Quota exceeded: code=%(code)s") code = 413 headers = {'Retry-After': '0'} safe = True
class UnexpectedOverQuota(QuotaError): message = _("Unexpected over quota on %(name)s.")
class TriggerNotFound(NotFound): message = _("Trigger %(id)s could not be found.")
class ServiceNotFound(NotFound): message = _("Service %(service_id)s could not be found.")
class InvalidProtectableInstance(Invalid): message = _("Invalid protectable instance.")
class MalformedRequestBody(KarborException): message = _("Malformed message body: %(reason)s")
class NotAuthorized(KarborException): message = _("Not authorized.") code = http_client.FORBIDDEN
def _set_read_deleted(self, read_deleted): if read_deleted not in ('no', 'yes', 'only'): raise ValueError( _("read_deleted can only be one of 'no', " "'yes' or 'only', not %r") % read_deleted) self._read_deleted = read_deleted
class InvalidName(Invalid): message = _("An invalid 'name' value was provided. %(reason)s")
def _get_operation(self, operation_type): if operation_type not in self._ops_map: msg = (_("Invalid operation type: %s") % operation_type) raise exception.InvalidInput(msg) return self._ops_map[operation_type]
class SwiftConnectionFailed(exception.KarborException): message = _("Connection to swift failed: %(reason)s")
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['karbor.context'] LOG.debug('Create checkpoint request ' 'body: %s provider_id:%s', body, provider_id) context.can(provider_policy.CHECKPOINT_CREATE_POLICY) 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) # check the provider_id if provider_id != plan.get("provider_id"): msg = _("The parameter provider_id is not the same as " "the value in the plan.") raise exception.InvalidPlan(reason=msg) extra_info = checkpoint.get("extra_info", None) if extra_info is not None: if not isinstance(extra_info, dict): msg = _("The extra_info in checkpoint must be a dict when " "creating a checkpoint.") raise exception.InvalidInput(reason=msg) elif not all(map(lambda s: isinstance(s, six.string_types), extra_info.keys())): msg = _("Key of extra_info in checkpoint must be string when" "creating a checkpoint.") raise exception.InvalidInput(reason=msg) else: extra_info = { 'created_by': constants.MANUAL } checkpoint_extra_info = None if extra_info is not None: checkpoint_extra_info = jsonutils.dumps(extra_info) checkpoint_properties = { 'project_id': context.project_id, 'status': constants.CHECKPOINT_STATUS_PROTECTING, 'provider_id': provider_id, "protection_plan": { "id": plan.get("id"), "name": plan.get("name"), "resources": plan.get("resources"), }, "extra_info": checkpoint_extra_info } try: checkpoint_id = self.protection_api.protect(context, plan, checkpoint_properties) except Exception as error: msg = _("Create checkpoint failed: %s") % error raise exc.HTTPBadRequest(explanation=msg) checkpoint_properties['id'] = checkpoint_id LOG.info("Create the checkpoint successfully. checkpoint_id:%s", checkpoint_id) returnval = self._checkpoint_view_builder.detail( req, checkpoint_properties) return returnval
class KarborException(Exception): """Base karbor Exception To correctly use this class, inherit from it and define a 'message' property. That message will get printf'd with the keyword arguments provided to the constructor. """ message = _("An unknown exception occurred.") code = http_client.INTERNAL_SERVER_ERROR headers = {} safe = True def __init__(self, message=None, **kwargs): """Initiate the instance of KarborException There are two ways to initiate the instance. 1. Specify the value of 'message' and leave the 'kwargs' None. 2. Leave 'message' None, and specify the keyword arguments matched with the format of KarborException.message. Especially, can't use the 'message' as the key in the 'kwargs', otherwise, the first argument('message') will be set. Note: This class doesn't support to create instance of KarborException with another instance. """ self.kwargs = kwargs if 'code' not in self.kwargs: try: self.kwargs['code'] = self.code except AttributeError: pass if not message: try: message = self.message % kwargs except Exception: exc_info = sys.exc_info() # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception('Exception in string format operation') for name, value in kwargs.items(): LOG.error("%(name)s: %(value)s", { 'name': name, 'value': value }) if CONF.fatal_exception_format_errors: six.reraise(*exc_info) # at least get the core message out if something happened message = self.message elif isinstance(message, Exception): message = six.text_type(message) # NOTE(luisg): We put the actual message in 'msg' so that we can access # it, because if we try to access the message via 'message' it will be # overshadowed by the class' message attribute self.msg = message super(KarborException, self).__init__(message) def __unicode__(self): return self.msg
class ConfigNotFound(NotFound): message = _("Could not find config at %(path)s")
class AdminRequired(NotAuthorized): message = _("User does not have admin privileges")
class InvalidContentType(Invalid): message = _("Invalid content type %(content_type)s.")
class PolicyNotAuthorized(NotAuthorized): message = _("Policy doesn't allow %(action)s to be performed.")
class PasteAppNotFound(NotFound): message = _("Could not load paste app '%(name)s' from %(path)s")
class AuthorizationFailure(NotAuthorized): message = _("Authorization for %(obj)s is failed ")
class HostBinaryNotFound(NotFound): message = _("Could not find binary %(binary)s on host %(host)s.")
class Invalid(KarborException): message = _("Unacceptable parameters.") code = http_client.BAD_REQUEST
class InvalidParameterValue(Invalid): message = _("%(err)s")
class InvalidInput(Invalid): message = _("Invalid input received: %(reason)s")
class PlanLimitExceeded(QuotaError): message = _("Maximum number of plans allowed (%(allowed)d) exceeded")
class ScheduledOperationExist(Invalid): message = _("Scheduled Operation%(op_id)s exists")
class InvalidQuotaValue(Invalid): message = _("Change would make usage less than 0 for the following " "resources: %(unders)s.")
class NotFound(KarborException): message = _("Resource could not be found.") code = http_client.NOT_FOUND safe = True
def _validate_quota_limit(self, limit): # NOTE: -1 is a flag value for unlimited if limit < -1: msg = _("Quota limit must be -1 or greater.") raise exc.HTTPBadRequest(explanation=msg)
def _run(self, operation_definition, param, log_ref): project_id = param.get("project_id") client = self._create_karbor_client(param.get("user_id"), project_id) provider_id = operation_definition.get("provider_id") plan_id = operation_definition.get("plan_id") trigger_id = param.get("trigger_id", None) scheduled_operation_id = param.get("scheduled_operation_id", None) extra_info = { 'created_by': constants.OPERATION_ENGINE, 'trigger_id': trigger_id, 'scheduled_operation_id': scheduled_operation_id } try: client.checkpoints.create(provider_id, plan_id, extra_info) except Exception: state = constants.OPERATION_EXE_STATE_FAILED else: state = constants.OPERATION_EXE_STATE_SUCCESS finally: self._update_log_when_operation_finished(log_ref, state) try: max_backups = int(operation_definition.get("max_backups", -1)) max_backups = -1 if max_backups <= 0 else max_backups except Exception: state = constants.OPERATION_GET_MAX_BACKUP_STATE_FAILED self._update_log_when_operation_finished(log_ref, state) reason = _("Failed to get max_backups") raise exception.InvalidOperationDefinition(reason=reason) try: retention_duration = int( operation_definition.get("retention_duration", -1)) retention_duration = -1 if retention_duration <= 0\ else retention_duration except Exception: state = constants.OPERATION_GET_DURATION_STATE_FAILED self._update_log_when_operation_finished(log_ref, state) reason = _("Failed to get retention_duration") raise exception.InvalidOperationDefinition(reason=reason) try: self._delete_old_backup_by_max_backups(client, max_backups, project_id, provider_id, plan_id) state = constants.OPERATION_EXE_MAX_BACKUP_STATE_SUCCESS except Exception: state = constants.OPERATION_EXE_MAX_BACKUP_STATE_FAILED reason = (_("Can't execute retention policy provider_id: " "%(provider_id)s plan_id:%(plan_id)s" " max_backups:%(max_backups)s") % { "provider_id": provider_id, "plan_id": plan_id, "max_backups": max_backups }) raise exception.InvalidOperationDefinition(reason=reason) finally: self._update_log_when_operation_finished(log_ref, state) try: self._delete_old_backup_by_duration(client, retention_duration, project_id, provider_id, plan_id) state = constants.OPERATION_EXE_DURATION_STATE_SUCCESS except Exception: state = constants.OPERATION_EXE_DURATION_STATE_FAILED reason = (_("Can't execute retention policy provider_id: " "%(provider_id)s plan_id:%(plan_id)s" " retention_duration:%(retention_duration)s") % { "provider_id": provider_id, "plan_id": plan_id, "retention_duration": retention_duration }) raise exception.InvalidOperationDefinition(reason=reason) finally: self._update_log_when_operation_finished(log_ref, state)