source: TI12-security/branches/PostAlpha/trunk/python/bin/GatekeeperServer.py @ 2007

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/branches/PostAlpha/trunk/python/bin/GatekeeperServer.py@2007
Revision 2007, 7.8 KB checked in by pjkersha, 13 years ago (diff)

python/conf/sessionMgrProperties.xml: fixed missing '>'
python/bin/*Server.py: modified do_GET method so that WSDL is picked up from a path
given by the environment variable NDG_SECURITY_WSDL_DIR rather than being hard coded.

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2
3"""NDG Gatekeeper Web Service server interface
4
5NERC Data Grid Project
6
7P J Kershaw 18/05/06
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# Gatekeeper Web Services stub code generated by wsdl2py and
28# wsdl2dispatch
29from NDG.gatekeeper_services import *
30from NDG.gatekeeper_services_server import gatekeeper
31
32# Gatekeeper
33from NDG.Gatekeeper import *
34
35
36#_____________________________________________________________________________
37class GatekeeperSOAPRequestHandler(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 = os.path.expandvars("$NDG_SECURITY_WSDL_DIR/gatekeeper.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/gatekeeper points to the
56          default port for the Gatekeeper."""
57          self.path = "/gatekeeper.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 = ("127.0.0.1", 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 Log Server in the same process as this script"""
79       
80    print "Gatekeeper Server listening..."
81    try:
82         AsServer(port=options.port, 
83                  services=(gatekeeper(gatekeeperSrv, debug=options.debug),), 
84                  RequestHandlerClass=GatekeeperSOAPRequestHandler)
85
86    except KeyboardInterrupt:
87        sys.exit(0)
88
89    except socket.error, e:
90        print >>sys.stderr, "Gatekeeper Server socket error: %s" % e[1]
91        sys.exit(1)
92       
93    except Exception, e:
94        print >>sys.stderr, "Gatekeeper Server: %s" % str(e)
95        sys.exit(1)       
96
97
98#_____________________________________________________________________________
99def fork(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
100    """Run Log Server 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    # Do second fork
135    try: 
136        pid = os.fork() 
137        if pid > 0:
138            # exit from second parent
139            sys.exit(pid) 
140    except OSError, e: 
141        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
142        sys.exit(1) 
143
144    # start the daemon main loop
145    try:
146         AsServer(port=options.port, 
147                  services=(gatekeeper(gatekeeperSrv, debug=options.debug),), 
148                  RequestHandlerClass=GatekeeperSOAPRequestHandler)
149
150    except socket.error, e:
151        print >>sys.stderr, "Gatekeeper Server socket error: %s" % e[1]
152        sys.exit(1)
153       
154    except Exception, e:
155        print >>sys.stderr, "Gatekeeper Server: %s" % str(e)
156        sys.exit(1)       
157
158
159#_____________________________________________________________________________
160if __name__ == '__main__':
161
162    parser = optparse.OptionParser()
163   
164    # Port may be set from an environment variable.  Note that this will be
165    # overridden if the port command line argument is set
166    gkPortNumEnvVarName = 'NDG_GK_PORT_NUM'
167    defaultPort = 5200
168   
169    initPort = gkPortNumEnvVarName in os.environ and \
170                        int(os.environ[gkPortNumEnvVarName]) or defaultPort
171   
172    parser.add_option("-p", 
173                      "--port", 
174                      dest="port",
175                      type="int",
176                      default=initPort,
177                      help=\
178"specify a port number - default is %d or set environment variable \"%s\"" % \
179                                          (defaultPort, gkPortNumEnvVarName))
180
181    propFileDir = 'NDG_DIR' in os.environ and \
182                            os.path.join(os.environ['NDG_DIR'], "conf") or "."
183
184    propFilename = 'gatekeeperProperties.xml'
185    parser.add_option("-f", 
186                      "--file",
187                      dest="propFilePath",
188                      help=\
189"""properties file path - default is $NDG_DIR/conf/%s or ./%s if NDG_DIR is
190not set""" % (propFilename, propFilename))
191
192    foregndFlags = ("-i", "--foreground")
193    parser.add_option(action="store_true",
194                      dest="foregndProc",
195                      default=False,
196                      help=\
197"run server as process in the foreground.  If not set, fork a child process",
198                      *foregndFlags)
199
200    parser.add_option("-d", 
201                      "--debug",
202                      dest="debug",
203                      action="store_true",
204                      default=False,
205                      help=\
206"set to stop in debugger on receipt of WS request.  %s flag must be set also"\
207                                            % '/'.join(foregndFlags))
208
209    (options, args) = parser.parse_args()
210
211
212    # Create server instance at start up
213    try:
214        gatekeeperSrv = Gatekeeper(propFilePath=options.propFilePath)
215
216    except Exception, e:
217        print >>sys.stderr, "Initialising Gatekeeper: %s" % str(e)
218        sys.exit(1)
219   
220
221    if options.foregndProc:
222        runInForegnd()
223    else:
224        if options.debug:
225            print >>sys.stderr, "%s must be set for debug option" % \
226                                                        '/'.join(foregndFlags)
227            parser.print_help()
228            sys.exit(1)
229       
230        # Set this flag to True to catch errors raised in the new process
231        # in a log.  Normally stderr is re-directed to /dev/null to avoid
232        # conflists with the parent process   
233        logForkErr = False
234        if logForkErr:
235            import tempfile
236            errLogH, errLogFilePath = tempfile.mkstemp(".err", 
237                                                       "GatekeeperServer-")
238        else:
239            errLogFilePath = '/dev/null'
240
241        # Run server in separate process
242        fork(stderr=errLogFilePath)   
243       
Note: See TracBrowser for help on using the repository browser.