commit edcf959b45229b8c39597cc51800b187b4d8f82f
Merge: eee0109 7f03821
Author: Klaus Aehlig <[email protected]>
Date: Tue Mar 24 17:06:59 2015 +0100
Merge branch 'stable-2.12' into stable-2.13
* stable-2.12
Upgrade codebase to support monad-control >=0.3.1.3 && <1.1
Add macros for the version of monad-control
Rename hs-lens-versions Makefile target to hs-pkg-versions
Verify master status before retrying a socket
Make LUClusterDestroy tell WConfD
Add an RPC to prepare cluster destruction
Support no-master state in ssconf
WConfD: do not clean up own livelock
Make WConfD have a livelock file as well
Add a prefix for a WConfD livelock
Detect if the own job file disappears
Keep track of the number LUs executing
Make job processes keep track of their job id
Make LuxiD clean up its lock file
* stable-2.11
Improve error handling when looking up instances
Capture last exception
Conflicts:
src/Ganeti/BasicTypes.hs
src/Ganeti/Logging/WriterLog.hs
src/Ganeti/THH/HsRPC.hs
src/Ganeti/WConfd/Core.hs
src/Ganeti/WConfd/Monad.hs
Resolution:
Use all the language pragmas
Signed-off-by: Klaus Aehlig <[email protected]>
diff --cc lib/cmdlib/cluster.py
index 291cf47,7d75239..c504d60
--- a/lib/cmdlib/cluster.py
+++ b/lib/cmdlib/cluster.py
@@@ -180,9 -157,10 +182,10 @@@ class LUClusterRenewCrypto(NoHooksLU)
nodes = self.cfg.GetAllNodesInfo()
for (node_uuid, node_info) in nodes.items():
if node_info.offline:
- feedback_fn("* Skipping offline node %s" % node_info.name)
+ logging.info("* Skipping offline node %s", node_info.name)
continue
if node_uuid != master_uuid:
+ last_exception = None
for _ in range(self._MAX_NUM_RETRIES):
try:
new_digest = CreateNewClientCert(self, node_uuid)
diff --cc src/Ganeti/BasicTypes.hs
index 460e635,3ebd788..9d9bd61
--- a/src/Ganeti/BasicTypes.hs
+++ b/src/Ganeti/BasicTypes.hs
@@@ -2,7 -2,8 +2,9 @@@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DeriveFunctor #-}
+ {-# LANGUAGE UndecidableInstances #-}
+ {-# LANGUAGE CPP #-}
{-
diff --cc src/Ganeti/Logging/WriterLog.hs
index 5e3d3bb,90b0339..e3a1499
--- a/src/Ganeti/Logging/WriterLog.hs
+++ b/src/Ganeti/Logging/WriterLog.hs
@@@ -1,6 -1,5 +1,5 @@@
--{-# LANGUAGE FlexibleInstances, FlexibleContexts, TypeFamilies,
- MultiParamTypeClasses, GeneralizedNewtypeDeriving,
- StandaloneDeriving #-}
- MultiParamTypeClasses, UndecidableInstances, CPP #-}
++{-# LANGUAGE FlexibleInstances, FlexibleContexts, TypeFamilies,
GeneralizedNewtypeDeriving,
++ StandaloneDeriving, MultiParamTypeClasses, UndecidableInstances,
CPP #-}
{-| A pure implementation of MonadLog using MonadWriter
@@@ -108,7 -111,42 +115,14 @@@ execWriterLog k = d
instance (Monad m) => MonadLog (WriterLogT m) where
logAt = curry (WriterLogT . tell . singleton)
-instance (MonadIO m) => MonadIO (WriterLogT m) where
- liftIO = WriterLogT . liftIO
-
-instance (MonadPlus m) => MonadPlus (WriterLogT m) where
- mzero = lift mzero
- mplus (WriterLogT x) (WriterLogT y) = WriterLogT $ mplus x y
-
-instance (MonadBase IO m) => MonadBase IO (WriterLogT m) where
- liftBase = WriterLogT . liftBase
-
-instance MonadTrans WriterLogT where
- lift = WriterLogT . lift
-
instance MonadTransControl WriterLogT where
+ #if MIN_VERSION_monad_control(1,0,0)
+ -- Needs Undecidable instances
+ type StT WriterLogT a = (a, LogSeq)
+ liftWith f = WriterLogT . WriterT $ liftM (\x -> (x, mempty))
+ (f runWriterLogT)
+ restoreT = WriterLogT . WriterT
+ #else
newtype StT WriterLogT a =
StWriterLog { unStWriterLog :: (a, LogSeq) }
liftWith f = WriterLogT . WriterT $ liftM (\x -> (x, mempty))
diff --cc src/Ganeti/THH/HsRPC.hs
index 791b81d,5660472..20c7089
--- a/src/Ganeti/THH/HsRPC.hs
+++ b/src/Ganeti/THH/HsRPC.hs
@@@ -1,6 -1,6 +1,5 @@@
- {-# LANGUAGE TemplateHaskell, FunctionalDependencies, FlexibleContexts,
- GeneralizedNewtypeDeriving, TypeFamilies #-}
- -- {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+ {-# LANGUAGE TemplateHaskell, FunctionalDependencies, FlexibleContexts, CPP,
- TypeFamilies, UndecidableInstances #-}
--- {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
++ GeneralizedNewtypeDeriving, TypeFamilies, UndecidableInstances
#-}
{-| Creates a client out of list of RPC server components.
@@@ -66,10 -74,37 +73,17 @@@ import Ganeti.UDSServe
-- result or the error.
newtype RpcClientMonad a =
RpcClientMonad { runRpcClientMonad :: ReaderT Client ResultG a }
-
-instance Functor RpcClientMonad where
- fmap f = RpcClientMonad . fmap f . runRpcClientMonad
-
-instance Applicative RpcClientMonad where
- pure = RpcClientMonad . pure
- (RpcClientMonad f) <*> (RpcClientMonad k) = RpcClientMonad (f <*> k)
-
-instance Monad RpcClientMonad where
- return = RpcClientMonad . return
- (RpcClientMonad k) >>= f = RpcClientMonad (k >>= runRpcClientMonad . f)
-
-instance MonadBase IO RpcClientMonad where
- liftBase = RpcClientMonad . liftBase
-
-instance MonadIO RpcClientMonad where
- liftIO = RpcClientMonad . liftIO
-
-instance MonadError GanetiException RpcClientMonad where
- throwError = RpcClientMonad . throwError
- catchError (RpcClientMonad k) h =
- RpcClientMonad (catchError k (runRpcClientMonad . h))
+ deriving (Functor, Applicative, Monad, MonadIO, MonadBase IO,
+ MonadError GanetiException)
instance MonadBaseControl IO RpcClientMonad where
+ #if MIN_VERSION_monad_control(1,0,0)
+ -- Needs Undecidable instances
+ type StM RpcClientMonad b = StM (ReaderT Client ResultG) b
+ liftBaseWith f = RpcClientMonad . liftBaseWith
+ $ \r -> f (r . runRpcClientMonad)
+ restoreM = RpcClientMonad . restoreM
+ #else
newtype StM RpcClientMonad b = StMRpcClientMonad
{ runStMRpcClientMonad :: StM (ReaderT Client ResultG) b }
liftBaseWith f = RpcClientMonad . liftBaseWith
diff --cc src/Ganeti/WConfd/Core.hs
index d48720b,07b6ec6..569182a
--- a/src/Ganeti/WConfd/Core.hs
+++ b/src/Ganeti/WConfd/Core.hs
@@@ -48,14 -51,19 +51,20 @@@ import System.Posix.Process (getProcess
import qualified System.Random as Rand
import Ganeti.BasicTypes
+ import qualified Ganeti.Constants as C
import qualified Ganeti.JSON as J
import qualified Ganeti.Locking.Allocation as L
- import Ganeti.Locking.Locks ( GanetiLocks(ConfigLock), LockLevel(LevelConfig)
- , lockLevel, LockLevel, ClientId )
+ import Ganeti.Logging (logDebug)
+ import Ganeti.Locking.Locks ( GanetiLocks(ConfigLock, BGL)
+ , LockLevel(LevelConfig)
+ , lockLevel, LockLevel
+ , ClientType(ClientOther), ClientId(..) )
import qualified Ganeti.Locking.Waiting as LW
import Ganeti.Objects (ConfigData, DRBDSecret, LogicalVolume, Ip4Address)
+ import Ganeti.Objects.Lens (configClusterL, clusterMasterNodeL)
+ import Ganeti.WConfd.ConfigState (csConfigDataL)
import qualified Ganeti.WConfd.ConfigVerify as V
+import Ganeti.WConfd.DeathDetection (cleanupLocks)
import Ganeti.WConfd.Language
import Ganeti.WConfd.Monad
import qualified Ganeti.WConfd.TempRes as T
@@@ -314,7 -355,7 +356,8 @@@ prepareClusterDestruction cid = d
exportedFunctions :: [Name]
exportedFunctions = [ 'echo
+ , 'cleanupLocks
+ , 'prepareClusterDestruction
-- config
, 'readConfig
, 'writeConfig
diff --cc src/Ganeti/WConfd/DeathDetection.hs
index 96d0fd5,ecfb5ce..20b85cd
--- a/src/Ganeti/WConfd/DeathDetection.hs
+++ b/src/Ganeti/WConfd/DeathDetection.hs
@@@ -62,10 -61,12 +62,11 @@@ import Ganeti.WConfd.Persisten
cleanupInterval :: Int
cleanupInterval = C.wconfdDeathdetectionIntervall * 1000000
--- | Thread periodically cleaning up locks of lock owners that died.
-cleanupLocksTask :: WConfdMonadInt ()
-cleanupLocksTask = forever . runResultT $ do
- logDebug "Death detection timer fired"
+-- | Go through all owners once and clean them up, if they're dead.
+cleanupLocks :: WConfdMonad ()
+cleanupLocks = do
owners <- liftM L.lockOwners readLockAllocation
+ mylivelock <- liftM dhLivelock daemonHandle
logDebug $ "Current lock owners: " ++ show owners
let cleanupIfDead owner = do
let fpath = ciLockFile owner
@@@ -78,16 -81,12 +81,19 @@@
:: WConfdMonad (Either IOError ())
return ()
mapM_ cleanupIfDead owners
+
+-- | Thread periodically cleaning up locks of lock owners that died.
+cleanupLocksTask :: WConfdMonadInt ()
+cleanupLocksTask = forever . runResultT $ do
+ logDebug "Death detection timer fired"
+ cleanupLocks
remainingFiles <- liftIO listLiveLocks
++ mylivelock <- liftM dhLivelock daemonHandle
logDebug $ "Livelockfiles remaining: " ++ show remainingFiles
let cleanupStaleIfDead fpath = do
- died <- liftIO (isDead fpath)
+ died <- if fpath == mylivelock
+ then return False
+ else liftIO (isDead fpath)
when died $ do
logInfo $ "Cleaning up stale file " ++ fpath
_ <- liftIO . E.try $ removeFile fpath
diff --cc src/Ganeti/WConfd/Monad.hs
index e0a9ec0,3148937..59ec4ce
--- a/src/Ganeti/WConfd/Monad.hs
+++ b/src/Ganeti/WConfd/Monad.hs
@@@ -1,7 -1,6 +1,6 @@@
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies,
- GeneralizedNewtypeDeriving #-}
- {-# LANGUAGE TemplateHaskell #-}
-
++ GeneralizedNewtypeDeriving,
+ TemplateHaskell, CPP, UndecidableInstances #-}
-
{-| All RPC calls are run within this monad.
It encapsulates:
@@@ -166,15 -179,42 +179,23 @@@ type WConfdMonadIntType = ReaderT Daemo
-- | The internal part of the monad without error handling.
newtype WConfdMonadInt a = WConfdMonadInt
{ getWConfdMonadInt :: WConfdMonadIntType a }
-
-instance Functor WConfdMonadInt where
- fmap f = WConfdMonadInt . fmap f . getWConfdMonadInt
-
-instance Applicative WConfdMonadInt where
- pure = WConfdMonadInt . pure
- WConfdMonadInt f <*> WConfdMonadInt k = WConfdMonadInt $ f <*> k
-
-instance Monad WConfdMonadInt where
- return = WConfdMonadInt . return
- (WConfdMonadInt k) >>= f = WConfdMonadInt $ k >>= getWConfdMonadInt . f
-
-instance MonadIO WConfdMonadInt where
- liftIO = WConfdMonadInt . liftIO
-
-instance MonadBase IO WConfdMonadInt where
- liftBase = WConfdMonadInt . liftBase
+ deriving (Functor, Applicative, Monad, MonadIO, MonadBase IO, MonadLog)
instance MonadBaseControl IO WConfdMonadInt where
+ #if MIN_VERSION_monad_control(1,0,0)
+ -- Needs Undecidable instances
+ type StM WConfdMonadInt b = StM WConfdMonadIntType b
+ liftBaseWith f = WConfdMonadInt . liftBaseWith
+ $ \r -> f (r . getWConfdMonadInt)
+ restoreM = WConfdMonadInt . restoreM
+ #else
newtype StM WConfdMonadInt b = StMWConfdMonadInt
{ runStMWConfdMonadInt :: StM WConfdMonadIntType b }
liftBaseWith f = WConfdMonadInt . liftBaseWith
$ \r -> f (liftM StMWConfdMonadInt . r . getWConfdMonadInt)
restoreM = WConfdMonadInt . restoreM . runStMWConfdMonadInt
+ #endif
-instance MonadLog WConfdMonadInt where
- logAt p = WConfdMonadInt . logAt p
-
-- | Runs the internal part of the WConfdMonad monad on a given daemon
-- handle.
runWConfdMonadInt :: WConfdMonadInt a -> DaemonHandle -> IO a
@@@ -226,10 -266,9 +247,10 @@@ modifyConfigStateErr f = d
logDebug "Config write and distribution finished"
else do
-- trigger the config. saving worker and wait for it
- logDebug "Triggering config write\
- \ and asynchronous distribution"
+ logDebug $ "Triggering config write" ++
+ " and asynchronous distribution"
liftBase . triggerAndWait (Any False) . dhSaveConfigWorker $ dh
+ logDebug "Config writer finished with local task"
return ()
return r
--
Klaus Aehlig
Google Germany GmbH, Dienerstr. 12, 80331 Muenchen
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschaeftsfuehrer: Graham Law, Christine Elizabeth Flores