X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=source%2Fsteps%2FInstallBootstrapFS.py;h=8875394c7734b05a082fbcf0fba6c9572117f7db;hb=d7f858a139c1b935b65e38a2d2b364a578b0a26f;hp=db502acd50e2a0646e39e3a1e7898fc33640ff42;hpb=fbb0f48516a3d3fb8b2e67e700a0b7fa6dea0869;p=bootmanager.git diff --git a/source/steps/InstallBootstrapFS.py b/source/steps/InstallBootstrapFS.py index db502ac..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: @@ -65,7 +72,7 @@ def Run(vars, log): val = PARTITIONS["root"] val = PARTITIONS["swap"] val = PARTITIONS["vservers"] - except KeyError, part: + except KeyError as part: log.write("Missing partition in PARTITIONS: {}\n".format(part)) return 0 @@ -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: @@ -142,8 +156,8 @@ def Run(vars, log): # Download SHA1 checksum file log.write("downloading sha1sum for {}\n".format(source_file)) result = bs_request.DownloadFile(source_hash_file, None, None, - 1, 1, dest_hash_file, - 30, 14400) + 1, 1, dest_hash_file, + 30, 14400) log.write("verifying sha1sum for {}\n".format(source_file)) if not utils.check_file_hash(dest_file, dest_hash_file): @@ -165,7 +179,7 @@ def Run(vars, log): raise BootManagerException( "FATAL: Unable to download main tarball {} from server."\ .format(source_file)) - # for extensions, just print a warning + # for extensions, just issue a warning else: log.write("WARNING: tarball for extension {} not found\n".format(name)) @@ -179,20 +193,26 @@ def Run(vars, log): log.write("Copying boot server certificates and public key\n") if os.path.exists("/usr/boot"): - utils.makedirs(SYSIMG_PATH + "/usr") - shutil.copytree("/usr/boot", SYSIMG_PATH + "/usr/boot") + # do nothing in case of upgrade + if not os.path.exists(SYSIMG_PATH + "/usr/boot"): + utils.makedirs(SYSIMG_PATH + "/usr") + shutil.copytree("/usr/boot", SYSIMG_PATH + "/usr/boot") elif os.path.exists("/usr/bootme"): - utils.makedirs(SYSIMG_PATH + "/usr/boot") - boot_server = file("/usr/bootme/BOOTSERVER").readline().strip() - shutil.copy("/usr/bootme/cacert/" + boot_server + "/cacert.pem", - SYSIMG_PATH + "/usr/boot/cacert.pem") - file(SYSIMG_PATH + "/usr/boot/boot_server", "w").write(boot_server) - shutil.copy("/usr/bootme/pubring.gpg", SYSIMG_PATH + "/usr/boot/pubring.gpg") + # do nothing in case of upgrade + if not os.path.exists(SYSIMG_PATH + "/usr/bootme"): + utils.makedirs(SYSIMG_PATH + "/usr/boot") + boot_server = file("/usr/bootme/BOOTSERVER").readline().strip() + shutil.copy("/usr/bootme/cacert/" + boot_server + "/cacert.pem", + SYSIMG_PATH + "/usr/boot/cacert.pem") + file(SYSIMG_PATH + "/usr/boot/boot_server", "w").write(boot_server) + shutil.copy("/usr/bootme/pubring.gpg", SYSIMG_PATH + "/usr/boot/pubring.gpg") # For backward compatibility if os.path.exists("/usr/bootme"): - utils.makedirs(SYSIMG_PATH + "/mnt/cdrom") - shutil.copytree("/usr/bootme", SYSIMG_PATH + "/mnt/cdrom/bootme") + # do nothing in case of upgrade + if not os.path.exists(SYSIMG_PATH + "/mnt/cdrom/bootme"): + utils.makedirs(SYSIMG_PATH + "/mnt/cdrom") + shutil.copytree("/usr/bootme", SYSIMG_PATH + "/mnt/cdrom/bootme") # ONE_PARTITION => new distribution type if (vars['ONE_PARTITION'] != '1'): @@ -208,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))