changeset 934:9dcfb8f36524

call scripts remotely, ScriptRequest infrastructure (unfinished)
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sun, 09 Jul 2006 10:55:43 +0200
parents a03c030a62c5
children 1da203931dc7
files MoinMoin/script/__init__.py MoinMoin/script/xmlrpc/remote.py MoinMoin/xmlrpc/RemoteScript.py
diffstat 3 files changed, 139 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/script/__init__.py	Sat Jul 08 22:52:38 2006 +0200
+++ b/MoinMoin/script/__init__.py	Sun Jul 09 10:55:43 2006 +0200
@@ -18,9 +18,72 @@
 flag_quiet = 0
 script_module = '__main__'
 
-#############################################################################
-### Logging
-#############################################################################
+
+# ScriptRequest -----------------------------------------------------------
+
+class ScriptRequest(object):
+    """this is for scripts (MoinMoin/script/*) running from the commandline (CLI)
+       or from the xmlrpc server (triggered by a remote xmlrpc client).
+
+       Every script needs to do IO using this ScriptRequest class object -
+       IT IS DIFFERENT from the usual "request" you have in moin (easily to be seen
+       when you look at an xmlrpc script invocation: request.write will write to the
+       xmlrpc "channel", but scriptrequest.write needs to write to some buffer we
+       transmit later as an xmlrpc function return value.
+    """
+    def __init__(self, in, out, err):
+        self.in = in
+        self.out = out
+        self.err = err
+
+    def read(self, n=None):
+        if n is None:
+            data = self.in.read()
+        else:
+            data = self.in.read(n)
+        return data
+
+    def write(self, data):
+        self.out.write(data)
+
+    def write_err(self, data):
+        self.err.write(data)
+
+
+class ScriptRequestCLI(ScriptRequest):
+    """ When a script runs directly on the shell, we just use the CLI request
+        object (see MoinMoin.request.CLI) to do I/O (which will use stdin/out/err).
+    """
+    def __init__(self, request):
+        self.request = request
+
+    def read(self, n=None):
+        return self.request.read(n)
+
+    def write(self, data):
+        return self.request.write(n)
+
+    def write_err(self, data):
+        return self.request.write(n) # XXX use correct request method - log, error, whatever.
+
+class ScriptRequestStrings(ScriptRequest):
+    """ When a script gets run by our xmlrpc server, we have the input as a
+        string and we also need to catch the output / error output as strings.
+    """
+    def __init__(self, instr):
+        self.in = StringIO(instr)
+        self.out = StringIO()
+        self.err = StringIO()
+
+    def fetch_output(self):
+        outstr = self.out.get_value()
+        errstr = self.err.get_value()
+        self.out.close()
+        self.err.close()
+        return outstr, errstr
+
+
+# Logging -----------------------------------------------------------------
 
 def fatal(msgtext, **kw):
     """ Print error msg to stderr and exit. """
@@ -38,9 +101,7 @@
         sys.stderr.write(msgtext + "\n")
 
 
-#############################################################################
-### Commandline Support
-#############################################################################
+# Commandline Support --------------------------------------------------------
 
 class Script:
     def __init__(self, script, usage, argv=None, def_values=None):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/script/xmlrpc/remote.py	Sun Jul 09 10:55:43 2006 +0200
@@ -0,0 +1,42 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - remote command execution, client part
+
+    This can be used as client to execute moin scripts remotely.
+
+    @copyright: 2006 by MoinMoin:ThomasWaldmann
+    @license: GNU GPL, see COPYING for details.
+"""
+
+import sys
+import xmlrpclib
+
+from MoinMoin.script import MoinScript, fatal
+
+class PluginScript(MoinScript):
+    """ Remote Script Execution Client """
+
+    def __init__(self, argv, def_values):
+        MoinScript.__init__(self, argv, def_values)
+        self.argv = argv
+
+    def mainloop(self):
+        try:
+            import remotescriptconf as conf
+        except ImportError:
+            fatal("Could not find the file remotescriptconf.py. Maybe you want to use the config param?")
+
+        secret = conf.remotescript_secret
+        url = conf.remotescript_url
+        print url, secret, self.argv
+
+        s = xmlrpclib.ServerProxy(url)
+
+        # TODO handle stdin 
+        # xmlrpclib.Binary(sys.stdin.read())
+        result = s.RemoteScript(secret, self.argv)
+        # TODO handle stdout, stderr
+
+        if result != "OK":
+            print >>sys.stderr, result
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/xmlrpc/RemoteScript.py	Sun Jul 09 10:55:43 2006 +0200
@@ -0,0 +1,30 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - Remote Script Execution Server part
+
+    @copyright: 2006 by MoinMoin:ThomasWaldmann
+    @license: GNU GPL, see COPYING for details.
+"""
+
+from MoinMoin.script import MoinScript
+
+def execute(xmlrpcobj, their_secret, argv):
+    request = xmlrpcobj.request
+    their_secret = xmlrpcobj._instr(their_secret)
+
+    our_secret = request.cfg.remote_script_secret
+    if not our_secret:
+        return u"No password set"
+
+    if our_secret != their_secret:
+        return u"Invalid password"
+
+    try:
+        request.log("RemoteScript argv: %r" % argv)
+        MoinScript(argv).run(showtime=0)
+    except Exception, err:
+        e = str(err)
+        request.log(e)
+        return xmlrpcobj._outstr(e)
+    return xmlrpcobj._outstr(u"OK")
+