Copyright notice for both Intel and Princeton
[bootmanager.git] / source / BootAPI.py
1 #!/usr/bin/python2
2
3 # Copyright (c) 2003 Intel Corporation
4 # All rights reserved.
5 #
6 # Copyright (c) 2004-2006 The Trustees of Princeton University
7 # All rights reserved.
8
9
10 import xmlrpclib
11 import xml.parsers.expat
12 import hmac
13 import string
14 import sha
15
16 from Exceptions import *
17
18
19 def create_auth_structure( vars, call_params ):
20     """
21     create and return an authentication structure for a Boot API
22     call. Vars contains the boot manager runtime variables, and
23     call_params is a tuple of the parameters that will be passed to the
24     API call. Return None if unable to (typically due to missing
25     keys in vars, such as node_id or node_key)
26     """
27     
28     auth= {}
29     auth['AuthMethod']= 'hmac'
30
31     try:
32         network= vars['NETWORK_SETTINGS']
33         
34         auth['node_id']= vars['NODE_ID']
35         auth['node_ip']= network['ip']
36         node_key= vars['NODE_KEY']
37     except KeyError, e:
38         return None
39
40     msg= serialize_params(call_params)
41     node_hmac= hmac.new(node_key,msg,sha).hexdigest()
42     auth['value']= node_hmac
43
44     return auth
45
46
47
48 def serialize_params( call_params ):
49     """
50     convert a list of parameters into a format that will be used in the
51     hmac generation. both the boot manager and plc must have a common
52     format. full documentation is in the boot manager technical document,
53     but essentially we are going to take all the values (and keys for
54     dictionary objects), and put them into a list. sort them, and combine
55     them into one long string encased in a set of braces.
56     """
57
58     # if there are no parameters, just return empty paren set
59     if len(call_params) == 0:
60         return "[]"
61
62     values= []
63     
64     for param in call_params:
65         if isinstance(param,list) or isinstance(param,tuple):
66             values= values + map(str,param)
67         elif isinstance(param,dict):
68             values= values + collapse_dict(param)        
69         else:
70             values.append( str(param) )
71                 
72     values.sort()
73     values= "[" + string.join(values,"") + "]"
74     return values
75
76     
77 def collapse_dict( value ):
78     """
79     given a dictionary, return a list of all the keys and values as strings,
80     in no particular order
81     """
82
83     item_list= []
84     
85     if not isinstance(value,dict):
86         return item_list
87     
88     for key in value.keys():
89         key_value= value[key]
90         if isinstance(key_value,list) or isinstance(key_value,tuple):
91             item_list= item_list + map(str,key_value)
92         elif isinstance(key_value,dict):
93             item_list= item_list + collapse_dict(key_value)
94         else:
95             item_list.append( str(key_value) )
96
97     return item_list
98             
99     
100     
101 def call_api_function( vars, function, user_params ):
102     """
103     call the named api function with params, and return the
104     value to the caller. the authentication structure is handled
105     automatically, and doesn't need to be passed in with params.
106
107     If the call fails, a BootManagerException is raised.
108     """
109     
110     try:
111         api_server= vars['API_SERVER_INST']
112     except KeyError, e:
113         raise BootManagerException, "No connection to the API server exists."
114
115     auth= create_auth_structure(vars,user_params)
116     if auth is None:
117         raise BootManagerException, \
118               "Could not create auth structure, missing values."
119     
120     params= (auth,)
121     params= params + user_params
122
123     try:
124         exec( "rc= api_server.%s(*params)" % function )
125         return rc
126     except xmlrpclib.Fault, fault:
127         raise BootManagerException, "API Fault: %s" % fault
128     except xmlrpclib.ProtocolError, err:
129         raise BootManagerException,"XML RPC protocol error: %s" % err
130     except xml.parsers.expat.ExpatError, err:
131         raise BootManagerException,"XML parsing error: %s" % err