Exemplo n.º 1
0
def update_workflow_definition(identifier, values, session=None):
    wf_def = get_workflow_definition(identifier)

    if wf_def.project_id != security.get_project_id():
        raise exc.NotAllowedException(
            "Can not update workflow of other tenants. "
            "[workflow_identifier=%s]" % identifier)

    if wf_def.is_system:
        raise exc.InvalidActionException(
            "Attempt to modify a system workflow: %s" % identifier)

    if wf_def.scope == 'public' and values['scope'] == 'private':
        cron_triggers = _get_associated_cron_triggers(identifier)

        try:
            [get_cron_trigger(name) for name in cron_triggers]
        except exc.NotFoundException:
            raise exc.NotAllowedException(
                "Can not update scope of workflow that has triggers "
                "associated in other tenants."
                "[workflow_identifier=%s]" % identifier)

    wf_def.update(values.copy())

    return wf_def
Exemplo n.º 2
0
    def __init__(self, action_def, action_ex=None, task_ex=None, task_ctx=None,
                 wf_ctx=None):
        self.action_spec = spec_parser.get_action_spec(action_def.spec)

        base_action_def = lookup_utils.find_action_definition_by_name(
            self.action_spec.get_base()
        )

        if not base_action_def:
            raise exc.InvalidActionException(
                "Failed to find action [action_name=%s]" %
                self.action_spec.get_base()
            )

        base_action_def = self._gather_base_actions(
            action_def,
            base_action_def
        )

        super(AdHocAction, self).__init__(
            base_action_def,
            action_ex,
            task_ex
        )

        self.adhoc_action_def = action_def
        self.task_ctx = task_ctx or {}
        self.wf_ctx = wf_ctx or {}
Exemplo n.º 3
0
def resolve_action_definition(action_spec_name,
                              wf_name=None,
                              wf_spec_name=None):
    """Resolve action definition accounting for ad-hoc action namespacing.

    :param action_spec_name: Action name according to a spec.
    :param wf_name: Workflow name.
    :param wf_spec_name: Workflow name according to a spec.
    :return: Action definition (python or ad-hoc).
    """

    action_db = None

    if wf_name and wf_name != wf_spec_name:
        # If workflow belongs to a workbook then check
        # action within the same workbook (to be able to
        # use short names within workbooks).
        # If it doesn't exist then use a name from spec
        # to find an action in DB.
        wb_name = wf_name.rstrip(wf_spec_name)[:-1]

        action_full_name = "%s.%s" % (wb_name, action_spec_name)

        action_db = db_api.load_action_definition(action_full_name)

    if not action_db:
        action_db = db_api.load_action_definition(action_spec_name)

    if not action_db:
        raise exc.InvalidActionException(
            "Failed to find action [action_name=%s]" % action_spec_name)

    return action_db
Exemplo n.º 4
0
def resolve_action_definition(action_spec_name, wf_name=None,
                              wf_spec_name=None):
    action_db = None

    if wf_name and wf_name != wf_spec_name:
        # If workflow belongs to a workbook then check
        # action within the same workbook (to be able to
        # use short names within workbooks).
        # If it doesn't exist then use a name from spec
        # to find an action in DB.
        wb_name = wf_name.rstrip(wf_spec_name)[:-1]

        action_full_name = "%s.%s" % (wb_name, action_spec_name)

        action_db = db_api.load_action_definition(action_full_name)

    if not action_db:
        action_db = db_api.load_action_definition(action_spec_name)

    if not action_db:
        raise exc.InvalidActionException(
            "Failed to find action [action_name=%s]" % action_spec_name
        )

    return action_db
Exemplo n.º 5
0
    def _visit_hierarchy(self, callback):
        callback_result = callback(self, None)

        action_spec = self.spec

        visited = {self.name}

        while action_spec:
            base_name = action_spec.get_base()

            if base_name in visited:
                raise ValueError('Found a cycle in an ad-hoc action chain '
                                 '[action_name=%s, duplicate_action_name=%s]' %
                                 (self.name, base_name))

            visited.add(base_name)

            system_provider = action_service.get_system_action_provider()

            base_action_desc = system_provider.find(base_name, self.namespace)

            if base_action_desc is None:
                raise exc.InvalidActionException(
                    "Failed to find base action [action_name=%s namespace=%s] "
                    % (base_name, self.namespace))

            # For every ad-hoc action in the hierarchy invoke the callback.
            callback_result = callback(base_action_desc, callback_result)

            if isinstance(base_action_desc, AdHocActionDescriptor):
                action_spec = base_action_desc.spec
            else:
                action_spec = None

        return callback_result
