source: TI12-security/trunk/python/bin/SessionMgrServer.py @ 1636

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/bin/SessionMgrServer.py@1636
Revision 1636, 9.2 KB checked in by pjkersha, 14 years ago (diff)

Change to new package structure. All refs to NDG package changed to ndg.security

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/env python
2
3"""NDG Session Manager Web Services server interface
4
5NERC Data Grid Project
6
7P J Kershaw 16/08/05
8
9Copyright (C) 2006 CCLRC & NERC
10
11This software may be distributed under the terms of the Q Public License,
12version 1.0 or later.
13"""
14
15# Handle socket errors from WS
16import socket 
17
18# Command line processing
19import sys
20import os
21import optparse
22
23# Web service interface
24from ZSI import dispatch
25from ZSI.ServiceContainer import ServiceContainer, SOAPRequestHandler
26
27# Session Manager Web Services stub code generated by wsdl2py and
28# wsdl2dispatch
29from ndg.security.sessionMgr_services import *
30from ndg.security.sessionMgr_services_server import sessionMgr
31
32# Session Manager
33from ndg.security.Session import *
34
35
36#_____________________________________________________________________________
37class SessionMgrSOAPRequestHandler(SOAPRequestHandler):
38     """Add a do_GET method to return the WSDL on HTTP GET requests.
39     Please note that the path to the wsdl file is derived from what
40     the HTTP invocation delivers (which is put into the self.path
41     attribute), so you might want to change this addressing scheme.
42     """
43     def do_GET(self):
44         """Return the WSDL file."""
45         
46         wsdlfile = "/var/www/html/sessionMgr.wsdl"
47         
48         print "> > > > > using wsdlfile", wsdlfile
49         wsdl = open(wsdlfile).read()
50         self.send_xml(wsdl)
51 
52     def do_POST(self):
53          """Fudge to get _Dispatch to pick up the correct address
54          - seems to be necessary when putting proxy redirect for port in
55          the wsdl e.g. http://glue.badc.rl.ac.uk/sessionMgr points to the
56          default port for the Session Manager."""
57          self.path = "/sessionMgr.wsdl"
58          SOAPRequestHandler.do_POST(self)
59           
60           
61#_____________________________________________________________________________
62# Copied from ZSI.ServiceContainer, extended to instantiate with a custom
63# request handler
64def AsServer(port=80, services=(), RequestHandlerClass=SOAPRequestHandler):
65      """port --
66          services -- list of service instances
67       """
68      address = ("", port)
69      sc = ServiceContainer(address, RequestHandlerClass=RequestHandlerClass)
70      for service in services:
71           path = service.getPost()
72           sc.setNode(service, path)
73      sc.serve_forever()
74
75
76#_____________________________________________________________________________
77def runInForegnd():
78    """Run Session Manager in the same process as this script"""
79   
80    print "Session Manager Server listening..."
81    try:
82         AsServer(port=options.port, 
83                  services=(sessionMgr(sm, debug=options.debug),), 
84                  RequestHandlerClass=SessionMgrSOAPRequestHandler)
85
86    except KeyboardInterrupt:
87        sys.exit(0)
88
89    except socket.error, e:
90        print >>sys.stderr, "Session Manager Server socket error: %s" % e[1]
91        sys.exit(1)
92
93    except Exception, e:
94        print >>sys.stderr, "Session Manager Server: %s" % e
95        sys.exit(1)
96       
97
98#_____________________________________________________________________________
99def fork(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
100    """Run Session Manager in a separate child process
101   
102    Thanks to Jorgen Hermann and user contributors for fork code
103   
104    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
105   
106    """
107   
108    try: 
109        pid = os.fork() 
110        if pid > 0:
111            # exit first parent
112            sys.exit(0) 
113    except OSError, e: 
114        print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
115        sys.exit(1)
116
117    # Decouple from parent environment
118    os.chdir("/") # Allows for current dir path being renamed or deleted
119    os.setsid() 
120    os.umask(0) 
121   
122    # Redirect standard file descriptors
123    si = file(stdin, 'r')
124    so = file(stdout, 'a+')
125    se = file(stderr, 'a+', 0)
126   
127    sys.stdout.flush()
128    sys.stderr.flush()
129
130    os.dup2(si.fileno(), sys.stdin.fileno())
131    os.dup2(so.fileno(), sys.stdout.fileno())
132    os.dup2(se.fileno(), sys.stderr.fileno())
133   
134
135    # Do second fork
136    try: 
137        pid = os.fork() 
138        if pid > 0:
139            # exit from second parent
140            sys.exit(pid) 
141    except OSError, e: 
142        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
143        sys.exit(1) 
144
145    # start the daemon main loop
146    try:
147         AsServer(port=options.port, 
148                  services=(sessionMgr(sm),), 
149                  RequestHandlerClass=SessionMgrSOAPRequestHandler)
150
151    except socket.error, e:
152        print >>sys.stderr, "Session Manager Server socket error: %s" % e[1]
153        sys.exit(1)
154
155    except Exception, e:
156        print >>sys.stderr, "Session Manager Server: %s" % e
157        sys.exit(1)
158
159
160#_____________________________________________________________________________
161if __name__ == '__main__':
162
163    parser = optparse.OptionParser()
164
165    # Check in installation area otherwise assume local directory
166    propFileDir = 'NDG_DIR' in os.environ and \
167                            os.path.join(os.environ['NDG_DIR'], "conf") or "."
168
169    propFilename = 'sessionMgrProperties.xml'
170    parser.add_option("-f",
171                      "--file",
172                      dest="propFilePath",
173                      default=os.path.join(propFileDir, propFilename),
174                      help=\
175"""properties file path - default is $NDG_DIR/conf/%s or ./%s if NDG_DIR is
176not set""" % (propFilename, propFilename))
177   
178    parser.add_option("-w",
179                      "--noencrkey",
180                      action="store_true",
181                      dest="noWSDLencrKey",
182                      default=False,
183                      help=\
184"""skip the prompt for the encryption key and pick up the key from the
185'sessMgrEncrKey' tag in the properties file.""")
186   
187    parser.add_option("-n", 
188                      "--nopassphrase",
189                      action="store_true",
190                      dest="noPPhrase",
191                      default=False,
192                      help=\
193"""skip the prompt for the database pass-phrase.  In this case, the
194pass-phrase must be set in the 'dbURI' tag in the configuration file.""")
195
196
197    # Port may be set from an environment variable.  Note that this will be
198    # overridden if the port command line argument is set
199    smPortNumEnvVarName = 'NDG_SM_PORT_NUM'
200    defaultPort = 5700
201   
202    initPort = smPortNumEnvVarName in os.environ and \
203                        int(os.environ[smPortNumEnvVarName]) or defaultPort
204           
205    parser.add_option("-p",
206                      "--port",
207                      dest="port",
208                      default=initPort,
209                      type="int",
210                      help=\
211"specify a port number - default is %d or set environment variable \"%s\"" % \
212                                          (defaultPort, smPortNumEnvVarName))
213   
214    foregndFlags = ("-i", "--foreground")
215    parser.add_option(action="store_true",
216                      dest="foregndProc",
217                      default=False,
218                      help=\
219"run server as process in the foreground.  If not set, fork a child process",
220                      *foregndFlags)
221   
222    parser.add_option("-d",
223                      "--debug",
224                      action="store_true",
225                      dest="debug",
226                      default=False,
227                      help=\
228"set to stop in debugger on receipt of WS request.  %s flag must be set also"\
229                                            % '/'.join(foregndFlags))
230                                           
231    (options, args) = parser.parse_args()
232
233
234    if options.noPPhrase is False:
235        import getpass
236        try:
237            credReposPPhrase = getpass.getpass(\
238                                prompt="Credential Repository pass-phrase: ")
239        except KeyboardInterrupt:
240            sys.exit(1)
241    else:
242        credReposPPhrase = None
243
244
245    if options.noWSDLencrKey is False:
246        import getpass
247        try:
248            sessMgrEncrKey = getpass.getpass(prompt="WSDL Encryption Key: ")
249        except KeyboardInterrupt:
250            sys.exit(1)
251    else:
252        sessMgrEncrKey = None
253
254
255    # Create server instance at start up
256    try:
257        sm = SessionMgr(options.propFilePath,
258                        credReposPPhrase=credReposPPhrase,
259                        sessMgrEncrKey=sessMgrEncrKey)
260
261    except Exception, e:
262        print >>sys.stderr, "Initialising Session Manager: %s" % e
263        sys.exit(1)
264
265
266    if options.foregndProc:
267        runInForegnd()
268    else:
269        if options.debug:
270            print >>sys.stderr, "%s must be set with debug option" % \
271                                                    '/'.join(foregndFlags)
272            parser.print_help()
273            sys.exit(1)
274           
275       
276        # Set this flag to True to catch errors raised in the new process
277        # in a log.  Normally stderr is re-directed to /dev/null to avoid
278        # conflists with the parent process   
279        logForkErr = False
280        if logForkErr:
281            import tempfile
282            errLogH, errLogFilePath = \
283                                tempfile.mkstemp(".err", "SessionMgrServer-")
284        else:
285            errLogFilePath = '/dev/null'
286
287        # Run server in separate process
288        fork(stderr=errLogFilePath)   
289
Note: See TracBrowser for help on using the repository browser.