...so that it can be used by other daemons as well.

Signed-off-by: Klaus Aehlig <[email protected]>
---
 Makefile.am                |  2 ++
 src/Ganeti/Daemon/Utils.hs | 85 ++++++++++++++++++++++++++++++++++++++++++++++
 src/Ganeti/Query/Server.hs | 49 ++------------------------
 3 files changed, 89 insertions(+), 47 deletions(-)
 create mode 100644 src/Ganeti/Daemon/Utils.hs

diff --git a/Makefile.am b/Makefile.am
index 10d8d27..ebd729b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -122,6 +122,7 @@ HS_DIRS = \
        src/Ganeti/Curl \
        src/Ganeti/Cpu \
        src/Ganeti/DataCollectors \
+       src/Ganeti/Daemon \
        src/Ganeti/Hs2Py \
        src/Ganeti/HTools \
        src/Ganeti/HTools/Backend \
@@ -749,6 +750,7 @@ HS_LIB_SRCS = \
        src/Ganeti/Cpu/Types.hs \
        src/Ganeti/Curl/Multi.hs \
        src/Ganeti/Daemon.hs \
+       src/Ganeti/Daemon/Utils.hs \
        src/Ganeti/DataCollectors/CLI.hs \
        src/Ganeti/DataCollectors/CPUload.hs \
        src/Ganeti/DataCollectors/Diskstats.hs \
diff --git a/src/Ganeti/Daemon/Utils.hs b/src/Ganeti/Daemon/Utils.hs
new file mode 100644
index 0000000..1f86e51
--- /dev/null
+++ b/src/Ganeti/Daemon/Utils.hs
@@ -0,0 +1,85 @@
+{-| Utility functions for complex operations carried out by several daemons.
+
+-}
+
+{-
+
+Copyright (C) 2014 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
+
+-}
+
+module Ganeti.Daemon.Utils
+  ( verifyMaster
+  ) where
+
+import Control.Concurrent (threadDelay)
+import Control.Monad (unless)
+import Data.Either (rights)
+import qualified Data.Foldable as F
+import Data.List (partition)
+
+import Ganeti.BasicTypes
+import qualified Ganeti.Config as Config
+import qualified Ganeti.Constants as C
+import Ganeti.Daemon (getFQDN)
+import Ganeti.Logging
+import Ganeti.Objects
+import qualified Ganeti.Path as Path
+import Ganeti.Rpc
+
+-- | Gather votes from all nodes and verify that we we are
+-- the master. Return True if the voting is won, False if
+-- not enough
+verifyMasterVotes :: IO (Result Bool)
+verifyMasterVotes = runResultT $ do
+  liftIO $ logDebug "Gathering votes for the master node"
+  myName <- liftIO getFQDN
+  liftIO . logDebug $ "My hostname is " ++ myName
+  conf_file <- liftIO Path.clusterConfFile
+  config <- mkResultT $ Config.loadConfig conf_file
+  let nodes = F.toList $ configNodes config
+  votes <- liftIO . executeRpcCall nodes $ RpcCallMasterNodeName
+  let (missing, valid) = partition (isLeft . snd) votes
+      noDataNodes = map (nodeName . fst) missing
+      validVotes = map rpcResultMasterNodeNameMaster . rights $ map snd valid
+      inFavor = length $ filter (== myName) validVotes
+      voters = length nodes
+      unknown = length missing
+  liftIO . unless (null noDataNodes) . logWarning
+    . (++) "No voting RPC result from " $ show noDataNodes
+  liftIO . logDebug . (++) "Valid votes: " $ show validVotes
+  if 2 * inFavor > voters
+    then return True
+    else if 2 * (inFavor + unknown) > voters
+           then return False
+           else fail $ "Voting cannot be won by " ++ myName
+                       ++ ", valid votes of " ++ show voters
+                       ++ " are " ++ show validVotes
+
+-- | Verify, by voting, that this node is the master. Bad if we're not.
+-- Allow the given number of retries to wait for not available nodes.
+verifyMaster :: Int -> IO (Result ())
+verifyMaster retries = runResultT $ do
+  won <- mkResultT verifyMasterVotes
+  unless won $
+    if retries <= 0
+      then fail "Couldn't gather voting results of enough nodes"
+      else do
+        liftIO $ logDebug "Voting not final due to missing votes."
+        liftIO . threadDelay $ C.masterVotingRetryIntervall * 1000000
+        mkResultT $ verifyMaster (retries - 1)
diff --git a/src/Ganeti/Query/Server.hs b/src/Ganeti/Query/Server.hs
index bf7ee97..70b1574 100644
--- a/src/Ganeti/Query/Server.hs
+++ b/src/Ganeti/Query/Server.hs
@@ -32,17 +32,13 @@ module Ganeti.Query.Server
 import Control.Applicative
 import Control.Concurrent
 import Control.Exception
