From 99e222b18a6f1adf01091443c493a7b7466173ce Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Tue, 11 Dec 2012 17:17:20 +0100 Subject: [PATCH] Add RPC for setting watcher pause The watcher pause file should be set/unset on all nodes at once, not only the master node. For that a new RPC is needed. Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: Guido Trotter <ultrotter@google.com> --- lib/backend.py | 20 +++++++++++++++++++ lib/rpc_defs.py | 3 +++ lib/server/noded.py | 8 ++++++++ test/ganeti.backend_unittest.py | 35 +++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/lib/backend.py b/lib/backend.py index 179e9f577..ccb6a1784 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -64,6 +64,7 @@ from ganeti import mcpu from ganeti import compat from ganeti import pathutils from ganeti import vcluster +from ganeti import ht _BOOT_ID_PATH = "/proc/sys/kernel/random/boot_id" @@ -3768,6 +3769,25 @@ def RunRestrictedCmd(cmd, lock = None +def SetWatcherPause(until, _filename=pathutils.WATCHER_PAUSEFILE): + """Creates or removes the watcher pause file. + + @type until: None or number + @param until: Unix timestamp saying until when the watcher shouldn't run + + """ + if until is None: + logging.info("Received request to no longer pause watcher") + utils.RemoveFile(_filename) + else: + logging.info("Received request to pause watcher until %s", until) + + if not ht.TNumber(until): + _Fail("Duration must be numeric") + + utils.WriteFile(_filename, data="%d\n" % (until, ), mode=0644) + + class HooksRunner(object): """Hook runner. diff --git a/lib/rpc_defs.py b/lib/rpc_defs.py index ecea05437..449b50ad8 100644 --- a/lib/rpc_defs.py +++ b/lib/rpc_defs.py @@ -505,6 +505,9 @@ _MISC_CALLS = [ ("hvname", None, "Hypervisor name"), ("hvfull", None, "Parameters to be validated"), ], None, None, "Validate hypervisor params"), + ("set_watcher_pause", MULTI, None, constants.RPC_TMO_URGENT, [ + ("until", None, None), + ], None, None, "Set watcher pause end"), ] CALLS = { diff --git a/lib/server/noded.py b/lib/server/noded.py index 91ce4cebc..0a1d0d6d5 100644 --- a/lib/server/noded.py +++ b/lib/server/noded.py @@ -827,6 +827,14 @@ class NodeRequestHandler(http.server.HttpServerHandler): (values,) = params return ssconf.WriteSsconfFiles(values) + @staticmethod + def perspective_set_watcher_pause(params): + """Set watcher pause. + + """ + (until, ) = params + return backend.SetWatcherPause(until) + # os ----------------------- @staticmethod diff --git a/test/ganeti.backend_unittest.py b/test/ganeti.backend_unittest.py index f551ac254..4a852425b 100755 --- a/test/ganeti.backend_unittest.py +++ b/test/ganeti.backend_unittest.py @@ -482,5 +482,40 @@ class TestRunRestrictedCmd(unittest.TestCase): self.fail("Did not raise exception") +class TestSetWatcherPause(unittest.TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + self.filename = utils.PathJoin(self.tmpdir, "pause") + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + def testUnsetNonExisting(self): + self.assertFalse(os.path.exists(self.filename)) + backend.SetWatcherPause(None, _filename=self.filename) + self.assertFalse(os.path.exists(self.filename)) + + def testSetNonNumeric(self): + for i in ["", [], {}, "Hello World", "0", "1.0"]: + self.assertFalse(os.path.exists(self.filename)) + + try: + backend.SetWatcherPause(i, _filename=self.filename) + except backend.RPCFail, err: + self.assertEqual(str(err), "Duration must be numeric") + else: + self.fail("Did not raise exception") + + self.assertFalse(os.path.exists(self.filename)) + + def testSet(self): + self.assertFalse(os.path.exists(self.filename)) + + for i in range(10): + backend.SetWatcherPause(i, _filename=self.filename) + self.assertEqual(utils.ReadFile(self.filename), "%s\n" % i) + self.assertEqual(os.stat(self.filename).st_mode & 0777, 0644) + + if __name__ == "__main__": testutils.GanetiTestProgram() -- GitLab