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

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