예제 #1
0
    def execute_action(self, params, context=None, request=None):
        """Execute the action."""
        body = json.loads(request.body)
        # e.g. name = 'nova:disconnectNetwork'
        items = re.split(':', body.get('name'))
        if len(items) != 2:
            (num, desc) = error_codes.get('service_action_syntax')
            raise webservice.DataModelException(num, desc)
        service = items[0].strip()
        action = items[1].strip()
        action_args = body.get('args', {})
        if (not isinstance(action_args, dict)):
            (num, desc) = error_codes.get('execute_action_args_syntax')
            raise webservice.DataModelException(num, desc)

        try:
            args = {'service_name': service,
                    'action': action,
                    'action_args': action_args}
            # Note(thread-safety): blocking call
            self.invoke_rpc(base.ENGINE_SERVICE_ID, 'execute_action', args)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('execute_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #2
0
    def execute_action(self, params, context=None, request=None):
        """Execute the action."""
        body = json.loads(request.body)
        # e.g. name = 'nova:disconnectNetwork'
        items = re.split(':', body.get('name'))
        if len(items) != 2:
            (num, desc) = error_codes.get('service_action_syntax')
            raise webservice.DataModelException(num, desc)
        service = items[0].strip()
        action = items[1].strip()
        action_args = body.get('args', {})
        if (not isinstance(action_args, dict)):
            (num, desc) = error_codes.get('execute_action_args_syntax')
            raise webservice.DataModelException(num, desc)

        try:
            args = {'service_name': service,
                    'action': action,
                    'action_args': action_args}
            # Note(thread-safety): blocking call
            self.invoke_rpc(base.ENGINE_SERVICE_ID, 'execute_action', args,
                            timeout=self.action_retry_timeout)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('execute_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #3
0
    def execute_action(self, params, context=None, request=None):
        "Execute the action."
        service = context.get('ds_id')
        body = json.loads(request.body)
        action = body.get('name')
        action_args = body.get('args', {})
        if (not isinstance(action_args, dict)):
            (num, desc) = error_codes.get('execute_action_args_syntax')
            raise webservice.DataModelException(num, desc)

        try:
            args = {
                'service_name': service,
                'action': action,
                'action_args': action_args
            }
            # TODO(ekcs): perhaps keep execution synchronous when explicitly
            #   called via API
            # Note(thread-safety): blocking call
            self.invoke_rpc(base.ENGINE_SERVICE_ID, 'execute_action', args)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('execute_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #4
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
        """
        if id_ is not None:
            raise webservice.DataModelException(
                *error_codes.get('add_item_id'))
        str_rule = item['rule']
        try:
            rule = self.engine.parse(str_rule)
            if len(rule) == 1:
                rule = rule[0]
            else:
                (num, desc) = error_codes.get('multiple_rules')
                raise webservice.DataModelException(
                    num, desc + ":: Received multiple rules: " +
                    "; ".join(str(x) for x in rule))
            changes = self.change_rule(rule, context)
        except PolicyException as e:
            LOG.debug("add_item error: invalid rule syntax")
            (num, desc) = error_codes.get('rule_syntax')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        for change in changes:
            if change.formula == rule:
                d = {'rule': rule.pretty_str(),
                     'id': str(uuid.uuid4()),
                     'comment': None,
                     'name': item.get('name')}
                policy_name = self.policy_name(context)
                try:
                    db_policy_rules.add_policy_rule(
                        d['id'], policy_name, str_rule, d['comment'],
                        rule_name=d['name'])
                    return (d['id'], d)
                except Exception as db_exception:
                    try:
                        self.change_rule(rule, context, insert=False)
                    except Exception as change_exception:
                        raise Exception(
                            "Error thrown during recovery from DB error. "
                            "Inconsistent state.  DB error: %s.  "
                            "New error: %s.", str(db_exception),
                            str(change_exception))

        num, desc = error_codes.get('rule_already_exists')
        raise webservice.DataModelException(
            num, desc, http_status_code=httplib.CONFLICT)
예제 #5
0
    def simulate_action(self, params, context=None, request=None):
        """Simulate the effects of executing a sequence of updates.

        :returns: the result of a query.
        """
        # grab string arguments
        theory = context.get('policy_id') or params.get('policy')
        if theory is None:
            (num, desc) = error_codes.get('simulate_without_policy')
            raise webservice.DataModelException(num, desc)

        body = json.loads(request.body)
        query = body.get('query')
        sequence = body.get('sequence')
        actions = body.get('action_policy')
        delta = self._get_boolean_param('delta', params)
        trace = self._get_boolean_param('trace', params)
        if query is None or sequence is None or actions is None:
            (num, desc) = error_codes.get('incomplete_simulate_args')
            raise webservice.DataModelException(num, desc)

        try:
            result = self.rpc(
                'simulate', query, theory, sequence, actions, delta=delta,
                trace=trace, as_list=True)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('simulate_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        # always return dict
        if trace:
            return {'result': result[0],
                    'trace': result[1]}
        return {'result': result}
예제 #6
0
    def simulate_action(self, params, context=None, request=None):
        """Simulate the effects of executing a sequence of updates and
        return the result of a query.
        """
        # grab string arguments
        theory = context.get('policy_id') or params.get('policy')
        if theory is None:
            (num, desc) = error_codes.get('simulate_without_policy')
            raise webservice.DataModelException(num, desc)

        query = params.get('query')
        sequence = params.get('sequence')
        actions = params.get('action_policy')
        delta = self._get_boolean_param('delta', params)
        trace = self._get_boolean_param('trace', params)
        if query is None or sequence is None or actions is None:
            (num, desc) = error_codes.get('incomplete_simulate_args')
            raise webservice.DataModelException(num, desc)

        # parse arguments so that result of simulate is an object
        query = self._parse_rule(query)
        sequence = self._parse_rules(sequence)

        try:
            result = self.engine.simulate(
                query, theory, sequence, actions, delta, trace)
        except compile.CongressException as e:
            (num, desc) = error_codes.get('simulate_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        # always return dict
        if trace:
            return {'result': [str(x) for x in result[0]],
                    'trace': result[1]}
        return {'result': [str(x) for x in result]}
예제 #7
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
            DataModelException: Addition cannot be performed.
        """
        # validation
        if id_ is None:
            id_ = str(uuidutils.generate_uuid())
        else:
            (num, desc) = error_codes.get('policy_id_must_not_be_provided')
            raise webservice.DataModelException(num, desc)
        if 'name' not in item:
            (num, desc) = error_codes.get('policy_name_must_be_provided')
            raise webservice.DataModelException(num, desc)
        name = item['name']
        try:
            self.engine.parse("%s() :- true()" % name)
        except PolicyException:
            (num, desc) = error_codes.get('policy_name_must_be_id')
            raise webservice.DataModelException(num, desc + ": " + str(name))

        # create policy in policy engine
        try:
            policy_obj = self.engine.create_policy(
                name, abbr=item.get('abbreviation'), kind=item.get('kind'))
        except PolicyException as e:
            (num, desc) = error_codes.get('failed_to_create_policy')
            raise webservice.DataModelException(num, desc + ": " + str(e))

        # save policy to database
        desc = item.get('description', '')
        if desc is None:
            desc = ''
        obj = {
            'id': id_,
            'name': name,
            'owner_id': 'user',
            'description': desc,
            'abbreviation': policy_obj.abbr,
            'kind': self.engine.policy_type(name)
        }
        # TODO(thinrichs): add rollback of policy engine if this fails
        db_policy_rules.add_policy(obj['id'], obj['name'], obj['abbreviation'],
                                   obj['description'], obj['owner_id'],
                                   obj['kind'])
        return (id_, obj)
예제 #8
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
        """
        if id_ is not None:
            LOG.debug("add_item error: should not be given ID")
            raise webservice.DataModelException(
                *error_codes.get('add_item_id'))
        str_rule = item['rule']
        try:
            rule = self.engine.parse(str_rule)
            if len(rule) == 1:
                rule = rule[0]
            else:
                LOG.debug("add_item error: given too many rules")
                (num, desc) = error_codes.get('multiple_rules')
                raise webservice.DataModelException(
                    num, desc + ":: Received multiple rules: " +
                    "; ".join(str(x) for x in rule))
            changes = self.change_rule(rule, context)
        except compile.CongressException as e:
            LOG.debug("add_item error: invalid rule syntax")
            (num, desc) = error_codes.get('rule_syntax')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        for change in changes:
            if change.formula == rule:
                d = {
                    'rule': rule.pretty_str(),
                    'id': str(uuid.uuid4()),
                    'comment': None,
                    'name': item.get('name')
                }
                policy_name = self.policy_name(context)
                db_policy_rules.add_policy_rule(d['id'],
                                                policy_name,
                                                str_rule,
                                                d['comment'],
                                                rule_name=d['name'])
                return (d['id'], d)
        num, desc = error_codes.get('rule_already_exists')
        raise webservice.DataModelException(num,
                                            desc,
                                            http_status_code=httplib.CONFLICT)
예제 #9
0
 def _check_create_policy_item(self, item):
     if 'name' not in item:
         (num, desc) = error_codes.get('policy_name_must_be_provided')
         raise webservice.DataModelException(num, desc)
     abbr = item.get('abbreviation')
     if abbr:
         # the length of abbreviation column is 5 chars in policy DB table,
         # check it in API layer and raise exception if it's too long.
         if not isinstance(abbr, six.string_types) or len(abbr) > 5:
             (num, desc) = error_codes.get('policy_abbreviation_error')
             raise webservice.DataModelException(num, desc)
예제 #10
0
 def _check_create_policy_item(self, item):
     if 'name' not in item:
         (num, desc) = error_codes.get('policy_name_must_be_provided')
         raise webservice.DataModelException(num, desc)
     abbr = item.get('abbreviation')
     if abbr:
         # the length of abbreviation column is 5 chars in policy DB table,
         # check it in API layer and raise exception if it's too long.
         if not isinstance(abbr, six.string_types) or len(abbr) > 5:
             (num, desc) = error_codes.get('policy_abbreviation_error')
             raise webservice.DataModelException(num, desc)
예제 #11
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
        """
        # TODO(thinrichs): add comment property to rule
        if id_ is not None:
            raise webservice.DataModelException(
                **error_codes.get('add_item_id'))
        str_rule = item['rule']
        try:
            rule = compile.parse(str_rule)
            if len(rule) == 1:
                rule = rule[0]
            else:
                (num, desc) = error_codes.get('add_item_multiple_rules')
                raise webservice.DataModelException(
                    num, desc + ":: Received multiple rules: " +
                    "; ".join(str(x) for x in rule))
            changes = self.change_rule(rule, context)
        except compile.CongressException as e:
            (num, desc) = error_codes.get('rule_syntax')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        for change in changes:
            if change.formula == rule:
                d = {'rule': str(rule),
                     'id': rule.id,
                     'comment': None}
                return (rule.id, d)
        # rule already existed
        policy_name = self.policy_name(context)
        for p in self.engine.theory[policy_name].policy():
            if p == rule:
                d = {'rule': str(rule),
                     'id': rule.id,
                     'comment': 'None'}
                return (rule.id, d)
        raise Exception("add_item added a rule but then could not find it.")
예제 #12
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
        """
        if id_ is not None:
            LOG.debug("add_item error: should not be given ID")
            raise webservice.DataModelException(
                *error_codes.get('add_item_id'))
        str_rule = item['rule']
        try:
            rule = compile.parse(str_rule, self.engine.module_schemas)
            if len(rule) == 1:
                rule = rule[0]
            else:
                LOG.debug("add_item error: given too many rules")
                (num, desc) = error_codes.get('multiple_rules')
                raise webservice.DataModelException(
                    num, desc + ":: Received multiple rules: " +
                    "; ".join(str(x) for x in rule))
            changes = self.change_rule(rule, context)
        except compile.CongressException as e:
            LOG.debug("add_item error: invalid rule syntax")
            (num, desc) = error_codes.get('rule_syntax')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        for change in changes:
            if change.formula == rule:
                d = {'rule': rule.pretty_str(),
                     'id': rule.id,
                     'comment': None}
                policy_name = self.policy_name(context)
                db_policy_rules.add_policy_rule(d['id'], policy_name,
                                                str_rule, d['comment'])
                return (rule.id, d)

        num, desc = error_codes.get('rule_already_exists')
        raise webservice.DataModelException(
            num, desc, http_status_code=httplib.CONFLICT)
예제 #13
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
        """
        if id_ is not None:
            raise webservice.DataModelException(*error_codes.get("add_item_id"))
        try:
            args = {
                "policy_name": self.policy_name(context),
                "str_rule": item.get("rule"),
                "rule_name": item.get("name"),
                "comment": item.get("comment"),
            }
            return self.invoke_rpc(self.engine, "persistent_insert_rule", args)
        except exception.CongressException as e:
            raise webservice.DataModelException.create(e)
예제 #14
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
            DataModelException: Addition cannot be performed.
        """
        self._check_create_policy(id_, item)
        name = item['name']
        try:
            policy_metadata = self.rpc(
                'persistent_create_policy', name,
                abbr=item.get('abbreviation'), kind=item.get('kind'),
                desc=item.get('description'))
        except exception.CongressException as e:
            (num, desc) = error_codes.get('failed_to_create_policy')
            raise webservice.DataModelException(
                num, desc + ": " + str(e))

        return (policy_metadata['id'], policy_metadata)
예제 #15
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        :param: item: The item to add to the model
        :param: params: A dict-like object containing parameters
                    from the request query string and body.
        :param: id\_: The ID of the item, or None if an ID should be generated
        :param: context: Key-values providing frame of reference of request

        :returns: Tuple of (ID, newly_created_item)

        :raises KeyError: ID already exists.
        """
        if id_ is not None:
            raise webservice.DataModelException(
                *error_codes.get('add_item_id'))
        try:
            args = {
                'policy_name': self.policy_name(context),
                'str_rule': item.get('rule'),
                'rule_name': item.get('name'),
                'comment': item.get('comment')
            }
            # Note(thread-safety): blocking call
            return self.invoke_rpc(base.ENGINE_SERVICE_ID,
                                   'persistent_insert_rule',
                                   args,
                                   timeout=self.dse_long_timeout)
        except exception.CongressException as e:
            raise webservice.DataModelException.create(e)
예제 #16
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        :param: item: The item to add to the model
        :param: params: A dict-like object containing parameters
                    from the request query string and body.
        :param: id\_: The unique name of the item
        :param: context: Key-values providing frame of reference of request

        :returns: Tuple of (ID, newly_created_item)

        :raises KeyError: ID already exists.
        :raises DataModelException: Addition cannot be performed.
        """
        if id_ is not None:
            (num, desc) = error_codes.get('policy_id_must_not_be_provided')
            raise webservice.DataModelException(num, desc)

        try:
            # Note(thread-safety): blocking call
            policy_metadata = self.invoke_rpc(
                base.LIBRARY_SERVICE_ID, 'create_policy',
                {'policy_dict': item})
        except exception.CongressException as e:
            raise webservice.DataModelException.create(e)

        return (policy_metadata['id'], policy_metadata)
예제 #17
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        :param: item: The item to add to the model
        :param: params: A dict-like object containing parameters
                    from the request query string and body.
        :param: id\_: The ID of the item, or None if an ID should be generated
        :param: context: Key-values providing frame of reference of request

        :returns: Tuple of (ID, newly_created_item)

        :raises KeyError: ID already exists.
        """
        if id_ is not None:
            raise webservice.DataModelException(
                *error_codes.get('add_item_id'))
        try:
            args = {'policy_name': self.policy_name(context),
                    'str_rule': item.get('rule'),
                    'rule_name': item.get('name'),
                    'comment': item.get('comment')}
            # Note(thread-safety): blocking call
            return self.invoke_rpc(base.ENGINE_SERVICE_ID,
                                   'persistent_insert_rule', args,
                                   timeout=self.dse_long_timeout)
        except exception.CongressException as e:
            raise webservice.DataModelException.create(e)
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The unique name of the item
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
            DataModelException: Addition cannot be performed.
        """
        if id_ is not None:
            (num, desc) = error_codes.get('policy_id_must_not_be_provided')
            raise webservice.DataModelException(num, desc)

        try:
            # Note(thread-safety): blocking call
            policy_metadata = self.invoke_rpc(base.LIBRARY_SERVICE_ID,
                                              'create_policy',
                                              {'policy_dict': item})
        except exception.CongressException as e:
            raise webservice.DataModelException.create(e)

        return (policy_metadata['id'], policy_metadata)
예제 #19
0
    def execute_action(self, params, context=None, request=None):
        "Execute the action."
        service = context.get('ds_id')
        body = json.loads(request.body)
        action = body.get('name')
        action_args = body.get('args', {})
        if (not isinstance(action_args, dict)):
            (num, desc) = error_codes.get('execute_action_args_syntax')
            raise webservice.DataModelException(num, desc)

        try:
            self.engine.execute_action(service, action, action_args)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('execute_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #20
0
    def execute_action(self, params, context=None, request=None):
        "Execute the action."
        service = context.get("ds_id")
        body = json.loads(request.body)
        action = body.get("name")
        action_args = body.get("args", {})
        if not isinstance(action_args, dict):
            (num, desc) = error_codes.get("execute_action_args_syntax")
            raise webservice.DataModelException(num, desc)

        try:
            args = {"service_name": service, "action": action, "action_args": action_args}
            self.invoke_rpc(self.engine, "execute_action", args)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get("execute_error")
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #21
0
    def simulate_action(self, params, context=None, request=None):
        """Simulate the effects of executing a sequence of updates.

        :returns: the result of a query.
        """
        # grab string arguments
        theory = context.get('policy_id') or params.get('policy')
        if theory is None:
            (num, desc) = error_codes.get('simulate_without_policy')
            raise webservice.DataModelException(num, desc)

        body = json.loads(request.body)
        query = body.get('query')
        sequence = body.get('sequence')
        actions = body.get('action_policy')
        delta = self._get_boolean_param('delta', params)
        trace = self._get_boolean_param('trace', params)
        if query is None or sequence is None or actions is None:
            (num, desc) = error_codes.get('incomplete_simulate_args')
            raise webservice.DataModelException(num, desc)

        try:
            args = {
                'query': query,
                'theory': theory,
                'sequence': sequence,
                'action_theory': actions,
                'delta': delta,
                'trace': trace,
                'as_list': True
            }
            # Note(thread-safety): blocking call
            result = self.invoke_rpc(base.ENGINE_SERVICE_ID,
                                     'simulate',
                                     args,
                                     timeout=self.dse_long_timeout)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('simulate_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        # always return dict
        if trace:
            return {'result': result[0], 'trace': result[1]}
        return {'result': result}
예제 #22
0
 def _parse_rules(self, string, errmsg=''):
     if errmsg:
         errmsg = errmsg + ":: "
     # basic parsing
     try:
         return self.engine.parse(string)
     except PolicyException as e:
         (num, desc) = error_codes.get('rule_syntax')
         raise webservice.DataModelException(num,
                                             desc + ":: " + errmsg + str(e))
예제 #23
0
 def _parse_rule(self, string, errmsg=''):
     rules = self._parse_rules(string, errmsg)
     if len(rules) == 1:
         return rules[0]
     if errmsg:
         errmsg = errmsg + ":: "
     (num, desc) = error_codes.get('multiple_rules')
     raise webservice.DataModelException(
         num, desc + ":: " + errmsg + string + " parses to " +
         "; ".join(str(x) for x in rules))
예제 #24
0
 def _parse_rules(self, string, errmsg=''):
     if errmsg:
         errmsg = errmsg + ":: "
     # basic parsing
     try:
         return self.engine.parse(string)
     except PolicyException as e:
         (num, desc) = error_codes.get('rule_syntax')
         raise webservice.DataModelException(
             num, desc + ":: " + errmsg + str(e))
예제 #25
0
 def _parse_rule(self, string, errmsg=''):
     rules = self._parse_rules(string, errmsg)
     if len(rules) == 1:
         return rules[0]
     if errmsg:
         errmsg = errmsg + ":: "
     (num, desc) = error_codes.get('multiple_rules')
     raise webservice.DataModelException(
         num, desc + ":: " + errmsg + string + " parses to " +
         "; ".join(str(x) for x in rules))
예제 #26
0
    def execute_action(self, params, context=None, request=None):
        """Execute the action."""
        body = json.loads(request.body)
        # e.g. name = 'nova:disconnectNetwork'
        items = re.split(':', body.get('name'))
        if len(items) != 2:
            (num, desc) = error_codes.get('service_action_syntax')
            raise webservice.DataModelException(num, desc)
        service = items[0].strip()
        action = items[1].strip()
        action_args = body.get('args')
        if (not isinstance(action_args, dict)):
            (num, desc) = error_codes.get('execute_action_args_syntax')
            raise webservice.DataModelException(num, desc)

        try:
            self.engine.execute_action(service, action, action_args)
        except PolicyException as e:
            (num, desc) = error_codes.get('execute_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #27
0
    def execute_action(self, params, context=None, request=None):
        "Execute the action."
        service = context.get('ds_id')
        body = json.loads(request.body)
        action = body.get('name')
        action_args = body.get('args', {})
        if (not isinstance(action_args, dict)):
            (num, desc) = error_codes.get('execute_action_args_syntax')
            raise webservice.DataModelException(num, desc)

        try:
            args = {'service_name': service, 'action': action,
                    'action_args': action_args}
            # TODO(ekcs): perhaps keep execution synchronous when explicitly
            #   called via API
            # Note(thread-safety): blocking call
            self.invoke_rpc(base.ENGINE_SERVICE_ID, 'execute_action', args)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('execute_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #28
0
    def execute_action(self, params, context=None, request=None):
        """Execute the action."""
        body = json.loads(request.body)
        # e.g. name = 'nova:disconnectNetwork'
        items = re.split(':', body.get('name'))
        if len(items) != 2:
            (num, desc) = error_codes.get('service_action_syntax')
            raise webservice.DataModelException(num, desc)
        service = items[0].strip()
        action = items[1].strip()
        action_args = body.get('args', {})
        if (not isinstance(action_args, dict)):
            (num, desc) = error_codes.get('execute_action_args_syntax')
            raise webservice.DataModelException(num, desc)

        try:
            self.engine.execute_action(service, action, action_args)
        except PolicyException as e:
            (num, desc) = error_codes.get('execute_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        return {}
예제 #29
0
    def simulate_action(self, params, context=None, request=None):
        """Simulate the effects of executing a sequence of updates.

        :returns: the result of a query.
        """
        # grab string arguments
        theory = context.get('policy_id') or params.get('policy')
        if theory is None:
            (num, desc) = error_codes.get('simulate_without_policy')
            raise webservice.DataModelException(num, desc)

        body = json.loads(request.body)
        query = body.get('query')
        sequence = body.get('sequence')
        actions = body.get('action_policy')
        delta = self._get_boolean_param('delta', params)
        trace = self._get_boolean_param('trace', params)
        if query is None or sequence is None or actions is None:
            (num, desc) = error_codes.get('incomplete_simulate_args')
            raise webservice.DataModelException(num, desc)

        try:
            args = {'query': query, 'theory': theory, 'sequence': sequence,
                    'action_theory': actions, 'delta': delta,
                    'trace': trace, 'as_list': True}
            # Note(thread-safety): blocking call
            result = self.invoke_rpc(base.ENGINE_SERVICE_ID, 'simulate',
                                     args, timeout=self.dse_long_timeout)
        except exception.PolicyException as e:
            (num, desc) = error_codes.get('simulate_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        # always return dict
        if trace:
            return {'result': result[0],
                    'trace': result[1]}
        return {'result': result}
예제 #30
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
            DataModelException: Addition cannot be performed.
        """
        if id_ is not None:
            (num, desc) = error_codes.get("policy_id_must_not_be_provided")
            raise webservice.DataModelException(num, desc)
        if "name" not in item:
            (num, desc) = error_codes.get("policy_name_must_be_provided")
            raise webservice.DataModelException(num, desc)
        name = item["name"]
        try:
            policy_metadata = self.rpc(
                "persistent_create_policy",
                name,
                abbr=item.get("abbreviation"),
                kind=item.get("kind"),
                desc=item.get("description"),
            )
        except exception.CongressException as e:
            (num, desc) = error_codes.get("failed_to_create_policy")
            raise webservice.DataModelException(num, desc + ": " + str(e))

        return (policy_metadata["id"], policy_metadata)
예제 #31
0
    def test_get_unknown__error_code(self):
        name = 'unknown'
        error_codes.errors = {
            "fake-error": (
                0000,
                'This is a fake error code.'
            )
        }
        expected_ret = (
            1000,
            'Unknown error'
        )

        ret = error_codes.get(name)
        self.assertEqual(expected_ret, ret)
예제 #32
0
    def simulate_action(self, params, context=None, request=None):
        """Simulate the effects of executing a sequence of updates.

        :returns: the result of a query.
        """
        # grab string arguments
        theory = context.get('policy_id') or params.get('policy')
        if theory is None:
            (num, desc) = error_codes.get('simulate_without_policy')
            raise webservice.DataModelException(num, desc)

        body = json.loads(request.body)
        query = body.get('query')
        sequence = body.get('sequence')
        actions = body.get('action_policy')
        delta = self._get_boolean_param('delta', params)
        trace = self._get_boolean_param('trace', params)
        if query is None or sequence is None or actions is None:
            (num, desc) = error_codes.get('incomplete_simulate_args')
            raise webservice.DataModelException(num, desc)

        # parse arguments so that result of simulate is an object
        query = self._parse_rule(query)
        sequence = self._parse_rules(sequence)

        try:
            result = self.engine.simulate(query, theory, sequence, actions,
                                          delta, trace)
        except PolicyException as e:
            (num, desc) = error_codes.get('simulate_error')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        # always return dict
        if trace:
            return {'result': [str(x) for x in result[0]], 'trace': result[1]}
        return {'result': [str(x) for x in result]}
예제 #33
0
    def test_get_error_code(self):
        name = 'fake-error'
        error_codes.errors = {
            "fake-error": (0000, 'This is a fake error code.', 400)
        }
        expected_num = 0000
        expected_desc = 'This is a fake error code.'
        expected_http = 400
        expected_ret = (expected_num, expected_desc)

        ret = error_codes.get(name)
        self.assertEqual(expected_ret, ret)

        num = error_codes.get_num(name)
        self.assertEqual(expected_num, num)

        desc = error_codes.get_desc(name)
        self.assertEqual(expected_desc, desc)

        http = error_codes.get_http(name)
        self.assertEqual(expected_http, http)
예제 #34
0
    def test_get_error_code(self):
        name = 'fake-error'
        error_codes.errors = {
            "fake-error": (0000, 'This is a fake error code.', 400)
        }
        expected_num = 0000
        expected_desc = 'This is a fake error code.'
        expected_http = 400
        expected_ret = (expected_num, expected_desc)

        ret = error_codes.get(name)
        self.assertEqual(expected_ret, ret)

        num = error_codes.get_num(name)
        self.assertEqual(expected_num, num)

        desc = error_codes.get_desc(name)
        self.assertEqual(expected_desc, desc)

        http = error_codes.get_http(name)
        self.assertEqual(expected_http, http)
예제 #35
0
    def test_get_unknown__error_code(self):
        name = 'fake_error_code'
        error_codes.errors = {
            error_codes.UNKNOWN: (0000, 'Unknown error', 400),
            'fake-error': (1000, 'Fake error', 404)
        }
        expected_num = 0000
        expected_desc = 'Unknown error'
        expected_http = 400
        expected_ret = (expected_num, expected_desc)

        ret = error_codes.get(name)
        self.assertEqual(expected_ret, ret)

        num = error_codes.get_num(name)
        self.assertEqual(expected_num, num)

        desc = error_codes.get_desc(name)
        self.assertEqual(expected_desc, desc)

        http = error_codes.get_http(name)
        self.assertEqual(expected_http, http)
예제 #36
0
    def test_get_unknown__error_code(self):
        name = 'fake_error_code'
        error_codes.errors = {
            error_codes.UNKNOWN: (0000, 'Unknown error', 400),
            'fake-error': (1000, 'Fake error', 404)
        }
        expected_num = 0000
        expected_desc = 'Unknown error'
        expected_http = 400
        expected_ret = (expected_num, expected_desc)

        ret = error_codes.get(name)
        self.assertEqual(expected_ret, ret)

        num = error_codes.get_num(name)
        self.assertEqual(expected_num, num)

        desc = error_codes.get_desc(name)
        self.assertEqual(expected_desc, desc)

        http = error_codes.get_http(name)
        self.assertEqual(expected_http, http)
예제 #37
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
        """
        if id_ is not None:
            raise webservice.DataModelException(
                *error_codes.get('add_item_id'))
        # Reject rules inserted into non-persisted policies
        # (i.e. datasource policies)
        policy_name = self.policy_name(context)
        policies = db_policy_rules.get_policies()
        persisted_policies = set([p.name for p in policies])
        if policy_name not in persisted_policies:
            if policy_name in self.engine.theory:
                LOG.debug("add_item error: rule not permitted for policy %s",
                          policy_name)
                raise webservice.DataModelException(
                    *error_codes.get('rule_not_permitted'),
                    http_status_code=httplib.FORBIDDEN)
            else:
                LOG.debug("add_item error: policy %s not exist", policy_name)
                raise webservice.DataModelException(
                    *error_codes.get('policy_not_exist'),
                    http_status_code=httplib.NOT_FOUND)

        str_rule = item['rule']
        id = uuid.uuid4()
        try:
            rule = self.engine.parse(str_rule)
            if len(rule) == 1:
                rule = rule[0]
            else:
                (num, desc) = error_codes.get('multiple_rules')
                raise webservice.DataModelException(
                    num, desc + ":: Received multiple rules: " +
                    "; ".join(str(x) for x in rule))
            rule.set_id(id)
            rule.set_name(item.get('name'))
            rule.set_comment(None)
            rule.set_original_str(str_rule)
            changes = self.change_rule(rule, context)
        except exception.PolicyException as e:
            LOG.debug("add_item error: invalid rule syntax")
            (num, desc) = error_codes.get('rule_syntax')
            raise webservice.DataModelException(num, desc + "::" + str(e))

        for change in changes:
            if change.formula == rule:
                d = {'rule': rule.pretty_str(),
                     'id': str(id),
                     'comment': rule.comment,
                     'name': item.get('name')}
                try:
                    db_policy_rules.add_policy_rule(
                        d['id'], policy_name, str_rule, d['comment'],
                        rule_name=d['name'])
                    return (d['id'], d)
                except Exception as db_exception:
                    try:
                        self.change_rule(rule, context, insert=False)
                    except Exception as change_exception:
                        raise Exception(
                            "Error thrown during recovery from DB error. "
                            "Inconsistent state.  DB error: %s.  "
                            "New error: %s.", str(db_exception),
                            str(change_exception))

        num, desc = error_codes.get('rule_already_exists')
        raise webservice.DataModelException(
            num, desc, http_status_code=httplib.CONFLICT)
예제 #38
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        Args:
            item: The item to add to the model
            params: A dict-like object containing parameters
                    from the request query string and body.
            id_: The ID of the item, or None if an ID should be generated
            context: Key-values providing frame of reference of request

        Returns:
             Tuple of (ID, newly_created_item)

        Raises:
            KeyError: ID already exists.
            DataModelException: Addition cannot be performed.
        """
        # validation
        if id_ is None:
            id_ = str(uuidutils.generate_uuid())
        else:
            (num, desc) = error_codes.get('policy_id_must_not_be_provided')
            raise webservice.DataModelException(num, desc)
        if 'name' not in item:
            (num, desc) = error_codes.get('policy_name_must_be_provided')
            raise webservice.DataModelException(num, desc)
        name = item['name']
        try:
            self.engine.parse("%s() :- true()" % name)
        except PolicyException:
            (num, desc) = error_codes.get('policy_name_must_be_id')
            raise webservice.DataModelException(
                num, desc + ": " + str(name))

        # create policy in policy engine
        try:
            policy_obj = self.engine.create_policy(
                name, abbr=item.get('abbreviation'), kind=item.get('kind'))
            policy_obj.set_id(id_)
        except PolicyException as e:
            (num, desc) = error_codes.get('failed_to_create_policy')
            raise webservice.DataModelException(
                num, desc + ": " + str(e))

        # save policy to database
        desc = item.get('description', '')
        if desc is None:
            desc = ''
        obj = {'id': id_,
               'name': name,
               'owner_id': 'user',
               'description': desc,
               'abbreviation': policy_obj.abbr,
               'kind': self.engine.policy_type(name)}
        # TODO(thinrichs): add rollback of policy engine if this fails
        db_policy_rules.add_policy(obj['id'],
                                   obj['name'],
                                   obj['abbreviation'],
                                   obj['description'],
                                   obj['owner_id'],
                                   obj['kind'])
        return (id_, obj)
예제 #39
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        :param: item: The item to add to the model
        :param: params: A dict-like object containing parameters
                    from the request query string and body.
        :param: id\_: The ID of the item, or None if an ID should be generated
        :param: context: Key-values providing frame of reference of request

        :returns: Tuple of (ID, newly_created_item)

        :raises KeyError: ID already exists.
        :raises DataModelException: Addition cannot be performed.
        :raises BadRequest: library_policy parameter and request body both
            present
        """

        if id_ is not None:
            (num, desc) = error_codes.get('policy_id_must_not_be_provided')
            raise webservice.DataModelException(num, desc)

        # case 1: parameter gives library policy UUID
        if 'library_policy' in params:
            if item:
                raise exception.BadRequest(
                    'Policy creation request with `library_policy` parameter '
                    'must not have non-empty body.')
            try:
                # Note(thread-safety): blocking call
                library_policy_object = self.invoke_rpc(
                    base.LIBRARY_SERVICE_ID,
                    'get_policy', {'id_': params['library_policy']})

                policy_metadata = self.invoke_rpc(
                    base.ENGINE_SERVICE_ID,
                    'persistent_create_policy_with_rules',
                    {'policy_rules_obj': library_policy_object},
                    timeout=self.dse_long_timeout)
            except exception.CongressException as e:
                raise webservice.DataModelException.create(e)

            return (policy_metadata['id'], policy_metadata)

        # case 2: item contains rules
        if 'rules' in item:
            self._check_create_policy_item(item)
            try:
                library_service.validate_policy_item(item)
                # Note(thread-safety): blocking call
                policy_metadata = self.invoke_rpc(
                    base.ENGINE_SERVICE_ID,
                    'persistent_create_policy_with_rules',
                    {'policy_rules_obj': item}, timeout=self.dse_long_timeout)
            except exception.CongressException as e:
                raise webservice.DataModelException.create(e)

            return (policy_metadata['id'], policy_metadata)

        # case 3: item does not contain rules
        self._check_create_policy_item(item)
        name = item['name']
        try:
            # Note(thread-safety): blocking call
            policy_metadata = self.invoke_rpc(
                base.ENGINE_SERVICE_ID, 'persistent_create_policy',
                {'name': name,
                 'abbr': item.get('abbreviation'),
                 'kind': item.get('kind'),
                 'desc': item.get('description')})
        except exception.CongressException as e:
            raise webservice.DataModelException.create(e)

        return (policy_metadata['id'], policy_metadata)
예제 #40
0
    def add_item(self, item, params, id_=None, context=None):
        """Add item to model.

        :param: item: The item to add to the model
        :param: params: A dict-like object containing parameters
                    from the request query string and body.
        :param: id\_: The ID of the item, or None if an ID should be generated
        :param: context: Key-values providing frame of reference of request

        :returns: Tuple of (ID, newly_created_item)

        :raises KeyError: ID already exists.
        :raises DataModelException: Addition cannot be performed.
        :raises BadRequest: library_policy parameter and request body both
            present
        """

        if id_ is not None:
            (num, desc) = error_codes.get('policy_id_must_not_be_provided')
            raise webservice.DataModelException(num, desc)

        # case 1: parameter gives library policy UUID
        if 'library_policy' in params:
            if item:
                raise exception.BadRequest(
                    'Policy creation request with `library_policy` parameter '
                    'must not have non-empty body.')
            try:
                # Note(thread-safety): blocking call
                library_policy_object = self.invoke_rpc(
                    base.LIBRARY_SERVICE_ID, 'get_policy',
                    {'id_': params['library_policy']})

                policy_metadata = self.invoke_rpc(
                    base.ENGINE_SERVICE_ID,
                    'persistent_create_policy_with_rules',
                    {'policy_rules_obj': library_policy_object},
                    timeout=self.dse_long_timeout)
            except exception.CongressException as e:
                raise webservice.DataModelException.create(e)

            return (policy_metadata['id'], policy_metadata)

        # case 2: item contains rules
        if 'rules' in item:
            self._check_create_policy_item(item)
            try:
                library_service.validate_policy_item(item)
                # Note(thread-safety): blocking call
                policy_metadata = self.invoke_rpc(
                    base.ENGINE_SERVICE_ID,
                    'persistent_create_policy_with_rules',
                    {'policy_rules_obj': item},
                    timeout=self.dse_long_timeout)
            except exception.CongressException as e:
                raise webservice.DataModelException.create(e)

            return (policy_metadata['id'], policy_metadata)

        # case 3: item does not contain rules
        self._check_create_policy_item(item)
        name = item['name']
        try:
            # Note(thread-safety): blocking call
            policy_metadata = self.invoke_rpc(
                base.ENGINE_SERVICE_ID, 'persistent_create_policy', {
                    'name': name,
                    'abbr': item.get('abbreviation'),
                    'kind': item.get('kind'),
                    'desc': item.get('description')
                })
        except exception.CongressException as e:
            raise webservice.DataModelException.create(e)

        return (policy_metadata['id'], policy_metadata)