Example #1
0
    def _executeFunction(self, request, func, auth, *args):
        """Executes the specified function and returns the result"""
        from ccsd_session import getSessionE
 
        if ccsd_xmlrpc.log_threads:
            exstart = time.time()
            ct = threading.currentThread()
            name = ct.getName().split()[0]
            log_debug("Executing '%s' in '%s'" % \
                    (func["function"].func_name, name))

        # Check for class method calls
        if func["classmethod"] == 1:
            # Init a class and build a class method call
            (inst, args) = _initClassMethod(auth["session_id"], func, *args)
            fstr = "inst.%s" % (func["function"].func_name)
        else:
            # Build a normal call
            fstr = "func[\"function\"]"
            if auth is not None:
                # Add session_id as first param
                args = (auth["session_id"], ) + args
        
        # Execute the function
        try:
            fin = time.time()
            rv = eval("%s(*args)" % fstr)
            fout = time.time()
            if self.log_times and func:
                log_custom(self.log_times, "Executed %s in %0.3f seconds" % \
                        (func["name"], (fout-fin)))
            # Shutdown the session if necessary
            try:
                if auth and "basicSession" in auth.keys():
                    sess = getSessionE(auth["sessionID"])
                    sess.close()
            except:
                log_error("Failed to close basic session!", sys.exc_info())
        except ccsd_error:
            # Expected error of some type
            (type, value, tb) = sys.exc_info()
            log_debug("Incoming XMLRPC call '%s' threw an exception" % \
                    func["name"], (type, value, tb))
            rv = xmlrpclib.Fault(CCSD_CALLFAILED, value)
        except:
            # Unexpected error
            (type, value, tb) = sys.exc_info()
            log_error("Incoming XMLRPC call failed (%s)" % func["name"], \
                    (type, value, tb))
            rv = xmlrpclib.Fault(CCSD_CALLFAILED, value)
        if ccsd_xmlrpc.log_threads:
            exend = time.time()
            log_custom(self.log_threads, "Executed %s in %0.3f seconds" % \
                    (func["name"], (exend-exstart)))
            
            log_debug("Finished executing '%s' in '%s'" % \
                    (func["function"].func_name, name))
        reactor.callFromThread(self._cbRender, enc(rv), request)
        return True
Example #2
0
    def returnSuccess(self):
        """Returns indicating success"""
        
        from ccsd_session import getSessionE
        session = getSessionE(self._session_id)  
        
        # Commit implicit changeset
        if session.changesetInitiator == self._csInit and self._csInit != "":
            session.commit()

        return self.SUCCESS     
Example #3
0
 def _forceChangeset(self, message, initiator="ccs_class"):
     """Starts an implicit changeset if there is no active changeset
     
     If you use this function it is *imperative* that you use the
     returnError and returnSuccess functions to leave the function you
     call it from to ensure any implicit changeset is finished properly.
     """
     from ccsd_session import getSessionE
     session = getSessionE(self._session_id)
     
     if session.changeset==0:
         session.begin(message, initiator=initiator)
         self._csInit = initiator
Example #4
0
    def returnError(self, errMsg):
        """Returns an error code and stores the error message
        
        Rollsback any implicit transactions started by this class.
        """

        # Record error message
        self._errMsg = errMsg
        
        from ccsd_session import getSessionE
        session = getSessionE(self._session_id)         
        
        # Rollback an implicit changeset
        if session.changesetInitiator == self._csInit and self._csInit != "":
            session.rollback()
            
        return self.FAILURE
Example #5
0
    def render(self, request):
        """Overrides the default render method 

        * Implements auto login based on the supplied client certificate
        * Dispatches requests to the appropriate function that was earlier
          registered via exportViaXMLRPC
        """
        rstart = time.time()
        func = None
        # We import this here to avoid a circular reference
        from ccsd_session import isSessionValid, getSessionE, \
                ccsd_session_error
            
        # Break the request out into the function and its arguments
        request.content.seek(0, 0)
        args, functionPath = xmlrpclib.loads(request.content.read())
        # Profile if requested
        if self.profile:
            ensureDirExists(self.prof_dir)
            prof = hotshot.Profile("%s/%s.prof.%s" % \
                    (self.prof_dir, functionPath, int(time.time())))
            prof.start()
        
        try:
            # Find a reference to the function that has been called
            try:
                func = self._findFunction(functionPath)
            except xmlrpc.Fault, f:
                self._cbRender(f, request)
                if self.profile:
                    prof.stop()
                    prof.close()
                if self.log_times and func:        
                    log_custom(self.log_times, "Rendered %s in %0.3f seconds" % \
                        (func["name"], (time.time()-rstart)))
                return server.NOT_DONE_YET

            # Throw an error now if we're out of threads
            if len(reactor.threadpool.threads) >= self.max_threads:
                if len(reactor.threadpool.waiters) < 2:
                    if not func["asynchronous"]:
                        raise ccs_server_error("No free threads")
                elif len(reactor.threadpool.waiters) < 1:
                    raise ccs_server_error("No free threads")

            # Handle special case function without session call
            if func["mode"] == SESSION_NONE:
                request.setHeader("content-type", "text/xml")
                reactor.callInThread(self._executeFunction, request, func, \
                        None, *args)
                if self.profile:
                    prof.stop()
                    prof.close()
                if self.log_times and func:        
                    log_custom(self.log_times, "Rendered %s in %0.3f seconds" % \
                        (func["name"], (time.time()-rstart)))
                return server.NOT_DONE_YET
            
            # Check authentication
            needsauth=True
            try:
                if args[0]!={} and isSessionValid(args[0]):
                    needsauth=False
            except ccsd_session_error:
                (type, value, tb) = sys.exc_info()
                log_debug("Invalid session supplied - %s!" % value)

            # If there is no valid session specified try and logon using the
            # certificate
            if needsauth:
                auth = self._doCertificateLogon(request)
                if auth is None:
                    raise ccs_server_error("Insufficient authentication " \
                            "information supplied!")
                log_info("Accepted SSL connection from %s" % auth["login_id"])
            else:
                # Use the user-supplied parameters
                auth = args[0]
            # Strip the dictionary from the real arguments
            args = args[1:]
            
            # If the function requested client information, prepend it 
            if func["includeClientAddress"]:
                args = (request.getClientIP(), ) + args

            # Check the user has the appropriate permissions for the function
            session = getSessionE(auth["session_id"])
            perm = session.hasPerms(func["mode"], func["group"])
            if perm == SESSION_NONE:
                raise ccs_server_error("Insufficient privileges for %s" % \
                        functionPath)
            
            # All OK so far
            request.setHeader("content-type", "text/xml")
            reactor.callInThread(self._executeFunction, request, func, auth, \
                    *args)