From d7f858a139c1b935b65e38a2d2b364a578b0a26f Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Tue, 23 Jun 2015 13:22:46 +0200 Subject: [PATCH] a first stab at upgrading nodes not working yet, but I need to build all this --- source/BootManager.py | 6 ++- source/steps/InstallBootstrapFS.py | 68 +++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/source/BootManager.py b/source/BootManager.py index 2d9db0b..55686ea 100755 --- a/source/BootManager.py +++ b/source/BootManager.py @@ -276,13 +276,15 @@ class BootManager: # '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' diff --git a/source/steps/InstallBootstrapFS.py b/source/steps/InstallBootstrapFS.py index 0587057..8875394 100644 --- a/source/steps/InstallBootstrapFS.py +++ b/source/steps/InstallBootstrapFS.py @@ -19,9 +19,16 @@ import BootServerRequest 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 @@ -36,7 +43,7 @@ def Run(vars, log): 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: @@ -101,6 +108,13 @@ def Run(vars, log): # 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: @@ -214,7 +228,57 @@ def Run(vars, log): 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)) -- 2.43.0