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)
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
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
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
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)
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))
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
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()