Merge branch 'ansible'
authorThierry Parmentelat <thierry.parmentelat@inria.fr>
Thu, 15 May 2014 09:28:36 +0000 (11:28 +0200)
committerThierry Parmentelat <thierry.parmentelat@inria.fr>
Thu, 15 May 2014 09:28:36 +0000 (11:28 +0200)
source/BootManager.py
source/configuration
source/steps/AnsibleHook.py [new file with mode: 0644]
source/steps/ChainBootNode.py
source/steps/GetAndUpdateNodeDetails.py
source/steps/InstallBootstrapFS.py
source/steps/InstallPartitionDisks.py
source/steps/InstallWriteConfig.py
source/steps/ValidateNodeInstall.py
source/steps/__init__.py

index 68c5052..5270c6c 100755 (executable)
@@ -6,8 +6,9 @@
 # Copyright (c) 2004-2006 The Trustees of Princeton University
 # All rights reserved.
 
+import sys, os
+import traceback
 import string
-import sys, os, traceback
 import time
 import gzip
 
@@ -109,6 +110,12 @@ class log:
         """
         self.LogEntry( str, 0, 1 )
     
+    def print_stack (self):
+        """
+        dump current stack in log
+        """
+        self.write ( traceback.format_exc() )
+
     # bm log uploading is available back again, as of nodeconfig-5.0-2
     def Upload( self, extra_file=None ):
         """
@@ -277,6 +284,7 @@ class BootManager:
             self.VARS['STATE_CHANGE_NOTIFY']= 1
             self.VARS['STATE_CHANGE_NOTIFY_MESSAGE']= \
                  notify_messages.MSG_INSTALL_FINISHED
+            AnsibleHook.Run( self.VARS, self.LOG )
             UpdateBootStateWithPLC.Run( self.VARS, self.LOG )
             _bootRun()
             
@@ -289,6 +297,8 @@ class BootManager:
             if not ConfirmInstallWithUser.Run( self.VARS, self.LOG ):
                 return 0
             self.VARS['BOOT_STATE']= 'reinstall'
+
+            AnsibleHook.Run( self.VARS, self.LOG )
             _reinstallRun()
 
         def _debugRun(state='failboot'):
@@ -329,18 +339,20 @@ class BootManager:
 
         except KeyError, e:
             self.LOG.write( "\n\nKeyError while running: %s\n" % str(e) )
+            self.LOG.print_stack ()
         except BootManagerException, e:
             self.LOG.write( "\n\nException while running: %s\n" % str(e) )
+            self.LOG.print_stack ()
         except BootManagerAuthenticationException, e:
             self.LOG.write( "\n\nFailed to Authenticate Node: %s\n" % str(e) )
+            self.LOG.print_stack ()
             # sets /tmp/CANCEL_BOOT flag
             StartDebug.Run(self.VARS, self.LOG )
             # Return immediately b/c any other calls to API will fail
             return success
         except:
             self.LOG.write( "\n\nImplementation Error\n")
-            traceback.print_exc(file=self.LOG.OutputFile)
-            traceback.print_exc()
+            self.LOG.print_stack ()
 
         if not success:
             try:
index 5ec5887..b6f0644 100644 (file)
@@ -95,3 +95,5 @@ NUM_AUTH_FAILURES_BEFORE_DEBUG=2
 
 # location of file containing http/https proxy info, if needed
 PROXY_FILE=/etc/planetlab/http_proxy
