X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=source%2Fsteps%2FChainBootNode.py;h=9695a8f426133a71290b854d6974a3bf04b0f79f;hb=aeecdf5a1be4c56b19e1ee8a902305742f4fd697;hp=181b934faf3458b4cdd7aba9f722373547e285e0;hpb=3d3501347eac5ca2db4bfd37d0af471984c56b48;p=bootmanager.git diff --git a/source/steps/ChainBootNode.py b/source/steps/ChainBootNode.py index 181b934..9695a8f 100644 --- a/source/steps/ChainBootNode.py +++ b/source/steps/ChainBootNode.py @@ -1,4 +1,5 @@ import string +import re from Exceptions import * import utils @@ -17,7 +18,10 @@ def Run( vars, log ): SYSIMG_PATH the path where the system image will be mounted (always starts with TEMP_PATH) ROOT_MOUNTED the node root file system is mounted - + NODE_SESSION the unique session val set when we requested + the current boot state + PLCONF_DIR The directory to store PL configuration files in + Sets the following variables: ROOT_MOUNTED the node root file system is mounted """ @@ -33,7 +37,14 @@ def Run( vars, log ): SYSIMG_PATH= vars["SYSIMG_PATH"] if SYSIMG_PATH == "": raise ValueError, "SYSIMG_PATH" - + + PLCONF_DIR= vars["PLCONF_DIR"] + if PLCONF_DIR == "": + raise ValueError, "PLCONF_DIR" + + # its ok if this is blank + NODE_SESSION= vars["NODE_SESSION"] + except KeyError, var: raise BootManagerException, "Missing variable in vars: %s\n" % var except ValueError, var: @@ -82,7 +93,18 @@ def Run( vars, log ): ssh_host_key_file= None except IOError, e: pass - + + # write out the session value /etc/planetlab/session + try: + session_file_path= "%s/%s/session" % (SYSIMG_PATH,PLCONF_DIR) + session_file= file( session_file_path, "w" ) + session_file.write( str(NODE_SESSION) ) + session_file.close() + session_file= None + log.write( "Updated /etc/planetlab/session\n" ) + except IOError, e: + log.write( "Unable to write out /etc/planetlab/session, continuing anyway\n" ) + update_vals= {} update_vals['ssh_host_key']= ssh_host_key BootAPI.call_api_function( vars, "BootUpdateNode", (update_vals,) ) @@ -101,10 +123,7 @@ def Run( vars, log ): ROOT_MOUNTED= 0 vars['ROOT_MOUNTED']= 0 - if BOOT_CD_VERSION[0] == 2: - log.write( "Unloading modules and chaining booting to new kernel.\n" ) - else: - log.write( "Chaining booting to new kernel.\n" ) + log.write( "Unloading modules and chain booting to new kernel.\n" ) # further use of log after Upload will only output to screen log.Upload() @@ -114,8 +133,10 @@ def Run( vars, log ): cancel_boot_flag= "/tmp/CANCEL_BOOT" utils.sysexec( "touch %s" % cancel_boot_flag, log ) - # on 2.x cds (2.4 kernel) for sure, we need to shutdown everything to - # get kexec to work correctly + # on 2.x cds (2.4 kernel) for sure, we need to shutdown everything + # to get kexec to work correctly. Even on 3.x cds (2.6 kernel), + # there are a few buggy drivers that don't disable their hardware + # correctly unless they are first unloaded. utils.sysexec_noerr( "ifconfig eth0 down", log ) @@ -133,13 +154,70 @@ def Run( vars, log ): for line in modules: module= string.strip(line) if module != "": + log.write( "Unloading %s\n" % module ) utils.sysexec_noerr( "modprobe -r %s" % module, log ) + + modules.close() + except IOError: + log.write( "Couldn't read /tmp/loadedmodules, continuing.\n" ) + + try: + modules= file("/proc/modules", "r") + + # Get usage count for USB + usb_usage = 0 + for line in modules: + try: + # Module Size UsageCount UsedBy State LoadAddress + parts= string.split(line) + + if parts[0] == "usb_storage": + usb_usage += int(parts[2]) + except IndexError, e: + log.write( "Couldn't parse /proc/modules, continuing.\n" ) + + modules.seek(0) + + for line in modules: + try: + # Module Size UsageCount UsedBy State LoadAddress + parts= string.split(line) + + # While we would like to remove all "unused" modules, + # you can't trust usage count, especially for things + # like network drivers or RAID array drivers. Just try + # and unload a few specific modules that we know cause + # problems during chain boot, such as USB host + # controller drivers (HCDs) (PL6577). + # if int(parts[2]) == 0: + if re.search('_hcd$', parts[0]): + if usb_usage > 0: + log.write( "NOT unloading %s since USB may be in use\n" % parts[0] ) + else: + log.write( "Unloading %s\n" % parts[0] ) + utils.sysexec_noerr( "modprobe -r %s" % parts[0], log ) + except IndexError, e: + log.write( "Couldn't parse /proc/modules, continuing.\n" ) + except IOError: + log.write( "Couldn't read /proc/modules, continuing.\n" ) + + + kargs = "ramdisk_size=8192" + try: + kargsfb = open("/kargs.txt","r") + moreargs = kargsfb.readline() + kargsfb.close() + moreargs = moreargs.strip() + log.write( 'Parsed in "%s" kexec args from /kargs.txt\n' % moreargs ) + kargs = kargs + " " + moreargs except IOError: - log.write( "Couldn't load /tmp/loadedmodules to unload, continuing.\n" ) + # /kargs.txt does not exist, which is fine. Just kexec with default + # kargs, which is ramdisk_size=8192 + pass try: - utils.sysexec( "kexec --force --initrd=/tmp/initrd " \ - "--append=ramdisk_size=8192 /tmp/kernel" ) + utils.sysexec( 'kexec --force --initrd=/tmp/initrd ' \ + '--append="%s" /tmp/kernel' % kargs) except BootManagerException, e: # if kexec fails, we've shut the machine down to a point where nothing # can run usefully anymore (network down, all modules unloaded, file