-import Control.Monad (forever, when, mzero, guard, zipWithM, liftM, void,
-                      unless)
+import Control.Monad (forever, when, mzero, guard, zipWithM, liftM, void)
 import Control.Monad.IO.Class
 import Control.Monad.Trans (lift)
 import Control.Monad.Trans.Maybe
 import Data.Bits (bitSize)
-import Data.Either (rights)
-import qualified Data.Foldable as F
 import qualified Data.Set as Set (toList)
 import Data.IORef
-import Data.List (partition)
 import Data.Maybe (fromMaybe)
 import qualified Text.JSON as J
 import Text.JSON (encode, showJSON, JSValue(..))
@@ -56,6 +52,7 @@ import qualified Ganeti.ConstantUtils as ConstantUtils 
(unFrozenSet)
 import Ganeti.Errors
 import qualified Ganeti.Path as Path
 import Ganeti.Daemon
+import Ganeti.Daemon.Utils (verifyMaster)
 import Ganeti.Objects
 import qualified Ganeti.Config as Config
 import Ganeti.ConfigReader
@@ -450,48 +447,6 @@ activateMasterIP = runResultT $ do
   liftIO $ logDebug "finished activating master IP address"
   return ()
 
--- | Gather votes from all nodes and verify that we we are
--- the master. Return True if the voting is won, False if
--- not enough
-verifyMasterVotes :: IO (Result Bool)
-verifyMasterVotes = runResultT $ do
-  liftIO $ logDebug "Gathering votes for the master node"
-  myName <- liftIO getFQDN
-  liftIO . logDebug $ "My hostname is " ++ myName
-  conf_file <- liftIO Path.clusterConfFile
-  config <- mkResultT $ Config.loadConfig conf_file
-  let nodes = F.toList $ configNodes config
-  votes <- liftIO . executeRpcCall nodes $ RpcCallMasterNodeName
-  let (missing, valid) = partition (isLeft . snd) votes
-      noDataNodes = map (nodeName . fst) missing
-      validVotes = map rpcResultMasterNodeNameMaster . rights $ map snd valid
-      inFavor = length $ filter (== myName) validVotes
-      voters = length nodes
-      unknown = length missing
-  liftIO . unless (null noDataNodes) . logWarning
-    . (++) "No voting RPC result from " $ show noDataNodes
-  liftIO . logDebug . (++) "Valid votes: " $ show validVotes
-  if 2 * inFavor > voters
-    then return True
-    else if 2 * (inFavor + unknown) > voters
-           then return False
-           else fail $ "Voting cannot be won by " ++ myName
-                       ++ ", valid votes of " ++ show voters
-                       ++ " are " ++ show validVotes
-
--- | Verify, by voting, that this node is the master. Bad if we're not.
--- Allow the given number of retries to wait for not available nodes.
-verifyMaster :: Int -> IO (Result ())
-verifyMaster retries = runResultT $ do
-  won <- mkResultT verifyMasterVotes
-  unless won $
-    if retries <= 0
-      then fail "Couldn't gather voting results of enough nodes"
-      else do
-        liftIO $ logDebug "Voting not final due to missing votes."
-        liftIO . threadDelay $ C.masterVotingRetryIntervall * 1000000
-        mkResultT $ verifyMaster (retries - 1)
-
 -- | Check function for luxid.
 checkMain :: CheckFn ()
 checkMain opts =
-- 
1.9.1.423.g4596e3a

Reply via email to