+
+ONE_PARTITION=0
diff --git a/source/steps/AnsibleHook.py b/source/steps/AnsibleHook.py
new file mode 100644 (file)
index 0000000..5275e72
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+#
+
+import os
+
+from Exceptions import *
+import utils
+import systeminfo
+
+def run_ansible(ansible_path, ansible_hash, playbook_name, log):
+    try:
+        if (ansible_hash):
+            hash_arg = '-U %s'%ansible_hash
+        else:
+            hash_arg = ''
+        utils.sysexec_noerr('ansible-pull -i hosts %s %s %s' % (ansible_path, hash_arg, playbook_name), log )
+    except:
+        pass
+
+
+def Run( vars, log ):
+    log.write( "\n\nStep: Running Ansible Hook\n" )
+    # make sure we have the variables we need
+    try:
+        ansible_path = vars["ANSIBLE_PATH"]
+        run_level = vars["RUN_LEVEL"]
+        try:
+            ansible_hash = vars["ANSIBLE_HASH"]
+        except KeyError:
+            ansible_hash = None
+
+        if (ansible_path):
+            run_ansible(ansible_path, ansible_hash, "%s.yml"%run_level, log)
+    except KeyError, var:
+        log.write( "No Ansible directive. Skipping.\n");
+        pass
index 5e7babf..6ea6213 100644 (file)
@@ -110,20 +110,22 @@ def Run( vars, log ):
     # update configuration files
     log.write( "Updating configuration files.\n" )
     # avoid using conf_files initscript as we're moving to systemd on some platforms
-    try:
-        cmd = "/usr/bin/env python /usr/share/NodeManager/conf_files.py --noscripts"
-        utils.sysexec_chroot( SYSIMG_PATH, cmd, log )
-    except IOError, e:
-        log.write("conf_files failed with \n %s" % e)
 
-    # update node packages
-    log.write( "Running node update.\n" )
-    if os.path.exists( SYSIMG_PATH + "/usr/bin/NodeUpdate.py" ):
-        cmd = "/usr/bin/NodeUpdate.py start noreboot"
-    else:
-        # for backwards compatibility
-        cmd = "/usr/local/planetlab/bin/NodeUpdate.py start noreboot"
-    utils.sysexec_chroot( SYSIMG_PATH, cmd, log )
+    if (vars['ONE_PARTITION']!='1'):
+        try:
+            cmd = "/usr/bin/env python /usr/share/NodeManager/conf_files.py --noscripts"
+            utils.sysexec_chroot( SYSIMG_PATH, cmd, log )
+        except IOError, e:
+            log.write("conf_files failed with \n %s" % e)
+
+        # update node packages
+        log.write( "Running node update.\n" )
+        if os.path.exists( SYSIMG_PATH + "/usr/bin/NodeUpdate.py" ):
+            cmd = "/usr/bin/NodeUpdate.py start noreboot"
+        else:
+            # for backwards compatibility
+            cmd = "/usr/local/planetlab/bin/NodeUpdate.py start noreboot"
+        utils.sysexec_chroot( SYSIMG_PATH, cmd, log )
 
     # Re-generate initrd right before kexec call
     # this is not required anymore on recent depls.
@@ -159,13 +161,21 @@ def Run( vars, log ):
         utils.sysexec( "cp %s/boot/initrd-boot%s /tmp/initrd" % (SYSIMG_PATH,option), log )
     else:
         # Use chroot to call rpm, b/c the bootimage&nodeimage rpm-versions may not work together
-        kversion = os.popen("chroot %s rpm -qa kernel | tail -1 | cut -c 8-" % SYSIMG_PATH).read().rstrip()
+        try:
+            kversion = os.popen("chroot %s rpm -qa kernel | tail -1 | cut -c 8-" % SYSIMG_PATH).read().rstrip()
+            major_version = int(kversion[0]) # Check if the string looks like a kernel version
+        except:
+            # Try a different method for non-rpm-based distributions
+            kversion = os.popen("ls -lrt %s/lib/modules | tail -1 | awk '{print $9;}'"%SYSIMG_PATH).read().rstrip()
+
         utils.sysexec( "cp %s/boot/vmlinuz-%s /tmp/kernel" % (SYSIMG_PATH,kversion), log )
         candidates=[]
         # f16/18: expect initramfs image here
         candidates.append ("/boot/initramfs-%s.img"%(kversion))
         # f20: uses a uid of some kind, e.g. /boot/543f88c129de443baaa65800cf3927ce/<kversion>/initrd
         candidates.append ("/boot/*/%s/initrd"%(kversion))
