def execute(self): LOG.info(_LI("Starting purge command")) self._objects_map = self.find_objects_to_delete() if (self.max_number is not None and len(self._objects_map) > self.max_number): if self.delete_up_to_max_prompt(self._objects_map): self._objects_map = self._get_objects_up_to_limit() else: return _orphans_note = (_(" (orphans excluded)") if self.exclude_orphans else _(" (may include orphans)")) if not self.dry_run and self.confirmation_prompt(): self.do_delete() print(_("Purge results summary%s:") % _orphans_note) LOG.info(_LI("Purge results summary%s:"), _orphans_note) else: LOG.debug(self._objects_map) print(_("Here below is a table containing the objects " "that can be purged%s:") % _orphans_note) LOG.info("\n%s", self._objects_map.get_count_table()) print(self._objects_map.get_count_table()) LOG.info(_LI("Purge process completed"))
def post(self, audit_p): """Create a new audit. :param audit_p: a audit within the request body. """ context = pecan.request.context policy.enforce(context, 'audit:create', action='audit:create') audit = audit_p.as_audit() if self.from_audits: raise exception.OperationNotPermitted if not audit._audit_template_uuid: raise exception.Invalid( message=_('The audit template UUID or name specified is ' 'invalid')) audit_template = objects.AuditTemplate.get(pecan.request.context, audit._audit_template_uuid) strategy_id = audit_template.strategy_id no_schema = True if strategy_id is not None: # validate parameter when predefined strategy in audit template strategy = objects.Strategy.get(pecan.request.context, strategy_id) schema = strategy.parameters_spec if schema: # validate input parameter with default value feedback no_schema = False utils.DefaultValidatingDraft4Validator(schema).validate( audit.parameters) if no_schema and audit.parameters: raise exception.Invalid(_('Specify parameters but no predefined ' 'strategy for audit template, or no ' 'parameter spec in predefined strategy')) audit_dict = audit.as_dict() context = pecan.request.context new_audit = objects.Audit(context, **audit_dict) new_audit.create(context) # Set the HTTP Location Header pecan.response.location = link.build_url('audits', new_audit.uuid) # trigger decision-engine to run the audit if new_audit.audit_type == objects.audit.AuditType.ONESHOT.value: dc_client = rpcapi.DecisionEngineAPI() dc_client.trigger_audit(context, new_audit.uuid) return Audit.convert_with_links(new_audit)
def delete_up_to_max_prompt(self, objects_map): print(objects_map.get_count_table()) print(_("The number of objects (%(num)s) to delete from the database " "exceeds the maximum number of objects (%(max_number)s) " "specified.") % dict(max_number=self.max_number, num=len(objects_map))) raw_val = input( _("Do you want to delete objects up to the specified maximum " "number? [y/N]")) self._delete_up_to_max = strutils.bool_from_string(raw_val) return self._delete_up_to_max
def select(self): """Selects a strategy :raises: :py:class:`~.LoadingError` if it failed to load a strategy :returns: A :py:class:`~.BaseStrategy` instance """ strategy_to_load = None try: if self.strategy_name: strategy_to_load = self.strategy_name else: available_strategies = self.strategy_loader.list_available() available_strategies_for_goal = list( key for key, strat in available_strategies.items() if strat.get_goal_name() == self.goal_name) if not available_strategies_for_goal: raise exception.NoAvailableStrategyForGoal( goal=self.goal_name) # TODO(v-francoise): We should do some more work here to select # a strategy out of a given goal instead of just choosing the # 1st one strategy_to_load = available_strategies_for_goal[0] return self.strategy_loader.load(strategy_to_load, osc=self.osc) except exception.NoAvailableStrategyForGoal: raise except Exception as exc: LOG.exception(exc) raise exception.LoadingError( _("Could not load any strategy for goal %(goal)s"), goal=self.goal_name)
def update_action_plan(self, action_plan_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "Action Plan.")) return self._do_update_action_plan(action_plan_id, values)
def validate_search_filters(filters, allowed_fields): # Very leightweight validation for now # todo: improve this (e.g. https://www.parse.com/docs/rest/guide/#queries) for filter_name in filters.keys(): if filter_name not in allowed_fields: raise wsme.exc.ClientSideError( _("Invalid filter: %s") % filter_name)
def get_count_table(self): headers = list(self.keymap.values()) headers.append(_("Total")) # We also add a total count counters = [len(cat_vals) for cat_vals in self.values()] + [len(self)] table = ptable.PrettyTable(field_names=headers) table.add_row(counters) return table.get_string()
def apply_jsonpatch(doc, patch): for p in patch: if p["op"] == "add" and p["path"].count("/") == 1: if p["path"].lstrip("/") not in doc: msg = _("Adding a new attribute (%s) to the root of " " the resource is not allowed") raise wsme.exc.ClientSideError(msg % p["path"]) return jsonpatch.apply_patch(doc, jsonpatch.JsonPatch(patch))
def post(self, audit): """Create a new audit. :param audit: a audit within the request body. """ if self.from_audits: raise exception.OperationNotPermitted if not audit._audit_template_uuid: raise exception.Invalid( message=_('The audit template UUID or name specified is ' 'invalid')) audit_dict = audit.as_dict() context = pecan.request.context new_audit = objects.Audit(context, **audit_dict) new_audit.create(context) # Set the HTTP Location Header pecan.response.location = link.build_url('audits', new_audit.uuid) # trigger decision-engine to run the audit dc_client = rpcapi.DecisionEngineAPI() dc_client.trigger_audit(context, new_audit.uuid) return Audit.convert_with_links(new_audit)
def patch(self, action_uuid, patch): """Update an existing action. :param action_uuid: UUID of a action. :param patch: a json PATCH document to apply to this action. """ # FIXME: blueprint edit-action-plan-flow raise exception.OperationNotPermitted( _("Cannot modify an action directly")) if self.from_actions: raise exception.OperationNotPermitted action_to_update = objects.Action.get_by_uuid(pecan.request.context, action_uuid) try: action_dict = action_to_update.as_dict() action = Action(**api_utils.apply_jsonpatch(action_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Action.fields: try: patch_val = getattr(action, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if action_to_update[field] != patch_val: action_to_update[field] = patch_val action_to_update.save() return Action.convert_with_links(action_to_update)
def save(self, context): """Save the changed fields back to the store. This is optional for subclasses, but is presented here in the base class for consistency among those that do. """ raise NotImplementedError(_("Cannot save anything in the base class"))
def confirmation_prompt(self): print(self._objects_map.get_count_table()) raw_val = input( _("There are %(count)d objects set for deletion. " "Continue? [y/N]") % dict(count=len(self._objects_map))) return strutils.bool_from_string(raw_val)
def validate(value): try: json.dumps(value) except TypeError: raise exception.Invalid(_('%s is not JSON serializable') % value) else: return value
def __init__(self): super(MigrationEfficacy, self).__init__( name="migration_efficacy", description=_("Represents the percentage of released nodes out of " "the total number of migrations."), unit="%", required=True )
def update_action(self, action_id, values): # NOTE(dtantsur): this can lead to very strange errors if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "Action.")) return self._do_update_action(action_id, values)
def validate(patch): serialized_patch = {'path': patch.path, 'op': patch.op} if patch.path in AuditPatchType.mandatory_attrs(): msg = _("%(field)s can't be updated.") raise exception.PatchError( patch=serialized_patch, reason=msg % dict(field=patch.path)) return types.JsonPatchType.validate(patch)
def apply_jsonpatch(doc, patch): for p in patch: if p['op'] == 'add' and p['path'].count('/') == 1: if p['path'].lstrip('/') not in doc: msg = _('Adding a new attribute (%s) to the root of ' ' the resource is not allowed') raise wsme.exc.ClientSideError(msg % p['path']) return jsonpatch.apply_patch(doc, jsonpatch.JsonPatch(patch))
def _validate_state(patch): serialized_patch = {"path": patch.path, "op": patch.op} if patch.value is not wsme.Unset: serialized_patch["value"] = patch.value # todo: use state machines to handle state transitions state_value = patch.value if state_value and not hasattr(ap_objects.State, state_value): msg = _("Invalid state: %(state)s") raise exception.PatchError(patch=serialized_patch, reason=msg % dict(state=state_value))
def _nova_manage_service(self, state): if state is None: raise exception.IllegalArgumentException(message=_("The target state is not defined")) nova = nova_helper.NovaHelper(osc=self.osc) if state is True: return nova.enable_service_nova_compute(self.host) else: return nova.disable_service_nova_compute(self.host)
def update_goal(self, goal_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing Goal.")) try: return self._update(models.Goal, goal_id, values) except exception.ResourceNotFound: raise exception.GoalNotFound(goal=goal_id)
def update_strategy(self, strategy_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing Strategy.")) try: return self._update(models.Strategy, strategy_id, values) except exception.ResourceNotFound: raise exception.StrategyNotFound(strategy=strategy_id)
def obj_load_attr(self, attrname): """Load an additional attribute from the real object. This should use self._conductor, and cache any data that might be useful for future load operations. """ raise NotImplementedError( _("Cannot load '%(attrname)s' in the base class") % {'attrname': attrname})
def update_audit(self, audit_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "Audit.")) try: return self._update(models.Audit, audit_id, values) except exception.ResourceNotFound: raise exception.AuditNotFound(audit=audit_id)
def validate(patch): _path = '/{0}'.format(patch.path.split('/')[1]) if _path in patch.internal_attrs(): msg = _("'%s' is an internal attribute and can not be updated") raise wsme.exc.ClientSideError(msg % patch.path) if patch.path in patch.mandatory_attrs() and patch.op == 'remove': msg = _("'%s' is a mandatory attribute and can not be removed") raise wsme.exc.ClientSideError(msg % patch.path) if patch.op != 'remove': if patch.value is wsme.Unset: msg = _("'add' and 'replace' operations needs value") raise wsme.exc.ClientSideError(msg) ret = {'path': patch.path, 'op': patch.op} if patch.value is not wsme.Unset: ret['value'] = patch.value return ret
def validate(patch): if patch.path == "/goal" and patch.op != "remove": AuditTemplatePatchType._validate_goal(patch) elif patch.path == "/goal" and patch.op == "remove": raise exception.OperationNotPermitted( _("Cannot remove 'goal' attribute " "from an audit template")) if patch.path == "/strategy": AuditTemplatePatchType._validate_strategy(patch) return types.JsonPatchType.validate(patch)
def validate(self, value): for t in self.types: if t is wsme.types.text and isinstance(value, wsme.types.bytes): value = value.decode() if isinstance(value, t): return value else: raise ValueError( _("Wrong type. Expected '%(type)s', got '%(value)s'"), type=self.types, value=type(value) )
def wrapped(*args, **kw): try: return func(*args, **kw) except keystone_exceptions.AuthorizationFailure: raise AuthorizationFailure( client=func.__name__, reason=sys.exc_info()[1]) except keystone_exceptions.ClientException: raise AuthorizationFailure( client=func.__name__, reason=(_('Unexpected keystone client error occurred: %s') % sys.exc_info()[1]))
def prepare_service(argv=(), conf=cfg.CONF): log.register_options(conf) gmr_opts.set_defaults(conf) config.parse_args(argv) cfg.set_defaults(_options.log_opts, default_log_levels=_DEFAULT_LOG_LEVELS) log.setup(conf, 'python-watcher') conf.log_opt_values(LOG, logging.DEBUG) gmr.TextGuruMeditation.register_section(_('Plugins'), opts.show_plugins) gmr.TextGuruMeditation.setup_autorun(version)
def update_efficacy_indicator(self, efficacy_indicator_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "efficacy indicator.")) try: return self._update( models.EfficacyIndicator, efficacy_indicator_id, values) except exception.ResourceNotFound: raise exception.EfficacyIndicatorNotFound( efficacy_indicator=efficacy_indicator_id)
def update_scoring_engine(self, scoring_engine_id, values): if 'id' in values: raise exception.Invalid( message=_("Cannot overwrite ID for an existing " "Scoring Engine.")) try: return self._update( models.ScoringEngine, scoring_engine_id, values) except exception.ResourceNotFound: raise exception.ScoringEngineNotFound( scoring_engine=scoring_engine_id)
class AuditAlreadyExists(Conflict): msg_fmt = _("An audit with UUID %(uuid)s already exists")
class ScoringEngineNotFound(ResourceNotFound): msg_fmt = _("ScoringEngine %(scoring_engine)s could not be found")
class ActionReferenced(Invalid): msg_fmt = _("Action plan %(action_plan)s is referenced by one or " "multiple goals")
class UnsupportedActionType(UnsupportedError): msg_fmt = _("Provided %(action_type) is not supported yet")
class ActionPlanIsOngoing(Conflict): msg_fmt = _("Action Plan %(action_plan)s is currently running.")
class MetricCollectorNotDefined(WatcherException): msg_fmt = _("The metrics resource collector is not defined")
class PatchError(Invalid): msg_fmt = _("Couldn't apply patch '%(patch)s'. Reason: %(reason)s")
class KeystoneFailure(WatcherException): msg_fmt = _("Keystone API endpoint is missing")
class ClusterEmpty(WatcherException): msg_fmt = _("The list of compute node(s) in the cluster is empty")
class AuthorizationFailure(WatcherException): msg_fmt = _('%(client)s connection failed. Reason: %(reason)s')
class NoDataFound(WatcherException): msg_fmt = _('No rows were returned')
class NoSuchMetric(WatcherException): msg_fmt = _('No such metric')
class EfficacyIndicatorAlreadyExists(Conflict): msg_fmt = _("An action with UUID %(uuid)s already exists")
class AuditParameterNotAllowed(Invalid): msg_fmt = _("Audit parameter %(parameter)s are not allowed")
class AuditNotFound(ResourceNotFound): msg_fmt = _("Audit %(audit)s could not be found")
class AuditTemplateReferenced(Invalid): msg_fmt = _("AuditTemplate %(audit_template)s is referenced by one or " "multiple audits")
class ClusterStateStale(WatcherException): msg_fmt = _("The cluster state is stale")
class WorkflowExecutionException(WatcherException): msg_fmt = _('Workflow execution error: %(error)s')
class AuditTypeNotFound(Invalid): msg_fmt = _("Audit type %(audit_type)s could not be found")
class ActionAlreadyExists(Conflict): msg_fmt = _("An action with UUID %(uuid)s already exists")
class AuditTemplateAlreadyExists(Conflict): msg_fmt = _("An audit_template with UUID or name %(audit_template)s " "already exists")
class AuditReferenced(Invalid): msg_fmt = _("Audit %(audit)s is referenced by one or multiple action " "plans")
class EfficacyIndicatorNotFound(ResourceNotFound): msg_fmt = _("Efficacy indicator %(efficacy_indicator)s could not be found")
class AuditIntervalNotAllowed(Invalid): msg_fmt = _("Interval of audit must not be set for %(audit_type)s.")
class ActionFilterCombinationProhibited(Invalid): msg_fmt = _("Filtering actions on both audit and action-plan is " "prohibited")
class AuditIntervalNotSpecified(Invalid): msg_fmt = _("Interval of audit must be specified for %(audit_type)s.")
class ClusterDataModelCollectionError(WatcherException): msg_fmt = _("The cluster data model '%(cdm)s' could not be built")
class ScoringEngineAlreadyExists(Conflict): msg_fmt = _("A scoring engine with UUID %(uuid)s already exists")
class IllegalArgumentException(WatcherException): msg_fmt = _('Illegal argument')
class ActionNotFound(ResourceNotFound): msg_fmt = _("Action %(action)s could not be found")