3 # Copyright (c) 2003 Intel Corporation
6 # Copyright (c) 2004-2006 The Trustees of Princeton University
11 import xml.parsers.expat
18 from Exceptions import *
22 def create_auth_structure( vars, call_params ):
24 create and return an authentication structure for a Boot API
25 call. Vars contains the boot manager runtime variables, and
26 call_params is a tuple of the parameters that will be passed to the
27 API call. Return None if unable to (typically due to missing
28 keys in vars, such as node_id or node_key)
32 auth['AuthMethod']= 'hmac'
35 auth['node_id'] = vars['NODE_ID']
36 auth['node_ip'] = vars['INTERFACE_SETTINGS']['ip']
40 #params= serialize_params(call_params)
42 #msg= "[" + "".join(params) + "]"
43 #node_hmac= hmac.new(vars['NODE_KEY'], msg.encode('utf-8'), sha).hexdigest()
44 node_hmac= hmac.new(vars['NODE_KEY'], "[]".encode('utf-8'), sha).hexdigest()
45 auth['value']= node_hmac
48 if not vars.has_key('NODE_SESSION'):
49 session = vars['API_SERVER_INST'].GetSession(auth)
50 auth_session['session'] = session
51 vars['NODE_SESSION'] = session
53 auth_session['session'] = vars['NODE_SESSION']
54 auth_session['AuthMethod'] = 'session'
62 def serialize_params( call_params ):
64 convert a list of parameters into a format that will be used in the
65 hmac generation. both the boot manager and plc must have a common
66 format. full documentation is in the boot manager technical document,
67 but essentially we are going to take all the values (and keys for
68 dictionary objects), and put them into a list. sort them, and combine
69 them into one long string encased in a set of braces.
74 for param in call_params:
75 if isinstance(param,list) or isinstance(param,tuple):
76 values += serialize_params(param)
77 elif isinstance(param,dict):
78 values += serialize_params(param.values())
79 elif isinstance(param,xmlrpclib.Boolean):
80 # bool was not a real type in Python <2.3 and had to be
81 # marshalled as a custom type in xmlrpclib. Make sure that
82 # bools serialize consistently.
86 values.append("False")
88 values.append(unicode(param))
93 def call_api_function( vars, function, user_params ):
95 call the named api function with params, and return the
96 value to the caller. the authentication structure is handled
97 automatically, and doesn't need to be passed in with params.
99 If the call fails, a BootManagerException is raised.
104 api_server= vars['API_SERVER_INST']
106 raise BootManagerException, "No connection to the API server exists."
108 if api_server is None:
112 if i[0] == function and i[1] == user_params:
114 raise BootManagerException, \
115 "Disconnected operation failed, insufficient stash."
117 auth= create_auth_structure(vars,user_params)
119 raise BootManagerException, \
120 "Could not create auth structure, missing values."
123 params= params + user_params
126 exec( "rc= api_server.%s(*params)" % function )
129 stash += [ [ function, user_params, rc ] ]
131 except xmlrpclib.Fault, fault:
132 raise BootManagerException, "API Fault: %s" % fault
133 except xmlrpclib.ProtocolError, err:
134 raise BootManagerException,"XML RPC protocol error: %s" % err
135 except xml.parsers.expat.ExpatError, err:
136 raise BootManagerException,"XML parsing error: %s" % err
140 mntpnt = '/tmp/stash'
141 def __init__(self, vars, mode):
142 utils.makedirs(self.mntpnt)
144 utils.sysexec('mount -t auto -U %s %s' % (vars['DISCONNECTED_OPERATION'], self.mntpnt))
145 # make sure it's not read-only
146 f = file('%s/api.cache' % self.mntpnt, 'a')
148 file.__init__(self, '%s/api.cache' % self.mntpnt, mode)
150 utils.sysexec_noerr('umount %s' % self.mntpnt)
151 raise BootManagerException, "Couldn't find API-cache for disconnected operation"
155 utils.sysexec_noerr('umount %s' % self.mntpnt)
160 stash = cPickle.load(s)
165 if vars['DISCONNECTED_OPERATION']:
167 cPickle.dump(stash, s)