+        # Ubuntu:
+        candidates.append ("/boot/initrd.img-%s"%(kversion))
         def find_file_in_sysimg (candidates):
             import glob
             for pattern in candidates:
@@ -181,7 +191,9 @@ def Run( vars, log ):
     BootAPI.save(vars)
 
     log.write( "Unmounting disks.\n" )
-    utils.sysexec( "umount %s/vservers" % SYSIMG_PATH, log )
+    
+    if (vars['ONE_PARTITION']!='1'):
+        utils.sysexec( "umount %s/vservers" % SYSIMG_PATH, log )
     utils.sysexec( "umount %s/proc" % SYSIMG_PATH, log )
     utils.sysexec_noerr( "umount %s/dev" % SYSIMG_PATH, log )
     utils.sysexec_noerr( "umount %s/sys" % SYSIMG_PATH, log )
index f384239..58e3bf8 100644 (file)
@@ -109,23 +109,33 @@ def Run( vars, log ):
     # call getNodeFlavour and store in VARS['node_flavour']
     try:
         node_flavour = BootAPI.call_api_function(vars, "GetNodeFlavour", (vars['NODE_ID'], ) )
-        nodefamily = node_flavour['nodefamily']
-        extensions = node_flavour['extensions']
-        plain = node_flavour['plain']
     except:
-        exc_type, exc_value, exc_traceback = sys.exc_info()
-        lines=traceback.format_exception(exc_type,exc_value,exc_traceback)
-        for line in lines: log.write(line)
-        raise BootManagerException ("Could not call GetNodeFlavour - need PLCAPI-5.2")
+        log.write("GetNodeFlavour failed, not fatal if the node flavor is available in ``configuration''\n")
+        pass
     
-    # 'vs' or 'lxc'
-    vars['virt'] = node_flavour['virt']
-    # the basename for downloading nodeimage
-    vars['nodefamily'] = node_flavour['nodefamily']
-    # extensions to be applied on top of the base nodeimage
-    vars['extensions'] = node_flavour ['extensions']
-    # false if compressed image, true if not
-    vars['plain'] = node_flavour ['plain']
+    flavour_keys = [
+            'virt',# 'vs' or 'lxc'
+            'nodefamily',# the basename for downloading nodeimage
+            'extensions',# extensions to be applied on top of the base nodeimage
+            'plain'# false if compressed image, true if not
+            ]
+
+    # MyPLC 5.0 workaround
+    # make sure to define 'extensions' even if not yet set
+    if ('extensions' not in vars or vars['extensions']==''):
+        vars['extensions']=[]
+
+    for k in flavour_keys:
+        # Support MyPLC <5.2
+        if (not vars.has_key(k)):
+            try:
+                vars[k] = node_flavour[k]
+            except:
+                exc_type, exc_value, exc_traceback = sys.exc_info()
+                lines=traceback.format_exception(exc_type,exc_value,exc_traceback)
+                for line in lines: log.write(line)
+                raise BootManagerException ("Could not call GetNodeFlavour - need PLCAPI-5.2")
+
     log.write ("NodeFlavour as returned from PLC: %s\n"%node_flavour)
 
     return 1
index 7354893..26fd0d3 100644 (file)
@@ -81,16 +81,20 @@ def Run( vars, log ):
     utils.sysexec( "mount -t ext3 %s %s" % (PARTITIONS["root"],SYSIMG_PATH), log )
 
     fstype = 'ext3' if vars['virt']=='vs' else 'btrfs'
-    log.write( "mounting vserver partition in root file system (type %s)\n"%fstype )
-    utils.makedirs( SYSIMG_PATH + "/vservers" )
-    utils.sysexec( "mount -t %s %s %s/vservers" % \
-                       (fstype, PARTITIONS["vservers"], SYSIMG_PATH), log )
 
