Add ugly hack to workaround O_CLOEXEC vs. O_ATOMICLOOKUP.
authorDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Tue, 1 Jul 2008 16:17:42 +0000 (16:17 +0000)
committerDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Tue, 1 Jul 2008 16:17:42 +0000 (16:17 +0000)
bootmanager.spec
source/libc-opendir-hack.c [new file with mode: 0644]
source/steps/ChainBootNode.py
source/steps/CheckForNewDisks.py
source/steps/InstallBootstrapFS.py
source/steps/InstallInit.py
source/steps/InstallUninitHardware.py
source/steps/InstallWriteConfig.py
source/steps/MakeInitrd.py
source/utils.py

index d77e1da..9ced617 100644 (file)
@@ -36,6 +36,7 @@ nodes.
 %setup -q
 
 %build
+gcc -shared -fPIC -Os -o source/libc-opendir-hack.so source/libc-opendir-hack.c
 
 %install
 rm -rf $RPM_BUILD_ROOT
diff --git a/source/libc-opendir-hack.c b/source/libc-opendir-hack.c
new file mode 100644 (file)
index 0000000..95786ef
--- /dev/null
@@ -0,0 +1,16 @@
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#define NAME   "O_CLOEXEC-vs-O_ATOMICLOOKUP"
+
+DIR *opendir(const char *name)
+{
+  int fd = open(name, O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE);
+  if (fd == -1)
+    return NULL;
+  return fdopendir(fd);
+}
index 10f068e..6d9d5c6 100644 (file)
@@ -120,18 +120,18 @@ def Run( vars, log ):
     log.write( "Updating configuration files.\n" )
     try:
         cmd = "/etc/init.d/conf_files start --noscripts"
-        utils.sysexec( "chroot %s %s" % (SYSIMG_PATH, cmd), log )
+        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 = "chroot %s /usr/bin/NodeUpdate.py start noreboot" % SYSIMG_PATH
+        cmd = "/usr/bin/NodeUpdate.py start noreboot"
     else:
         # for backwards compatibility
-        cmd = "chroot %s /usr/local/planetlab/bin/NodeUpdate.py start noreboot" % SYSIMG_PATH
-    utils.sysexec( cmd, log )
+        cmd = "/usr/local/planetlab/bin/NodeUpdate.py start noreboot"
+    utils.sysexec_chroot( SYSIMG_PATH, cmd, log )
 
     # the following step should be done by NM
     UpdateNodeConfiguration.Run( vars, log )
@@ -165,7 +165,7 @@ def Run( vars, log ):
     try:
         # backwards compat, though, we should never hit this case post PL 3.2
         os.stat("%s/rcfs/taskclass"%SYSIMG_PATH)
-        utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log )
+        utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log )
     except OSError, e:
         pass
 
index e90e459..a952b09 100644 (file)
@@ -138,7 +138,7 @@ def Run( vars, log ):
         try:
             # backwards compat, though, we should never hit this case post PL 3.2
             os.stat("%s/rcfs/taskclass"%SYSIMG_PATH)
-            utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log )
+            utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log )
         except OSError, e:
             pass
 
index e04f930..a8f5174 100644 (file)
@@ -200,8 +200,7 @@ def Run( vars, log ):
     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))
-    utils.sysexec("chroot %s rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab" % \
-                  SYSIMG_PATH)
+    utils.sysexec_chroot(SYSIMG_PATH, "rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab")
 
     # yum-based extensions:
     # before we can use yum, yum.conf needs to get installed
@@ -229,7 +228,7 @@ def Run( vars, log ):
             yum_command="yum groupinstall extension%s"%extension
             utils.breakpoint ("before chroot %s %s"%(SYSIMG_PATH,yum_command))
             log.write("Attempting to install extension %s through yum\n"%extension)
-            utils.sysexec_noerr("chroot %s %s" % (SYSIMG_PATH,yum_command))
+            utils.sysexec_chroot_noerr(SYSIMG_PATH, "%s" % (yum_command))
             # xxx how to check that this completed correctly ?
         # let's cleanup
         utils.sysexec_noerr( "umount %s/proc" % SYSIMG_PATH, log )
index 2e6b66b..c0980c1 100644 (file)
@@ -60,7 +60,7 @@ def Run( vars, log ):
     try:
         # backwards compat, though, we should never hit this case post PL 3.2
         os.stat("%s/rcfs/taskclass"%SYSIMG_PATH)
-        utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log )
+        utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log )
     except OSError, e:
         pass
 
index df99515..0b01209 100644 (file)
@@ -66,7 +66,7 @@ def Run( vars, log ):
     try:
         # backwards compat, though, we should never hit this case post PL 3.2
         os.stat("%s/rcfs/taskclass"%SYSIMG_PATH)
-        utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log )
+        utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log )
     except OSError, e:
         pass
             
index 60a53c3..f7afb52 100644 (file)
@@ -75,11 +75,11 @@ def Run( vars, log ):
         raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var
 
     log.write( "Setting local time to UTC\n" )
-    utils.sysexec( "chroot %s ln -sf /usr/share/zoneinfo/UTC /etc/localtime" % \
-                   SYSIMG_PATH, log )
+    utils.sysexec_chroot( SYSIMG_PATH,
+        "ln -sf /usr/share/zoneinfo/UTC /etc/localtime", log )
 
     log.write( "Enabling ntp at boot\n" )
