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 proxy (request,format): """the view associated with /manifold/proxy/ with the query passed using POST""" # expecting a POST if request.method != 'POST': print "manifoldproxy.api: unexpected method %s -- exiting"%request.method return # we only support json for now # if needed in the future we should probably cater for # format_in : how is the query encoded in POST # format_out: how to serve the results if format != 'json': print "manifoldproxy.proxy: unexpected format %s -- exiting"%format return try: # translate incoming POST request into a query object if debug: print 'manifoldproxy.proxy: request.POST',request.POST manifold_query = Query() #manifold_query = ManifoldQuery() manifold_query.fill_from_POST(request.POST) # retrieve session for request # We allow some requests to use the ADMIN user account if (manifold_query.get_from() == 'local:user' and manifold_query.get_action() == 'create') \ or (manifold_query.get_from() == 'local:platform' and manifold_query.get_action() == 'get'): admin_user, admin_password = ConfigEngine().manifold_admin_user_password() manifold_api_session_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password} else: print request.session['manifold'] manifold_api_session_auth = request.session['manifold']['auth'] if debug_empty and manifold_query.action.lower()=='get': json_answer=json.dumps({'code':0,'value':[]}) print "By-passing : debug_empty & 'get' request : returning a fake empty list" return HttpResponse (json_answer, mimetype="application/json") # actually forward manifold_api= ManifoldAPI(auth=manifold_api_session_auth) if debug: print '===> manifoldproxy.proxy: sending to backend', manifold_query # for the benefit of the python code, manifoldAPI raises an exception if something is wrong # however in this case we want to propagate the complete manifold result to the js world result = manifold_api.forward(manifold_query.to_dict()) # XXX TEMP HACK if 'description' in result and result['description'] \ and isinstance(result['description'], (tuple, list, set, frozenset)): result [ 'description' ] = [ ResultValue.to_html (x) for x in result['description'] ] json_answer=json.dumps(result) return HttpResponse (json_answer, mimetype="application/json") except Exception,e: print "** PROXY ERROR **",e import traceback traceback.print_exc()
def v_exc_handler(*args, **kwargs): try: v(*args, **kwargs) except Exception, e: ret = dict( ResultValue(origin=(ResultValue.CORE, cls.__class__.__name__), type=ResultValue.ERROR, code=ResultValue.ERROR, description=str(e), traceback=traceback.format_exc())) return ret
def func(*args, **kwds): # shorthand def repr(): return self._repr_query(methodName, args[0]) try: if debug: start, msg = mytime() print("====>", msg, "ManifoldAPI.%s" % repr(), "url", self.url) # No password in the logs logAuth = copy.copy(self.auth) for obfuscate in ['Authring', 'session']: if obfuscate in logAuth: logAuth[obfuscate] = "XXX" if debug_deep: print("=> auth", logAuth) if debug_deep: print("=> args", args, "kwds", kwds) annotations = {'authentication': self.auth} args += (annotations, ) result = getattr(self.server, methodName)(*args, **kwds) print("%s%r" % (methodName, args)) if debug: print('<= result=', ) self._print_result(result) end, msg = mytime(start) print("<====", msg, "backend call %s returned" % (repr())) return ResultValue(**result) except Exception as error: print("** MANIFOLD API ERROR **") if debug: print("===== xmlrpc catch-all exception:", error) import traceback traceback.print_exc(limit=3) if "Connection refused" in error: raise ManifoldException( ManifoldResult(code=ManifoldCode.SERVER_UNREACHABLE, output="%s answered %s" % (self.url, error))) # otherwise print("<==== ERROR On ManifoldAPI.%s" % repr()) raise ManifoldException( ManifoldResult(code=ManifoldCode.SERVER_UNREACHABLE, output="%s" % error))
def func(*args, **kwds): import time start = time.time() # the message to display auth_message = "<AuthMethod not set in {}>".format(self.auth) if 'AuthMethod' not in self.auth \ else "[session]" if self.auth['AuthMethod'] == 'session' \ else "user:{}".format(self.auth['Username']) if self.auth['AuthMethod'] == 'password' \ else "anonymous" if self.auth['AuthMethod'] == 'anonymous' \ else "[???]" + "{}".format(self.auth) end_message = "MANIFOLD <- {}( {}( {} ) ) with auth={} to {}"\ .format(methodName, args[0]['action'] or '', args[0]['object'] or '', auth_message, self.url) try: args += ({'authentication': self.auth}, ) result = getattr(self.server, methodName)(*args, **kwds) logger.debug("{} executed in {} seconds -> {}"\ .format(end_message, time.time() - start, truncate_result(result))) return ResultValue(**result) except Exception as error: logger.error( "===== xmlrpc catch-all exception: {}".format(error)) import traceback logger.error(traceback.format_exc(limit=3)) if "Connection refused" in error: raise ManifoldException( ManifoldResult(code=ManifoldCode.SERVER_UNREACHABLE, output="{} answered {}".format( self.url, error))) # otherwise logger.error("{} FAILED - executed in {} seconds"\ .format(end_message, time.time() - start)) logger.error("MANIFOLD {}".format(error)) raise ManifoldException( ManifoldResult(code=ManifoldCode.SERVER_UNREACHABLE, output="{}".format(error)))
def send(self, query, records, annotations, is_deferred): rv = ResultValue.get_success(records) return self.send_result_value(query, rv, annotations, is_deferred)
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())
def _proxy(url, request, format): """the view associated with /manifold/proxy/ with the query passed using POST""" # expecting a POST if request.method != 'POST': logger.error("MANIFOLDPROXY unexpected method {} -- exiting".format(request.method)) return HttpResponse ({"ret":0}, content_type="application/json") # we only support json for now # if needed in the future we should probably cater for # format_in : how is the query encoded in POST # format_out: how to serve the results if format != 'json': logger.error("MANIFOLDPROXY unexpected format {} -- exiting".format(format)) return HttpResponse ({"ret":0}, content_type="application/json") try: # translate incoming POST request into a query object #logger.debug("MANIFOLDPROXY request.POST {}".format(request.POST)) manifold_query = Query() #manifold_query = ManifoldQuery() manifold_query.fill_from_POST(request.POST) # retrieve session for request # We allow some requests to use the ADMIN user account if (manifold_query.get_from() == 'local:user' and manifold_query.get_action() == 'create') \ or (manifold_query.get_from() == 'local:platform' and manifold_query.get_action() == 'get'): admin_user, admin_password = config.manifold_admin_user_password() manifold_api_session_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password} else: if 'manifold' in request.session: manifold_api_session_auth = request.session['manifold']['auth'] else: #manifold_api_session_auth = SessionCache().get_auth(request) #if not manifold_api_session_auth: return HttpResponse (json.dumps({'code':0,'value':[]}), content_type="application/json") if debug_empty and manifold_query.action.lower()=='get': return HttpResponse (json.dumps({'code':0,'value':[]}), content_type="application/json") # actually forward manifold_api= ManifoldAPI(url, auth=manifold_api_session_auth) # for the benefit of the python code, manifoldAPI raises an exception if something is wrong # however in this case we want to propagate the complete manifold result to the js world result = manifold_api.forward(manifold_query.to_dict()) # XXX TEMP HACK if 'description' in result and result['description'] \ and isinstance(result['description'], (tuple, list, set, frozenset)): result [ 'description' ] = [ ResultValue.to_html (x) for x in result['description'] ] # # register activity # # resource reservation if (manifold_query.action.lower() == 'update') : logger.debug(result['value'][0]) if 'resource' in result['value'][0] : for resource in result['value'][0]['resource'] : activity.slice.resource(request, { 'slice' : result['value'][0]['slice_hrn'], 'resource' : resource['hostname'], 'resource_type' : resource['type'], 'facility' : resource['facility_name'], 'testbed' : resource['testbed_name'] } ) json_answer=json.dumps(result) return HttpResponse (json_answer, content_type="application/json") except Exception as e: logger.error("MANIFOLDPROXY {}".format(e)) import traceback logger.error(traceback.format_exc()) return HttpResponse ({"ret":0}, content_type="application/json")
def proxy(request, format): """the view associated with /manifold/proxy/ with the query passed using POST""" # expecting a POST if request.method != 'POST': print("manifoldproxy.api: unexpected method %s -- exiting" % request.method) return # we only support json for now # if needed in the future we should probably cater for # format_in : how is the query encoded in POST # format_out: how to serve the results if format != 'json': print("manifoldproxy.proxy: unexpected format %s -- exiting" % format) return try: # translate incoming POST request into a query object if debug: print('manifoldproxy.proxy: request.POST', request.POST) manifold_query = Query() #manifold_query = ManifoldQuery() manifold_query.fill_from_POST(request.POST) # retrieve session for request # We allow some requests to use the ADMIN user account if (manifold_query.get_from() == 'local:user' and manifold_query.get_action() == 'create') \ or (manifold_query.get_from() == 'local:platform' and manifold_query.get_action() == 'get'): admin_user, admin_password = ConfigEngine( ).manifold_admin_user_password() manifold_api_session_auth = { 'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password } else: print(request.session['manifold']) manifold_api_session_auth = request.session['manifold']['auth'] if debug_empty and manifold_query.action.lower() == 'get': json_answer = json.dumps({'code': 0, 'value': []}) print( "By-passing : debug_empty & 'get' request : returning a fake empty list" ) return HttpResponse(json_answer, mimetype="application/json") # actually forward manifold_api = ManifoldAPI(auth=manifold_api_session_auth) if debug: print('===> manifoldproxy.proxy: sending to backend', manifold_query) # for the benefit of the python code, manifoldAPI raises an exception if something is wrong # however in this case we want to propagate the complete manifold result to the js world result = manifold_api.forward(manifold_query.to_dict()) # XXX TEMP HACK if 'description' in result and result['description'] \ and isinstance(result['description'], (tuple, list, set, frozenset)): result['description'] = [ ResultValue.to_html(x) for x in result['description'] ] json_answer = json.dumps(result) return HttpResponse(json_answer, mimetype="application/json") except Exception as e: print("** PROXY ERROR **", e) import traceback traceback.print_exc()