1 {-| Implementation of the iallocator interface.
5 module Ganeti.HTools.IAlloc
16 import Text.JSON (JSObject, JSValue(JSBool, JSString, JSArray),
17 makeObj, encodeStrict, decodeStrict,
18 fromJSObject, toJSString)
19 --import Text.Printf (printf)
20 import qualified Ganeti.HTools.Container as Container
21 import qualified Ganeti.HTools.Node as Node
22 import qualified Ganeti.HTools.Instance as Instance
23 import Ganeti.HTools.Loader
24 import Ganeti.HTools.Utils
25 import Ganeti.HTools.Types
28 = Allocate Instance.Instance Int
29 | Relocate Idx Int [Ndx]
32 data Request = Request RqType Node.List Instance.List String
35 parseBaseInstance :: String
37 -> Result (String, Instance.Instance)
38 parseBaseInstance n a = do
39 disk <- case fromObj "disk_usage" a of
41 all_d <- fromObj "disks" a >>= asObjectList
42 szd <- mapM (fromObj "size") all_d
43 let sze = map (+128) szd
47 mem <- fromObj "memory" a
48 let running = "running"
49 return $ (n, Instance.create n mem disk running 0 0)
51 parseInstance :: NameAssoc
54 -> Result (String, Instance.Instance)
55 parseInstance ktn n a = do
56 base <- parseBaseInstance n a
57 nodes <- fromObj "nodes" a
58 pnode <- readEitherString $ head nodes
59 pidx <- lookupNode ktn n pnode
60 let snodes = tail nodes
61 sidx <- (if null snodes then return Node.noSecondary
62 else (readEitherString $ head snodes) >>= lookupNode ktn n)
63 return (n, Instance.setBoth (snd base) pidx sidx)
65 parseNode :: String -> JSObject JSValue -> Result (String, Node.Node)
68 offline <- fromObj "offline" a
69 drained <- fromObj "drained" a
70 node <- (case offline of
71 True -> return $ Node.create name 0 0 0 0 0 True
73 mtotal <- fromObj "total_memory" a
74 mnode <- fromObj "reserved_memory" a
75 mfree <- fromObj "free_memory" a
76 dtotal <- fromObj "total_disk" a
77 dfree <- fromObj "free_disk" a
78 return $ Node.create n mtotal mnode mfree
79 dtotal dfree (offline || drained))
82 parseData :: String -> Result Request
84 decoded <- fromJResult $ decodeStrict body
87 request <- fromObj "request" obj
88 rname <- fromObj "name" request
89 -- existing node parsing
90 nlist <- fromObj "nodes" obj
91 let ndata = fromJSObject nlist
92 nobj <- (mapM (\(x,y) -> asJSObject y >>= parseNode x)) ndata
93 let (ktn, nl) = assignIndices nobj
94 -- existing instance parsing
95 ilist <- fromObj "instances" obj
96 let idata = fromJSObject ilist
97 iobj <- (mapM (\(x,y) -> asJSObject y >>= parseInstance ktn x)) idata
98 let (kti, il) = assignIndices iobj
99 (map_n, map_i, csf) <- mergeData (nl, il)
100 req_nodes <- fromObj "required_nodes" request
101 optype <- fromObj "type" request
106 inew <- parseBaseInstance rname request
108 return $ Allocate io req_nodes
111 ridx <- lookupNode kti rname rname
112 ex_nodes <- fromObj "relocate_from" request
113 let ex_nodes' = map (stripSuffix $ length csf) ex_nodes
114 ex_idex <- mapM (Container.findByName map_n) ex_nodes'
115 return $ Relocate ridx req_nodes ex_idex
116 other -> fail $ ("Invalid request type '" ++ other ++ "'")
117 return $ Request rqtype map_n map_i csf
119 formatResponse :: Bool -> String -> [String] -> String
120 formatResponse success info nodes =
122 e_success = ("success", JSBool success)
123 e_info = ("info", JSString . toJSString $ info)
124 e_nodes = ("nodes", JSArray $ map (JSString . toJSString) nodes)
125 in encodeStrict $ makeObj [e_success, e_info, e_nodes]