2 # PLCAPI XML-RPC and SOAP interfaces
4 # Aaron Klingaman <alk@absarokasoft.com>
5 # Mark Huang <mlhuang@cs.princeton.edu>
7 # Copyright (C) 2004-2006 The Trustees of Princeton University
8 # $Id: API.py,v 1.2 2006/09/08 19:43:31 mlhuang Exp $
17 from SOAPpy.Parser import parseSOAPRPC
18 from SOAPpy.Types import faultType
19 from SOAPpy.NS import NS
20 from SOAPpy.SOAPBuilder import buildSOAP
22 from PLC.Config import Config
23 from PLC.PostgreSQL import PostgreSQL
24 from PLC.Faults import *
28 methods = PLC.Methods.methods
30 def __init__(self, config = "/etc/planetlab/plc_config", encoding = "utf-8"):
31 self.encoding = encoding
33 # Better just be documenting the API
38 self.config = Config(config)
40 # Initialize database connection
41 if self.config.PLC_DB_TYPE == "postgresql":
42 self.db = PostgreSQL(self)
44 raise PLCAPIError, "Unsupported database type " + config.PLC_DB_TYPE
46 def callable(self, method):
48 Return a new instance of the specified method.
52 if method not in self.methods:
53 raise PLCInvalidAPIMethod, method
55 # Get new instance of method
57 classname = method.split(".")[-1]
58 module = __import__("PLC.Methods." + method, globals(), locals(), [classname])
59 return getattr(module, classname)(self)
60 except ImportError, AttributeError:
61 raise PLCInvalidAPIMethod, method
63 def call(self, source, method, *args):
65 Call the named method from the specified source with the
69 function = self.callable(method)
70 function.source = source
71 return function(*args)
73 def handle(self, source, data):
75 Handle an XML-RPC or SOAP request from the specified source.
78 # Parse request into method name and arguments
81 (args, method) = xmlrpclib.loads(data)
85 (r, header, body, attrs) = parseSOAPRPC(data, header = 1, body = 1, attrs = 1)
88 # XXX Support named arguments
91 result = self.call(source, method, *args)
92 except PLCFault, fault:
93 # Handle expected faults
94 if interface == xmlrpclib:
97 elif interface == SOAPpy:
98 result = faultParameter(NS.ENV_T + ":Server", "Method Failed", method)
99 result._setDetail("Fault %d: %s" % (fault.faultCode, fault.faultString))
102 if interface == xmlrpclib:
103 if not isinstance(result, PLCFault):
105 data = xmlrpclib.dumps(result, methodresponse = True, encoding = self.encoding, allow_none = 1)
106 elif interface == SOAPpy:
107 data = buildSOAP(kw = {'%sResponse' % method: {'Result': result}}, encoding = self.encoding)