module Ganeti.Jobs
( submitJobs
, execJobsWait
, execJobsWaitOk
, waitForJobs
) where
import Control.Concurrent (threadDelay)
import Data.List
import Ganeti.BasicTypes
import Ganeti.Errors
import qualified Ganeti.Luxi as L
import Ganeti.OpCodes
import Ganeti.Types
submitJobs :: [[MetaOpCode]] -> L.Client -> IO (Result [L.JobId])
submitJobs opcodes client = do
jids <- L.submitManyJobs client opcodes
return (case jids of
Bad e -> Bad $ "Job submission error: " ++ formatError e
Ok jids' -> Ok jids')
execJobsWait :: [[MetaOpCode]]
-> ([L.JobId] -> IO ())
-> L.Client
-> IO (Result [(L.JobId, JobStatus)])
execJobsWait opcodes callback client = do
jids <- submitJobs opcodes client
case jids of
Bad e -> return $ Bad e
Ok jids' -> do
callback jids'
waitForJobs jids' client
waitForJobs :: [L.JobId] -> L.Client -> IO (Result [(L.JobId, JobStatus)])
waitForJobs jids client = waitForJobs' 500000 15000000
where
waitForJobs' delay maxdelay = do
threadDelay delay
sts <- L.queryJobsStatus client jids
case sts of
Bad e -> return . Bad $ "Checking job status: " ++ formatError e
Ok sts' -> if any (<= JOB_STATUS_RUNNING) sts' then
waitForJobs' (min (delay * 2) maxdelay) maxdelay
else
return . Ok $ zip jids sts'
execJobsWaitOk :: [[MetaOpCode]] -> L.Client -> IO (Result ())
execJobsWaitOk opcodes client = do
let nullog = const (return () :: IO ())
failed = filter ((/=) JOB_STATUS_SUCCESS . snd)
fmtfail (i, s) = show (fromJobId i) ++ "=>" ++ jobStatusToRaw s
sts <- execJobsWait opcodes nullog client
case sts of
Bad e -> return $ Bad e
Ok sts' -> return (if null $ failed sts' then
Ok ()
else
Bad ("The following jobs failed: " ++
(intercalate ", " . map fmtfail $ failed sts')))