4 from Exceptions import *
7 from systeminfo import systeminfo
13 Load the kernel off of a node and boot to it.
14 This step assumes the disks are mounted on SYSIMG_PATH.
16 Expect the following variables:
17 BOOT_CD_VERSION A tuple of the current bootcd version
18 SYSIMG_PATH the path where the system image will be mounted
19 (always starts with TEMP_PATH)
20 ROOT_MOUNTED the node root file system is mounted
22 Sets the following variables:
23 ROOT_MOUNTED the node root file system is mounted
26 log.write( "\n\nStep: Chain booting node.\n" )
28 # make sure we have the variables we need
30 BOOT_CD_VERSION= vars["BOOT_CD_VERSION"]
31 if BOOT_CD_VERSION == "":
32 raise ValueError, "BOOT_CD_VERSION"
34 SYSIMG_PATH= vars["SYSIMG_PATH"]
36 raise ValueError, "SYSIMG_PATH"
39 raise BootManagerException, "Missing variable in vars: %s\n" % var
40 except ValueError, var:
41 raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var
44 if 'ROOT_MOUNTED' in vars.keys():
45 ROOT_MOUNTED= vars['ROOT_MOUNTED']
48 log.write( "Mounting node partitions\n" )
50 # old cds need extra utilities to run lvm
51 if BOOT_CD_VERSION[0] == 2:
52 compatibility.setup_lvm_2x_cd( vars, log )
54 # simply creating an instance of this class and listing the system
55 # block devices will make them show up so vgscan can find the planetlab
57 systeminfo().get_block_device_list()
59 utils.sysexec( "vgscan", log )
60 utils.sysexec( "vgchange -ay planetlab", log )
62 utils.makedirs( SYSIMG_PATH )
64 utils.sysexec( "mount /dev/planetlab/root %s" % SYSIMG_PATH, log )
65 utils.sysexec( "mount /dev/planetlab/vservers %s/vservers" %
69 vars['ROOT_MOUNTED']= 1
72 node_update_cmd= "/usr/local/planetlab/bin/NodeUpdate.py start noreboot"
74 log.write( "Running node update.\n" )
75 utils.sysexec( "chroot %s %s" % (SYSIMG_PATH,node_update_cmd), log )
77 log.write( "Updating ssh public host key with PLC.\n" )
80 ssh_host_key_file= file("%s/etc/ssh/ssh_host_rsa_key.pub"%SYSIMG_PATH,"r")
81 ssh_host_key= ssh_host_key_file.read().strip()
82 ssh_host_key_file.close()
83 ssh_host_key_file= None
88 update_vals['ssh_host_key']= ssh_host_key
89 BootAPI.call_api_function( vars, "BootUpdateNode", (update_vals,) )
92 log.write( "Copying kernel and initrd for booting.\n" )
93 utils.sysexec( "cp %s/boot/kernel-boot /tmp/kernel" % SYSIMG_PATH, log )
94 utils.sysexec( "cp %s/boot/initrd-boot /tmp/initrd" % SYSIMG_PATH, log )
96 log.write( "Unmounting disks.\n" )
97 utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log )
98 utils.sysexec_noerr( "umount -r /dev/planetlab/vservers", log )
99 utils.sysexec_noerr( "umount -r /dev/planetlab/root", log )
100 utils.sysexec_noerr( "vgchange -an", log )
103 vars['ROOT_MOUNTED']= 0
105 log.write( "Unloading modules and chain booting to new kernel.\n" )
107 # further use of log after Upload will only output to screen
110 # regardless of whether kexec works or not, we need to stop trying to
112 cancel_boot_flag= "/tmp/CANCEL_BOOT"
113 utils.sysexec( "touch %s" % cancel_boot_flag, log )
115 # on 2.x cds (2.4 kernel) for sure, we need to shutdown everything
116 # to get kexec to work correctly. Even on 3.x cds (2.6 kernel),
117 # there are a few buggy drivers that don't disable their hardware
118 # correctly unless they are first unloaded.
120 utils.sysexec_noerr( "ifconfig eth0 down", log )
122 if BOOT_CD_VERSION[0] == 2:
123 utils.sysexec_noerr( "killall dhcpcd", log )
124 elif BOOT_CD_VERSION[0] == 3:
125 utils.sysexec_noerr( "killall dhclient", log )
127 utils.sysexec_noerr( "umount -a -r -t ext2,ext3", log )
128 utils.sysexec_noerr( "modprobe -r lvm-mod", log )
131 modules= file("/tmp/loadedmodules","r")
134 module= string.strip(line)
136 log.write( "Unloading %s\n" % module )
137 utils.sysexec_noerr( "modprobe -r %s" % module, log )
141 log.write( "Couldn't read /tmp/loadedmodules, continuing.\n" )
144 modules= file("/proc/modules", "r")
146 # Get usage count for USB
150 # Module Size UsageCount UsedBy State LoadAddress
151 parts= string.split(line)
153 if parts[0] == "usb_storage":
154 usb_usage += int(parts[2])
155 except IndexError, e:
156 log.write( "Couldn't parse /proc/modules, continuing.\n" )
162 # Module Size UsageCount UsedBy State LoadAddress
163 parts= string.split(line)
165 # While we would like to remove all "unused" modules,
166 # you can't trust usage count, especially for things
167 # like network drivers or RAID array drivers. Just try
168 # and unload a few specific modules that we know cause
169 # problems during chain boot, such as USB host
170 # controller drivers (HCDs) (PL6577).
171 # if int(parts[2]) == 0:
172 if re.search('_hcd$', parts[0]):
174 log.write( "NOT unloading %s since USB may be in use\n" % parts[0] )
176 log.write( "Unloading %s\n" % parts[0] )
177 utils.sysexec_noerr( "modprobe -r %s" % parts[0], log )
178 except IndexError, e:
179 log.write( "Couldn't parse /proc/modules, continuing.\n" )
181 log.write( "Couldn't read /proc/modules, continuing.\n" )
184 utils.sysexec( "kexec --force --initrd=/tmp/initrd " \
185 "--append=ramdisk_size=8192 /tmp/kernel" )
186 except BootManagerException, e:
187 # if kexec fails, we've shut the machine down to a point where nothing
188 # can run usefully anymore (network down, all modules unloaded, file
189 # systems unmounted. write out the error, and cancel the boot process
192 log.write( "-------------------------------------------------------\n" )
193 log.write( "kexec failed with the following error. Please report\n" )
194 log.write( "this problem to support@planet-lab.org.\n\n" )
195 log.write( str(e) + "\n\n" )
196 log.write( "The boot process has been canceled.\n" )
197 log.write( "-------------------------------------------------------\n\n" )