-    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 %s/vservers\n"%SYSIMG_PATH )
-        utils.sysexec_noerr( "btrfs quota enable %s/vservers" % SYSIMG_PATH )
+    one_partition = vars['ONE_PARTITION']=='1'
+
+    if (not one_partition):
+        log.write( "mounting vserver partition in root file system (type %s)\n"%fstype )
+        utils.makedirs( SYSIMG_PATH + "/vservers" )
+        utils.sysexec( "mount -t %s %s %s/vservers" % \
+                           (fstype, PARTITIONS["vservers"], SYSIMG_PATH), log )
+
+        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 %s/vservers\n"%SYSIMG_PATH )
+            utils.sysexec_noerr( "btrfs quota enable %s/vservers" % SYSIMG_PATH )
 
     vars['ROOT_MOUNTED']= 1
 
@@ -187,12 +191,14 @@ def Run( vars, log ):
         utils.makedirs(SYSIMG_PATH + "/mnt/cdrom")
         shutil.copytree("/usr/bootme", SYSIMG_PATH + "/mnt/cdrom/bootme")
 
-    # Import the GPG key into the RPM database so that RPMS can be verified
-    utils.makedirs(SYSIMG_PATH + "/etc/pki/rpm-gpg")
-    utils.sysexec("gpg --homedir=/root --export --armor" \
-                  " --no-default-keyring --keyring %s/usr/boot/pubring.gpg" \
-                  " >%s/etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab" % (SYSIMG_PATH, SYSIMG_PATH), log)
-    utils.sysexec_chroot(SYSIMG_PATH, "rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab", log)
+    # ONE_PARTITION => new distribution type
+    if (vars['ONE_PARTITION']!='1'):
+        # Import the GPG key into the RPM database so that RPMS can be verified
+        utils.makedirs(SYSIMG_PATH + "/etc/pki/rpm-gpg")
+        utils.sysexec("gpg --homedir=/root --export --armor" \
+                      " --no-default-keyring --keyring %s/usr/boot/pubring.gpg" \
+                      " >%s/etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab" % (SYSIMG_PATH, SYSIMG_PATH), log)
+        utils.sysexec_chroot(SYSIMG_PATH, "rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab", log)
 
     # keep a log on the installed hdd
     stamp=file(SYSIMG_PATH + "/bm-install.txt",'w')
index dc14016..65d87dd 100644 (file)
@@ -130,19 +130,22 @@ def Run( vars, log ):
     # create swap logical volume
     utils.sysexec( "lvcreate -L%s -nswap planetlab" % SWAP_SIZE, log )
 
-    # create root logical volume
-    utils.sysexec( "lvcreate -L%s -nroot planetlab" % ROOT_SIZE, log )
-
-    if vars['NODE_MODEL_OPTIONS'] & ModelOptions.RAWDISK and VSERVERS_SIZE != "-1":
-        utils.sysexec( "lvcreate -L%s -nvservers planetlab" % VSERVERS_SIZE, log )
+    # check if we want a separate partition for VMs
+    one_partition = vars['ONE_PARTITION']=='1'
+    if (one_partition):
         remaining_extents= get_remaining_extents_on_vg( vars, log )
-        utils.sysexec( "lvcreate -l%s -nrawdisk planetlab" % remaining_extents, log )
+        utils.sysexec( "lvcreate -l%s -nroot planetlab" % remaining_extents, log )
     else:
