...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