disabled btrfs quota because of a bug making the node gain a very high load
[bootmanager.git] / source / steps / InstallBootstrapFS.py
index 0587057..f0414e0 100644 (file)
@@ -15,13 +15,21 @@ import time
 
 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
@@ -36,7 +44,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:
@@ -71,6 +79,19 @@ def Run(vars, log):
 
     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)
 
@@ -90,17 +111,24 @@ def Run(vars, 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:
@@ -214,7 +242,64 @@ 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 = [
+        '/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))