Revision 2cdaf225
b/Makefile.am | ||
---|---|---|
1358 | 1358 |
$(PEP8) --ignore='$(PEP8_IGNORE)' --exclude='$(PEP8_EXCLUDE)' \ |
1359 | 1359 |
--repeat $(pep8_python_code) |
1360 | 1360 |
|
1361 |
# FIXME: remove ignore "Use void" when GHC 6.x is deprecated |
|
1361 | 1362 |
.PHONY: hlint |
1362 | 1363 |
hlint: $(HS_BUILT_SRCS) htools/lint-hints.hs |
1363 | 1364 |
@test -n "$(HLINT)" || { echo 'hlint' not found during configure; exit 1; } |
... | ... | |
1367 | 1368 |
--ignore "Use comparing" \ |
1368 | 1369 |
--ignore "Use on" \ |
1369 | 1370 |
--ignore "Reduce duplication" \ |
1371 |
--ignore "Use &&&" \ |
|
1372 |
--ignore "Use void" \ |
|
1370 | 1373 |
--hint htools/lint-hints \ |
1371 | 1374 |
$(filter-out htools/Ganeti/THH.hs,$(HS_LIB_SRCS)) |
1372 | 1375 |
|
b/htools/Ganeti/Confd.hs | ||
---|---|---|
89 | 89 |
-- converts them to strings anyway, as they're used as dict-keys. |
90 | 90 |
|
91 | 91 |
$(buildObject "ConfdReqQ" "confdReqQ" |
92 |
[ renameField "Ip" $
|
|
92 |
[ renameField "Ip" .
|
|
93 | 93 |
optionalField $ simpleField C.confdReqqIp [t| String |] |
94 |
, renameField "IpList" $
|
|
94 |
, renameField "IpList" .
|
|
95 | 95 |
defaultField [| [] |] $ |
96 | 96 |
simpleField C.confdReqqIplist [t| [String] |] |
97 |
, renameField "Link" $ optionalField $
|
|
97 |
, renameField "Link" . optionalField $
|
|
98 | 98 |
simpleField C.confdReqqLink [t| String |] |
99 |
, renameField "Fields" $ defaultField [| [] |] $
|
|
99 |
, renameField "Fields" . defaultField [| [] |] $
|
|
100 | 100 |
simpleField C.confdReqqFields [t| [ConfdReqField] |] |
101 | 101 |
]) |
102 | 102 |
|
b/htools/Ganeti/Confd/Server.hs | ||
---|---|---|
31 | 31 |
|
32 | 32 |
import Control.Concurrent |
33 | 33 |
import Control.Exception |
34 |
import Control.Monad (forever, liftM) |
|
34 |
import Control.Monad (forever, liftM, when)
|
|
35 | 35 |
import qualified Data.ByteString as B |
36 | 36 |
import Data.IORef |
37 | 37 |
import Data.List |
38 | 38 |
import qualified Data.Map as M |
39 |
import Data.Maybe (fromMaybe) |
|
39 | 40 |
import qualified Network.Socket as S |
40 | 41 |
import Prelude hiding (catch) |
41 | 42 |
import System.Posix.Files |
... | ... | |
217 | 218 |
buildResponse cdata (ConfdRequest { confdRqType = ReqNodePipByInstPip |
218 | 219 |
, confdRqQuery = DictQuery query}) = |
219 | 220 |
let (cfg, linkipmap) = cdata |
220 |
link = maybe (getDefaultNicLink cfg) id (confdReqQLink query)
|
|
221 |
link = fromMaybe (getDefaultNicLink cfg) (confdReqQLink query)
|
|
221 | 222 |
in case confdReqQIp query of |
222 | 223 |
Just ip -> return $ getNodePipByInstanceIp cfg linkipmap link ip |
223 | 224 |
Nothing -> return (ReplyStatusOk, |
... | ... | |
333 | 334 |
-- | Wrapper over 'buildFileStatus'. This reads the data from the |
334 | 335 |
-- filesystem and then builds our cache structure. |
335 | 336 |
getFStat :: FilePath -> IO FStat |
336 |
getFStat p = getFileStatus p >>= (return . buildFileStatus)
|
|
337 |
getFStat p = liftM buildFileStatus (getFileStatus p)
|
|
337 | 338 |
|
338 | 339 |
-- | Check if the file needs reloading |
339 | 340 |
needsReload :: FStat -> FilePath -> IO (Maybe FStat) |
... | ... | |
389 | 390 |
onReloadTimer :: IO Bool -> FilePath -> CRef -> MVar ServerState -> IO () |
390 | 391 |
onReloadTimer inotiaction path cref state = do |
391 | 392 |
continue <- modifyMVar state (onReloadInner inotiaction path cref) |
392 |
if continue |
|
393 |
then do |
|
394 |
threadDelay configReloadRatelimit |
|
395 |
onReloadTimer inotiaction path cref state |
|
396 |
else -- the inotify watch has been re-established, we can exit |
|
397 |
return () |
|
393 |
when continue $ |
|
394 |
do threadDelay configReloadRatelimit |
|
395 |
onReloadTimer inotiaction path cref state |
|
396 |
-- the inotify watch has been re-established, we can exit |
|
398 | 397 |
|
399 | 398 |
-- | Inner onReload handler. |
400 | 399 |
-- |
... | ... | |
425 | 424 |
_ -> True |
426 | 425 |
return (state' { reloadModel = newmode }, continue) |
427 | 426 |
|
427 |
-- the following hint is because hlint doesn't understand our const |
|
428 |
-- (return False) is so that we can give a signature to 'e' |
|
429 |
{-# ANN addNotifier "HLint: ignore Evaluate" #-} |
|
428 | 430 |
-- | Setup inotify watcher. |
429 | 431 |
-- |
430 | 432 |
-- This tries to setup the watch descriptor; in case of any IO errors, |
b/htools/Ganeti/Config.hs | ||
---|---|---|
37 | 37 |
, instNodes |
38 | 38 |
) where |
39 | 39 |
|
40 |
import Control.Monad (liftM) |
|
40 | 41 |
import Data.List (foldl') |
41 | 42 |
import qualified Data.Map as M |
42 | 43 |
import qualified Data.Set as S |
... | ... | |
134 | 135 |
-- | Looks up an instance's primary node. |
135 | 136 |
getInstPrimaryNode :: ConfigData -> String -> Result Node |
136 | 137 |
getInstPrimaryNode cfg name = |
137 |
getInstance cfg name >>= return . instPrimaryNode >>= getNode cfg
|
|
138 |
liftM instPrimaryNode (getInstance cfg name) >>= getNode cfg
|
|
138 | 139 |
|
139 | 140 |
-- | Filters DRBD minors for a given node. |
140 | 141 |
getDrbdMinorsForNode :: String -> Disk -> [(Int, String)] |
b/htools/Ganeti/Daemon.hs | ||
---|---|---|
314 | 314 |
|
315 | 315 |
when (optShowHelp opts) $ do |
316 | 316 |
putStr $ usageHelp progname options |
317 |
exitWith ExitSuccess
|
|
317 |
exitSuccess |
|
318 | 318 |
when (optShowVer opts) $ do |
319 | 319 |
printf "%s %s\ncompiled with %s %s\nrunning on %s %s\n" |
320 | 320 |
progname Version.version |
321 | 321 |
compilerName (Data.Version.showVersion compilerVersion) |
322 | 322 |
os arch :: IO () |
323 |
exitWith ExitSuccess
|
|
323 |
exitSuccess |
|
324 | 324 |
|
325 | 325 |
exitUnless (null args) "This program doesn't take any arguments" |
326 | 326 |
|
b/htools/Ganeti/HTools/Cluster.hs | ||
---|---|---|
931 | 931 |
let no_nodes = Left "no nodes available" |
932 | 932 |
node_pairs = [(p,s) | p <- avail_nodes, s <- avail_nodes, p /= s] |
933 | 933 |
(nl', il', ops, _) <- |
934 |
annotateResult "Can't find any good nodes for relocation" $
|
|
934 |
annotateResult "Can't find any good nodes for relocation" .
|
|
935 | 935 |
eitherToResult $ |
936 | 936 |
foldl' |
937 | 937 |
(\accu nodes -> case evacDrbdAllInner nl il inst gdx nodes of |
... | ... | |
974 | 974 |
MirrorNone -> Bad "Can't relocate/evacuate non-mirrored instances" |
975 | 975 |
MirrorInternal -> Ok ReplaceSecondary |
976 | 976 |
MirrorExternal -> Ok FailoverToAny |
977 |
(nl', inst', _, ndx) <- annotateResult "Can't find any good node" $
|
|
977 |
(nl', inst', _, ndx) <- annotateResult "Can't find any good node" .
|
|
978 | 978 |
eitherToResult $ |
979 | 979 |
foldl' (evacOneNodeInner nl inst gdx op_fn) |
980 | 980 |
(Left "no nodes available") avail_nodes |
... | ... | |
1046 | 1046 |
if Node.offline primary |
1047 | 1047 |
then do |
1048 | 1048 |
(nl', inst', _, _) <- |
1049 |
annotateResult "Failing over to the secondary" $
|
|
1049 |
annotateResult "Failing over to the secondary" .
|
|
1050 | 1050 |
opToResult $ applyMove nl inst Failover |
1051 | 1051 |
return (nl', inst', [Failover]) |
1052 | 1052 |
else return (nl, inst, []) |
... | ... | |
1056 | 1056 |
-- we now need to execute a replace secondary to the future |
1057 | 1057 |
-- primary node |
1058 | 1058 |
(nl2, inst2, _, _) <- |
1059 |
annotateResult "Changing secondary to new primary" $
|
|
1059 |
annotateResult "Changing secondary to new primary" .
|
|
1060 | 1060 |
opToResult $ |
1061 | 1061 |
applyMove nl1 inst1 o1 |
1062 | 1062 |
let ops2 = o1:ops1 |
1063 | 1063 |
-- we now execute another failover, the primary stays fixed now |
1064 |
(nl3, inst3, _, _) <- annotateResult "Failing over to new primary" $
|
|
1064 |
(nl3, inst3, _, _) <- annotateResult "Failing over to new primary" .
|
|
1065 | 1065 |
opToResult $ applyMove nl2 inst2 o2 |
1066 | 1066 |
let ops3 = o2:ops2 |
1067 | 1067 |
-- and finally another replace secondary, to the final secondary |
1068 | 1068 |
(nl4, inst4, _, _) <- |
1069 |
annotateResult "Changing secondary to final secondary" $
|
|
1069 |
annotateResult "Changing secondary to final secondary" .
|
|
1070 | 1070 |
opToResult $ |
1071 | 1071 |
applyMove nl3 inst3 o3 |
1072 | 1072 |
let ops4 = o3:ops3 |
b/htools/Ganeti/HTools/ExtLoader.hs | ||
---|---|---|
55 | 55 |
|
56 | 56 |
-- | Error beautifier. |
57 | 57 |
wrapIO :: IO (Result a) -> IO (Result a) |
58 |
wrapIO = flip catch (\e -> return . Bad . show $ (e::IOException))
|
|
58 |
wrapIO = handle (\e -> return . Bad . show $ (e::IOException))
|
|
59 | 59 |
|
60 | 60 |
-- | Parses a user-supplied utilisation string. |
61 | 61 |
parseUtilisation :: String -> Result (String, DynUtil) |
... | ... | |
102 | 102 |
input_data <- |
103 | 103 |
case () of |
104 | 104 |
_ | setRapi -> wrapIO $ Rapi.loadData mhost |
105 |
| setLuxi -> wrapIO $ Luxi.loadData $ fromJust lsock
|
|
105 |
| setLuxi -> wrapIO . Luxi.loadData $ fromJust lsock
|
|
106 | 106 |
| setSim -> Simu.loadData simdata |
107 |
| setFile -> wrapIO $ Text.loadData $ fromJust tfile
|
|
108 |
| setIAllocSrc -> wrapIO $ IAlloc.loadData $ fromJust iallocsrc
|
|
107 |
| setFile -> wrapIO . Text.loadData $ fromJust tfile
|
|
108 |
| setIAllocSrc -> wrapIO . IAlloc.loadData $ fromJust iallocsrc
|
|
109 | 109 |
| otherwise -> return $ Bad "No backend selected! Exiting." |
110 | 110 |
|
111 | 111 |
let ldresult = input_data >>= mergeData util_data exTags selInsts exInsts |
b/htools/Ganeti/HTools/IAlloc.hs | ||
---|---|---|
276 | 276 |
MirrorNone -> fail "Can't relocate non-mirrored instances" |
277 | 277 |
MirrorInternal -> return (sorig, "secondary", ChangeSecondary) |
278 | 278 |
MirrorExternal -> return (porig, "primary", ChangePrimary) |
279 |
when (exndx /= [exp_node]) $
|
|
279 |
when (exndx /= [exp_node]) .
|
|
280 | 280 |
-- FIXME: we can't use the excluded nodes here; the logic is |
281 | 281 |
-- already _but only partially_ implemented in tryNodeEvac... |
282 | 282 |
fail $ "Unsupported request: excluded nodes not equal to\ |
b/htools/Ganeti/HTools/Program/Hail.hs | ||
---|---|---|
75 | 75 |
|
76 | 76 |
let Request rq cdata = request |
77 | 77 |
|
78 |
when (verbose > 1) $
|
|
78 |
when (verbose > 1) .
|
|
79 | 79 |
hPutStrLn stderr $ "Received request: " ++ show rq |
80 | 80 |
|
81 |
when (verbose > 2) $
|
|
81 |
when (verbose > 2) .
|
|
82 | 82 |
hPutStrLn stderr $ "Received cluster data: " ++ show cdata |
83 | 83 |
|
84 | 84 |
maybePrintNodes shownodes "Initial cluster" |
b/htools/Ganeti/HTools/Program/Hbal.hs | ||
---|---|---|
297 | 297 |
-- nothing to do on an empty cluster |
298 | 298 |
when (Container.null il) $ do |
299 | 299 |
printf "Cluster is empty, exiting.\n"::IO () |
300 |
exitWith ExitSuccess
|
|
300 |
exitSuccess |
|
301 | 301 |
|
302 | 302 |
-- hbal doesn't currently handle split clusters |
303 | 303 |
let split_insts = Cluster.findSplitInstances nl il |
... | ... | |
328 | 328 |
"Initial check done: %d bad nodes, %d bad instances.\n" |
329 | 329 |
(length bad_nodes) (length bad_instances) |
330 | 330 |
|
331 |
when (not (null bad_nodes)) $
|
|
331 |
unless (null bad_nodes) $
|
|
332 | 332 |
putStrLn "Cluster is not N+1 happy, continuing but no guarantee \ |
333 | 333 |
\that the cluster will end N+1 happy." |
334 | 334 |
|
... | ... | |
340 | 340 |
printf "Cluster is already well balanced (initial score %.6g,\n\ |
341 | 341 |
\minimum score %.6g).\nNothing to do, exiting\n" |
342 | 342 |
ini_cv min_cv:: IO () |
343 |
exitWith ExitSuccess
|
|
343 |
exitSuccess |
|
344 | 344 |
|
345 | 345 |
-- | Main function. |
346 | 346 |
main :: Options -> [String] -> IO () |
... | ... | |
411 | 411 |
|
412 | 412 |
let cmd_jobs = Cluster.splitJobs cmd_strs |
413 | 413 |
|
414 |
when (isJust $ optShowCmds opts) $
|
|
414 |
when (isJust $ optShowCmds opts) .
|
|
415 | 415 |
saveBalanceCommands opts $ Cluster.formatCmds cmd_jobs |
416 | 416 |
|
417 | 417 |
maybeSaveData (optSaveCluster opts) "balanced" "after balancing" |
b/htools/Ganeti/HTools/Program/Hcheck.hs | ||
---|---|---|
188 | 188 |
unless (verbose == 0) $ do |
189 | 189 |
putStrLn "" |
190 | 190 |
putStr prefix |
191 |
mapM_ (\(a,b) -> printf " %s: %s\n" a b) (zip descr values)
|
|
191 |
mapM_ (uncurry (printf " %s: %s\n")) (zip descr values)
|
|
192 | 192 |
|
193 | 193 |
-- | Extract name or idx from group. |
194 | 194 |
extractGroupData :: Bool -> Group.Group -> String |
... | ... | |
230 | 230 |
perGroupChecks gl (gidx, (nl, il)) = |
231 | 231 |
let grp = Container.find gidx gl |
232 | 232 |
offnl = filter Node.offline (Container.elems nl) |
233 |
n1violated = length $ fst $ Cluster.computeBadItems nl il
|
|
233 |
n1violated = length . fst $ Cluster.computeBadItems nl il
|
|
234 | 234 |
conflicttags = length $ filter (>0) |
235 | 235 |
(map Node.conflictingPrimaries (Container.elems nl)) |
236 | 236 |
offline_pri = sum . map length $ map Node.pList offnl |
... | ... | |
335 | 335 |
|
336 | 336 |
printFinalHTC machineread |
337 | 337 |
|
338 |
unless exitOK $ exitWith $ ExitFailure 1 |
|
338 |
unless exitOK . exitWith $ ExitFailure 1 |
b/htools/Ganeti/HTools/Program/Hscan.hs | ||
---|---|---|
118 | 118 |
oname = odir </> fixSlash name |
119 | 119 |
putStrLn $ printCluster nl il |
120 | 120 |
hFlush stdout |
121 |
when (isJust shownodes) $
|
|
121 |
when (isJust shownodes) .
|
|
122 | 122 |
putStr $ Cluster.printNodes nl (fromJust shownodes) |
123 | 123 |
writeFile (oname <.> "data") (serializeCluster cdata) |
124 | 124 |
return True |
... | ... | |
142 | 142 |
let name = local |
143 | 143 |
input_data <- Luxi.loadData lsock |
144 | 144 |
result <- writeData nlen name opts input_data |
145 |
unless result $ exitWith $ ExitFailure 2
|
|
145 |
unless result . exitWith $ ExitFailure 2
|
|
146 | 146 |
|
147 | 147 |
results <- mapM (\name -> Rapi.loadData name >>= writeData nlen name opts) |
148 | 148 |
clusters |
b/htools/Ganeti/HTools/QC.hs | ||
---|---|---|
1426 | 1426 |
case genClusterAlloc count node inst of |
1427 | 1427 |
Types.Bad msg -> failTest msg |
1428 | 1428 |
Types.Ok (nl, il, inst') -> |
1429 |
conjoin $ map (\mode -> check_EvacMode defGroup inst' $
|
|
1429 |
conjoin . map (\mode -> check_EvacMode defGroup inst' $
|
|
1430 | 1430 |
Cluster.tryNodeEvac defGroupList nl il mode |
1431 | 1431 |
[Instance.idx inst']) . |
1432 | 1432 |
evacModeOptions . |
... | ... | |
1894 | 1894 |
-- ready |
1895 | 1895 |
server <- run $ Luxi.getServer fpath |
1896 | 1896 |
-- fork the server responder |
1897 |
_ <- run $ forkIO $
|
|
1897 |
_ <- run . forkIO $
|
|
1898 | 1898 |
bracket |
1899 | 1899 |
(Luxi.acceptClient server) |
1900 | 1900 |
(\c -> Luxi.closeClient c >> removeFile fpath) |
b/htools/Ganeti/HTools/Rapi.hs | ||
---|---|---|
85 | 85 |
-- | Helper to convert I/O errors in 'Bad' values. |
86 | 86 |
ioErrToResult :: IO a -> IO (Result a) |
87 | 87 |
ioErrToResult ioaction = |
88 |
catch (ioaction >>= return . Ok)
|
|
88 |
catch (liftM Ok ioaction)
|
|
89 | 89 |
(\e -> return . Bad . show $ (e::IOException)) |
90 | 90 |
|
91 | 91 |
-- | Append the default port if not passed in. |
... | ... | |
203 | 203 |
readDataFile:: String -- ^ Path to the directory containing the files |
204 | 204 |
-> IO (Result String, Result String, Result String, Result String) |
205 | 205 |
readDataFile path = do |
206 |
group_body <- ioErrToResult $ readFile $ path </> "groups.json"
|
|
207 |
node_body <- ioErrToResult $ readFile $ path </> "nodes.json"
|
|
208 |
inst_body <- ioErrToResult $ readFile $ path </> "instances.json"
|
|
209 |
info_body <- ioErrToResult $ readFile $ path </> "info.json"
|
|
206 |
group_body <- ioErrToResult . readFile $ path </> "groups.json"
|
|
207 |
node_body <- ioErrToResult . readFile $ path </> "nodes.json"
|
|
208 |
inst_body <- ioErrToResult . readFile $ path </> "instances.json"
|
|
209 |
info_body <- ioErrToResult . readFile $ path </> "info.json"
|
|
210 | 210 |
return (group_body, node_body, inst_body, info_body) |
211 | 211 |
|
212 | 212 |
-- | Loads data via either 'readDataFile' or 'readDataHttp'. |
b/htools/Ganeti/HTools/Simu.hs | ||
---|---|---|
30 | 30 |
, parseData |
31 | 31 |
) where |
32 | 32 |
|
33 |
import Control.Monad (mplus) |
|
33 |
import Control.Monad (mplus, zipWithM)
|
|
34 | 34 |
import Text.Printf (printf) |
35 | 35 |
|
36 | 36 |
import Ganeti.HTools.Utils |
... | ... | |
90 | 90 |
parseData :: [String] -- ^ Cluster description in text format |
91 | 91 |
-> Result ClusterData |
92 | 92 |
parseData ndata = do |
93 |
grpNodeData <- mapM (uncurry createGroup) $ zip [1..] ndata
|
|
93 |
grpNodeData <- zipWithM createGroup [1..] ndata
|
|
94 | 94 |
let (groups, nodes) = unzip grpNodeData |
95 | 95 |
nodes' = concat nodes |
96 | 96 |
let ktn = map (\(idx, n) -> (idx, Node.setIdx n idx)) |
b/htools/Ganeti/HTools/Text.hs | ||
---|---|---|
182 | 182 |
loadNode ktg [name, tm, nm, fm, td, fd, tc, fo, gu, spindles] = do |
183 | 183 |
gdx <- lookupGroup ktg name gu |
184 | 184 |
new_node <- |
185 |
if any (== "?") [tm,nm,fm,td,fd,tc] || fo == "Y" then
|
|
185 |
if "?" `elem` [tm,nm,fm,td,fd,tc] || fo == "Y" then
|
|
186 | 186 |
return $ Node.create name 0 0 0 0 0 0 True 0 gdx |
187 | 187 |
else do |
188 | 188 |
vtm <- tryRead name tm |
... | ... | |
224 | 224 |
disk_template <- annotateResult ("Instance " ++ name) |
225 | 225 |
(diskTemplateFromRaw dt) |
226 | 226 |
spindle_use <- tryRead name su |
227 |
when (sidx == pidx) $ fail $ "Instance " ++ name ++
|
|
227 |
when (sidx == pidx) . fail $ "Instance " ++ name ++
|
|
228 | 228 |
" has same primary and secondary node - " ++ pnode |
229 | 229 |
let vtags = commaSplit tags |
230 | 230 |
newinst = Instance.create name vmem vdsk vvcpus vstatus vtags |
b/htools/Ganeti/HTools/Utils.hs | ||
---|---|---|
168 | 168 |
-- | Constructs a printable table from given header and rows |
169 | 169 |
printTable :: String -> [String] -> [[String]] -> [Bool] -> String |
170 | 170 |
printTable lp header rows isnum = |
171 |
unlines . map ((++) lp) . map ((:) ' ' . unwords) $
|
|
171 |
unlines . map ((++) lp . (:) ' ' . unwords) $
|
|
172 | 172 |
formatTable (header:rows) isnum |
173 | 173 |
|
174 | 174 |
-- | Converts a unit (e.g. m or GB) into a scaling factor. |
b/htools/Ganeti/Hash.hs | ||
---|---|---|
47 | 47 |
|
48 | 48 |
-- | Converts a list of bytes to a string. |
49 | 49 |
word8ToString :: HashKey -> String |
50 |
word8ToString = concat . map (printf "%02x")
|
|
50 |
word8ToString = concatMap (printf "%02x")
|
|
51 | 51 |
|
52 | 52 |
-- | Computes the HMAC for a given key/test and salt. |
53 | 53 |
computeMac :: HashKey -> Maybe String -> String -> String |
b/htools/Ganeti/Logging.hs | ||
---|---|---|
112 | 112 |
Just path -> openFormattedHandler file_logging fmt $ |
113 | 113 |
fileHandler path level |
114 | 114 |
|
115 |
let handlers = concat [file_handlers, stderr_handlers]
|
|
115 |
let handlers = file_handlers ++ stderr_handlers
|
|
116 | 116 |
updateGlobalLogger rootLoggerName $ setHandlers handlers |
117 | 117 |
-- syslog handler is special (another type, still instance of the |
118 | 118 |
-- typeclass, and has a built-in formatter), so we can't pass it in |
b/htools/Ganeti/Luxi.hs | ||
---|---|---|
310 | 310 |
buildCall :: LuxiOp -- ^ The method |
311 | 311 |
-> String -- ^ The serialized form |
312 | 312 |
buildCall lo = |
313 |
let ja = [ (strOfKey Method, JSString $ toJSString $ strOfOp lo::JSValue)
|
|
314 |
, (strOfKey Args, opToArgs lo::JSValue)
|
|
313 |
let ja = [ (strOfKey Method, J.showJSON $ strOfOp lo)
|
|
314 |
, (strOfKey Args, opToArgs lo) |
|
315 | 315 |
] |
316 | 316 |
jo = toJSObject ja |
317 | 317 |
in encodeStrict jo |
b/htools/Ganeti/Rpc.hs | ||
---|---|---|
102 | 102 |
"Node " ++ nodeName node ++ " is marked as offline" |
103 | 103 |
|
104 | 104 |
rpcErrorJsonReport :: (Monad m) => J.Result a -> m (Either RpcError a) |
105 |
rpcErrorJsonReport (J.Error x) = return $ Left $ JsonDecodeError x
|
|
105 |
rpcErrorJsonReport (J.Error x) = return . Left $ JsonDecodeError x
|
|
106 | 106 |
rpcErrorJsonReport (J.Ok x) = return $ Right x |
107 | 107 |
|
108 | 108 |
-- | Basic timeouts for RPC calls. |
... | ... | |
162 | 162 |
url = requestUrl request |
163 | 163 |
-- FIXME: This is very similar to getUrl in Htools/Rapi.hs |
164 | 164 |
(code, !body) <- curlGetString url $ curlOpts ++ reqOpts |
165 |
case code of |
|
166 |
CurlOK -> return $ Right body
|
|
167 |
_ -> return $ Left $ CurlLayerError node (show code)
|
|
165 |
return $ case code of
|
|
166 |
CurlOK -> Right body
|
|
167 |
_ -> Left $ CurlLayerError node (show code)
|
|
168 | 168 |
#endif |
169 | 169 |
|
170 | 170 |
-- | Prepare url for the HTTP request. |
b/htools/Ganeti/Ssconf.hs | ||
---|---|---|
128 | 128 |
getPrimaryIPFamily :: Maybe FilePath -> IO (Result Socket.Family) |
129 | 129 |
getPrimaryIPFamily optpath = do |
130 | 130 |
result <- readSSConfFile optpath (Just (show C.ip4Family)) SSPrimaryIpFamily |
131 |
return (result >>= return . rstripSpace >>=
|
|
131 |
return (liftM rstripSpace result >>=
|
|
132 | 132 |
tryRead "Parsing af_family" >>= parseIPFamily) |
b/htools/lint-hints.hs | ||
---|---|---|
1 |
{- Custom hint lints for Ganeti. |
|
2 |
|
|
3 |
Since passing --hint to hlint will override, not extend the built-in hints, we need to import the existing hints so that we get full coverage. |
|
4 |
|
|
5 |
-} |
|
6 |
|
|
7 |
import "hint" HLint.Default |
|
8 |
import "hint" HLint.Dollar |
|
9 |
|
|
1 | 10 |
-- The following two hints warn to simplify e.g. "map (\v -> (v, |
2 | 11 |
-- True)) lst" to "zip lst (repeat True)", which is more abstract |
3 | 12 |
warn = map (\v -> (v, x)) y ==> zip y (repeat x) |
Also available in: Unified diff