summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rtslib/root.py5
-rw-r--r--rtslib/utils.py31
2 files changed, 35 insertions, 1 deletions
diff --git a/rtslib/root.py b/rtslib/root.py
index d558445..13d7f2a 100644
--- a/rtslib/root.py
+++ b/rtslib/root.py
@@ -28,7 +28,7 @@ from fabric import FabricModule
from tcm import (StorageObject, FileIOStorageObject, BlockStorageObject,
PSCSIStorageObject, RDMCPStorageObject)
from utils import RTSLibError, RTSLibBrokenLink, modprobe, mount_configfs
-from utils import dict_remove, set_attributes
+from utils import dict_remove, set_attributes, locked
storageobjects = dict(
fileio=FileIOStorageObject,
@@ -126,6 +126,7 @@ class RTSRoot(CFSNode):
# RTSRoot public stuff
+ @locked
def dump(self):
'''
Returns a dict representing the complete state of the target
@@ -140,6 +141,7 @@ class RTSRoot(CFSNode):
if f.discovery_enable_auth]
return d
+ @locked
def clear_existing(self, confirm=False):
'''
Remove entire current configuration.
@@ -155,6 +157,7 @@ class RTSRoot(CFSNode):
for so in self.storage_objects:
so.delete()
+ @locked
def restore(self, config, clear_existing=False, abort_on_error=False):
'''
Takes a dict generated by dump() and reconfigures the target to match.
diff --git a/rtslib/utils.py b/rtslib/utils.py
index 8f86d6d..1f36946 100644
--- a/rtslib/utils.py
+++ b/rtslib/utils.py
@@ -23,6 +23,8 @@ import stat
import uuid
import socket
import subprocess
+import fcntl
+import time
from contextlib import contextmanager
class RTSLibError(Exception):
@@ -391,6 +393,35 @@ def ignored(*exceptions):
except exceptions:
pass
+@contextmanager
+def file_lock(lock_file, timeout=10):
+ '''
+ A context manager for locking a file, with timeout.
+ '''
+ with open(lock_file, "w") as f:
+ for x in xrange(timeout):
+ try:
+ fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ except IOError:
+ time.sleep(1)
+ else:
+ try:
+ yield
+ finally:
+ fcntl.lockf(f, fcntl.LOCK_UN)
+ break
+ else:
+ raise IOError("Acquiring lock timed out after %d seconds" % timeout)
+
+def locked(func):
+ '''
+ A decorator that enforces mutual exclusion between methods using it.
+ '''
+ def inner(*args, **kwargs):
+ with file_lock("/var/run/target.lock"):
+ return func(*args, **kwargs)
+ return inner
+
#
# These two functions are meant to be used with functools.partial and
# properties.