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
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
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
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
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)