For the new renew-crypto operation, we need to run
functions while most of the daemons are stopped,
except for WConfd. This refactors our code a bit
and generalizes the method that runs functions
while *all* daemons are stopped to one that
accepts a list of daemons to not be stopped.

Signed-off-by: Helga Velroyen <[email protected]>
---
 lib/cli.py              | 52 +++++++++++++++++++++++++++++++++++++++++++------
 lib/pathutils.py        |  2 +-
 src/Ganeti/Constants.hs | 15 +++++++++-----
 3 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/lib/cli.py b/lib/cli.py
index c51c2a5..195a77b 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -267,6 +267,7 @@ __all__ = [
   "JobSubmittedException",
   "ParseTimespec",
   "RunWhileClusterStopped",
+  "RunWhileDaemonsStopped",
   "SubmitOpCode",
   "SubmitOpCodeToDrainedQueue",
   "SubmitOrSend",
@@ -2935,12 +2936,12 @@ def GenericInstanceCreate(mode, opts, args):
   return 0
 
 
-class _RunWhileClusterStoppedHelper(object):
-  """Helper class for L{RunWhileClusterStopped} to simplify state management
+class _RunWhileDaemonsStoppedHelper(object):
+  """Helper class for L{RunWhileDaemonsStopped} to simplify state management
 
   """
   def __init__(self, feedback_fn, cluster_name, master_node,
-               online_nodes, ssh_ports):
+               online_nodes, ssh_ports, exclude_daemons):
     """Initializes this class.
 
     @type feedback_fn: callable
@@ -2953,6 +2954,8 @@ class _RunWhileClusterStoppedHelper(object):
     @param online_nodes: List of names of online nodes
     @type ssh_ports: list
     @param ssh_ports: List of SSH ports of online nodes
+    @type exclude_daemons: list of string
+    @param exclude_daemons: list of daemons to shutdown
 
     """
     self.feedback_fn = feedback_fn
@@ -2966,6 +2969,8 @@ class _RunWhileClusterStoppedHelper(object):
     self.nonmaster_nodes = [name for name in online_nodes
                             if name != master_node]
 
+    self.exclude_daemons = exclude_daemons
+
     assert self.master_node not in self.nonmaster_nodes
 
   def _RunCmd(self, node_name, cmd):
@@ -3017,6 +3022,13 @@ class _RunWhileClusterStoppedHelper(object):
         for node_name in self.online_nodes:
           self.feedback_fn("Stopping daemons on %s" % node_name)
           self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "stop-all"])
+          # Starting any daemons listed as exception
+          for daemon in self.exclude_daemons:
+            if (daemon in constants.DAEMONS_MASTER and
+                node_name != self.master_node):
+              continue
+            self.feedback_fn("Starting daemon '%s' on %s" % (daemon, 
node_name))
+            self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "start", daemon])
 
         # All daemons are shut down now
         try:
@@ -3029,18 +3041,31 @@ class _RunWhileClusterStoppedHelper(object):
       finally:
         # Start cluster again, master node last
         for node_name in self.nonmaster_nodes + [self.master_node]:
+          # Stopping any daemons listed as exception.
+          # This might look unnecessary, but it makes sure that daemon-util
+          # starts all daemons in the right order.
+          for daemon in self.exclude_daemons:
+            if (daemon in constants.DAEMONS_MASTER and
+                node_name != self.master_node):
+              continue
+            self.feedback_fn("Stopping daemon '%s' on %s" % (daemon, 
node_name))
+            self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "stop", daemon])
           self.feedback_fn("Starting daemons on %s" % node_name)
           self._RunCmd(node_name, [pathutils.DAEMON_UTIL, "start-all"])
+
     finally:
       # Resume watcher
       watcher_block.Close()
 
 
-def RunWhileClusterStopped(feedback_fn, fn, *args):
+def RunWhileDaemonsStopped(feedback_fn, exclude_daemons, fn, *args):
   """Calls a function while all cluster daemons are stopped.
 
   @type feedback_fn: callable
   @param feedback_fn: Feedback function
+  @type exclude_daemons: list of string
+  @param exclude_daemons: list of daemons that are NOT stopped. If None,
+                          all daemons will be stopped.
   @type fn: callable
   @param fn: Function to be called when daemons are stopped
 
@@ -3060,9 +3085,24 @@ def RunWhileClusterStopped(feedback_fn, fn, *args):
   del cl
 
   assert master_node in online_nodes
+  if exclude_daemons is None:
+    exclude_daemons = []
+
+  return _RunWhileDaemonsStoppedHelper(
+      feedback_fn, cluster_name, master_node, online_nodes, ssh_ports,
+      exclude_daemons).Call(fn, *args)
+
+
+def RunWhileClusterStopped(feedback_fn, fn, *args):
+  """Calls a function while all cluster daemons are stopped.
 
-  return _RunWhileClusterStoppedHelper(feedback_fn, cluster_name, master_node,
-                                       online_nodes, ssh_ports).Call(fn, *args)
+  @type feedback_fn: callable
+  @param feedback_fn: Feedback function
+  @type fn: callable
+  @param fn: Function to be called when daemons are stopped
+
+  """
+  RunWhileDaemonsStopped(feedback_fn, None, fn, *args)
 
 
 def GenerateTable(headers, fields, separator, data,
diff --git a/lib/pathutils.py b/lib/pathutils.py
index 0e02142..203df47 100644
--- a/lib/pathutils.py
+++ b/lib/pathutils.py
@@ -132,7 +132,7 @@ NODED_CERT_MODE = 0440
 RESTRICTED_COMMANDS_LOCK_FILE = LOCK_DIR + "/ganeti-restricted-commands.lock"
 
 #: Lock file for watcher, locked in shared mode by watcher; lock in exclusive
-# mode to block watcher (see L{cli._RunWhileClusterStoppedHelper.Call}
+# mode to block watcher (see L{cli._RunWhileDaemonsStoppedHelper.Call}
 WATCHER_LOCK_FILE = LOCK_DIR + "/ganeti-watcher.lock"
 
 #: Status file for per-group watcher, locked in exclusive mode by watcher
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index dea59a5..9428780 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -375,14 +375,19 @@ rapi = Runtime.daemonName GanetiRapi
 kvmd :: String
 kvmd = Runtime.daemonName GanetiKvmd
 
+-- Set of daemons which only run on the master.
+-- Keep in sync with the 'daemon-util' script.
+daemonsMaster :: FrozenSet String
+daemonsMaster = ConstantUtils.mkSet [wconfd, luxid, rapi]
+
 daemons :: FrozenSet String
 daemons =
-  ConstantUtils.mkSet [confd,
+  ConstantUtils.mkSet [noded,
+                       wconfd,
+                       rapi,
                        luxid,
-                       masterd,
-                       mond,
-                       noded,
-                       rapi]
+                       kvmd,
+                       mond]
 
 defaultConfdPort :: Int
 defaultConfdPort = 1814
-- 
2.4.3.573.g4eafbef

Reply via email to