.. as it needs to be stored and reloaded if WConfd is restarted while jobs are running.
Signed-off-by: Petr Pudlak <[email protected]> --- src/Ganeti/Path.hs | 5 +++++ src/Ganeti/WConfd/Core.hs | 3 +-- src/Ganeti/WConfd/DeathDetection.hs | 3 ++- src/Ganeti/WConfd/Monad.hs | 23 ++++++++++++++++++----- src/Ganeti/WConfd/Persistent.hs | 14 +++++++++++++- src/Ganeti/WConfd/Server.hs | 3 +++ src/Ganeti/WConfd/TempRes.hs | 4 ++-- 7 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/Ganeti/Path.hs b/src/Ganeti/Path.hs index d6a1252..4638143 100644 --- a/src/Ganeti/Path.hs +++ b/src/Ganeti/Path.hs @@ -36,6 +36,7 @@ module Ganeti.Path , confdHmacKey , clusterConfFile , lockStatusFile + , tempResStatusFile , watcherPauseFile , nodedCertFile , nodedClientCertFile @@ -125,6 +126,10 @@ clusterConfFile = dataDirP "config.data" lockStatusFile :: IO FilePath lockStatusFile = dataDirP "locks.data" +-- | Path to the file representing the lock status. +tempResStatusFile :: IO FilePath +tempResStatusFile = dataDirP "tempres.data" + -- | Path to the watcher pause file. watcherPauseFile :: IO FilePath watcherPauseFile = dataDirP "watcher.pause" diff --git a/src/Ganeti/WConfd/Core.hs b/src/Ganeti/WConfd/Core.hs index 528fb27..b73a0fc 100644 --- a/src/Ganeti/WConfd/Core.hs +++ b/src/Ganeti/WConfd/Core.hs @@ -33,7 +33,6 @@ module Ganeti.WConfd.Core where import Control.Arrow ((&&&)) import Control.Monad (liftM, unless, when) -import Control.Monad.State (modify) import qualified Data.Map as M import qualified Data.Set as S import Language.Haskell.TH (Name) @@ -123,7 +122,7 @@ flushConfig = forceConfigStateDistribution dropAllReservations :: ClientId -> WConfdMonad () dropAllReservations cid = - modifyTempResState (const . modify $ T.dropAllReservations cid) + modifyTempResState (const $ T.dropAllReservations cid) -- *** DRBD diff --git a/src/Ganeti/WConfd/DeathDetection.hs b/src/Ganeti/WConfd/DeathDetection.hs index 0cecbe7..3b0e69c 100644 --- a/src/Ganeti/WConfd/DeathDetection.hs +++ b/src/Ganeti/WConfd/DeathDetection.hs @@ -62,8 +62,9 @@ cleanupLocksTask = forever . runResultT $ do let fpath = ciLockFile owner died <- liftIO (isDead fpath) when died $ do - logInfo $ show owner ++ " died, releasing locks" + logInfo $ show owner ++ " died, releasing locks and reservations" persCleanup persistentLocks owner + persCleanup persistentTempRes owner _ <- liftIO . E.try $ removeFile fpath :: WConfdMonad (Either IOError ()) return () diff --git a/src/Ganeti/WConfd/Monad.hs b/src/Ganeti/WConfd/Monad.hs index afc30ef..a1b863b 100644 --- a/src/Ganeti/WConfd/Monad.hs +++ b/src/Ganeti/WConfd/Monad.hs @@ -104,11 +104,13 @@ data DaemonHandle = DaemonHandle -- all IDs of threads that do asynchronous work should probably also go here , dhSaveConfigWorker :: AsyncWorker Any () , dhSaveLocksWorker :: AsyncWorker () () + , dhSaveTempResWorker :: AsyncWorker () () } mkDaemonHandle :: FilePath -> ConfigState -> GanetiLockWaiting + -> TempResState -> (IO ConfigState -> [AsyncWorker () ()] -> ResultG (AsyncWorker Any ())) -- ^ A function that creates a worker that asynchronously @@ -122,11 +124,14 @@ mkDaemonHandle :: FilePath -> (IO GanetiLockWaiting -> ResultG (AsyncWorker () ())) -- ^ A function that creates a worker that asynchronously -- saves the lock allocation state. + -> (IO TempResState -> ResultG (AsyncWorker () ())) + -- ^ A function that creates a worker that asynchronously + -- saves the temporary reservations state. -> ResultG DaemonHandle -mkDaemonHandle cpath cstat lstat +mkDaemonHandle cpath cstat lstat trstat saveWorkerFn distMCsWorkerFn distSSConfWorkerFn - saveLockWorkerFn = do - ds <- newIORef $ DaemonState cstat lstat emptyTempResState + saveLockWorkerFn saveTempResWorkerFn = do + ds <- newIORef $ DaemonState cstat lstat trstat let readConfigIO = dsConfigState `liftM` readIORef ds :: IO ConfigState ssconfWorker <- distSSConfWorkerFn readConfigIO @@ -136,7 +141,9 @@ mkDaemonHandle cpath cstat lstat saveLockWorker <- saveLockWorkerFn $ dsLockWaiting `liftM` readIORef ds - return $ DaemonHandle ds cpath saveWorker saveLockWorker + saveTempResWorker <- saveTempResWorkerFn $ dsTempRes `liftM` readIORef ds + + return $ DaemonHandle ds cpath saveWorker saveLockWorker saveTempResWorker -- * The monad and its instances @@ -244,7 +251,13 @@ modifyTempResStateErr f = do let f' ds = traverseOf2 dsTempResL (runStateT (f (csConfigData . dsConfigState $ ds))) ds dh <- daemonHandle - toErrorBase $ atomicModifyIORefErr (dhDaemonState dh) (liftM swap . f') + r <- toErrorBase $ atomicModifyIORefErr (dhDaemonState dh) + (liftM swap . f') + -- logDebug $ "Current temporary reservations: " ++ J.encode tr + logDebug "Triggering temporary reservations write" + liftBase . triggerAndWait_ . dhSaveTempResWorker $ dh + logDebug "Temporary reservations write finished" + return r -- | Atomically modifies the state of temporary reservations in -- WConfdMonad. diff --git a/src/Ganeti/WConfd/Persistent.hs b/src/Ganeti/WConfd/Persistent.hs index 1ff3ded..3d01a0a 100644 --- a/src/Ganeti/WConfd/Persistent.hs +++ b/src/Ganeti/WConfd/Persistent.hs @@ -34,6 +34,7 @@ module Ganeti.WConfd.Persistent , writePersistentAsyncTask , readPersistent , persistentLocks + , persistentTempRes ) where import Control.Monad.Error @@ -47,8 +48,9 @@ import Ganeti.Locking.Waiting (emptyWaiting) import Ganeti.Locking.Locks (ClientId(..), GanetiLockWaiting) import Ganeti.Logging import qualified Ganeti.Path as Path -import Ganeti.WConfd.Core (freeLocks) +import Ganeti.WConfd.Core (freeLocks, dropAllReservations) import Ganeti.WConfd.Monad +import Ganeti.WConfd.TempRes (TempResState, emptyTempResState) import Ganeti.Utils.Atomic import Ganeti.Utils.AsyncWorker @@ -112,3 +114,13 @@ persistentLocks = Persistent , persEmpty = emptyWaiting , persCleanup = freeLocks } + +-- ** Temporary reservations + +persistentTempRes :: Persistent TempResState +persistentTempRes = Persistent + { persName = "temporary reservations" + , persPath = Path.tempResStatusFile + , persEmpty = emptyTempResState + , persCleanup = dropAllReservations + } diff --git a/src/Ganeti/WConfd/Server.hs b/src/Ganeti/WConfd/Server.hs index 375e237..67d8e05 100644 --- a/src/Ganeti/WConfd/Server.hs +++ b/src/Ganeti/WConfd/Server.hs @@ -83,13 +83,16 @@ prepMain _ _ = do (cdata, cstat) <- loadConfigFromFile conf_file verifyConfigErr cdata lock <- readPersistent persistentLocks + tempres <- readPersistent persistentTempRes mkDaemonHandle conf_file (mkConfigState cdata) lock + tempres (saveConfigAsyncTask conf_file cstat) (distMCsAsyncTask ents conf_file) distSSConfAsyncTask (writePersistentAsyncTask persistentLocks) + (writePersistentAsyncTask persistentTempRes) return (s, dh) diff --git a/src/Ganeti/WConfd/TempRes.hs b/src/Ganeti/WConfd/TempRes.hs index 110d5e3..effde60 100644 --- a/src/Ganeti/WConfd/TempRes.hs +++ b/src/Ganeti/WConfd/TempRes.hs @@ -245,8 +245,8 @@ generateRand rgen jobid existing genfn tr = -- | Removes all resources reserved by a given job. -- -- If a new reservation resource type is added, it must be added here as well. -dropAllReservations :: ClientId -> TempResState -> TempResState -dropAllReservations jobId = +dropAllReservations :: ClientId -> State TempResState () +dropAllReservations jobId = modify $ (trsMACsL %~ dropReservationsFor jobId) . (trsDRBDSecretsL %~ dropReservationsFor jobId) . (trsLVsL %~ dropReservationsFor jobId) -- 2.0.0.526.g5318336
