def start(self, action_plan_uuid, **kwargs): """Start an action_plan :param action_plan_uuid: UUID of an action_plan. """ action_plan_to_start = api_utils.get_resource('ActionPlan', action_plan_uuid, eager=True) context = pecan.request.context policy.enforce(context, 'action_plan:start', action_plan_to_start, action='action_plan:start') if action_plan_to_start['state'] != \ objects.action_plan.State.RECOMMENDED: raise exception.StartError(state=action_plan_to_start.state) action_plan_to_start['state'] = objects.action_plan.State.PENDING action_plan_to_start.save() self.applier_client.launch_action_plan(pecan.request.context, action_plan_uuid) action_plan_to_start = objects.ActionPlan.get_by_uuid( pecan.request.context, action_plan_uuid) return ActionPlan.convert_with_links(action_plan_to_start)
def patch(self, audit, patch): """Update an existing audit. :param audit: UUID or name of an audit. :param patch: a json PATCH document to apply to this audit. """ if self.from_audits: raise exception.OperationNotPermitted context = pecan.request.context audit_to_update = api_utils.get_resource('Audit', audit, eager=True) policy.enforce(context, 'audit:update', audit_to_update, action='audit:update') try: audit_dict = audit_to_update.as_dict() initial_state = audit_dict['state'] new_state = api_utils.get_patch_value(patch, 'state') if not api_utils.check_audit_state_transition( patch, initial_state): error_message = _("State transition not allowed: " "(%(initial_state)s -> %(new_state)s)") raise exception.PatchError( patch=patch, reason=error_message % dict(initial_state=initial_state, new_state=new_state)) patch_path = api_utils.get_patch_key(patch, 'path') if patch_path in ('start_time', 'end_time'): patch_value = api_utils.get_patch_value(patch, patch_path) # convert string format to UTC time new_patch_value = wutils.parse_isodatetime( patch_value).replace(tzinfo=tz.tzlocal()).astimezone( tz.tzutc()).replace(tzinfo=None) api_utils.set_patch_value(patch, patch_path, new_patch_value) audit = Audit(**api_utils.apply_jsonpatch(audit_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.Audit.fields: try: patch_val = getattr(audit, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if audit_to_update[field] != patch_val: audit_to_update[field] = patch_val audit_to_update.save() return Audit.convert_with_links(audit_to_update)
def delete(self, audit_uuid): """Delete a audit. :param audit_uuid: UUID of a audit. """ context = pecan.request.context audit_to_delete = api_utils.get_resource('Audit', audit_uuid) policy.enforce(context, 'audit:update', audit_to_delete, action='audit:update') audit_to_delete.soft_delete()
def delete(self, action_plan_uuid): """Delete an action plan. :param action_plan_uuid: UUID of a action. """ context = pecan.request.context action_plan = api_utils.get_resource('ActionPlan', action_plan_uuid) policy.enforce(context, 'action_plan:delete', action_plan, action='action_plan:delete') action_plan.soft_delete()
def delete(self, action_plan_uuid): """Delete an action plan. :param action_plan_uuid: UUID of a action. """ context = pecan.request.context action_plan = api_utils.get_resource( 'ActionPlan', action_plan_uuid, eager=True) policy.enforce(context, 'action_plan:delete', action_plan, action='action_plan:delete') action_plan.soft_delete()
def delete(self, audit_template): """Delete a audit template. :param audit template_uuid: UUID or name of an audit template. """ context = pecan.request.context audit_template_to_delete = api_utils.get_resource('AuditTemplate', audit_template) policy.enforce(context, 'audit_template:update', audit_template_to_delete, action='audit_template:update') audit_template_to_delete.soft_delete()
def get_one(self, goal): """Retrieve information about the given goal. :param goal: UUID or name of the goal. """ if self.from_goals: raise exception.OperationNotPermitted context = pecan.request.context rpc_goal = api_utils.get_resource('Goal', goal) policy.enforce(context, 'goal:get', rpc_goal, action='goal:get') return Goal.convert_with_links(rpc_goal)
def get_one(self, action_uuid): """Retrieve information about the given action. :param action_uuid: UUID of a action. """ if self.from_actions: raise exception.OperationNotPermitted context = pecan.request.context action = api_utils.get_resource('Action', action_uuid) policy.enforce(context, 'action:get', action, action='action:get') return Action.convert_with_links(action)
def get_one(self, audit): """Retrieve information about the given audit. :param audit: UUID or name of an audit. """ if self.from_audits: raise exception.OperationNotPermitted context = pecan.request.context rpc_audit = api_utils.get_resource('Audit', audit) policy.enforce(context, 'audit:get', rpc_audit, action='audit:get') return Audit.convert_with_links(rpc_audit)
def delete(self, audit): """Delete an audit. :param audit: UUID or name of an audit. """ context = pecan.request.context audit_to_delete = api_utils.get_resource('Audit', audit, eager=True) policy.enforce(context, 'audit:update', audit_to_delete, action='audit:update') audit_to_delete.soft_delete()
def get_one(self, audit_uuid): """Retrieve information about the given audit. :param audit_uuid: UUID of a audit. """ if self.from_audits: raise exception.OperationNotPermitted context = pecan.request.context rpc_audit = api_utils.get_resource('Audit', audit_uuid) policy.enforce(context, 'audit:get', rpc_audit, action='audit:get') return Audit.convert_with_links(rpc_audit)
def get_one(self, strategy): """Retrieve information about the given strategy. :param strategy: UUID or name of the strategy. """ if self.from_strategies: raise exception.OperationNotPermitted context = pecan.request.context rpc_strategy = api_utils.get_resource('Strategy', strategy) policy.enforce(context, 'strategy:get', rpc_strategy, action='strategy:get') return Strategy.convert_with_links(rpc_strategy)
def get_one(self, service): """Retrieve information about the given service. :param service: ID or name of the service. """ if self.from_services: raise exception.OperationNotPermitted context = pecan.request.context rpc_service = api_utils.get_resource('Service', service) policy.enforce(context, 'service:get', rpc_service, action='service:get') return Service.convert_with_links(rpc_service)
def patch(self, audit_uuid, patch): """Update an existing audit. :param audit_uuid: UUID of a audit. :param patch: a json PATCH document to apply to this audit. """ if self.from_audits: raise exception.OperationNotPermitted context = pecan.request.context audit_to_update = api_utils.get_resource('Audit', audit_uuid, eager=True) policy.enforce(context, 'audit:update', audit_to_update, action='audit:update') try: audit_dict = audit_to_update.as_dict() audit = Audit(**api_utils.apply_jsonpatch(audit_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) initial_state = audit_dict['state'] new_state = api_utils.get_patch_value(patch, 'state') allowed_states = ALLOWED_AUDIT_TRANSITIONS.get(initial_state, []) if new_state is not None and new_state not in allowed_states: error_message = _("State transition not allowed: " "(%(initial_state)s -> %(new_state)s)") raise exception.PatchError( patch=patch, reason=error_message % dict(initial_state=initial_state, new_state=new_state)) # Update only the fields that have changed for field in objects.Audit.fields: try: patch_val = getattr(audit, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if audit_to_update[field] != patch_val: audit_to_update[field] = patch_val audit_to_update.save() return Audit.convert_with_links(audit_to_update)
def get_one(self, audit_template): """Retrieve information about the given audit template. :param audit audit_template: UUID or name of an audit template. """ if self.from_audit_templates: raise exception.OperationNotPermitted context = pecan.request.context rpc_audit_template = api_utils.get_resource('AuditTemplate', audit_template) policy.enforce(context, 'audit_template:get', rpc_audit_template, action='audit_template:get') return AuditTemplate.convert_with_links(rpc_audit_template)
def get_one(self, scoring_engine): """Retrieve information about the given Scoring Engine. :param scoring_engine_name: The name of the Scoring Engine. """ context = pecan.request.context policy.enforce(context, 'scoring_engine:get', action='scoring_engine:get') if self.from_scoring_engines: raise exception.OperationNotPermitted rpc_scoring_engine = api_utils.get_resource( 'ScoringEngine', scoring_engine) return ScoringEngine.convert_with_links(rpc_scoring_engine)
def patch(self, audit_template, patch): """Update an existing audit template. :param audit template_uuid: UUID of a audit template. :param patch: a json PATCH document to apply to this audit template. """ if self.from_audit_templates: raise exception.OperationNotPermitted context = pecan.request.context audit_template_to_update = api_utils.get_resource('AuditTemplate', audit_template) policy.enforce(context, 'audit_template:update', audit_template_to_update, action='audit_template:update') if common_utils.is_uuid_like(audit_template): audit_template_to_update = objects.AuditTemplate.get_by_uuid( pecan.request.context, audit_template) else: audit_template_to_update = objects.AuditTemplate.get_by_name( pecan.request.context, audit_template) try: audit_template_dict = audit_template_to_update.as_dict() audit_template = AuditTemplate(**api_utils.apply_jsonpatch( audit_template_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.AuditTemplate.fields: try: patch_val = getattr(audit_template, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if audit_template_to_update[field] != patch_val: audit_template_to_update[field] = patch_val audit_template_to_update.save() return AuditTemplate.convert_with_links(audit_template_to_update)
def state(self, strategy): """Retrieve an information about strategy requirements. :param strategy: name of the strategy. """ context = pecan.request.context policy.enforce(context, 'strategy:state', action='strategy:state') parents = pecan.request.path.split('/')[:-1] if parents[-2] != "strategies": raise exception.HTTPNotFound rpc_strategy = api_utils.get_resource('Strategy', strategy) de_client = rpcapi.DecisionEngineAPI() strategy_state = de_client.get_strategy_info(context, rpc_strategy.name) strategy_state.extend([{ 'type': 'Name', 'state': rpc_strategy.name, 'mandatory': '', 'comment': ''}]) return strategy_state
def delete(self, audit): """Delete an audit. :param audit: UUID or name of an audit. """ context = pecan.request.context audit_to_delete = api_utils.get_resource('Audit', audit, eager=True) policy.enforce(context, 'audit:delete', audit_to_delete, action='audit:delete') initial_state = audit_to_delete.state new_state = objects.audit.State.DELETED if not objects.audit.AuditStateTransitionManager().check_transition( initial_state, new_state): raise exception.DeleteError(state=initial_state) audit_to_delete.soft_delete()
def delete(self, action_plan_uuid): """Delete an action plan. :param action_plan_uuid: UUID of a action. """ context = pecan.request.context action_plan = api_utils.get_resource( 'ActionPlan', action_plan_uuid, eager=True) policy.enforce(context, 'action_plan:delete', action_plan, action='action_plan:delete') allowed_states = (ap_objects.State.SUCCEEDED, ap_objects.State.RECOMMENDED, ap_objects.State.FAILED, ap_objects.State.SUPERSEDED, ap_objects.State.CANCELLED) if action_plan.state not in allowed_states: raise exception.DeleteError( state=action_plan.state) action_plan.soft_delete()
def post(self, audit_ident, body): """Trigger the given audit. :param audit_ident: UUID or name of an audit. """ LOG.debug("Webhook trigger Audit: %s.", audit_ident) context = pecan.request.context audit = utils.get_resource('Audit', audit_ident) if audit is None: raise exception.AuditNotFound(audit=audit_ident) if audit.audit_type != objects.audit.AuditType.EVENT.value: raise exception.AuditTypeNotAllowed(audit_type=audit.audit_type) allowed_state = ( objects.audit.State.PENDING, objects.audit.State.SUCCEEDED, ) if audit.state not in allowed_state: raise exception.AuditStateNotAllowed(state=audit.state) # trigger decision-engine to run the audit self.dc_client.trigger_audit(context, audit.uuid)
def patch(self, action_plan_uuid, patch): """Update an existing action plan. :param action_plan_uuid: UUID of a action plan. :param patch: a json PATCH document to apply to this action plan. """ if self.from_actionsPlans: raise exception.OperationNotPermitted context = pecan.request.context action_plan_to_update = api_utils.get_resource('ActionPlan', action_plan_uuid, eager=True) policy.enforce(context, 'action_plan:update', action_plan_to_update, action='action_plan:update') try: action_plan_dict = action_plan_to_update.as_dict() action_plan = ActionPlan( **api_utils.apply_jsonpatch(action_plan_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) launch_action_plan = False cancel_action_plan = False # transitions that are allowed via PATCH allowed_patch_transitions = [ (ap_objects.State.RECOMMENDED, ap_objects.State.PENDING), (ap_objects.State.RECOMMENDED, ap_objects.State.CANCELLED), (ap_objects.State.ONGOING, ap_objects.State.CANCELLING), (ap_objects.State.PENDING, ap_objects.State.CANCELLED), ] # todo: improve this in blueprint watcher-api-validation if hasattr(action_plan, 'state'): transition = (action_plan_to_update.state, action_plan.state) if transition not in allowed_patch_transitions: error_message = _("State transition not allowed: " "(%(initial_state)s -> %(new_state)s)") raise exception.PatchError( patch=patch, reason=error_message % dict(initial_state=action_plan_to_update.state, new_state=action_plan.state)) if action_plan.state == ap_objects.State.PENDING: launch_action_plan = True if action_plan.state == ap_objects.State.CANCELLED: cancel_action_plan = True # Update only the fields that have changed for field in objects.ActionPlan.fields: try: patch_val = getattr(action_plan, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if action_plan_to_update[field] != patch_val: action_plan_to_update[field] = patch_val if (field == 'state' and patch_val == objects.action_plan.State.PENDING): launch_action_plan = True action_plan_to_update.save() # NOTE: if action plan is cancelled from pending or recommended # state update action state here only if cancel_action_plan: filters = {'action_plan_uuid': action_plan.uuid} actions = objects.Action.list(pecan.request.context, filters=filters, eager=True) for a in actions: a.state = objects.action.State.CANCELLED a.save() if launch_action_plan: self.applier_client.launch_action_plan(pecan.request.context, action_plan.uuid) action_plan_to_update = objects.ActionPlan.get_by_uuid( pecan.request.context, action_plan_uuid) return ActionPlan.convert_with_links(action_plan_to_update)
def patch(self, action_plan_uuid, patch): """Update an existing action plan. :param action_plan_uuid: UUID of a action plan. :param patch: a json PATCH document to apply to this action plan. """ launch_action_plan = True if self.from_actionsPlans: raise exception.OperationNotPermitted context = pecan.request.context action_plan_to_update = api_utils.get_resource('ActionPlan', action_plan_uuid) policy.enforce(context, 'action_plan:update', action_plan_to_update, action='action_plan:update') try: action_plan_dict = action_plan_to_update.as_dict() action_plan = ActionPlan(**api_utils.apply_jsonpatch( action_plan_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) launch_action_plan = False # transitions that are allowed via PATCH allowed_patch_transitions = [ (ap_objects.State.RECOMMENDED, ap_objects.State.PENDING), (ap_objects.State.RECOMMENDED, ap_objects.State.CANCELLED), (ap_objects.State.ONGOING, ap_objects.State.CANCELLED), (ap_objects.State.PENDING, ap_objects.State.CANCELLED), ] # todo: improve this in blueprint watcher-api-validation if hasattr(action_plan, 'state'): transition = (action_plan_to_update.state, action_plan.state) if transition not in allowed_patch_transitions: error_message = _("State transition not allowed: " "(%(initial_state)s -> %(new_state)s)") raise exception.PatchError( patch=patch, reason=error_message % dict( initial_state=action_plan_to_update.state, new_state=action_plan.state)) if action_plan.state == ap_objects.State.PENDING: launch_action_plan = True # Update only the fields that have changed for field in objects.ActionPlan.fields: try: patch_val = getattr(action_plan, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if action_plan_to_update[field] != patch_val: action_plan_to_update[field] = patch_val if (field == 'state' and patch_val == objects.action_plan.State.PENDING): launch_action_plan = True action_plan_to_update.save() if launch_action_plan: applier_client = rpcapi.ApplierAPI() applier_client.launch_action_plan(pecan.request.context, action_plan.uuid) action_plan_to_update = objects.ActionPlan.get_by_uuid( pecan.request.context, action_plan_uuid) return ActionPlan.convert_with_links(action_plan_to_update)