-        # create vservers logical volume with all remaining space
-        # first, we need to get the number of remaining extents we can use
-        remaining_extents= get_remaining_extents_on_vg( vars, log )
-        
-        utils.sysexec( "lvcreate -l%s -nvservers planetlab" % remaining_extents, log )
+        utils.sysexec( "lvcreate -L%s -nroot planetlab" % ROOT_SIZE, log )
+        if vars['NODE_MODEL_OPTIONS'] & ModelOptions.RAWDISK and VSERVERS_SIZE != "-1":
+            utils.sysexec( "lvcreate -L%s -nvservers planetlab" % VSERVERS_SIZE, log )
+            remaining_extents= get_remaining_extents_on_vg( vars, log )
+            utils.sysexec( "lvcreate -l%s -nrawdisk planetlab" % remaining_extents, log )
+        else:
+            # create vservers logical volume with all remaining space
+            # first, we need to get the number of remaining extents we can use
+            remaining_extents= get_remaining_extents_on_vg( vars, log )
+            utils.sysexec( "lvcreate -l%s -nvservers planetlab" % remaining_extents, log )
 
     # activate volume group (should already be active)
     #utils.sysexec( TEMP_PATH + "vgchange -ay planetlab", log )
@@ -179,7 +182,7 @@ def Run( vars, log ):
         utils.sysexec( "mkfs.ext2 -q %s -m %d -j %s" % (option,rbp,devname), log )
         # disable time/count based filesystems checks
         utils.sysexec_noerr( "tune2fs -c -1 -i 0 %s" % devname, log)
-    else:
+    elif (not one_partition):
         log.write("formatting %s btrfs partition (%s).\n" % (fs,devname))
         # early BootCD's seem to come with a version of mkfs.btrfs that does not support -f
         # let's check for that before invoking it
index 563a8d4..a702937 100644 (file)
@@ -82,12 +82,13 @@ def Run( vars, log ):
                  PARTITIONS["mapper-swap"] )
     fstab.write( "%s           /           ext3      defaults  1 1\n" % \
                  PARTITIONS["mapper-root"] )
-    if vars['virt'] == 'vs':
-        fstab.write( "%s           /vservers   ext3      tagxid,defaults  1 2\n" % \
-                         PARTITIONS["mapper-vservers"] )
-    else:
-        fstab.write( "%s           /vservers   btrfs     defaults  1 2\n" % \
-                         PARTITIONS["mapper-vservers"] )
+    if (vars['ONE_PARTITION']!='1'):
+        if vars['virt'] == 'vs':
+            fstab.write( "%s           /vservers   ext3      tagxid,defaults  1 2\n" % \
+                             PARTITIONS["mapper-vservers"] )
+        else:
+            fstab.write( "%s           /vservers   btrfs     defaults  1 2\n" % \
+                             PARTITIONS["mapper-vservers"] )
     fstab.write( "none         /proc       proc      defaults  0 0\n" )
     fstab.write( "none         /dev/shm    tmpfs     defaults  0 0\n" )
     fstab.write( "none         /dev/pts    devpts    defaults  0 0\n" )
@@ -100,15 +101,16 @@ def Run( vars, log ):
     issue.write( "http://www.planet-lab.org\n\n" )
     issue.close()
 
-    log.write( "Setting up authentication (non-ssh)\n" )
-    utils.sysexec_chroot( SYSIMG_PATH, "authconfig --nostart --kickstart --enablemd5 " \
-                   "--enableshadow", log )
-    utils.sysexec( "sed -e 's/^root\:\:/root\:*\:/g' " \
-                   "%s/etc/shadow > %s/etc/shadow.new" % \
-                   (SYSIMG_PATH,SYSIMG_PATH), log )
-    utils.sysexec_chroot( SYSIMG_PATH, "mv " \
-                   "/etc/shadow.new /etc/shadow", log )
-    utils.sysexec_chroot( SYSIMG_PATH, "chmod 400 /etc/shadow", log )
+    if (vars['ONE_PARTITION']!='1'):
+        log.write( "Setting up authentication (non-ssh)\n" )
+        utils.sysexec_chroot( SYSIMG_PATH, "authconfig --nostart --kickstart --enablemd5 " \
+                       "--enableshadow", log )
+        utils.sysexec( "sed -e 's/^root\:\:/root\:*\:/g' " \
+                       "%s/etc/shadow > %s/etc/shadow.new" % \
+                       (SYSIMG_PATH,SYSIMG_PATH), log )
+        utils.sysexec_chroot( SYSIMG_PATH, "mv " \
+                       "/etc/shadow.new /etc/shadow", log )
+        utils.sysexec_chroot( SYSIMG_PATH, "chmod 400 /etc/shadow", log )
 
     # if we are setup with dhcp, copy the current /etc/resolv.conf into
     # the system image so we can run programs inside that need network access