-    utils.sysexec( "chroot %s chkconfig ntpd on" % SYSIMG_PATH, log )
+    utils.sysexec_chroot( SYSIMG_PATH, "chkconfig ntpd on", log )
 
     log.write( "Creating system directory %s\n" % PLCONF_DIR )
     if not utils.makedirs( "%s/%s" % (SYSIMG_PATH,PLCONF_DIR) ):
@@ -109,14 +109,14 @@ def Run( vars, log ):
     issue.close()
 
     log.write( "Setting up authentication (non-ssh)\n" )
-    utils.sysexec( "chroot %s authconfig --nostart --kickstart --enablemd5 " \
-                   "--enableshadow" % SYSIMG_PATH, log )
+    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 %s mv " \
-                   "/etc/shadow.new /etc/shadow" % SYSIMG_PATH, log )
-    utils.sysexec( "chroot %s chmod 400 /etc/shadow" % 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
@@ -140,22 +140,22 @@ def Run( vars, log ):
 
     log.write( "Generating SSH1 RSA host key:\n" )
     key_file= "/etc/ssh/ssh_host_key"
-    utils.sysexec( "chroot %s %s -q -t rsa1 -f %s -C '' -N ''" %
-                   (SYSIMG_PATH,key_gen_prog,key_file), log )
+    utils.sysexec_chroot( SYSIMG_PATH, "%s -q -t rsa1 -f %s -C '' -N ''" %
+                   (key_gen_prog,key_file), log )
     utils.sysexec( "chmod 600 %s/%s" % (SYSIMG_PATH,key_file), log )
     utils.sysexec( "chmod 644 %s/%s.pub" % (SYSIMG_PATH,key_file), log )
     
     log.write( "Generating SSH2 RSA host key:\n" )
     key_file= "/etc/ssh/ssh_host_rsa_key"
-    utils.sysexec( "chroot %s %s -q -t rsa -f %s -C '' -N ''" %
-                   (SYSIMG_PATH,key_gen_prog,key_file), log )
+    utils.sysexec_chroot( SYSIMG_PATH, "%s -q -t rsa -f %s -C '' -N ''" %
+                   (key_gen_prog,key_file), log )
     utils.sysexec( "chmod 600 %s/%s" % (SYSIMG_PATH,key_file), log )
     utils.sysexec( "chmod 644 %s/%s.pub" % (SYSIMG_PATH,key_file), log )
     
     log.write( "Generating SSH2 DSA host key:\n" )
     key_file= "/etc/ssh/ssh_host_dsa_key"
-    utils.sysexec( "chroot %s %s -q -t dsa -f %s -C '' -N ''" %
-                   (SYSIMG_PATH,key_gen_prog,key_file), log )
+    utils.sysexec_chroot( SYSIMG_PATH, "%s -q -t dsa -f %s -C '' -N ''" %
+                   (key_gen_prog,key_file), log )
     utils.sysexec( "chmod 600 %s/%s" % (SYSIMG_PATH,key_file), log )
     utils.sysexec( "chmod 644 %s/%s.pub" % (SYSIMG_PATH,key_file), log )
 
index f742859..b5abb2c 100644 (file)
@@ -44,12 +44,12 @@ def Run( vars, log ):
     initrd, kernel_version= systeminfo.getKernelVersion(vars,log)
     utils.removefile( "%s/boot/%s" % (SYSIMG_PATH, initrd) )
     if checkKern() == True:
-        utils.sysexec( "chroot %s mkinitrd -v /boot/initrd-%s.img %s" % \
-                   (SYSIMG_PATH, kernel_version, kernel_version), log )
+        utils.sysexec_chroot( SYSIMG_PATH, "mkinitrd -v /boot/initrd-%s.img %s" % \
+                   (kernel_version, kernel_version), log )
     else:
         shutil.copy("./mkinitrd.sh","%s/tmp/mkinitrd.sh" % SYSIMG_PATH)
         os.chmod("%s/tmp/mkinitrd.sh" % SYSIMG_PATH, 755)
-        utils.sysexec( "chroot %s /tmp/mkinitrd.sh %s" % (SYSIMG_PATH, kernel_version))
+        utils.sysexec_chroot( SYSIMG_PATH, "/tmp/mkinitrd.sh %s" % (kernel_version))
 
     utils.sysexec_noerr("umount %s/sys" % SYSIMG_PATH)
     utils.sysexec_noerr("umount %s/dev" % SYSIMG_PATH)
index 35496ed..5c75606 100644 (file)
@@ -93,6 +93,34 @@ def sysexec( cmd, log= None ):
     return 1
 
 
+def sysexec_chroot( path, cmd, log= None ):
+    """
+    same as sysexec, but inside a chroot
+    """
+    preload = ""
+    release = os.uname()[2]
+    # 2.6.12 kernels need this
+    if release[:5] == "2.6.1":
+        library = "%s/lib/libc-opendir-hack.so" % path
+        if not os.path.exists(library):
+            shutil.copy("./libc-opendir-hack.so", library)
+        preload = "/bin/env LD_PRELOAD=/lib/libc-opendir-hack.so"
+    sysexec("chroot %s %s %s" % (path, preload, cmd), log)
+
+
+def sysexec_chroot_noerr( path, cmd, log= None ):
+    """
+    same as sysexec_chroot, but capture boot manager exceptions
+    """
+    try:
+        rc= 0
+        rc= syexec_chroot( cmd, log )
+    except BootManagerException, e:
+        pass
+
+    return rc
+
+
 def sysexec_noerr( cmd, log= None ):
     """
     same as sysexec, but capture boot manager exceptions