add lockfile support for mic/chroot.py module
authorGui Chen <gui.chen@intel.com>
Fri, 9 Aug 2013 03:58:40 +0000 (23:58 -0400)
committerGui Chen <gui.chen@intel.com>
Tue, 13 Aug 2013 09:23:52 +0000 (05:23 -0400)
a simple lockfile implementation is added,
and it is supposed to provide an exclusive
locking in the chroot dir

Signed-off-by: Gui Chen <gui.chen@intel.com>
mic/chroot.py
mic/utils/lock.py [new file with mode: 0644]

index 20ae215..8792cad 100644 (file)
@@ -23,15 +23,14 @@ import subprocess
 
 from mic import msger
 from mic.conf import configmgr
-from mic.utils import misc, errors, runner, fs_related
+from mic.utils import misc, errors, runner, fs_related, lock
 
 #####################################################################
 ### GLOBAL CONSTANTS
 #####################################################################
 
 chroot_bindmounts = None
-chroot_lockfd = -1
-chroot_lock = ""
+chroot_lock = None
 BIND_MOUNTS = (
                 "/proc",
                 "/proc/sys/fs/binfmt_misc",
@@ -142,6 +141,13 @@ def setup_mtab(chrootdir):
         shutil.copyfile(mtab, dstmtab)
 
 def setup_chrootenv(chrootdir, bindmounts = None):
+    global chroot_lock
+
+    # acquire the lock
+    if not chroot_lock:
+        lockpath = os.path.join(chrootdir, '.chroot.lock')
+        chroot_lock = lock.SimpleLockfile(lockpath)
+    chroot_lock.acquire()
     # bind mounting
     bind_mount(get_bindmounts(chrootdir, bindmounts))
     # setup resolv.conf
@@ -207,8 +213,6 @@ def cleanup_mounts(chrootdir):
                 msger.warning("%s is not directory or is not empty" % point)
 
 def cleanup_chrootenv(chrootdir, bindmounts=None, globalmounts=()):
-    # unlock
-    chroot_lockfd.close()
     # kill processes
     kill_proc_inchroot(chrootdir)
     # clean mtab
@@ -219,6 +223,8 @@ def cleanup_chrootenv(chrootdir, bindmounts=None, globalmounts=()):
     bind_unmount(get_bindmounts(chrootdir, bindmounts))
     # clean up mounts
     cleanup_mounts(chrootdir)
+    # release the lock
+    chroot_lock.release()
 
     return None
 
diff --git a/mic/utils/lock.py b/mic/utils/lock.py
new file mode 100644 (file)
index 0000000..0bd14d8
--- /dev/null
@@ -0,0 +1,50 @@
+# Copyright (c) 2011 Intel, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or any later version.
+
+import os
+import errno
+
+class LockfileError(Exception):
+    """ Lockfile Exception"""
+    pass
+
+class SimpleLockfile(object):
+    """ Simple implementation of lockfile """
+    def __init__(self, fpath):
+        self.fpath = fpath
+        self.lockf = None
+
+    def acquire(self):
+        """ acquire the lock """
+        try:
+            self.lockf = os.open(self.fpath,
+                                 os.O_CREAT | os.O_EXCL | os.O_WRONLY)
+        except OSError as err:
+            if err.errno == errno.EEXIST:
+                raise LockfileError("File %s is locked already" % self.fpath)
+            raise
+
+    def release(self):
+        """ release the lock """
+        try:
+            # FIXME: open file and close it immediately
+            os.close(self.lockf)
+        except IOError as err:
+            if err.errno != errno.EBADF:
+                raise LockfileError("Failed to release file: %s" % self.fpath)
+        try:
+            os.remove(self.fpath)
+        except OSError as err:
+            if err.errno != errno.ENOENT:
+                raise LockfileError("Failed to release file: %s" % self.fpath)
+
+    def __enter__(self):
+        self.acquire()
+        return self
+
+    def __exit__(self, *args):
+        self.release()
+