-#!/usr/bin/python
+#!/usr/bin/python2
#
# Copyright (c) 2003 Intel Corporation
# All rights reserved.
from Exceptions import *
import utils
+import systeminfo
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
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:
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
bs_request = BootServerRequest.BootServerRequest(vars)
+ # in upgrade mode, since we skip InstallPartitionDisks
+ # we need to run this
+ if upgrade:
+ log.write("Upgrade mode init : Scanning for devices\n")
+ systeminfo.get_block_devices_dict(vars, log)
+ utils.sysexec_noerr("vgscan --mknodes", log)
+ utils.sysexec_noerr("vgchange -ay", log)
+
+ # debugging info - show in either mode
+ utils.display_disks_status(PARTITIONS, "In InstallBootstrapFS", log)
+
+ utils.breakpoint("we need to make /dev/mapper/* appear")
+
log.write("turning on swap space\n")
utils.sysexec("swapon {}".format(PARTITIONS["swap"]), log)
utils.sysexec("mount -t {} {} {}/vservers"\
.format(fstype, PARTITIONS["vservers"], SYSIMG_PATH), log)
- if vars['virt']=='lxc':
+ #if vars['virt']=='lxc':
# NOTE: btrfs quota is supported from version: >= btrfs-progs-0.20 (f18+)
# older versions will not recongize the 'quota' command.
- log.write("Enabling btrfs quota on {}/vservers\n".format(SYSIMG_PATH))
- utils.sysexec_noerr("btrfs quota enable {}/vservers".format(SYSIMG_PATH))
+ #log.write("Enabling btrfs quota on {}/vservers\n".format(SYSIMG_PATH))
+ #utils.sysexec_noerr("btrfs quota enable {}/vservers".format(SYSIMG_PATH))
vars['ROOT_MOUNTED'] = 1
# 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:
# 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):
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))
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'):
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 = [
+ '/boot',
+ '/usr',
+ '/var',
+ '/etc',
+ '/run',
+ '/vsys',
+ ]
+
+ 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('-')
+ # do not break here, bm-install is additive, we want the last one..
+ with open("{}/etc/planetlab/virt".format(sysimg)) as infile:
+ installed_virt = infile.read().strip()
+ except Exception as e:
+ traceback.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':
+ message = """Can only upgrade nodes already running lxc containers
+a node running vservers has its /vservers/ partition formatted as ext3
+and we need btrfs to move to containers
+your only option here is reinstall"""
+ raise BootManagerException(message)
+
+ # 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))