aboutsummaryrefslogtreecommitdiff
path: root/steuermann/rexecd.py
diff options
context:
space:
mode:
authorsienkiew <sienkiew@d34015c8-bcbb-4646-8ac8-8ba5febf221d>2012-02-24 17:58:55 -0500
committersienkiew <sienkiew@d34015c8-bcbb-4646-8ac8-8ba5febf221d>2012-02-24 17:58:55 -0500
commit6787ea30126ef097db80430f151ae0848dc25a9e (patch)
tree3379c847619ec9d518592f3db4193414a0a8d05f /steuermann/rexecd.py
parente80782b878fcc80f32a7aec6993c2cbdd5201885 (diff)
downloadsteuermann-6787ea30126ef097db80430f151ae0848dc25a9e.tar.gz
steuermann rexec
git-svn-id: https://svn.stsci.edu/svn/ssb/etal/steuermann/trunk@556 d34015c8-bcbb-4646-8ac8-8ba5febf221d
Diffstat (limited to 'steuermann/rexecd.py')
-rw-r--r--steuermann/rexecd.py242
1 files changed, 242 insertions, 0 deletions
diff --git a/steuermann/rexecd.py b/steuermann/rexecd.py
new file mode 100644
index 0000000..712d48f
--- /dev/null
+++ b/steuermann/rexecd.py
@@ -0,0 +1,242 @@
+#
+# steuermann remote execution daemon - use this when you can't use
+# something better (like ssh) to get your commands running in the
+# other machine.
+#
+# Copyright 2012 Association of Universities for Research in Astronomy (AURA)
+#
+
+import os
+import time
+import CGIHTTPServer
+import BaseHTTPServer
+import SocketServer
+import platform
+import subprocess
+import urllib
+import urlparse
+
+os.chdir('/')
+print os.getcwd()
+
+#####
+#
+
+valid_client_ip = (
+ '130.167.180.22', # arzach
+ '130.167.180.4', # ssb
+ '130.167.237.185', # banana
+ '130.167.237.55', # vxp-dukat
+ )
+
+#####
+#
+# This uses the python stock http server. Here is a request handler
+# that services GET requests by executing the command passed in.
+# All other requests are invalid.
+
+password = "pass"
+
+class my_handler( CGIHTTPServer.CGIHTTPRequestHandler ) :
+
+ def __init__(self, request, client_address, server) :
+ # init the superclass
+ CGIHTTPServer.CGIHTTPRequestHandler.__init__(self, request, client_address, server)
+
+ def reject_client(self) :
+ print self.client_address
+ if not ( self.client_address[0] in valid_client_ip ) :
+ self.bad_client('a')
+ return 1
+
+ if self.path.startswith('/' + password + '/' ) :
+ self.path = self.path[len(password)+2:]
+ else :
+ self.bad_client('p')
+ return 1
+
+ return 0
+
+ def do_GET(self) :
+ # GET /password/command...
+ # run the command
+
+ if self.reject_client() :
+ return
+
+ path = self.path
+
+ print "GET",path
+ self.send_response(200)
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ self.wfile.write("Hello world: %s\n"%path)
+ self.wfile.flush()
+
+ def bad_client(self, why) :
+ self.send_response(500)
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ self.wfile.write("bad client: %s\n"%why)
+ self.wfile.flush()
+ return
+
+ def do_INVALID(self) :
+ self.send_response(500)
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ self.wfile.write("error\n")
+ self.wfile.flush()
+ return
+
+ def do_POST(self) :
+ # POST password=pass&name=filename&data=filedata
+ # upload data to a file
+
+ if self.reject_client() :
+ return
+
+ print self.path
+
+
+ length = int(self.headers['Content-Length'])
+ data = self.rfile.read(length)
+ d = urlparse.parse_qs(data)
+
+ for x in sorted([ x for x in d]) :
+ print x,d[x]
+
+ if d['password'][0] != password :
+ self.bad_client('p')
+ return
+
+ dirname = d['dirname'][0]
+ print "CD",dirname
+ os.chdir(dirname)
+
+ if self.path == 'upload' :
+
+ filename = d['filename'][0]
+
+ mode = 'wb'
+ if 'mode' in d :
+ t = d['mode'][0]
+ if t == 't' or t == 'text' :
+ mode = 'w'
+ elif t == 'b' or t == 'binary' :
+ mode = 'wb'
+ else :
+ return self.bad_client('mode')
+
+ f = open(filename,'wb')
+ f.write(d['data'][0])
+ f.close()
+
+ self.send_response(200)
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ self.wfile.write("uploaded %s\n"%filename)
+ self.wfile.flush()
+
+ elif self.path == 'run' :
+ cmd = d['cmd'][0]
+ self.send_response(200)
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ self.wfile.write("Hello world: %s\n"%cmd)
+ run_child(cmd, self.wfile)
+ self.wfile.write("done\n")
+ self.wfile.flush()
+ else :
+ return self.bad_client('c')
+
+
+ def do_HEAD(self) :
+ self.do_invalid()
+
+
+class MultiThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
+ pass
+
+####
+
+windows = platform.system() == 'Windows'
+
+def run_child(path, wfile) :
+ env = os.environ
+ cmd = urllib.unquote_plus(path)
+ print "COMMAND",cmd
+
+ # bug: implement timeouts
+ if windows :
+ status = subprocess_windows( cmd, wfile, env )
+ else :
+ status = subprocess_unix( cmd, wfile, env )
+
+ # subprocess gives you weird status values
+ if status > 0 :
+ t_status="exit %d"%(status >> 8)
+ if status != 0 :
+ return_status = 1
+ else :
+ return_status = 1
+ t_status="signal %d" % ( - status )
+ # subprocess does not tell you if there was a core
+ # dump, but there is nothing we can do about it.
+
+ print "COMMAND EXIT:",status,t_status
+
+
+def subprocess_windows(cmd, wfile, env ) :
+ # You might think that subprocess.Popen() would be portable,
+ # but you would be wrong.
+ #
+ # On Windows, sockets are NOT file descriptors. Since we are in a web server, wfile here is a socket.
+
+ # print wfile.fileno()
+ # import msvcrt
+ # print msvcrt.get_osfhandle(wfile.fileno())
+ p = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, env = env, creationflags = subprocess.CREATE_NEW_PROCESS_GROUP )
+ while 1 :
+ n = p.stdout.read(256)
+ if n == '' :
+ break
+ wfile.write(n)
+ return p.wait()
+
+def subprocess_unix( cmd, wfile, env ) :
+ p = subprocess.Popen( cmd, stdout=wfile, stderr=wfile, shell=True, env = env, preexec_fn=os.setpgrp )
+ return p.wait()
+
+#####
+
+
+def run( args = [ ] ) :
+ # you could parse args here if you wanted to. I don't care to spend
+ # the time. This is just here for people who can't (or don't want to)
+ # install a full featured web server just to try things out.
+ if len(args) > 0 :
+ ip = args[0]
+ else :
+ ip = platform.node()
+
+ port = 7070
+
+ print "http://%s:%s/"%(str(ip),str(port))
+
+ httpd = MultiThreadedHTTPServer( (ip, port) , my_handler)
+
+ sa = httpd.socket.getsockname()
+ print "Serving HTTP on", sa[0], "port", sa[1], "..."
+ while 1 :
+ httpd.handle_request()
+
+if __name__ == '__main__' :
+ run()
+
+
+##
+# in case we need to kill child processes:
+# http://code.activestate.com/recipes/347462-terminating-a-subprocess-on-windows/
+
+