summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Washenberger <mark.washenberger@rackspace.com>2011-03-09 16:32:06 -0500
committerMark Washenberger <mark.washenberger@rackspace.com>2011-03-09 16:32:06 -0500
commit95d25ba3f4cd3345355922018295f3789d5ddb7c (patch)
tree83c37b89d96150fd7d7bc04459b5e3b62986f1ad
parent82c4d6309909d6508df0944683ce4d3d7341de10 (diff)
parent5662a822a013bd0d159c15b990231c4d1f12797f (diff)
downloadnova-95d25ba3f4cd3345355922018295f3789d5ddb7c.tar.gz
nova-95d25ba3f4cd3345355922018295f3789d5ddb7c.tar.xz
nova-95d25ba3f4cd3345355922018295f3789d5ddb7c.zip
merge lp:nova and resolve conflicts
-rw-r--r--nova/flags.py2
-rw-r--r--nova/tests/test_misc.py48
-rw-r--r--nova/utils.py20
3 files changed, 67 insertions, 3 deletions
diff --git a/nova/flags.py b/nova/flags.py
index 8cf199b2f..213d4d4e1 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -321,6 +321,8 @@ DEFINE_integer('auth_token_ttl', 3600, 'Seconds for auth tokens to linger')
DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'),
"Top-level directory for maintaining nova's state")
+DEFINE_string('lock_path', os.path.join(os.path.dirname(__file__), '../'),
+ "Directory for lock files")
DEFINE_string('logdir', None, 'output to a per-service log file in named '
'directory')
diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py
index e6da6112a..a658e4978 100644
--- a/nova/tests/test_misc.py
+++ b/nova/tests/test_misc.py
@@ -14,10 +14,12 @@
# License for the specific language governing permissions and limitations
# under the License.
+import errno
import os
+import select
from nova import test
-from nova.utils import parse_mailmap, str_dict_replace
+from nova.utils import parse_mailmap, str_dict_replace, synchronized
class ProjectTestCase(test.TestCase):
@@ -55,3 +57,47 @@ class ProjectTestCase(test.TestCase):
'%r not listed in Authors' % missing)
finally:
tree.unlock()
+
+
+class LockTestCase(test.TestCase):
+ def test_synchronized_wrapped_function_metadata(self):
+ @synchronized('whatever')
+ def foo():
+ """Bar"""
+ pass
+ self.assertEquals(foo.__doc__, 'Bar', "Wrapped function's docstring "
+ "got lost")
+ self.assertEquals(foo.__name__, 'foo', "Wrapped function's name "
+ "got mangled")
+
+ def test_synchronized(self):
+ rpipe1, wpipe1 = os.pipe()
+ rpipe2, wpipe2 = os.pipe()
+
+ @synchronized('testlock')
+ def f(rpipe, wpipe):
+ try:
+ os.write(wpipe, "foo")
+ except OSError, e:
+ self.assertEquals(e.errno, errno.EPIPE)
+ return
+
+ rfds, _, __ = select.select([rpipe], [], [], 1)
+ self.assertEquals(len(rfds), 0, "The other process, which was"
+ " supposed to be locked, "
+ "wrote on its end of the "
+ "pipe")
+ os.close(rpipe)
+
+ pid = os.fork()
+ if pid > 0:
+ os.close(wpipe1)
+ os.close(rpipe2)
+
+ f(rpipe1, wpipe2)
+ else:
+ os.close(rpipe1)
+ os.close(wpipe2)
+
+ f(rpipe2, wpipe1)
+ os._exit(0)
diff --git a/nova/utils.py b/nova/utils.py
index 02b71900c..3007bf19d 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -23,10 +23,14 @@ System-level utilities and helper functions.
import base64
import datetime
+import functools
import inspect
import json
+import lockfile
+import netaddr
import os
import random
+import re
import socket
import string
import struct
@@ -34,8 +38,6 @@ import sys
import time
import types
from xml.sax import saxutils
-import re
-import netaddr
from eventlet import event
from eventlet import greenthread
@@ -43,11 +45,13 @@ from eventlet.green import subprocess
from nova import exception
from nova.exception import ProcessExecutionError
+from nova import flags
from nova import log as logging
LOG = logging.getLogger("nova.utils")
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
+FLAGS = flags.FLAGS
def import_class(import_str):
@@ -491,6 +495,18 @@ def loads(s):
return json.loads(s)
+def synchronized(name):
+ def wrap(f):
+ @functools.wraps(f)
+ def inner(*args, **kwargs):
+ lock = lockfile.FileLock(os.path.join(FLAGS.lock_path,
+ 'nova-%s.lock' % name))
+ with lock:
+ return f(*args, **kwargs)
+ return inner
+ return wrap
+
+
def get_from_path(items, path):
""" Returns a list of items matching the specified path. Takes an
XPath-like expression e.g. prop1/prop2/prop3, and for each item in items,