svn merge -c 9766 https://svn.planet-lab.org/svn/BootManager/branches/3.2 into trunk
authorStephen Soltesz <soltesz@cs.princeton.edu>
Wed, 22 Jul 2009 23:02:31 +0000 (23:02 +0000)
committerStephen Soltesz <soltesz@cs.princeton.edu>
Wed, 22 Jul 2009 23:02:31 +0000 (23:02 +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 7973393..f97ef29 100644 (file)
@@ -40,6 +40,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..e7f6953
--- /dev/null
@@ -0,0 +1,157 @@
+<<<<<<< .working
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <glob.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define INIT(x)        real_ ## x = dlsym(RTLD_NEXT, #x); \
+               if (!real_ ## x) { \
+                 fprintf(stderr, "Would the real " #x " please stand up? %s\n", dlerror()); \
+                 exit(1); \
+               }
+
+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);
+}
+
+DIR *__opendir(const char *name)
+{
+  return opendir(name);
+}
+
+static int (*real_glob)(const char *pattern, int flags,
+         int (*errfunc) (const char *epath, int eerrno),
+         glob_t *pglob);
+
+int glob(const char *pattern, int flags,
+         int (*errfunc) (const char *epath, int eerrno),
+         glob_t *pglob)
+{
+  if (!(flags & GLOB_ALTDIRFUNC)) {
+    pglob->gl_closedir = closedir;
+    pglob->gl_readdir = readdir;
+    pglob->gl_opendir = opendir;
+    pglob->gl_lstat = lstat;
+    pglob->gl_stat = stat;
+    flags |= GLOB_ALTDIRFUNC;
+  }
+  if (!real_glob) {
+    INIT(glob)
+  }
+  return real_glob(pattern, flags, errfunc, pglob);
+}
+
+#define PWD_LOCKFILE "/etc/.pwd.lock"
+
+static int lock_fd = -1;
+
+/* FIXME: Ignores multi-thread issues.
+ *        Doesn't wait for the file to become lockable
+ */
+int lckpwdf(void)
+{
+  struct flock fl = { 0 };
+
+  /* This process already holds the lock */
+  if (lock_fd != -1)
+    return -1;
+
+  lock_fd = open(PWD_LOCKFILE, O_WRONLY|O_CREAT, 0600);
+  if (lock_fd == -1)
+    return -1;
+
+  if (fcntl(lock_fd, F_SETFD, fcntl(lock_fd, F_GETFD, 0) | FD_CLOEXEC) == -1) {
+    close(lock_fd);
+    return -1;
+  }
+
+  fl.l_type = F_WRLCK;
+  fl.l_whence = SEEK_SET;
+  return fcntl(lock_fd, F_SETLKW, &fl);
+}
+
+int ulckpwdf(void)
+{
+  int result;
+
+  if (lock_fd == -1)
+    return -1;
+
+  result = close(lock_fd);
+  lock_fd = -1;
+  return result;
+}
+
+static (*real_open)(const char *name, int flags, ...);
+int open(const char *name, int flags, ...)
+{
+  mode_t mode;
+  if (flags & O_CREAT) {
+    va_list va;
+    va_start(va, flags);
+    mode = va_arg(va, mode_t);
+    va_end(va);
+  }
+  if (!real_open) {
+    INIT(open)
+  }
+  return real_open(name, flags, mode);
+}
+
+static FILE *(*real_fopen)(const char *name, const char *flags);
+FILE *fopen(const char *name, const char *flags)
+{
+  char *str, *ptr = strchr(flags, 'e');
+  FILE *ret;
+  if (ptr) {
+    str = strdup(flags);
+    ptr = (str + (ptr - flags));
+    strcpy(ptr, ptr + 1);
+  }
+  else
+    str = flags;
+  if (!real_fopen) {
+    INIT(fopen)
+  }
+  ret = real_fopen(name, str);
+  if (ptr)
+    free(str);
+  return ret;
+}
+
+static void _init() __attribute__((constructor));
+static void _init()
+{
+  INIT(glob)
+  INIT(open)
+  INIT(fopen)
+}
+=======
+#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);
+}
+>>>>>>> .merge-right.r9766
index 6d1e39e..f246162 100644 (file)
@@ -110,18 +110,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 )
@@ -155,7 +155,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 44489e8..d53351c 100644 (file)
@@ -136,7 +136,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 b9862ef..72cfe16 100644 (file)
@@ -229,8 +229,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")
 
     # the yum config has changed entirely; 
     # in addition yum installs have more or less never worked - let's forget about this
index 9eb9900..c609818 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 5f9dd61..ccf1d12 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 e272fdb..29b4e4c 100644 (file)
@@ -69,11 +69,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) ):
@@ -103,14 +103,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
@@ -134,22 +134,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 7fa7178..3abbd73 100644 (file)
@@ -71,12 +71,12 @@ def Run( vars, log ):
     # hack for CentOS 5.3
     bypassRaidIfNeeded(SYSIMG_PATH)
     if kernelHasMkinitrd() == 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 407216b..ebd5430 100644 (file)
@@ -149,6 +149,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