Changeset 058f58e
- Timestamp:
- Nov 20, 2008 7:14:58 PM (16 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
- Children:
- cfabc40
- Parents:
- c922f23
- Location:
- fedd
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
fedd/fedd.py
rc922f23 r058f58e 212 212 def do_POST(self): 213 213 """Treat an HTTP POST request as an XMLRPC service call""" 214 # NB: XMLRPC faults are not HTTP errors, so the code is always 200, 215 # unless an HTTP error occurs, which we don't handle. 214 216 215 217 resp = None 216 218 data = None 217 219 method = None 218 code = 200219 220 cl = int(self.headers['content-length']) 220 221 data = self.rfile.read(cl) … … 225 226 data = xmlrpclib.dumps(xmlrpclib.Fault("Client", 226 227 "Malformed request"), methodresponse=True) 227 code = 500228 228 229 229 if method != None: … … 236 236 data = xmlrpclib.dumps(f, methodresponse=True) 237 237 resp = None 238 code = 500 239 240 self.send_xml(data, code) 238 239 self.send_xml(data) 241 240 242 241 def log_request(self, code=0, size=0): -
fedd/fedd_access.py
rc922f23 r058f58e 52 52 id_list_attrs = ("restricted",) 53 53 54 proxy_request, proxy_xmlrpc_request = make_service_callers('RequestAccess', 55 'getfeddPortType', RequestAccessRequestMessage, 56 'RequestAccessRequestBody') 54 proxy_RequestAccess= \ 55 service_caller('RequestAccess', 'getfeddPortType', 56 feddServiceLocator, RequestAccessRequestMessage, 57 'RequestAccessRequestBody') 57 58 58 59 def __init__(self, config=None): … … 153 154 154 155 self.soap_services = {\ 155 'RequestAccess': make_soap_handler(\156 'RequestAccess': soap_handler(\ 156 157 RequestAccessRequestMessage.typecode,\ 157 158 self.RequestAccess, RequestAccessResponseMessage,\ 158 159 "RequestAccessResponseBody"), \ 159 'ReleaseAccess': make_soap_handler(\160 'ReleaseAccess': soap_handler(\ 160 161 ReleaseAccessRequestMessage.typecode,\ 161 162 self.ReleaseAccess, ReleaseAccessResponseMessage,\ … … 163 164 } 164 165 self.xmlrpc_services = {\ 165 'RequestAccess': make_xmlrpc_handler(\166 'RequestAccess': xmlrpc_handler(\ 166 167 self.RequestAccess, "RequestAccessResponseBody"),\ 167 'ReleaseAccess': make_xmlrpc_handler(\168 'ReleaseAccess': xmlrpc_handler(\ 168 169 self.ReleaseAccess, "ReleaseAccessResponseBody")\ 169 170 } … … 698 699 return resp 699 700 else: 700 p_fault = None # Any SOAP failure (sent unless XMLRPC works) 701 try: 702 # Proxy the request using SOAP 703 self.log.debug("Sending proxy message to %s" % dt) 704 resp = self.proxy_request(dt, req, feddServiceLocator, 701 resp = self.proxy_RequestAccess.call_service(dt, req, 705 702 self.proxy_cert_file, self.proxy_cert_pwd, 706 703 self.proxy_trusted_certs) 707 if resp.has_key('RequestAccessResponseBody'): 708 return resp['RequestAccessResponseBody'] 709 elif resp.has_key('Fedd_FaultBody'): 710 raise service_error(resp['FeddFaultBody']['code'], 711 resp['FeddFaultBody']['desc']) 712 except service_error, e: 713 if e.code == service_error.proxy: p_fault = None 714 else: raise 715 except ZSI.FaultException, f: 716 p_fault = f.fault.detail[0] 717 718 719 # If we could not get a valid SOAP response to the request above, 720 # try the same address using XMLRPC and let any faults flow back 721 # out. 722 if p_fault == None: 723 resp = self.proxy_xmlrpc_request(dt, req, self.proxy_cert_file, 724 self.proxy_cert_pwd, self.proxy_trusted_certs) 725 if resp.has_key('RequestAccessResponseBody'): 726 return resp['RequestAccessResponseBody'] 704 if resp.has_key('RequestAccessResponseBody'): 705 return resp['RequestAccessResponseBody'] 727 706 else: 728 # Build the fault 729 body = p_fault.get_element_FeddFaultBody() 730 if body != None: 731 raise service_error(body.get_element_code(), 732 body.get_element_desc()); 733 else: 734 raise service_error(\ 735 service_error.proxy, 736 "Undefined fault from proxy??"); 707 return None 737 708 738 709 def ReleaseAccess(self, req, fid): -
fedd/fedd_allocate_project.py
rc922f23 r058f58e 74 74 # Internal services are SOAP only 75 75 self.soap_services = {\ 76 "AllocateProject": make_soap_handler(\76 "AllocateProject": soap_handler(\ 77 77 AllocateProjectRequestMessage.typecode,\ 78 78 self.dynamic_project, AllocateProjectResponseMessage,\ 79 79 "AllocateProjectResponseBody"), 80 "StaticProject": make_soap_handler(\80 "StaticProject": soap_handler(\ 81 81 StaticProjectRequestMessage.typecode,\ 82 82 self.static_project, StaticProjectResponseMessage,\ 83 83 "StaticProjectResponseBody"),\ 84 "ReleaseProject": make_soap_handler(\84 "ReleaseProject": soap_handler(\ 85 85 ReleaseProjectRequestMessage.typecode,\ 86 86 self.release_project, ReleaseProjectResponseMessage,\ … … 345 345 return { 'project': req['ReleaseProjectRequestBody']['project']} 346 346 347 def make_proxy(method, req_name, req_alloc, resp_name):348 """349 Construct the proxy calling function from the given parameters.350 """351 352 # Define the proxy, NB, the parameters to make_proxy are visible to the353 # definition of proxy.354 def proxy(self, req, fedid=None):355 """356 Send req on to a remote project instantiator.357 358 Req is just the message to be sent. This function re-wraps it.359 It also rethrows any faults.360 """361 362 # No retry loop here. Proxy servers must correctly authenticate363 # themselves without help364 try:365 ctx = fedd_ssl_context(self.cert_file, self.trusted_certs,366 password=self.cert_pwd)367 except SSL.SSLError:368 raise service_error(service_error.server_config,369 "Server certificates misconfigured")370 371 loc = feddInternalServiceLocator();372 port = loc.getfeddInternalPortType(self.url,373 transport=M2Crypto.httpslib.HTTPSConnection,374 transdict={ 'ssl_context' : ctx })375 376 if req.has_key(req_name):377 req = req[req_name]378 else:379 raise service_error(service_error.req, "Bad formated request");380 381 # Reconstruct the full request message382 msg = req_alloc()383 set_elem = getattr(msg, "set_element_%s" % req_name)384 set_elem(pack_soap(msg, req_name, req))385 try:386 mattr = getattr(port, method)387 resp = mattr(msg)388 except ZSI.ParseException, e:389 raise service_error(service_error.proxy,390 "Bad format message (XMLRPC??): %s" % str(e))391 except ZSI.FaultException, e:392 resp = e.fault.detail[0]393 394 r = unpack_soap(resp)395 396 if r.has_key(resp_name):397 return r[resp_name]398 else:399 raise service_error(service_error.proxy, "Bad proxy response")400 # NB: end of proxy function definition401 return proxy402 403 347 class fedd_allocate_project_remote: 404 348 """ 405 349 Allocate projects on a remote machine using the internal SOAP interface 406 350 """ 407 dynamic_project = make_proxy("AllocateProject", 408 "AllocateProjectRequestBody", AllocateProjectRequestMessage, 409 "AllocateProjectResponseBody") 410 static_project = make_proxy("StaticProject", 411 "StaticProjectRequestBody", StaticProjectRequestMessage, 412 "StaticProjectResponseBody") 413 release_project = make_proxy("ReleaseProject", 414 "ReleaseProjectRequestBody", ReleaseProjectRequestMessage, 415 "ReleaseProjectResponseBody") 416 351 class proxy(service_caller): 352 """ 353 This class is a proxy functor (callable) that has the same signature as 354 a function called by soap_handler or xmlrpc_handler, but that used the 355 service_caller class to call the function remotely. 356 """ 357 358 def __init__(self, url, cert_file, cert_pwd, trusted_certs, 359 method, req_name, req_alloc, resp_name): 360 service_caller.__init__(self, method, 'getfeddInternalPortType', 361 feddInternalServiceLocator, req_alloc, req_name) 362 self.url = url 363 self.cert_file = cert_file 364 self.cert_pwd = cert_pwd 365 self.trusted_certs = trusted_certs 366 self.resp_name = resp_name 367 # Calling the proxy object directly invokes the proxy_call method, 368 # not the service_call method. 369 self.__call__ = self.proxy_call 370 371 372 # Define the proxy, NB, the parameters to make_proxy are visible to the 373 # definition of proxy. 374 def proxy_call(self, req, fedid=None): 375 """ 376 Send req on to a remote project instantiator. 377 378 Req is just the message to be sent. This function re-wraps it. 379 It also rethrows any faults. 380 """ 381 382 if req.has_key(self.request_body_name): 383 req = req[self.request_body_name] 384 else: 385 raise service_error(service_error.req, "Bad formated request"); 386 387 r = self.call_service(self.url, req, self.cert_file, self.cert_pwd, 388 self.trusted_certs) 389 if r.has_key(self.resp_name): 390 return r[self.resp_name] 391 else: 392 raise service_error(service_error.protocol, 393 "Bad proxy response") 394 395 # back to defining the fedd_allocate_project_remote class 417 396 def __init__(self, config): 418 397 """ … … 457 436 self.log = logging.getLogger("fedd.allocate.remote") 458 437 set_log_level(config, "access", self.log) 438 # The specializations of the proxy functions 439 self.dynamic_project = self.proxy(self.url, self.cert_file, 440 self.cert_pwd, self.trusted_certs, "AllocateProject", 441 "AllocateProjectRequestBody", AllocateProjectRequestMessage, 442 "AllocateProjectResponseBody") 443 self.static_project = self.proxy(self.url, self.cert_file, 444 self.cert_pwd, self.trusted_certs, "StaticProject", 445 "StaticProjectRequestBody", StaticProjectRequestMessage, 446 "StaticProjectResponseBody") 447 self.release_project = self.proxy(self.url, self.cert_file, 448 self.cert_pwd, self.trusted_certs, "ReleaseProject", 449 "ReleaseProjectRequestBody", ReleaseProjectRequestMessage, 450 "ReleaseProjectResponseBody") 451 -
fedd/fedd_client.py
rc922f23 r058f58e 21 21 22 22 from fedd_util import fedid, fedd_ssl_context, pack_soap, unpack_soap, \ 23 pack_id, unpack_id, encapsulate_binaries, decapsulate_binaries 23 pack_id, unpack_id, encapsulate_binaries, decapsulate_binaries, \ 24 service_caller 25 from service_error import * 24 26 25 27 from optparse import OptionParser, OptionValueError … … 190 192 def __init__(self, pre): 191 193 """ 192 Specialize the class for the pr cmethod194 Specialize the class for the pre method 193 195 """ 194 196 self.RequestMessage = globals()["%sRequestMessage" % pre] … … 197 199 self.ResponseBody="%sResponseBody" % pre 198 200 self.method = pre 201 202 method_call = getattr(feddServiceLocator().getfeddPortType(), 203 self.method, None) 204 if method_call: 205 # The pre method is a fedd external service 206 self.caller = service_caller(self.method, 'getfeddPortType', 207 feddServiceLocator, self.RequestMessage, self.RequestBody) 208 else: 209 # The pre method is a fedd internal service 210 self.caller = service_caller(self.method, 211 'getfeddInternalPortType', feddInternalServiceLocator, 212 self.RequestMessage, self.RequestBody) 213 199 214 self.RPCException = fedd_rpc.RPCException 200 215 … … 265 280 266 281 if transport == "soap": 267 loc = feddServiceLocator();268 port = loc.getfeddPortType(url,269 transport=M2Crypto.httpslib.HTTPSConnection,270 transdict={ 'ssl_context' : context },271 tracefile=tracefile)272 method_call = getattr(port, self.method, None)273 274 if not method_call:275 loc = feddInternalServiceLocator();276 port = loc.getfeddInternalPortType(url,277 transport=M2Crypto.httpslib.HTTPSConnection,278 transdict={ 'ssl_context' : context },279 tracefile=tracefile)280 method_call = getattr(port, self.method, None)281 if not method_call:282 raise RuntimeError("Can't find method: %s" % self.method)283 284 req = self.RequestMessage()285 286 set_req = getattr(req, "set_element_%s" % self.RequestBody, None)287 set_req(pack_soap(req, self.RequestBody, req_dict))288 289 282 if serialize_only: 290 283 sw = SoapWriter() … … 292 285 print str(sw) 293 286 sys.exit(0) 294 295 try: 296 method_call = getattr(port, self.method, None) 297 resp = method_call(req) 298 except ZSI.ParseException, e: 299 raise RuntimeError("Malformed response (XMLPRC?): %s" % e) 300 except ZSI.FaultException, e: 301 resp = e.fault.detail[0] 302 303 if resp: 304 resp_call = getattr(resp, "get_element_%s" %self.ResponseBody, 305 None) 306 if resp_call: 307 resp_body = resp_call() 308 if ( resp_body != None): 309 try: 310 return unpack_soap(resp_body) 311 except RuntimeError, e: 312 raise RuntimeError("Bad response. %s" % e.message) 313 elif 'get_element_FeddFaultBody' in dir(resp): 314 resp_body = resp.get_element_FeddFaultBody() 315 if resp_body != None: 316 try: 317 fb = unpack_soap(resp_body) 318 except RuntimeError, e: 319 raise RuntimeError("Bad response. %s" % e.message) 320 raise self.RPCException(fb) 321 else: 322 raise RuntimeError("No body in response!?") 323 else: 324 raise RuntimeError("No response?!?") 287 else: 288 try: 289 resp = self.caller.call_soap_service(url, req_dict, 290 context=context, tracefile=tracefile) 291 except service_error, e: 292 raise self.RPCException( {'code': e.code, 'desc': e.desc }) 325 293 elif transport == "xmlrpc": 326 294 if serialize_only: … … 328 296 print ser 329 297 sys.exit(0) 330 331 xtransport = SSL_Transport(context) 332 port = ServerProxy(url, transport=xtransport) 333 334 try: 335 method_call = getattr(port, self.method, None) 336 resp = method_call( 337 encapsulate_binaries({ self.RequestBody: req_dict},\ 338 ('fedid',))) 339 except Error, e: 340 resp = { 'FeddFaultBody': \ 341 { 'errstr' : getattr(e, "faultCode", "No fault code"), 342 'desc' : getattr(e, "faultString", "No fault string") }\ 343 } 344 if resp: 345 if resp.has_key(self.ResponseBody): 346 return decapsulate_binaries(resp[self.ResponseBody], 347 ('fedid',)) 348 elif resp.has_key('FeddFaultBody'): 349 raise self.RPCException(resp['FeddFaultBody']) 350 else: 351 raise RuntimeError("No body in response!?") 352 else: 353 raise RuntimeError("No response?!?") 298 else: 299 try: 300 resp = self.caller.call_xmlrpc_service(url, req_dict, 301 context=context, tracefile=tracefile) 302 except service_error, e: 303 raise self.RPCException( {'code': e.code, 'desc': e.desc }) 304 354 305 else: 355 306 raise RuntimeError("Unknown RPC transport: %s" % transport) 307 308 if resp.has_key(self.ResponseBody): 309 return resp[self.ResponseBody] 310 else: 311 raise RuntimeError("No body in response??") 356 312 357 313 # Querying experiment data follows the same control flow regardless of the … … 606 562 for id in eid: 607 563 for k in id.keys(): 608 if k == 'fedid': print "%s: %s" % (k,fedid(bits=id[k])) 609 else: print "%s: %s" % (k, id[k]) 564 print "%s: %s" % (k, id[k]) 610 565 611 566 class split(fedd_rpc): -
fedd/fedd_experiment_control.py
rc922f23 r058f58e 145 145 self.pdata.terminate() 146 146 147 call_RequestAccess = service_caller('RequestAccess', 148 'getfeddPortType', feddServiceLocator, 149 RequestAccessRequestMessage, 'RequestAccessRequestBody') 150 151 call_ReleaseAccess = service_caller('ReleaseAccess', 152 'getfeddPortType', feddServiceLocator, 153 ReleaseAccessRequestMessage, 'ReleaseAccessRequestBody') 154 155 call_Ns2Split = service_caller('Ns2Split', 156 'getfeddInternalPortType', feddInternalServiceLocator, 157 Ns2SplitRequestMessage, 'Ns2SplitRequestBody') 158 147 159 def __init__(self, config=None): 148 160 """ … … 242 254 # Dispatch tables 243 255 self.soap_services = {\ 244 'Create': make_soap_handler(\256 'Create': soap_handler(\ 245 257 CreateRequestMessage.typecode, 246 258 getattr(self, "create_experiment"), 247 259 CreateResponseMessage, 248 260 "CreateResponseBody"), 249 'Vtopo': make_soap_handler(\261 'Vtopo': soap_handler(\ 250 262 VtopoRequestMessage.typecode, 251 263 getattr(self, "get_vtopo"), 252 264 VtopoResponseMessage, 253 265 "VtopoResponseBody"), 254 'Vis': make_soap_handler(\266 'Vis': soap_handler(\ 255 267 VisRequestMessage.typecode, 256 268 getattr(self, "get_vis"), 257 269 VisResponseMessage, 258 270 "VisResponseBody"), 259 'Info': make_soap_handler(\271 'Info': soap_handler(\ 260 272 InfoRequestMessage.typecode, 261 273 getattr(self, "get_info"), 262 274 InfoResponseMessage, 263 275 "InfoResponseBody"), 264 'Terminate': make_soap_handler(\276 'Terminate': soap_handler(\ 265 277 TerminateRequestMessage.typecode, 266 278 getattr(self, "terminate_experiment"), … … 270 282 271 283 self.xmlrpc_services = {\ 272 'Create': make_xmlrpc_handler(\284 'Create': xmlrpc_handler(\ 273 285 getattr(self, "create_experiment"), 274 286 "CreateResponseBody"), 275 'Vtopo': make_xmlrpc_handler(\287 'Vtopo': xmlrpc_handler(\ 276 288 getattr(self, "get_vtopo"), 277 289 "VtopoResponseBody"), 278 'Vis': make_xmlrpc_handler(\290 'Vis': xmlrpc_handler(\ 279 291 getattr(self, "get_vis"), 280 292 "VisResponseBody"), 281 'Info': make_xmlrpc_handler(\293 'Info': xmlrpc_handler(\ 282 294 getattr(self, "get_info"), 283 295 "InfoResponseBody"), 284 'Terminate': make_xmlrpc_handler(\296 'Terminate': xmlrpc_handler(\ 285 297 getattr(self, "terminate_experiment"), 286 298 "TerminateResponseBody"), … … 816 828 req['resources']['node'] = rnodes 817 829 818 # No retry loop here. Proxy servers must correctly authenticate 819 # themselves without help 820 821 try: 822 ctx = fedd_ssl_context(self.cert_file, 823 self.trusted_certs, password=self.cert_pwd) 824 except SSL.SSLError: 825 raise service_error(service_error.server_config, 826 "Server certificates misconfigured") 827 828 loc = feddServiceLocator(); 829 port = loc.getfeddPortType(uri, 830 transport=M2Crypto.httpslib.HTTPSConnection, 831 transdict={ 'ssl_context' : ctx }) 832 833 # Reconstruct the full request message 834 msg = RequestAccessRequestMessage() 835 msg.set_element_RequestAccessRequestBody( 836 pack_soap(msg, "RequestAccessRequestBody", req)) 837 838 try: 839 resp = port.RequestAccess(msg) 840 except ZSI.ParseException, e: 841 raise service_error(service_error.req, 842 "Bad format message (XMLRPC??): %s" % str(e)) 843 except ZSI.FaultException, e: 844 resp = e.fault.detail[0] 845 846 # Again, weird incompatibilities rear their head. userRoles, which are 847 # restricted strings, seem to be encoded by ZSI as non-unicode strings 848 # in a way that confuses the pickling and XMLRPC sending systems. 849 # Explicitly unicoding them seems to fix this, though it concerns me 850 # some. It may be that these things are actually a ZSI string 851 # subclass, and the character encoding is not the major issue. In any 852 # case, making all the subclasses of basestring into unicode strings 853 # unifies the response format and solves the problem. 854 r = make_unicode(fedids_to_obj(unpack_soap(resp))) 830 r = self.call_RequestAccess(uri, req, 831 self.cert_file, self.cert_pwd, self.trusted_certs) 855 832 856 833 if r.has_key('RequestAccessResponseBody'): 857 834 r = r['RequestAccessResponseBody'] 858 835 else: 859 raise service_error(service_error.pro xy,836 raise service_error(service_error.protocol, 860 837 "Bad proxy response") 861 838 … … 894 871 "Unknown testbed: %s" % tb) 895 872 896 # The basic request 897 req = { 'allocID' : aid } 898 899 # No retry loop here. Proxy servers must correctly authenticate 900 # themselves without help 901 try: 902 ctx = fedd_ssl_context(self.cert_file, 903 self.trusted_certs, password=self.cert_pwd) 904 except SSL.SSLError: 905 raise service_error(service_error.server_config, 906 "Server certificates misconfigured") 907 908 loc = feddServiceLocator(); 909 port = loc.getfeddPortType(uri, 910 transport=M2Crypto.httpslib.HTTPSConnection, 911 transdict={ 'ssl_context' : ctx }) 912 913 # Reconstruct the full request message 914 msg = ReleaseAccessRequestMessage() 915 msg.set_element_ReleaseAccessRequestBody( 916 pack_soap(msg, "ReleaseAccessRequestBody", req)) 917 918 try: 919 resp = port.ReleaseAccess(msg) 920 except ZSI.ParseException, e: 921 raise service_error(service_error.req, 922 "Bad format message (XMLRPC??): %s" % str(e)) 923 except ZSI.FaultException, e: 924 resp = e.fault.detail[0] 873 resp = self.call_ReleaseAccess(uri, {'allocID': aid}, 874 self.cert_file, self.cert_pwd, self.trusted_certs) 925 875 926 876 # better error coding … … 934 884 } 935 885 936 # No retry loop here. Proxy servers must correctly authenticate 937 # themselves without help 938 try: 939 ctx = fedd_ssl_context(self.cert_file, 940 self.trusted_certs, password=self.cert_pwd) 941 except SSL.SSLError: 942 raise service_error(service_error.server_config, 943 "Server certificates misconfigured") 944 945 loc = feddInternalServiceLocator(); 946 port = loc.getfeddInternalPortType(uri, 947 transport=M2Crypto.httpslib.HTTPSConnection, 948 transdict={ 'ssl_context' : ctx }) 949 950 # Reconstruct the full request message 951 msg = Ns2SplitRequestMessage() 952 msg.set_element_Ns2SplitRequestBody( 953 pack_soap(msg, "Ns2SplitRequestBody", req)) 954 955 try: 956 resp = port.Ns2Split(msg) 957 except ZSI.ParseException, e: 958 raise service_error(service_error.req, 959 "Bad format message (XMLRPC??): %s" % 960 str(e)) 961 r = unpack_soap(resp) 886 r = self.call_Ns2Split(uri, req, self.cert_file, self.cert_pwd, 887 self.trusted_certs) 888 962 889 if r.has_key('Ns2SplitResponseBody'): 963 890 r = r['Ns2SplitResponseBody'] … … 965 892 return r['output'].splitlines() 966 893 else: 967 raise service_error(service_error.pro xy,894 raise service_error(service_error.protocol, 968 895 "Bad splitter response (no output)") 969 896 else: 970 raise service_error(service_error.pro xy, "Bad splitter response")897 raise service_error(service_error.protocol, "Bad splitter response") 971 898 972 899 class current_testbed: -
fedd/fedd_split.py
rc922f23 r058f58e 62 62 # Dispatch tables 63 63 self.soap_services = {\ 64 'Ns2Split': make_soap_handler(\64 'Ns2Split': soap_handler(\ 65 65 Ns2SplitRequestMessage.typecode, 66 66 getattr(self, "run_splitter"), … … 70 70 71 71 self.xmlrpc_services = {\ 72 'Ns2Split': make_xmlrpc_handler(\72 'Ns2Split': xmlrpc_handler(\ 73 73 getattr(self, "run_splitter"), 74 74 "Ns2SplitResponseBody"), -
fedd/fedd_types.xsd
rc922f23 r058f58e 629 629 <xsd:restriction> 630 630 <xsd:enumeration value="1"/> <!-- access denied --> 631 <xsd:enumeration value="2"/> <!-- pro xyerror -->631 <xsd:enumeration value="2"/> <!-- protocol error --> 632 632 <xsd:enumeration value="3"/> <!-- badly formed request --> 633 633 <xsd:enumeration value="4"/> <!-- server configuration error --> -
fedd/fedd_util.py
rc922f23 r058f58e 368 368 369 369 370 def make_soap_handler(typecode, method, constructor, body_name):371 """ 372 Generate the handler code to unpack and pack SOAP requests and responses370 class soap_handler: 371 """ 372 Encapsulate the handler code to unpack and pack SOAP requests and responses 373 373 and call the given method. 374 374 375 375 The code to decapsulate and encapsulate parameters encoded in SOAP is the 376 same modulo a few parameters. This is basically a stub compiler for 377 calling a fedd service trhough a soap interface. The parameters are the 378 typecode of the request parameters, the method to call (usually a bound 379 instance of a method on a fedd service providing class), the constructor of 380 a response packet and the name of the body element of that packet. The 381 handler takes a ParsedSoap object (the request) and returns an instance of 382 the class created by constructor containing the response. Failures of the 383 constructor or badly created constructors will result in None being 384 returned. 385 """ 386 def handler(ps, fid): 387 req = ps.Parse(typecode) 388 389 msg = method(fedids_to_obj(unpack_soap(req)), fid) 390 391 resp = constructor() 392 set_element = getattr(resp, "set_element_%s" % body_name, None) 376 same modulo a few parameters. This is a functor that calls a fedd service 377 trhough a soap interface. The parameters are the typecode of the request 378 parameters, the method to call (usually a bound instance of a method on a 379 fedd service providing class), the constructor of a response packet and the 380 name of the body element of that packet. The handler takes a ParsedSoap 381 object (the request) and returns an instance of the class created by 382 constructor containing the response. Failures of the constructor or badly 383 created constructors will result in None being returned. 384 """ 385 def __init__(self, typecode, method, constructor, body_name): 386 self.typecode = typecode 387 self.method = method 388 self.constructor = constructor 389 self.body_name = body_name 390 391 def __call__(self, ps, fid): 392 req = ps.Parse(self.typecode) 393 394 msg = self.method(fedids_to_obj(unpack_soap(req)), fid) 395 396 resp = self.constructor() 397 set_element = getattr(resp, "set_element_%s" % self.body_name, None) 393 398 if set_element and callable(set_element): 394 399 try: 395 set_element(pack_soap(resp, body_name, msg))400 set_element(pack_soap(resp, self.body_name, msg)) 396 401 return resp 397 402 except (NameError, TypeError): … … 400 405 return None 401 406 402 return handler 403 404 def make_xmlrpc_handler(method, body_name): 405 """ 406 Generate the handler code to unpack and pack SOAP requests and responses 407 class xmlrpc_handler: 408 """ 409 Generate the handler code to unpack and pack XMLRPC requests and responses 407 410 and call the given method. 408 411 … … 416 419 to fedid objects on input and encapsulated as Binaries on output. 417 420 """ 418 def handler(params, fid): 419 decap_fedids = (('fedid', lambda x: fedid(bits=x.data)),) 420 421 p = apply_to_tags(params[0], decap_fedids) 422 msg = method(p, fid) 423 421 def __init__(self, method, body_name): 422 self.method = method 423 self.body_name = body_name 424 # A map used by apply_to_tags to convert fedids from xmlrpclib.Binary 425 # objects to fedid objects in one sweep. 426 self.decap_fedids = (('fedid', lambda x: fedid(bits=x.data)),) 427 428 def __call__(self, params, fid): 429 msg = None 430 431 p = apply_to_tags(params[0], self.decap_fedids) 432 try: 433 msg = self.method(p, fid) 434 except service_error, e: 435 raise Fault(e.code_string(), e.desc) 424 436 if msg != None: 425 return make_unicode(encapsulate_binaries({ body_name: msg }, ('fedid',))) 437 return make_unicode(encapsulate_binaries(\ 438 { self.body_name: msg }, ('fedid',))) 426 439 else: 427 440 return None 428 441 429 return handler 430 431 def make_service_callers(service_name, port_name, request_message, 432 request_body_name): 442 class service_caller: 443 def __init__(self, service_name, port_name, locator, request_message, 444 request_body_name, tracefile=None): 445 self.service_name = service_name 446 self.port_name = port_name 447 self.locator = locator 448 self.request_message = request_message 449 self.request_body_name = request_body_name 450 self.tracefile = tracefile 451 self.__call__ = self.call_service 433 452 434 453 def call_xmlrpc_service(self, url, req, cert_file=None, cert_pwd=None, 435 trusted_certs=None ):454 trusted_certs=None, context=None, tracefile=None): 436 455 """Send an XMLRPC request. """ 437 456 decap_fedids = (('fedid', lambda x: fedid(bits=x.data)),) 438 457 439 # No retry loop here. Proxy servers must correctly authenticate 440 # themselves without help 441 try: 442 ctx = fedd_ssl_context(cert_file, trusted_certs, password=cert_pwd) 443 except SSL.SSLError: 444 raise service_error(service_error.server_config, 445 "Server certificates misconfigured") 458 459 # If a context is given, use it. Otherwise construct one from 460 # components. The construction shouldn't call out for passwords. 461 if context: 462 ctx = context 463 else: 464 try: 465 ctx = fedd_ssl_context(cert_file, trusted_certs, 466 password=cert_pwd) 467 except SSL.SSLError: 468 raise service_error(service_error.server_config, 469 "Certificates misconfigured") 446 470 447 471 # Of all the dumbass things. The XMLRPC library in use here won't 448 # properly encode unicode strings, so we make a copy of req with the449 # unicode objects converted. We also convert the url to a basic string450 # if it isn't one already.472 # properly encode unicode strings, so we make a copy of req with 473 # the unicode objects converted. We also convert the url to a 474 # basic string if it isn't one already. 451 475 r = strip_unicode(copy.deepcopy(req)) 452 476 url = str(url) … … 454 478 transport = SSL_Transport(ctx) 455 479 port = ServerProxy(url, transport=transport) 480 # Make the call, and convert faults back to service_errors 456 481 try: 457 remote_method = getattr(port, se rvice_name, None)458 resp = remote_method(encapsulate_binaries( { request_body_name: r},459 ('fedid',)))482 remote_method = getattr(port, self.service_name, None) 483 resp = remote_method(encapsulate_binaries(\ 484 { self.request_body_name: r}, ('fedid',))) 460 485 except Fault, f: 461 486 raise service_error(None, f.faultString, f.faultCode) 462 487 except Error, e: 463 raise service_error(service_error.pro xy,488 raise service_error(service_error.protocol, 464 489 "Remote XMLRPC Fault: %s" % e) 465 490 466 491 return apply_to_tags(resp, decap_fedids) 467 492 468 def call_soap_service(self, url, req, loc_const, cert_file=None, cert_pwd=None,469 trusted_certs=None ):493 def call_soap_service(self, url, req, cert_file=None, cert_pwd=None, 494 trusted_certs=None, context=None, tracefile=None): 470 495 """ 471 496 Send req on to the real destination in dt and return the response … … 474 499 also rethrows any faults. 475 500 """ 476 # No retry loop here. Proxy servers must correctly authenticate 477 # themselves without help 478 try: 479 ctx = fedd_ssl_context(cert_file, trusted_certs, password=cert_pwd) 480 except SSL.SSLError: 481 raise service_error(service_error.server_config, 482 "Server certificates misconfigured") 483 484 loc = loc_const() 485 get_port = getattr(loc, port_name, None) 501 502 tf = tracefile or self.tracefile or None 503 504 # If a context is given, use it. Otherwise construct one from 505 # components. The construction shouldn't call out for passwords. 506 if context: 507 ctx = context 508 else: 509 try: 510 ctx = fedd_ssl_context(cert_file, trusted_certs, 511 password=cert_pwd) 512 except SSL.SSLError: 513 raise service_error(service_error.server_config, 514 "Certificates misconfigured") 515 loc = self.locator() 516 get_port = getattr(loc, self.port_name, None) 486 517 if not get_port: 487 518 raise service_error(service_error.internal, 488 "Cannot get port %s from locator" % port_name)519 "Cannot get port %s from locator" % self.port_name) 489 520 port = get_port(url, 490 521 transport=M2Crypto.httpslib.HTTPSConnection, 491 transdict={ 'ssl_context' : ctx }) 492 remote_method = getattr(port, service_name, None) 522 transdict={ 'ssl_context' : ctx }, 523 tracefile=tf) 524 remote_method = getattr(port, self.service_name, None) 493 525 if not remote_method: 494 526 raise service_error(service_error.internal, … … 496 528 497 529 # Reconstruct the full request message 498 msg = request_message() 499 set_element = getattr(msg, "set_element_%s" % request_body_name, None) 530 msg = self.request_message() 531 set_element = getattr(msg, "set_element_%s" % self.request_body_name, 532 None) 500 533 if not set_element: 501 534 raise service_error(service_error.internal, 502 535 "Cannot get element setting method for %s" % \ 503 request_body_name)504 set_element(pack_soap(msg, request_body_name, req))536 self.request_body_name) 537 set_element(pack_soap(msg, self.request_body_name, req)) 505 538 try: 506 539 resp = remote_method(msg) 507 540 except ZSI.ParseException, e: 508 raise service_error(service_error.proxy, 509 "Bad format message (XMLRPC??): %s" % 510 str(e)) 511 r = unpack_soap(resp) 541 raise service_error(service_error.protocol, 542 "Bad format message (XMLRPC??): %s" % e) 543 except ZSI.FaultException, e: 544 ee = unpack_soap(e.fault.detail[0]).get('FeddFaultBody', { }) 545 if ee: 546 raise service_error(ee['code'], ee['desc']) 547 else: 548 raise service_error(service_error.internal, 549 "Unexpected fault body") 550 r = make_unicode(fedids_to_obj(unpack_soap(resp))) 512 551 return r 513 552 514 return (call_soap_service, call_xmlrpc_service) 553 def call_service(self, url, req, cert_file=None, cert_pwd=None, 554 trusted_certs=None, context=None, tracefile=None): 555 p_fault = None # Any SOAP failure (sent unless XMLRPC works) 556 resp = None 557 try: 558 # Try the SOAP request 559 resp = self.call_soap_service(url, req, 560 cert_file, cert_pwd, trusted_certs, context, tracefile) 561 return resp 562 except service_error, e: 563 if e.code == service_error.protocol: p_fault = None 564 else: raise 565 except ZSI.FaultException, f: 566 p_fault = f.fault.detail[0] 567 568 569 # If we could not get a valid SOAP response to the request above, 570 # try the same address using XMLRPC and let any faults flow back 571 # out. 572 if p_fault == None: 573 resp = self.call_xmlrpc_service(url, req, cert_file, 574 cert_pwd, trusted_certs, context, tracefile) 575 return resp 576 else: 577 # Build the fault 578 ee = unpack_soap(p_fault).get('FeddFaultBody', { }) 579 if ee: 580 raise service_error(ee['code'], ee['desc']) 581 else: 582 raise service_error(service_error.internal, 583 "Unexpected fault body") 584 515 585 516 586 def set_log_level(config, sect, log): -
fedd/service_error.py
rc922f23 r058f58e 6 6 class service_error(RuntimeError): 7 7 access = 1 8 pro xy= 28 protocol= 2 9 9 req = 3 10 10 server_config = 4 … … 14 14 code_str = { 15 15 access : "Access Denied", 16 pro xy : "ProxyError",16 protocol : "Protocol Error", 17 17 req : "Badly Formed Request", 18 18 server_config: "Server Configuration Error", … … 23 23 str_code = dict([ (v, k) for k, v in code_str.iteritems() ]) 24 24 client_errors = ( req ) 25 server_errors = ( access, pro xy, server_config, internal)25 server_errors = ( access, protocol, server_config, internal) 26 26 27 27 def __init__(self, code=None, desc=None, from_string=None):
Note: See TracChangeset
for help on using the changeset viewer.