def add_item(self, item, params, id_=None, context=None): """Add item to model. :param: item: The item to add to the model :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. """ obj = None try: # Note(thread-safety): blocking call obj = self.invoke_rpc(base.DS_MANAGER_SERVICE_ID, 'add_datasource', {'items': item}, timeout=self.dse_long_timeout) # Let PE synchronizer take care of creating the policy. except (exception.BadConfig, exception.DatasourceNameInUse, exception.DriverNotFound, exception.DatasourceCreationError) as e: LOG.debug(_("Datasource creation failed.")) raise webservice.DataModelException( e.code, webservice.original_msg(e), http_status_code=e.code) except exception.RpcTargetNotFound as e: LOG.debug("Datasource creation failed.") LOG.warning(webservice.original_msg(e)) raise webservice.DataModelException( e.code, webservice.original_msg(e), http_status_code=503) return (obj['id'], obj)
def get_item(self, id_, params, context=None): """Retrieve item with id id_ from model. Args: id_: The ID of the item to retrieve params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: The matching item or None if item with id_ does not exist. """ datasource = context.get('ds_id') table = context.get('table_id') try: schema = self.datasource_mgr.get_datasource_schema( datasource) except (datasource_manager.DatasourceNotFound, datasource_manager.DriverNotFound) as e: raise webservice.DataModelException(e.code, e.message, http_status_code=e.code) # request to see the schema for one table if table: if table not in schema: raise webservice.DataModelException( 404, ("Table '{}' for datasource '{}' has no " "schema ".format(id_, datasource)), http_status_code=404) return self.datasource_mgr.create_table_dict(table, schema) tables = [self.datasource_mgr.create_table_dict(table_, schema) for table_ in schema] return {'tables': tables}
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 {}
def delete_item(self, id_, params, context=None): ds_id = context.get('ds_id') try: # Note(thread-safety): blocking call datasource = self.bus.get_datasource(ds_id) # FIXME(thread-safety): # by the time greenthread resumes, the # returned datasource name could refer to a totally different # datasource, causing the rest of this code to unintentionally # delete a different datasource # Fix: check UUID of datasource before operating. # Abort if mismatch self.invoke_rpc(base.DS_MANAGER_SERVICE_ID, 'delete_datasource', {'datasource': datasource}, timeout=self.dse_long_timeout) # Let PE synchronizer takes care of deleting policy except (exception.DatasourceNotFound, exception.DanglingReference) as e: LOG.debug("Datasource deletion failed.") raise webservice.DataModelException(e.code, str(e)) except exception.RpcTargetNotFound as e: LOG.debug("Datasource deletion failed.") LOG.warning(webservice.original_msg(e)) raise webservice.DataModelException( e.code, webservice.original_msg(e), http_status_code=503)
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 {}
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)
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)
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)
def get_item(self, id_, params, context=None): """Retrieve item with id id_ from model. Args: id_: The ID of the item to retrieve params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: The matching item or None if item with id_ does not exist. """ # Note(thread-safety): blocking call caller, source_id = api_utils.get_id_from_context(context) # FIXME(threod-safety): in DSE2, the returned caller can be a # datasource name. But the datasource name may now refer to a new, # unrelated datasource. Causing the rest of this code to operate on # an unintended datasource. # Fix: check UUID of datasource before operating. Abort if mismatch try: rpc_args = {'params': context, 'source_id': source_id} # Note(thread-safety): blocking call status = self.invoke_rpc(caller, 'get_status', rpc_args) except exception.CongressException as e: raise webservice.DataModelException( exception.NotFound.code, str(e), http_status_code=exception.NotFound.code) return status
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 get_item(self, id_, params, context=None): """Retrieve item with id id_ from model. Args: id_: The ID of the item to retrieve params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: The matching item or None if item with id_ does not exist. """ # FIXME(arosen): we need better API validation in congress if 'ds_id' not in context: raise Exception( "The only element that currently has a status is datasource " "but ds-id does not exist in context: " + str(context)) service = self.cage.getservice(id_=context['ds_id'], type_='datasource_driver') if service: return service['object'].get_status() raise webservice.DataModelException(NotFound.code, 'Could not find service %s' % id_, http_status_code=NotFound.code)
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)
def get_item(self, id_, params, context=None): """Retrieve item with id id_ from model. Args: id_: The ID of the item to retrieve params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: The matching item or None if item with id_ does not exist. """ datasource = context.get('driver_id') try: schema = self.datasource_mgr.get_driver_schema( datasource) driver = self.datasource_mgr.get_driver_info(datasource) except datasource_manager.DriverNotFound as e: raise webservice.DataModelException(e.code, e.message, http_status_code=e.code) tables = [self.datasource_mgr.create_table_dict(table_, schema) for table_ in schema] driver['tables'] = tables return driver
def test_data_model_exception(self): exc = webservice.DataModelException(1, "error1", [1, {'a': 'b'}], 409) model = webservice.SimpleDataModel("test") for method in [m for m in dir(model) if "_item" in m]: setattr(model, method, mock.Mock(side_effect=exc)) resource_mgr = application.ResourceManager() app = application.ApiApplication(resource_mgr) collection_handler = webservice.CollectionHandler(r'/c', model) resource_mgr.register_handler(collection_handler) for method in ['GET', 'POST']: request = webob.Request.blank('/c', body='{}'.encode('utf-8'), method=method) response = app(request) self._check_data_model_exc_response(method, exc, response) element_handler = webservice.ElementHandler(r'/e', model) resource_mgr.register_handler(element_handler) for method in ['GET', 'PUT', 'PATCH', 'DELETE']: request = webob.Request.blank('/e', body='{}'.encode('utf-8'), method=method) response = app(request) self._check_data_model_exc_response(method, exc, response)
def get_item(self, id_, params, context=None): """Get datasource corresponding to id\_ in model.""" try: datasource = self.bus.get_datasource(id_) return datasource except exception.DatasourceNotFound as e: LOG.debug("Datasource '%s' not found", id_) raise webservice.DataModelException(e.code, str(e), http_status_code=e.code)
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}
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))
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))
def get_item(self, id_, params, context=None): """Retrieve item with id id_ from model. Args: id_: The ID of the item to retrieve params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: The matching item or None if item with id_ does not exist. """ # Note(thread-safety): blocking call caller, source_id = api_utils.get_id_from_context(context) # FIXME(threod-safety): in DSE2, the returned caller can be a # datasource name. But the datasource name may now refer to a new, # unrelated datasource. Causing the rest of this code to operate on # an unintended datasource. # Fix: check UUID of datasource before operating. Abort if mismatch table = context.get('table_id') args = {'source_id': source_id} try: # Note(thread-safety): blocking call schema = self.invoke_rpc(caller, 'get_datasource_schema', args) except exception.CongressException as e: raise webservice.DataModelException(e.code, str(e), http_status_code=e.code) # request to see the schema for one table if table: if table not in schema: raise webservice.DataModelException( 404, ("Table '{}' for datasource '{}' has no " "schema ".format(id_, source_id)), http_status_code=404) return api_utils.create_table_dict(table, schema) tables = [ api_utils.create_table_dict(table_, schema) for table_ in schema ] return {'tables': tables}
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 {}
def get_id_from_context(context): if 'ds_id' in context: # Note(thread-safety): blocking call ds_name = db_datasources.get_datasource_name(context.get('ds_id')) return ds_name, context.get('ds_id') elif 'policy_id' in context: return base.ENGINE_SERVICE_ID, context.get('policy_id') else: msg = "Internal error: context %s should have included " % str(context) "either ds_id or policy_id" try: # Py3: ensure LOG.exception is inside except raise webservice.DataModelException('404', msg) except webservice.DataModelException: LOG.exception(msg) raise
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]}
def get_items(self, params, context=None): """Get items in model. Args: params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: A dict containing at least a 'results' key whose value is a list of items in the model. Additional keys set in the dict will also be rendered for the user. """ LOG.info('get_items has context %s', context) # data-source if 'ds_id' in context: # FIXME(arosen): this file needs refactoring. datasource = context.get('ds_id') try: datasource = self.datasource_mgr.get_datasource( datasource) except datasource_manager.DatasourceNotFound as e: raise webservice.DataModelException(e.code, e.message) service_name = context['ds_id'] service_obj = self.engine.d6cage.service_object(datasource['name']) if service_obj is None: LOG.info("data-source %s not found", service_name) return [] LOG.info("data-source %s found", service_name) results = [{'id': x} for x in service_obj.state.keys()] # policy elif 'policy_id' in context: policy_name = context['policy_id'] if policy_name not in self.engine.theory: LOG.info("data-source %s not found", service_name) return None results = [{'id': x} for x in self.engine.theory[policy_name].tablenames()] # should not happen else: LOG.error("Blackhole for table context %s", context) results = [] return {'results': results}
def get_item(self, id_, params, context=None): """Retrieve item with id id_ from model. Args: id_: The ID of the item to retrieve params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: The matching item or None if item with id_ does not exist. """ driver = context.get('ds_id') try: datasource_info = self.datasource_mgr.get_driver_info(driver) except datasource_manager.DriverNotFound as e: raise webservice.DataModelException(e.code, e.message) return datasource_info
def get_items(self, params, context=None): """Retrieve items from this model. :param: params: A dict-like object containing parameters from the request query string and body. :param: context: Key-values providing frame of reference of request :returns: A dict containing at least a 'actions' key whose value is a list of items in this model. """ # Note: blocking call caller, source_id = api_utils.get_id_from_context(context) try: rpc_args = {'source_id': source_id} # Note(dse2): blocking call return self.invoke_rpc(caller, 'get_actions', rpc_args) except exception.CongressException as e: raise webservice.DataModelException( exception.NotFound.code, str(e), http_status_code=exception.NotFound.code)
def get_item(self, id_, params, context=None): """Retrieve item with id id\_ from model. :param: id\_: The ID of the item to retrieve :param: params: A dict-like object containing parameters from the request query string and body. :param: context: Key-values providing frame of reference of request :returns: The matching item or None if item with id\_ does not exist. """ datasource = context.get('driver_id') try: driver = self.bus.get_driver_info(datasource) schema = self.bus.get_driver_schema(datasource) except exception.DriverNotFound as e: raise webservice.DataModelException(e.code, str(e), http_status_code=e.code) tables = [ api_utils.create_table_dict(table_, schema) for table_ in schema ] driver['tables'] = tables return driver
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)
def get_items(self, params, context=None): """Get items in model. Args: params: A dict-like object containing parameters from the request query string and body. context: Key-values providing frame of reference of request Returns: A dict containing at least a 'results' key whose value is a list of items in the model. Additional keys set in the dict will also be rendered for the user. """ LOG.info("get_items(context=%s)", context) gen_trace = False trace = "Not available" if 'trace' in params and params['trace'].lower() == 'true': gen_trace = True # table defined by data-source if 'ds_id' in context: service_name = context['ds_id'] try: datasource = self.datasource_mgr.get_datasource(service_name) except datasource_manager.DatasourceNotFound as e: raise webservice.DataModelException(e.code, e.message, http_status_code=e.code) service_name = datasource['name'] service_obj = self.engine.d6cage.service_object(service_name) if service_obj is None: LOG.info("Unknown data-source name %s", service_name) return {"results": []} tablename = context['table_id'] if tablename not in service_obj.state: LOG.info("Unknown tablename %s for datasource %s", service_name, tablename) raise webservice.DataModelException(404, "Not Found", httplib.NOT_FOUND) results = [] for tup in service_obj.state[tablename]: d = {} d['data'] = tup results.append(d) # table defined by policy elif 'policy_id' in context: policy_name = context['policy_id'] if policy_name not in self.engine.theory: LOG.info("Unknown policy name %s", policy_name) return {"results": []} tablename = context['table_id'] if tablename not in self.engine.theory[policy_name].tablenames(): LOG.info("Unknown tablename %s for policy %s", tablename, policy_name) raise webservice.DataModelException(404, "Not Found", httplib.NOT_FOUND) arity = self.engine.theory[policy_name].get_arity(tablename) if arity is None: LOG.info("Unknown arity for table %s for policy %s", tablename, policy_name) return {"results": []} args = ["x" + str(i) for i in xrange(0, arity)] query = self.engine.parse1(tablename + "(" + ",".join(args) + ")") # LOG.debug("query: %s", query) result = self.engine.select(query, target=policy_name, trace=gen_trace) if gen_trace: literals = result[0] trace = result[1] else: literals = result # should NOT need to convert to set -- see bug 1344466 literals = frozenset(literals) # LOG.info("results: %s", '\n'.join(str(x) for x in literals)) results = [] for lit in literals: d = {} d['data'] = [arg.name for arg in lit.arguments] results.append(d) # unknown else: LOG.info("Unknown source for row data %s", context) results = {"results": []} if gen_trace: return {"results": results, "trace": trace} return {"results": results}