release
[mirror/userdir-ldap.git] / ud-generate
index 5529d93..6116cd0 100755 (executable)
@@ -6,7 +6,7 @@
 #   Copyright (c) 2003-2004  James Troup <troup@debian.org>
 #   Copyright (c) 2004-2005,7  Joey Schulze <joey@infodrom.org>
 #   Copyright (c) 2001-2007  Ryan Murray <rmurray@debian.org>
-#   Copyright (c) 2008,2009,2010 Peter Palfrader <peter@palfrader.org>
+#   Copyright (c) 2008,2009,2010,2011 Peter Palfrader <peter@palfrader.org>
 #   Copyright (c) 2008 Andreas Barth <aba@not.so.argh.org>
 #   Copyright (c) 2008 Mark Hymers <mhy@debian.org>
 #   Copyright (c) 2008 Luk Claes <luk@debian.org>
@@ -29,6 +29,7 @@
 #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 import string, re, time, ldap, getopt, sys, os, pwd, posix, socket, base64, sha, shutil, errno, tarfile, grp
+import lockfile
 from userdir_ldap import *
 from userdir_exceptions import *
 import UDLdap
@@ -88,6 +89,27 @@ def safe_rmtree(dir):
       else:
          raise e
 
+def get_lock(fn, wait=5*60, max_age=3600*6):
+   try:
+      stat = os.stat(fn)
+      if stat[ST_MTIME] < time.time() - max_age:
+         sys.stderr.write("Removing stale lock %s"%(fn))
+         os.unlink(fn)
+   except OSError, error:
+      if error.errno == errno.ENOENT:
+         pass
+      else:
+         raise
+
+   lock = lockfile.FileLock(fn)
+   try:
+      lock.acquire(timeout=wait)
+   except lockfile.LockTimeout:
+      return None
+
+   return lock
+
+
 def Sanitize(Str):
    return Str.translate(string.maketrans("\n\r\t", "$$$"))
 
@@ -959,9 +981,18 @@ def GenHosts(host_attrs, File):
       raise
    Done(File, F, None)
 
+def replaceTree(src, dst_basedir):
+   bn = os.path.basename(src)
+   dst = os.path.join(dst_basedir, bn)
+   safe_rmtree(dst)
+   shutil.copytree(src, dst)
+
 def GenKeyrings(OutDir):
    for k in Keyrings:
-      shutil.copy(k, OutDir)
+      if os.path.isdir(k):
+         replaceTree(k, OutDir)
+      else:
+         shutil.copy(k, OutDir)
 
 
 def get_accounts(ldap_conn):
@@ -1142,11 +1173,21 @@ def generate_host(host, global_dir, accounts, ssh_files):
 
    if 'KEYRING' in ExtraList:
       for k in Keyrings:
-        DoLink(global_dir, OutDir, os.path.basename(k))
+         bn = os.path.basename(k)
+         if os.path.isdir(k):
+            src = os.path.join(global_dir, bn)
+            replaceTree(src, OutDir)
+         else:
+            DoLink(global_dir, OutDir, bn)
    else:
       for k in Keyrings:
          try:
-            posix.remove(OutDir + os.path.basename(k))
+            bn = os.path.basename(k)
+            target = os.path.join(OutDir, bn)
+            if os.path.isdir(target):
+               safe_rmtree(dst)
+            else:
+               posix.remove(target)
          except:
             pass
 
@@ -1171,7 +1212,17 @@ for x in attrs:
 if 'UD_GENERATEDIR' in os.environ:
    GenerateDir = os.environ['UD_GENERATEDIR']
 
-generate_all(GenerateDir, l)
+try:
+   lock = get_lock( os.path.join(GenerateDir, 'ud-generate.lock') )
+   if lock is None:
+      sys.stderr.write("Could not acquire lock %s.\n"%(fn))
+      sys.exit(1)
+
+   generate_all(GenerateDir, l)
+
+finally:
+   if not lock is None:
+      lock.release()
 
 # vim:set et:
 # vim:set ts=3: