# 'boot' state and chainboot into the production system
if not CheckHardwareRequirements.Run(self.VARS, self.LOG):
self.VARS['RUN_LEVEL'] = 'failboot'
- raise BootManagerException, "Hardware requirements not met."
+ raise BootManagerException("Hardware requirements not met.")
# runinstaller
InstallInit.Run(self.VARS, self.LOG)
+ # do not erase disks in upgrade mode
if not upgrade:
InstallPartitionDisks.Run(self.VARS, self.LOG)
- InstallBootstrapFS.Run(self.VARS, self.LOG)
+ # pass upgrade boolean to this step so we can do extra cleanup
+ InstallBootstrapFS.Run(self.VARS, upgrade, self.LOG)
InstallWriteConfig.Run(self.VARS, self.LOG)
InstallUninitHardware.Run(self.VARS, self.LOG)
self.VARS['BOOT_STATE'] = 'boot'
import BootAPI
-def Run(vars, log):
+def Run(vars, upgrade, log):
"""
Download core + extensions bootstrapfs tarballs and install on the hard drive
+
+ the upgrade boolean is True when we are upgrading a node root install while
+ preserving its slice contents; in that case we just perform extra cleanup
+ before unwrapping the bootstrapfs
+ this is because the running system may have extraneous files
+ that is to say, files that are *not* present in the bootstrapfs
+ and that can impact/clobber the resulting upgrade
Expect the following variables from the store:
SYSIMG_PATH the path where the system image will be mounted
are mounted.
"""
- log.write("\n\nStep: Install: bootstrapfs tarball.\n")
+ log.write("\n\nStep: Install: bootstrapfs tarball (upgrade={}).\n".format(upgrade))
# make sure we have the variables we need
try:
# this is now retrieved in GetAndUpdateNodeDetails
nodefamily = vars['nodefamily']
extensions = vars['extensions']
+
+ # in upgrade mode: we need to cleanup the disk to make
+ # it safe to just untar the new bootstrapfs tarball again
+ # on top of the hard drive
+ if upgrade:
+ CleanupSysimgBeforeUpgrade(SYSIMG_PATH, nodefamily, log)
+
# the 'plain' option is for tests mostly
plain = vars['plain']
if plain:
now = time.strftime("%Y-%b-%d @ %H:%M %Z", time.gmtime())
stamp.write("Hard drive installed by BootManager {}\n".format(VERSION))
stamp.write("Finished extraction of bootstrapfs on {}\n".format(now))
+ # do not modify this, the upgrade code uses this line for checking compatibility
stamp.write("Using nodefamily {}\n".format(nodefamily))
stamp.close()
return 1
+
+# the upgrade hook
+def CleanupSysimgBeforeUpgrade(sysimg, target_nodefamily, log):
+
+ areas_to_cleanup = [
+ '/usr/lib',
+ '/var',
+ '/etc',
+ '/boot',
+ ]
+
+ target_pldistro, target_fcdistro, target_arch = target_nodefamily.split('-')
+
+ # minimal check : not all configurations are possible...
+
+ installed_pldistro, installed_fcdistro, installed_arch = None, None, None
+ installed_virt = None
+ prefix = "Using nodefamily "
+ try:
+ with open("{}/bm-install.txt".format(sysimg)) as infile:
+ for line in infile:
+ if line.startswith(prefix):
+ installed_nodefamily = line.replace(prefix,"").strip()
+ installed_pldistro, installed_fcdistro, installed_arch = installed_nodefamily.split('-')
+ with open("{}/etc/planetlab/virt".format(sysimg)) as infile:
+ installed_virt = infile.read().strip()
+ except Exception as e:
+ print_exc()
+ raise BootManagerException("Could not retrieve data about previous installation - cannot upgrade")
+
+ # moving from vservers to lxc also means another filesystem
+ # so plain reinstall is the only option
+ if installed_virt != 'lxc':
+ raise BootManagerException("Can only upgrade nodes running lxc containers (vservers not supported)")
+
+ # changing arch is not reasonable either
+ if target_arch != installed_arch:
+ raise BootManagerException("Cannot upgrade from arch={} to arch={}"
+ .format(installed_arch, target_arch))
+
+ if target_pldistro != installed_pldistro:
+ log.write("\nWARNING: upgrading across pldistros {} to {} - might not work well..\n"
+ .format(installed_pldistro, target_pldistro))
+
+ # otherwise at this point we do not do any more advanced checking
+ log.write("\n\nPseudo step CleanupSysimgBeforeUpgrade : cleaning up hard drive\n")
+
+ for area in areas_to_cleanup:
+ utils.sysexec("rm -rf {}/{}".format(sysimg, area))