Commit fc428e32 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Replace watcher state file atomically

- Lock it before renaming
- Code cleanup; close() automatically unlocks it

Reviewed-by: iustinp
parent 78f3bd30
# Copyright (C) 2006, 2007 Google Inc.
# Copyright (C) 2006, 2007, 2008 Google 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
......@@ -93,6 +93,18 @@ def DoCmd(cmd):
return res
def LockFile(fd):
"""Locks a file using POSIX locks.
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError, err:
if err.errno == errno.EAGAIN:
raise StandardError("File already locked")
class WatcherState(object):
"""Interface to a state file recording restart attempts.
......@@ -106,17 +118,10 @@ class WatcherState(object):
# The two-step dance below is necessary to allow both opening existing
# file read/write and creating if not existing. Vanilla open will truncate
# an existing file -or- allow creating if not existing.
f =, os.O_RDWR | os.O_CREAT)
f = os.fdopen(f, 'w+')
fd =, os.O_RDWR | os.O_CREAT)
self.statefile = os.fdopen(fd, 'w+')
fcntl.flock(f.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
except IOError, x:
if x.errno == errno.EAGAIN:
raise StandardError("State file already locked")
self.statefile = f
try: = serializer.Load(
......@@ -131,21 +136,26 @@ class WatcherState(object):
if "node" not in["node"] = {}
def __del__(self):
"""Called on destruction.
def Save(self):
"""Save state to file, then unlock and close it.
if self.statefile:
assert self.statefile
# We need to make sure the file is locked before renaming it, otherwise
# starting ganeti-watcher again at the same time will create a conflict.
fd = utils.WriteFile(constants.WATCHER_STATEFILE,
prewrite=LockFile, close=False)
self.statefile = os.fdopen(fd, 'w+')
def _Close(self):
def Close(self):
"""Unlock configuration file and close it.
assert self.statefile
fcntl.flock(self.statefile.fileno(), fcntl.LOCK_UN)
# Files are automatically unlocked when closing them
self.statefile = None
......@@ -217,19 +227,6 @@ class WatcherState(object):
if in idata:
del idata[]
def Save(self):
"""Save state to file, then unlock and close it.
assert self.statefile
class Instance(object):
"""Abstraction for a Virtual Machine instance.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment