Revision b2245847 hbal.hs
b/hbal.hs | ||
---|---|---|
25 | 25 |
|
26 | 26 |
module Main (main) where |
27 | 27 |
|
28 |
import Control.Concurrent (threadDelay) |
|
29 |
import Control.Exception (bracket) |
|
28 | 30 |
import Data.List |
29 | 31 |
import Data.Function |
30 | 32 |
import Data.Maybe (isJust, fromJust) |
... | ... | |
34 | 36 |
import qualified System |
35 | 37 |
|
36 | 38 |
import Text.Printf (printf, hPrintf) |
39 |
import Text.JSON (showJSON) |
|
37 | 40 |
|
38 | 41 |
import qualified Ganeti.HTools.Container as Container |
39 | 42 |
import qualified Ganeti.HTools.Cluster as Cluster |
40 | 43 |
import qualified Ganeti.HTools.Node as Node |
44 |
import qualified Ganeti.HTools.Instance as Instance |
|
41 | 45 |
|
42 | 46 |
import Ganeti.HTools.CLI |
43 | 47 |
import Ganeti.HTools.ExtLoader |
44 | 48 |
import Ganeti.HTools.Utils |
45 | 49 |
import Ganeti.HTools.Types |
46 | 50 |
|
51 |
import qualified Ganeti.Luxi as L |
|
52 |
import qualified Ganeti.OpCodes as OpCodes |
|
53 |
import Ganeti.Jobs |
|
54 |
|
|
47 | 55 |
-- | Options list and functions |
48 | 56 |
options :: [OptType] |
49 | 57 |
options = |
... | ... | |
54 | 62 |
, oInstFile |
55 | 63 |
, oRapiMaster |
56 | 64 |
, oLuxiSocket |
65 |
, oExecJobs |
|
57 | 66 |
, oMaxSolLength |
58 | 67 |
, oVerbose |
59 | 68 |
, oQuiet |
... | ... | |
109 | 118 |
printf "%.8f %d %.8f %8.3f" ini_cv plc_len fin_cv |
110 | 119 |
(if fin_cv == 0 then 1 else ini_cv / fin_cv) |
111 | 120 |
|
121 |
-- | Submits a list of jobs and waits for all to finish execution |
|
122 |
execJobs :: L.Client -> [[OpCodes.OpCode]] -> IO (Result [String]) |
|
123 |
execJobs client = L.submitManyJobs client . showJSON |
|
124 |
|
|
125 |
-- | Polls a set of jobs at a fixed interval until all are finished |
|
126 |
-- one way or another |
|
127 |
waitForJobs :: L.Client -> [String] -> IO (Result [JobStatus]) |
|
128 |
waitForJobs client jids = do |
|
129 |
sts <- L.queryJobsStatus client jids |
|
130 |
case sts of |
|
131 |
Bad x -> return $ Bad x |
|
132 |
Ok s -> if any (<= JobRunning) s |
|
133 |
then do |
|
134 |
-- TODO: replace hardcoded value with a better thing |
|
135 |
threadDelay (1000000 * 15) |
|
136 |
waitForJobs client jids |
|
137 |
else return $ Ok s |
|
138 |
|
|
139 |
-- | Check that a set of job statuses is all success |
|
140 |
checkJobsStatus :: [JobStatus] -> Bool |
|
141 |
checkJobsStatus = all (== JobSuccess) |
|
142 |
|
|
143 |
-- | Execute an entire jobset |
|
144 |
execJobSet :: String -> String -> Node.List |
|
145 |
-> Instance.List -> [JobSet] -> IO () |
|
146 |
execJobSet _ _ _ _ [] = return () |
|
147 |
execJobSet master csf nl il (js:jss) = do |
|
148 |
-- map from jobset (htools list of positions) to [[opcodes]] |
|
149 |
let jobs = map (\(_, idx, move, _) -> |
|
150 |
Cluster.iMoveToJob csf nl il idx move) js |
|
151 |
let descr = map (\(_, idx, _, _) -> Container.nameOf il idx) js |
|
152 |
putStrLn $ "Executing jobset for instances " ++ commaJoin descr |
|
153 |
jrs <- bracket (L.getClient master) L.closeClient |
|
154 |
(\client -> do |
|
155 |
jids <- execJobs client jobs |
|
156 |
case jids of |
|
157 |
Bad x -> return $ Bad x |
|
158 |
Ok x -> do |
|
159 |
putStrLn $ "Got job IDs " ++ commaJoin x |
|
160 |
waitForJobs client x |
|
161 |
) |
|
162 |
(case jrs of |
|
163 |
Bad x -> do |
|
164 |
hPutStrLn stderr $ "Cannot compute job status, aborting: " ++ show x |
|
165 |
return () |
|
166 |
Ok x -> if checkJobsStatus x |
|
167 |
then execJobSet master csf nl il jss |
|
168 |
else do |
|
169 |
hPutStrLn stderr $ "Not all jobs completed successfully: " ++ |
|
170 |
show x |
|
171 |
hPutStrLn stderr "Aborting.") |
|
172 |
|
|
112 | 173 |
-- | Main function. |
113 | 174 |
main :: IO () |
114 | 175 |
main = do |
... | ... | |
212 | 273 |
unless (oneline || verbose == 0) $ |
213 | 274 |
printf "Solution length=%d\n" (length ord_plc) |
214 | 275 |
|
215 |
let cmd_data = Cluster.formatCmds . Cluster.splitJobs $ cmd_strs |
|
276 |
let cmd_jobs = Cluster.splitJobs cmd_strs |
|
277 |
cmd_data = Cluster.formatCmds cmd_jobs |
|
216 | 278 |
|
217 | 279 |
when (isJust $ optShowCmds opts) $ |
218 | 280 |
do |
... | ... | |
227 | 289 |
writeFile out_path (shTemplate ++ cmd_data) |
228 | 290 |
printf "The commands have been written to file '%s'\n" out_path) |
229 | 291 |
|
292 |
when (optExecJobs opts && not (null ord_plc)) |
|
293 |
(case optLuxi opts of |
|
294 |
Nothing -> do |
|
295 |
hPutStrLn stderr "Execution of commands possible only on LUXI" |
|
296 |
exitWith $ ExitFailure 1 |
|
297 |
Just master -> execJobSet master csf fin_nl il cmd_jobs) |
|
298 |
|
|
230 | 299 |
when (optShowNodes opts) $ |
231 | 300 |
do |
232 | 301 |
let ini_cs = Cluster.totalResources nl |
Also available in: Unified diff