Пример #1
0
    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))
Пример #2
0
    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)
Пример #3
0
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()
Пример #4
0
 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
Пример #5
0
        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))
Пример #6
0
        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)))
Пример #7
0
 def send(self, query, records, annotations, is_deferred):
     rv = ResultValue.get_success(records)
     return self.send_result_value(query, rv, annotations, is_deferred)
Пример #8
0
    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())
Пример #9
0
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")
Пример #10
0
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()