예제 #1
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: 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)
예제 #2
0
    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}
예제 #3
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 {}
예제 #4
0
 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)
예제 #5
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 {}
예제 #6
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)
예제 #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.
        """
        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)
예제 #8
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)
예제 #9
0
    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
예제 #10
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)
예제 #11
0
    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)
예제 #13
0
    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
예제 #14
0
    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)
예제 #15
0
 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)
예제 #16
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}
예제 #17
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))
예제 #18
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))
예제 #19
0
    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}
예제 #20
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 {}
예제 #21
0
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
예제 #22
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]}
예제 #23
0
    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
예제 #25
0
    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)
예제 #26
0
    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
예제 #27
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)
예제 #28
0
    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}