6 Wrapper around safexmlrpc.ServerProxy to automagically add an Auth
7 struct as the first argument to every XML-RPC call. Initialize
10 (node_id, key) => BootAuth
12 session => SessionAuth
14 To authenticate using the Boot Manager authentication method, or
15 the new session-based method.
18 def __init__(self, uri, cacert, auth, timeout = 300, **kwds):
19 if isinstance(auth, (tuple, list)):
20 (self.node_id, self.key) = auth
23 self.node_id = self.key = None
26 self.server = safexmlrpc.ServerProxy(uri, cacert, timeout, allow_none = 1, **kwds)
28 def add_auth(self, function):
30 Returns a wrapper which adds an Auth struct as the first
31 argument when the function is called.
34 def canonicalize(args):
36 BootAuth canonicalization method. Parameter values are
37 collected, sorted, converted to strings, then hashed with
44 if isinstance(arg, list) or isinstance(arg, tuple):
45 # The old implementation did not recursively handle
46 # lists of lists. But neither did the old API itself.
47 values += canonicalize(arg)
48 elif isinstance(arg, dict):
49 # Yes, the comments in the old implementation are
50 # misleading. Keys of dicts are not included in the
52 values += canonicalize(arg.values())
54 # We use unicode() instead of str().
55 values.append(unicode(arg))
61 Adds an Auth struct as the first argument when the
65 if self.session is not None:
66 # Use session authentication
67 auth = {'AuthMethod': "session",
68 'session': self.session}
70 # Yes, this is the "canonicalization" method used.
71 args = canonicalize(params)
73 msg = "[" + "".join(args) + "]"
75 # We encode in UTF-8 before calculating the HMAC, which is
77 digest = hmac.new(self.key, msg.encode('utf-8'), sha).hexdigest()
79 auth = {'AuthMethod': "hmac",
80 'node_id': self.node_id,
83 # Automagically add auth struct to every call
84 params = (auth,) + params
86 return function(*params)
90 def __getattr__(self, methodname):
91 function = getattr(self.server, methodname)
92 return self.add_auth(function)