Exemplo n.º 6
0
    def __init__(self, action_def, action_ex=None, task_ex=None, task_ctx=None,
                 wf_ctx=None):
        self.action_spec = spec_parser.get_action_spec(action_def.spec)

        try:
            base_action_def = db_api.get_action_definition(
                self.action_spec.get_base()
            )
        except exc.DBEntityNotFoundError:
            raise exc.InvalidActionException(
                "Failed to find action [action_name=%s]" %
                self.action_spec.get_base()
            )

        base_action_def = self._gather_base_actions(
            action_def, base_action_def
        )

        super(AdHocAction, self).__init__(
            base_action_def,
            action_ex,
            task_ex
        )

        self.adhoc_action_def = action_def
        self.task_ctx = task_ctx or {}
        self.wf_ctx = wf_ctx or {}
Exemplo n.º 7
0
def build_action_by_name(action_name, namespace=''):
    action_desc = action_service.get_system_action_provider().find(
        action_name, namespace=namespace)

    if action_desc is None:
        raise exc.InvalidActionException(
            "Failed to find action [action_name=%s]" % action_name)

    return actions.RegularAction(action_desc)
Exemplo n.º 8
0
def create_or_update_action(action_spec, definition, scope):
    action = db_api.load_action_definition(action_spec.get_name())

    if action and action.is_system:
        raise exc.InvalidActionException(
            "Attempt to modify a system action: %s" % action.name)

    values = _get_action_values(action_spec, definition, scope)

    return db_api.create_or_update_action_definition(values['name'], values)
Exemplo n.º 9
0
def update_action(action_spec, definition, scope, identifier=None):
    action = db_api.load_action_definition(action_spec.get_name())

    if action and action.is_system:
        raise exc.InvalidActionException(
            "Attempt to modify a system action: %s" % action.name)

    values = _get_action_values(action_spec, definition, scope)

    return db_api.update_action_definition(
        identifier if identifier else values['name'], values)
Exemplo n.º 10
0
    def schedule(self,
                 input_dict,
                 target,
                 index=0,
                 desc='',
                 safe_rerun=False,
                 timeout=None):
        assert not self.action_ex

        self.action_desc.check_parameters(input_dict)

        wf_ex = self.task_ex.workflow_execution if self.task_ex else None

        wf_ctx = data_flow.ContextView(
            self.task_ctx, data_flow.get_workflow_environment_dict(wf_ex),
            wf_ex.context if wf_ex else {})

        try:
            action = self.action_desc.instantiate(input_dict, wf_ctx)
        except Exception:
            raise exc.InvalidActionException(
                'Failed to instantiate an action'
                ' [action_desc=%s, input_dict=%s]' %
                (self.action_desc, input_dict))

        # Assign the action execution ID here to minimize database calls.
        # Otherwise, the input property of the action execution DB object needs
        # to be updated with the action execution ID after the action execution
        # DB object is created.
        action_ex_id = utils.generate_unicode_uuid()

        self._create_action_execution(input_dict,
                                      self._prepare_runtime_context(
                                          index, safe_rerun),
                                      desc=desc,
                                      action_ex_id=action_ex_id,
                                      is_sync=action.is_sync())

        def _run_action():
            executor = exe.get_executor(cfg.CONF.executor.type)

            return executor.run_action(
                action,
                self.action_ex.id if self.action_ex is not None else None,
                safe_rerun,
                self._prepare_execution_context(),
                target=target,
                timeout=timeout)

        # Register an asynchronous command to run the action
        # on an executor outside of the main DB transaction.
        post_tx_queue.register_operation(_run_action)
Exemplo n.º 11
0
def _build_action(action_ex):
    if isinstance(action_ex, models.WorkflowExecution):
        return actions.WorkflowAction(wf_name=action_ex.name,
                                      action_ex=action_ex)

    action_desc = action_service.get_system_action_provider().find(
        action_ex.name, action_ex.workflow_namespace)

    if action_desc is None:
        raise exc.InvalidActionException(
            "Failed to find action [action_name=%s]" % action_ex.name)

    return actions.RegularAction(action_desc, action_ex)
