Example #1
0
 def compile_atom(literal, pos=-1):
     """Compiles an atom in Z3"""
     name = literal.table.table
     svc = literal.table.service
     if svc == 'builtin':
         translators = [
             self.type_registry.get_translator(str(arg_type['type']))
             for arg_type in type_env[pos]
         ]
         fullname = 'builtin:' + name
     else:
         lit_theory = theory if svc is None else self.theories[svc]
         translators = [
             self.type_registry.get_translator(str(arg_type.type))
             for arg_type in lit_theory.schema.types(name)
         ]
         fullname = lit_theory.name + ":" + name
     try:
         z3func = (z3builtins.BUILTINS[name].z3
                   if svc == 'builtin' else self.relations[fullname])
         z3args = (compile_expr(arg, tr) for (
             arg, tr) in six.moves.zip(literal.arguments, translators))
         z3lit = z3func(*z3args)
         return (Z3OPT.Not(z3lit) if literal.negated else z3lit)
     except KeyError:
         raise exception.PolicyException(
             "Z3: Relation %s not registered" % fullname)
Example #2
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the events EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", utility.iterstr(events))
        errors = []
        for event in events:
            if not compile.is_datalog(event.formula):
                errors.append(
                    exception.PolicyException("Non-formula found: {}".format(
                        str(event.formula))))
            else:
                if event.formula.is_atom():
                    errors.extend(
                        compile.fact_errors(event.formula, self.theories,
                                            self.name))
                else:
                    errors.extend(
                        compile.rule_head_has_no_theory(
                            event.formula,
                            permit_head=lambda lit: lit.is_update()))
                    # Should put this back in place, but there are some
                    # exceptions that we don't handle right now.
                    # Would like to mark some tables as only being defined
                    #   for certain bound/free arguments and take that into
                    #   account when doing error checking.
                    # errors.extend(compile.rule_negation_safety(event.formula))
        return errors
Example #3
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the insert/deletes of policy statements dictated by
        EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", utility.iterstr(events))
        errors = []
        for event in events:
            if not compile.is_datalog(event.formula):
                errors.append(
                    exception.PolicyException("Non-formula found: {}".format(
                        str(event.formula))))
            else:
                if event.formula.is_atom():
                    errors.extend(
                        compile.fact_errors(event.formula, self.theories,
                                            self.name))
                else:
                    errors.extend(
                        compile.rule_errors(event.formula, self.theories,
                                            self.name))
        # Would also check that rules are non-recursive, but that
        #   is currently being handled by Runtime.  The current implementation
        #   disallows recursion in all theories.
        return errors
Example #4
0
    def create_policy(self, policy_dict):
        policy_dict = copy.deepcopy(policy_dict)
        validate_policy_item(policy_dict)
        policy_name = policy_dict['name']

        # check name is valid
        if not compile.string_is_servicename(policy_name):
            raise exception.PolicyException(
                'name `%s` is not a valid policy name' % policy_name)

        # make defaults
        if 'kind' not in policy_dict:
            policy_dict['kind'] = 'nonrecursive'
        if 'abbreviation' not in policy_dict:
            policy_dict['abbreviation'] = policy_name[:5]
        if 'description' not in policy_dict:
            policy_dict['description'] = ''

        try:
            # Note(thread-safety): blocking call
            policy = db_library_policies.add_policy(policy_dict=policy_dict)
            return policy.to_dict()
        except db_exc.DBError:
            LOG.exception('Creating a new library policy failed due to '
                          'backend database error.')
            raise
Example #5
0
    def _update_lit_schema(self, lit, is_insert):
        if self.schema is None:
            raise exception.PolicyException(
                "Cannot update schema because theory %s doesn't have "
                "schema." % self.name)

        if self.schema.complete:
            # complete means the schema is pre-built and shouldn't be updated
            return None
        return self.schema.update(lit, is_insert)
Example #6
0
 def compile_expr(expr, translator):
     """Compiles an expression to Z3"""
     if isinstance(expr, ast.Variable):
         name = expr.name
         if name in variables:
             return variables[name]
         var = Z3OPT.Const(name, translator.type())
         variables[name] = var
         z3vars.append(var)
         return var
     elif isinstance(expr, ast.ObjectConstant):
         return translator.to_z3(expr.name)
     else:
         raise exception.PolicyException(
             "Expr {} not handled by Z3".format(expr))
Example #7
0
    def update_would_cause_errors(self, events):
        """Return a list of Policyxception.

        Return a list of PolicyException if we were
        to apply the events EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", utility.iterstr(events))
        errors = []
        for event in events:
            if not compile.is_atom(event.formula):
                errors.append(
                    exception.PolicyException(
                        "Non-atomic formula is not permitted: {}".format(
                            str(event.formula))))
            else:
                errors.extend(
                    compile.fact_errors(event.formula, self.theories,
                                        self.name))
        return errors
Example #8
0
    def replace_policy(self, id_, policy_dict):
        validate_policy_item(policy_dict)
        policy_name = policy_dict['name']

        # check name is valid
        if not compile.string_is_servicename(policy_name):
            raise exception.PolicyException(
                "Policy name %s is not a valid service name" % policy_name)

        # make defaults
        if 'kind' not in policy_dict:
            policy_dict['kind'] = 'nonrecursive'
        if 'abbreviation' not in policy_dict:
            policy_dict['abbreviation'] = policy_name[:5]
        if 'description' not in policy_dict:
            policy_dict['description'] = ''

        # Note(thread-safety): blocking call
        policy = db_library_policies.replace_policy(id_,
                                                    policy_dict=policy_dict)
        return policy.to_dict()