Disconnected operation. disconnectedops disconnectedops
authorDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Thu, 16 Aug 2007 20:13:46 +0000 (20:13 +0000)
committerDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Thu, 16 Aug 2007 20:13:46 +0000 (20:13 +0000)
source/BootAPI.py
source/steps/AuthenticateWithPLC.py
source/steps/ChainBootNode.py
source/steps/ReadNodeConfiguration.py

index c0d0c3b..9565128 100644 (file)
@@ -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 ):
     """
@@ -86,12 +89,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, \
@@ -102,6 +115,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
@@ -109,3 +125,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()
index 55511dc..dddb5ee 100644 (file)
@@ -56,6 +56,13 @@ def Run( vars, log ):
             return 1
     except BootManagerException, e:
         log.write( "Authentication failed: %s.\n" % e )
+    except:
+        # This is ugly.
+        if vars['DISCONNECTED_OPERATION']:
+            vars['API_SERVER_INST']= None
+            return 1
+        else:
+            raise
 
     # increment auth failure
     auth_failure_count= 0
index b04756d..3e76d9c 100644 (file)
@@ -151,6 +151,8 @@ def Run( vars, log ):
     utils.sysexec( "cp %s/boot/kernel-boot%s /tmp/kernel" % (SYSIMG_PATH,option), log )
     utils.sysexec( "cp %s/boot/initrd-boot%s /tmp/initrd" % (SYSIMG_PATH,option), log )
 
+    BootAPI.save(vars)
+
     log.write( "Unmounting disks.\n" )
     try:
         # backwards compat, though, we should never hit this case post PL 3.2
@@ -234,7 +236,7 @@ def Run( vars, log ):
                 # problems during chain boot, such as USB host
                 # controller drivers (HCDs) (PL6577).
                 # if int(parts[2]) == 0:
-                if re.search('_hcd$', parts[0]):
+                if False and re.search('_hcd$', parts[0]):
                     if usb_usage > 0:
                         log.write( "NOT unloading %s since USB may be in use\n" % parts[0] )
                     else:
index c04cadf..d19439e 100644 (file)
@@ -116,6 +116,8 @@ def Run( vars, log ):
     vars['WAS_NODE_ID_IN_CONF']= 0
     vars['WAS_NODE_KEY_IN_CONF']= 0
 
+    vars['DISCONNECTED_OPERATION']= ''
+
     # for any devices that need to be mounted to get the configuration
     # file, mount them here.
     mount_point= "/tmp/conffilemount"
@@ -439,7 +441,10 @@ def __parse_configuration_file( vars, log, file_contents ):
 
             if name == "NET_DEVICE":
                 NETWORK_SETTINGS['mac']= string.upper(value)
-                
+
+            if name == "DISCONNECTED_OPERATION":
+                vars['DISCONNECTED_OPERATION']= value.strip()
+
 
     except IndexError, e:
         log.write( "Unable to parse configuration file\n" )
@@ -622,7 +627,7 @@ def __parse_configuration_file( vars, log, file_contents ):
         
     vars["NETWORK_SETTINGS"]= NETWORK_SETTINGS
 
-    if not hostname_resolve_ok:
+    if not hostname_resolve_ok and not vars['DISCONNECTED_OPERATION']:
         log.write( "Hostname does not resolve correctly, will not continue.\n" )
 
         if can_make_api_call: