def xmlrpc_forward(self, request, query, annotations=None): """ """ Log.info("Incoming XMLRPC request, query = %r, annotations = %r" % (self.display_query(query), annotations)) if Options().disable_auth: Log.info("Authentication disabled by configuration") else: if not annotations or not 'authentication' in annotations: msg = "You need to specify an authentication token in annotations" return dict(ResultValue.get_error(ResultValue.FORBIDDEN, msg)) # We expect to find an authentication token in the annotations if annotations: auth = annotations.get('authentication', None) else: auth = {} auth['request'] = request # Check login password try: user = Auth(auth, self.interface).check() except Exception, e: Log.warning( "XMLRPCAPI::xmlrpc_forward: Authentication failed...: %s" % str(e)) msg = "Authentication failed: %s" % e return dict(ResultValue.get_error(ResultValue.FORBIDDEN, msg))
def process_qp_results(self, namespace, query, records, annotations, query_plan, policy=True): # namespace and table are back together in process_qp_results # in order to send the results in the right Cache entry if namespace is not None: query.object = namespace + ':' + query.object # Handling internal queries is_local = (namespace == self.LOCAL_NAMESPACE) is_metadata = (namespace and query.object == "object") if policy and not is_local and not is_metadata: # XXX What to do in case of errors, and records is [] for record in records: # We process records one by one... (decision, data) = self.policy.filter(query, record, annotations, is_query=False) if decision == Policy.ACCEPT: pass elif decision == Policy.REWRITE: print "WEIRD CASE: maybe it should be changed since here we are not replacing a query but a record" _query, _annotations = data if _query: query = _query if _annotations: annotations = _annotations elif decision in [Policy.DENIED, Policy.ERROR]: print "WEIRD CASE also for records" if decision == Policy.DENIED: data = ResultValue.get_error(ResultValue.FORBIDDEN) return self.send_result_value(query, data, annotations, is_deferred) else: raise Exception, "Unknown RECORD decision from policy engine: %s" % Policy.map_decision[ decision] description = query_plan.get_result_value_array() return ResultValue.get_result_value(records, description)
def forward(self, query, annotations=None, is_deferred=False, execute=True): """ Forwards an incoming Query to the appropriate Gateways managed by this Router. Args: query: The user's Query. is_deferred: (bool) execute: Set to true if the QueryPlan must be executed. user: The user issuing the Query. Returns: A ResultValue in case of success. None in case of failure. """ Log.info("Router::forward: %s" % query) # TMP CACHE DEBUG #import pdb #pdb.set_trace() # INVALIDATE CACHE - should be per object? if query.get_action() != 'get': self.delete_cache(annotations) user = annotations[ 'user'] if annotations and 'user' in annotations else None if annotations is None: annotations = {} ret = super(Router, self).forward(query, annotations, is_deferred, execute) if ret: # Note: we do not run hooks at the moment for local queries return ret # Previously, cache etc had nothing to do. We now enforce policy, and # eventually this will give us a new query plan query_plan = None # Enforcing policy # XXX This issues after a check (in interface) that we are not # considering local or object tables... and we need to do the proper # check when records are received, otherwise the query is absent from # the cache. This is sources of errors, and should be fixed. # # Possible results and related actions: # - ACCEPT : the query passes and will trigger a new query plan # - CACHED : ill named, the cache is taking care of everything, no new query plan to do # This will handle multiple scenarios such as buffered (a mixed of # cached and real time records), and multicast (real time records). # - DENIED # - ERROR (decision, data) = self.policy.filter(query, None, annotations) # TMP CACHE DEBUG #pdb.set_trace() if decision == Policy.ACCEPT: pass elif decision == Policy.REWRITE: _query, _annotations = data if _query: query = _query if _annotations: annotations = _annotations elif decision == Policy.CACHE_HIT: query_plan = data #return self.send(query, data, annotations, is_deferred) elif decision in [Policy.DENIED, Policy.ERROR]: if decision == Policy.DENIED: data = ResultValue.get_error(ResultValue.FORBIDDEN) return self.send_result_value(query, data, annotations, is_deferred) else: raise Exception, "Unknown QUERY decision from policy engine: %s" % Policy.map_decision[ decision] # TMP CACHE DEBUG #pdb.set_trace() # We suppose we have no namespace from here if not execute: if not query_plan: query_plan = QueryPlan() query_plan.build(query, self.g_3nf, allowed_platforms, self.allowed_capabilities, user) Log.info(query_plan.dump()) # Note: no hook either for queries that are not executed return ResultValue.get_success(None) # The query plan will be the same whatever the action: it represents # the easier way to reach the destination = routing # We do not need the full query for the query plan, in fact just the # destination, which is a subpart of the query = (fact, filters, fields) # action = what to do on this QP # ts = how it behaves # XXX disabled #if query.get_action() == "update": # # At the moment we can only update if the primary key is present # keys = self.metadata_get_keys(query.get_from()) # if not keys: # raise Exception, "Missing metadata for table %s" % query.get_from() # key_fields = keys.one().get_minimal_names() # # # XXX THIS SHOULD BE ABLE TO ACCEPT TUPLES # #if not query.filters.has_eq(key): # # raise Exception, "The key field(s) '%r' must be present in update request" % key # Execute query plan # the deferred object is sent to execute function of the query_plan # This might be a deferred, we cannot put any hook here... try: # Namespace and table are splited if prefix is used in the query # namespace is passed as a parameter # Then namespace and table are back together in process_qp_results # in order to send the results in the right Cache entry if ":" in query.get_from(): namespace, table_name = query.get_from().rsplit(":", 2) query.object = table_name else: namespace = None if query_plan: return self.execute_query_plan(namespace, query, annotations, query_plan, is_deferred, policy=False) else: return self.execute_query(namespace, query, annotations, is_deferred) except Exception, e: return ResultValue.get_error(e, traceback.format_exc())