root / Ganeti / HTools / IAlloc.hs @ 144f190b
History | View | Annotate | Download (4.1 kB)
1 |
{-| Implementation of the iallocator interface. |
---|---|
2 |
|
3 |
-} |
4 |
|
5 |
module Ganeti.HTools.IAlloc |
6 |
( |
7 |
parseData |
8 |
, formatResponse |
9 |
) where |
10 |
|
11 |
import Data.Either () |
12 |
import Data.Maybe |
13 |
import Control.Monad |
14 |
import Text.JSON |
15 |
import Text.Printf (printf) |
16 |
import Ganeti.HTools.Utils |
17 |
|
18 |
data RqType |
19 |
= Allocate |
20 |
| Relocate |
21 |
deriving (Show) |
22 |
|
23 |
parseInstance :: String -> JSObject JSValue -> Either String String |
24 |
parseInstance n a = |
25 |
let name = Right n |
26 |
disk = case getIntElement "disk_usage" a of |
27 |
Left _ -> let all_d = getListElement "disks" a `combineEithers` |
28 |
asObjectList |
29 |
szd = all_d `combineEithers` |
30 |
(ensureEitherList . |
31 |
map (getIntElement "size")) |
32 |
sze = applyEither1 (map (+128)) szd |
33 |
szf = applyEither1 sum sze |
34 |
in szf |
35 |
Right x -> Right x |
36 |
nodes = getListElement "nodes" a |
37 |
pnode = eitherListHead nodes |
38 |
`combineEithers` readEitherString |
39 |
snode = applyEither1 (head . tail) nodes |
40 |
`combineEithers` readEitherString |
41 |
mem = getIntElement "memory" a |
42 |
running = Right "running" --getStringElement "status" a |
43 |
in |
44 |
concatEitherElems name $ |
45 |
concatEitherElems (show `applyEither1` mem) $ |
46 |
concatEitherElems (show `applyEither1` disk) $ |
47 |
concatEitherElems running $ |
48 |
concatEitherElems pnode snode |
49 |
|
50 |
parseNode :: String -> JSObject JSValue -> Either String String |
51 |
parseNode n a = |
52 |
let name = Right n |
53 |
mtotal = getIntElement "total_memory" a |
54 |
mnode = getIntElement "reserved_memory" a |
55 |
mfree = getIntElement "free_memory" a |
56 |
dtotal = getIntElement "total_disk" a |
57 |
dfree = getIntElement "free_disk" a |
58 |
in concatEitherElems name $ |
59 |
concatEitherElems (show `applyEither1` mtotal) $ |
60 |
concatEitherElems (show `applyEither1` mnode) $ |
61 |
concatEitherElems (show `applyEither1` mfree) $ |
62 |
concatEitherElems (show `applyEither1` dtotal) |
63 |
(show `applyEither1` dfree) |
64 |
|
65 |
validateRequest :: String -> Either String RqType |
66 |
validateRequest rq = |
67 |
case rq of |
68 |
"allocate" -> Right Allocate |
69 |
"relocate" -> Right Relocate |
70 |
_ -> Left ("Invalid request type '" ++ rq ++ "'") |
71 |
|
72 |
parseData :: String -> Either String (String, String) |
73 |
parseData body = |
74 |
let |
75 |
decoded = resultToEither $ decodeStrict body |
76 |
obj = decoded -- decoded `combineEithers` fromJSObject |
77 |
-- request parser |
78 |
request = obj `combineEithers` getObjectElement "request" |
79 |
rname = request `combineEithers` getStringElement "name" |
80 |
rtype = request `combineEithers` getStringElement "type" |
81 |
`combineEithers` validateRequest |
82 |
-- existing intstance parsing |
83 |
ilist = obj `combineEithers` getObjectElement "instances" |
84 |
idata = applyEither1 fromJSObject ilist |
85 |
iobj = idata `combineEithers` (ensureEitherList . |
86 |
map (\(x,y) -> |
87 |
asJSObject y `combineEithers` |
88 |
parseInstance x)) |
89 |
ilines = iobj `combineEithers` (Right . unlines) |
90 |
-- existing node parsing |
91 |
nlist = obj `combineEithers` getObjectElement "nodes" |
92 |
ndata = applyEither1 fromJSObject nlist |
93 |
nobj = ndata `combineEithers` (ensureEitherList . |
94 |
map (\(x,y) -> |
95 |
asJSObject y `combineEithers` |
96 |
parseNode x)) |
97 |
nlines = nobj `combineEithers` (Right . unlines) |
98 |
in applyEither2 (,) nlines ilines |
99 |
|
100 |
formatResponse :: Bool -> String -> [String] -> String |
101 |
formatResponse success info nodes = |
102 |
let |
103 |
e_success = ("success", JSBool success) |
104 |
e_info = ("info", JSString . toJSString $ info) |
105 |
e_nodes = ("nodes", JSArray $ map (JSString . toJSString) nodes) |
106 |
in encodeStrict $ makeObj [e_success, e_info, e_nodes] |