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.3 2006/10/03 19:24:31 mlhuang Exp $
18 from SOAPpy.Parser import parseSOAPRPC
19 from SOAPpy.Types import faultType
20 from SOAPpy.NS import NS
21 from SOAPpy.SOAPBuilder import buildSOAP
25 from PLC.Config import Config
26 from PLC.PostgreSQL import PostgreSQL
27 from PLC.Faults import *
31 methods = PLC.Methods.methods
33 def __init__(self, config = "/etc/planetlab/plc_config", encoding = "utf-8"):
34 self.encoding = encoding
36 # Better just be documenting the API
41 self.config = Config(config)
43 # Initialize database connection
44 if self.config.PLC_DB_TYPE == "postgresql":
45 self.db = PostgreSQL(self)
47 raise PLCAPIError, "Unsupported database type " + config.PLC_DB_TYPE
49 def callable(self, method):
51 Return a new instance of the specified method.
55 if method not in self.methods:
56 raise PLCInvalidAPIMethod, method
58 # Get new instance of method
60 classname = method.split(".")[-1]
61 module = __import__("PLC.Methods." + method, globals(), locals(), [classname])
62 return getattr(module, classname)(self)
63 except ImportError, AttributeError:
64 raise PLCInvalidAPIMethod, method
66 def call(self, source, method, *args):
68 Call the named method from the specified source with the
72 function = self.callable(method)
73 function.source = source
74 return function(*args)
76 def handle(self, source, data):
78 Handle an XML-RPC or SOAP request from the specified source.
81 # Parse request into method name and arguments
84 (args, method) = xmlrpclib.loads(data)
87 if SOAPpy is not None:
89 (r, header, body, attrs) = parseSOAPRPC(data, header = 1, body = 1, attrs = 1)
92 # XXX Support named arguments
97 result = self.call(source, method, *args)
98 except PLCFault, fault:
99 # Handle expected faults
100 if interface == xmlrpclib:
102 methodresponse = None
103 elif interface == SOAPpy:
104 result = faultParameter(NS.ENV_T + ":Server", "Method Failed", method)
105 result._setDetail("Fault %d: %s" % (fault.faultCode, fault.faultString))
108 if interface == xmlrpclib:
109 if not isinstance(result, PLCFault):
111 data = xmlrpclib.dumps(result, methodresponse = True, encoding = self.encoding, allow_none = 1)
112 elif interface == SOAPpy:
113 data = buildSOAP(kw = {'%sResponse' % method: {'Result': result}}, encoding = self.encoding)