X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=source%2FBootAPI.py;h=d69755b0bf7d3b649a1c9ee8b70bce3107e3fc3b;hb=008c4db00ad126481773f3b0f0bfdabe25553b0e;hp=f3092fbf62461bb8aacac2e27fd5da49f1133b5e;hpb=1d04d56e905cc4ba9a1bf84bfa44f9df425c8cbc;p=bootmanager.git diff --git a/source/BootAPI.py b/source/BootAPI.py index f3092fb..d69755b 100644 --- a/source/BootAPI.py +++ b/source/BootAPI.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2 +#!/usr/bin/python # Copyright (c) 2003 Intel Corporation # All rights reserved. @@ -12,9 +12,12 @@ import xml.parsers.expat import hmac import string import sha +import cPickle +import utils from Exceptions import * +stash = None def create_auth_structure( vars, call_params ): """ @@ -24,27 +27,62 @@ def create_auth_structure( vars, call_params ): API call. Return None if unable to (typically due to missing keys in vars, such as node_id or node_key) """ - + auth= {} - auth['AuthMethod']= 'hmac' try: - network= vars['NETWORK_SETTINGS'] - - auth['node_id']= vars['NODE_ID'] - auth['node_ip']= network['ip'] - node_key= vars['NODE_KEY'] - except KeyError, e: - return None + auth_session = {} + auth_session['AuthMethod'] = 'session' - params= serialize_params(call_params) - params.sort() - msg= "[" + "".join(params) + "]" - node_hmac= hmac.new(node_key,msg.encode('utf-8'),sha).hexdigest() - auth['value']= node_hmac + if not vars.has_key('NODE_SESSION'): + # Try to load /etc/planetlab/session if it exists. + sessionfile = open('/etc/planetlab/session', 'r') + session = sessionfile.read().strip() - return auth + auth_session['session'] = session + # Test session. Faults if it's no good. + vars['API_SERVER_INST'].AuthCheck(auth_session) + vars['NODE_SESSION'] = session + sessionfile.close() + else: + auth_session['session'] = vars['NODE_SESSION'] + + auth = auth_session + + except: + auth['AuthMethod']= 'hmac' + + try: + auth['node_id'] = vars['NODE_ID'] + auth['node_ip'] = vars['INTERFACE_SETTINGS']['ip'] + except KeyError, e: + return None + + node_hmac= hmac.new(vars['NODE_KEY'], "[]".encode('utf-8'), sha).hexdigest() + auth['value']= node_hmac + try: + auth_session = {} + if not vars.has_key('NODE_SESSION'): + session = vars['API_SERVER_INST'].GetSession(auth) + auth_session['session'] = session + vars['NODE_SESSION'] = session + # NOTE: save session value to /etc/planetlab/session for + # RunlevelAgent and future BootManager runs + sessionfile = open('/etc/planetlab/session', 'w') + sessionfile.write( vars['NODE_SESSION'] ) + sessionfile.close() + else: + auth_session['session'] = vars['NODE_SESSION'] + + auth_session['AuthMethod'] = 'session' + auth = auth_session + + except Exception, e: + print e + pass + + return auth def serialize_params( call_params ): @@ -64,6 +102,14 @@ def serialize_params( call_params ): values += serialize_params(param) elif isinstance(param,dict): values += serialize_params(param.values()) + elif isinstance(param,xmlrpclib.Boolean): + # bool was not a real type in Python <2.3 and had to be + # marshalled as a custom type in xmlrpclib. Make sure that + # bools serialize consistently. + if param: + values.append("True") + else: + values.append("False") else: values.append(unicode(param)) @@ -78,12 +124,22 @@ def call_api_function( vars, function, user_params ): If the call fails, a BootManagerException is raised. """ - + global stash + try: api_server= vars['API_SERVER_INST'] except KeyError, e: raise BootManagerException, "No connection to the API server exists." + if api_server is None: + if not stash: + load(vars) + for i in stash: + if i[0] == function and i[1] == user_params: + return i[2] + raise BootManagerException, \ + "Disconnected operation failed, insufficient stash." + auth= create_auth_structure(vars,user_params) if auth is None: raise BootManagerException, \ @@ -94,6 +150,9 @@ def call_api_function( vars, function, user_params ): try: exec( "rc= api_server.%s(*params)" % function ) + if stash is None: + stash = [] + stash += [ [ function, user_params, rc ] ] return rc except xmlrpclib.Fault, fault: raise BootManagerException, "API Fault: %s" % fault @@ -101,3 +160,35 @@ def call_api_function( vars, function, user_params ): raise BootManagerException,"XML RPC protocol error: %s" % err except xml.parsers.expat.ExpatError, err: raise BootManagerException,"XML parsing error: %s" % err + + +class Stash(file): + mntpnt = '/tmp/stash' + def __init__(self, vars, mode): + utils.makedirs(self.mntpnt) + try: + utils.sysexec('mount -t auto -U %s %s' % (vars['DISCONNECTED_OPERATION'], self.mntpnt)) + # make sure it's not read-only + f = file('%s/api.cache' % self.mntpnt, 'a') + f.close() + file.__init__(self, '%s/api.cache' % self.mntpnt, mode) + except: + utils.sysexec_noerr('umount %s' % self.mntpnt) + raise BootManagerException, "Couldn't find API-cache for disconnected operation" + + def close(self): + file.close(self) + utils.sysexec_noerr('umount %s' % self.mntpnt) + +def load(vars): + global stash + s = Stash(vars, 'r') + stash = cPickle.load(s) + s.close() + +def save(vars): + global stash + if vars['DISCONNECTED_OPERATION']: + s = Stash(vars, 'w') + cPickle.dump(stash, s) + s.close()