Commit 05e50653 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Add file to pause watcher for a certain duration



This can be used during maintenance work.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent dff85078
......@@ -296,6 +296,22 @@ class ClientOps:
drain_flag)
return queue.SetDrainFlag(drain_flag)
elif method == luxi.REQ_SET_WATCHER_PAUSE:
(until, ) = args
if until is None:
logging.info("Received request to no longer pause the watcher")
else:
if not isinstance(until, (int, float)):
raise TypeError("Duration must be an integer or float")
if until < time.time():
raise errors.GenericError("Unable to set pause end time in the past")
logging.info("Received request to pause the watcher until %s", until)
return _SetWatcherPause(until)
else:
logging.info("Received invalid request '%s'", method)
raise ValueError("Invalid operation '%s'" % method)
......@@ -384,6 +400,20 @@ class GanetiContext(object):
self.glm.remove(locking.LEVEL_NODE, name)
def _SetWatcherPause(until):
"""Creates or removes the watcher pause file.
@type until: None or int
@param until: Unix timestamp saying until when the watcher shouldn't run
"""
if until is None:
utils.RemoveFile(constants.WATCHER_PAUSEFILE)
else:
utils.WriteFile(constants.WATCHER_PAUSEFILE,
data="%d\n" % (until, ))
def CheckAgreement():
"""Check the agreement on who is the master.
......
......@@ -3086,7 +3086,8 @@ class LUQueryConfigValues(NoHooksLU):
_OP_REQP = []
REQ_BGL = False
_FIELDS_DYNAMIC = utils.FieldSet()
_FIELDS_STATIC = utils.FieldSet("cluster_name", "master_node", "drain_flag")
_FIELDS_STATIC = utils.FieldSet("cluster_name", "master_node", "drain_flag",
"watcher_pause")
def ExpandNames(self):
self.needed_locks = {}
......@@ -3113,6 +3114,8 @@ class LUQueryConfigValues(NoHooksLU):
entry = self.cfg.GetMasterNode()
elif field == "drain_flag":
entry = os.path.exists(constants.JOB_QUEUE_DRAIN_FILE)
elif field == "watcher_pause":
return utils.ReadWatcherPauseFile(constants.WATCHER_PAUSEFILE)
else:
raise errors.ParameterError(field)
values.append(entry)
......
......@@ -99,6 +99,7 @@ SSL_CERT_FILE = DATA_DIR + "/server.pem"
RAPI_CERT_FILE = DATA_DIR + "/rapi.pem"
HMAC_CLUSTER_KEY = DATA_DIR + "/hmac.key"
WATCHER_STATEFILE = DATA_DIR + "/watcher.data"
WATCHER_PAUSEFILE = DATA_DIR + "/watcher.pause"
INSTANCE_UPFILE = RUN_GANETI_DIR + "/instance-status"
SSH_KNOWN_HOSTS_FILE = DATA_DIR + "/known_hosts"
RAPI_USERS_FILE = DATA_DIR + "/rapi_users"
......
......@@ -57,6 +57,7 @@ REQ_QUERY_EXPORTS = "QueryExports"
REQ_QUERY_CONFIG_VALUES = "QueryConfigValues"
REQ_QUERY_CLUSTER_INFO = "QueryClusterInfo"
REQ_QUEUE_SET_DRAIN_FLAG = "SetDrainFlag"
REQ_SET_WATCHER_PAUSE = "SetWatcherPause"
DEF_CTMO = 10
DEF_RWTO = 60
......@@ -339,6 +340,9 @@ class Client(object):
def SetQueueDrainFlag(self, drain_flag):
return self.CallMethod(REQ_QUEUE_SET_DRAIN_FLAG, drain_flag)
def SetWatcherPause(self, until):
return self.CallMethod(REQ_SET_WATCHER_PAUSE, [until])
def SubmitJob(self, ops):
ops_state = map(lambda op: op.__getstate__(), ops)
return self.CallMethod(REQ_SUBMIT_JOB, ops_state)
......
......@@ -1951,6 +1951,33 @@ def FormatTime(val):
return time.strftime("%F %T", time.localtime(val))
def ReadWatcherPauseFile(filename, now=None):
"""Reads the watcher pause file.
"""
if now is None:
now = time.time()
try:
value = ReadFile(filename)
except IOError, err:
if err.errno != errno.ENOENT:
raise
value = None
if value is not None:
try:
value = int(value)
except ValueError:
value = None
if value is not None:
if now > value:
value = None
return value
class FileLock(object):
"""Utility class for file locks.
......
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