Exemplo n.º 12
0
def check_db_obj_access(db_obj):
    """Check accessibility to db object."""
    ctx = context.ctx()
    is_admin = ctx.is_admin

    if not is_admin and db_obj.project_id != security.get_project_id():
        raise exc.NotAllowedException(
            "Can not access %s resource of other projects, ID: %s" %
            (db_obj.__class__.__name__, db_obj.id))

    if not is_admin and hasattr(db_obj, 'is_system') and db_obj.is_system:
        raise exc.InvalidActionException(
            "Can not modify a system %s resource, ID: %s" %
            (db_obj.__class__.__name__, db_obj.id))
Exemplo n.º 13
0
    def _gather_base_actions(self, action_def, base_action_def):
        """Find all base ad-hoc actions and store them.

        An ad-hoc action may be based on another ad-hoc action and this
        works recursively, so that the base action can also be based on an
        ad-hoc action. Using the same base action more than once in this
        action hierarchy is not allowed to avoid infinite loops.
        The method stores the list of ad-hoc actions.

        :param action_def: Action definition
        :type action_def: ActionDefinition
        :param base_action_def: Original base action definition
        :type base_action_def: ActionDefinition
        :return: The definition of the base system action
        :rtype: ActionDefinition
        """

        self.adhoc_action_defs = [action_def]

        original_base_name = self.action_spec.get_name()
        action_names = set([original_base_name])

        base = base_action_def

        while not base.is_system and base.name not in action_names:
            action_names.add(base.name)
            self.adhoc_action_defs.append(base)

            base_name = base.spec['base']
            try:
                base = db_api.get_action_definition(base_name,
                                                    namespace=base.namespace)
            except exc.DBEntityNotFoundError:
                raise exc.InvalidActionException(
                    "Failed to find action [action_name=%s namespace=%s] "
                    % (base_name, base.namespace)
                )

        # if the action is repeated
        if base.name in action_names:
            raise ValueError(
                'An ad-hoc action cannot use twice the same action, %s is '
                'used at least twice' % base.name
            )

        return base
Exemplo n.º 14
0
    def run(self,
            input_dict,
            target,
            index=0,
            desc='',
            save=True,
            safe_rerun=False,
            timeout=None):
        assert not self.action_ex

        self.action_desc.check_parameters(input_dict)

        try:
            action = self.action_desc.instantiate(input_dict, {})
        except Exception:
            raise exc.InvalidActionException(
                'Failed to instantiate an action'
                ' [action_desc=%s, input_dict=%s]' %
                (self.action_desc, input_dict))

        # Assign the action execution ID here to minimize database calls.
        # Otherwise, the input property of the action execution DB object needs
        # to be updated with the action execution ID after the action execution
        # DB object is created.
        action_ex_id = utils.generate_unicode_uuid()

        if save:
            self._create_action_execution(input_dict,
                                          self._prepare_runtime_context(
                                              index, safe_rerun),
                                          desc=desc,
                                          action_ex_id=action_ex_id,
                                          is_sync=action.is_sync())

        executor = exe.get_executor(cfg.CONF.executor.type)

        return executor.run_action(
            action,
            self.action_ex.id if self.action_ex is not None else None,
            safe_rerun,
            self._prepare_execution_context(),
            target=target,
            async_=False,
            timeout=timeout)
Exemplo n.º 15
0
def update_workflow_definition(identifier, values, session=None):
    wf_def = get_workflow_definition(identifier)

    if wf_def.project_id != security.get_project_id():
        raise exc.NotAllowedException(
            "Can not update workflow of other tenants. "
            "[workflow_identifier=%s]" % identifier
        )

    if wf_def.is_system:
        raise exc.InvalidActionException(
            "Attempt to modify a system workflow: %s" % identifier
        )

    if wf_def.scope == 'public' and values['scope'] == 'private':
        # Check cron triggers.
        cron_triggers = get_cron_triggers(insecure=True, workflow_id=wf_def.id)

        for c_t in cron_triggers:
            if c_t.project_id != wf_def.project_id:
                raise exc.NotAllowedException(
                    "Can not update scope of workflow that has cron triggers "
                    "associated in other tenants. [workflow_identifier=%s]" %
                    identifier
                )

        # Check event triggers.
        event_triggers = get_event_triggers(
            insecure=True,
            workflow_id=wf_def.id
        )
        for e_t in event_triggers:
            if e_t.project_id != wf_def.project_id:
                raise exc.NotAllowedException(
                    "Can not update scope of workflow that has event triggers "
                    "associated in other tenants. [workflow_identifier=%s]" %
                    identifier
                )

    wf_def.update(values.copy())

    return wf_def