index 2f038ec..4ae1ff8 100644 (file)
@@ -88,6 +88,7 @@ def Run( vars, log ):
             filesystems_tocheck = ['root', 'vservers']
         else:
             filesystems_tocheck = ['root']
+
         for filesystem in filesystems_tocheck:
             try:
                 # first run fsck to prevent fs corruption from hanging mount...
@@ -124,17 +125,21 @@ def Run( vars, log ):
             log.write( "BootManagerException during mount of /proc: %s\n" % str(e) )
             return -2
 
-        try:
-            VSERVERS_PATH = "%s/vservers" % SYSIMG_PATH
-            utils.makedirs(VSERVERS_PATH)
-            log.write( "mounting vservers partition in root file system\n" )
-            if vars['virt']=='vs':
-                utils.sysexec("mount -t ext3 %s %s" % (PARTITIONS["vservers"], VSERVERS_PATH), log)
-            else:
-                utils.sysexec("mount -t btrfs %s %s" % (PARTITIONS["vservers"], VSERVERS_PATH), log)
-        except BootManagerException, e:
-            log.write( "BootManagerException during mount of /vservers: %s\n" % str(e) )
-            return -2
+
+        one_partition = vars['ONE_PARTITION']=='1'
+
+        if (not one_partition):
+            try:
+                VSERVERS_PATH = "%s/vservers" % SYSIMG_PATH
+                utils.makedirs(VSERVERS_PATH)
+                log.write( "mounting vservers partition in root file system\n" )
+                if vars['virt']=='vs':
+                    utils.sysexec("mount -t ext3 %s %s" % (PARTITIONS["vservers"], VSERVERS_PATH), log)
+                else:
+                    utils.sysexec("mount -t btrfs %s %s" % (PARTITIONS["vservers"], VSERVERS_PATH), log)
+            except BootManagerException, e:
+                log.write( "BootManagerException during mount of /vservers: %s\n" % str(e) )
+                return -2
 
         ROOT_MOUNTED= 1
         vars['ROOT_MOUNTED']= 1
@@ -146,8 +151,12 @@ def Run( vars, log ):
         if vars['virt'] == 'vs':
             os.stat("%s/boot/kernel-boot" % SYSIMG_PATH)
         else:
-            kversion = os.popen("chroot %s rpm -qa kernel | tail -1 | cut -c 8-" % SYSIMG_PATH).read().rstrip()
-            os.stat("%s/boot/vmlinuz-%s" % (SYSIMG_PATH,kversion))
+            try:
+                kversion = os.popen("chroot %s rpm -qa kernel | tail -1 | cut -c 8-" % SYSIMG_PATH).read().rstrip()
+                os.stat("%s/boot/vmlinuz-%s" % (SYSIMG_PATH,kversion))
+                major_version = int(kversion[0]) # Check if the string looks like a kernel version
+            except:
+                kversion = os.popen("ls -lrt %s/lib/modules | tail -1 | awk '{print $9;}'"%SYSIMG_PATH).read().rstrip()
     except OSError, e:            
         log.write( "Couldn't locate base kernel (you might be using the stock kernel).\n")
         return -3
index bfef9bc..5042299 100644 (file)
@@ -35,4 +35,5 @@ __all__ = ["ReadNodeConfiguration",
            "InstallWriteConfig",
            "MakeInitrd",
            "WriteNetworkConfig",
-           "WriteModprobeConfig"]
+           "WriteModprobeConfig",
+           "AnsibleHook"]