-
Iustin Pop authored
In order to simplify the data structures, we add back the name on the node and instance objects. We still keep the index for, well, indexing, but we will use the name directly from the object, in order to get rid of the ktn/kti arguments which are passed around everywhere.
2727257a
IAlloc.hs 3.63 KiB
{-| Implementation of the iallocator interface.
-}
module Ganeti.HTools.IAlloc
(
parseData
, formatResponse
) where
import Data.Either ()
--import Data.Maybe
import Control.Monad
import Text.JSON (JSObject, JSValue(JSBool, JSString, JSArray),
makeObj, encodeStrict, decodeStrict,
fromJSObject, toJSString)
--import Text.Printf (printf)
import qualified Ganeti.HTools.Node as Node
import qualified Ganeti.HTools.Instance as Instance
import Ganeti.HTools.Loader
import Ganeti.HTools.Utils
import Ganeti.HTools.Types
data RqType
= Allocate String Instance.Instance
| Relocate Int
deriving (Show)
data Request = Request RqType IdxNode IdxInstance NameList NameList
deriving (Show)
parseBaseInstance :: String
-> JSObject JSValue
-> Result (String, Instance.Instance)
parseBaseInstance n a = do
disk <- case fromObj "disk_usage" a of
Bad _ -> do
all_d <- fromObj "disks" a >>= asObjectList
szd <- mapM (fromObj "size") all_d
let sze = map (+128) szd
szf = (sum sze)::Int
return szf
x@(Ok _) -> x
mem <- fromObj "memory" a
let running = "running"
return $ (n, Instance.create n mem disk running 0 0)
parseInstance :: NameAssoc
-> String
-> JSObject JSValue
-> Result (String, Instance.Instance)
parseInstance ktn n a = do
base <- parseBaseInstance n a
nodes <- fromObj "nodes" a
pnode <- readEitherString $ head nodes
snode <- readEitherString $ (head . tail) nodes
pidx <- lookupNode ktn n pnode
sidx <- lookupNode ktn n snode
return (n, Instance.setBoth (snd base) pidx sidx)
parseNode :: String -> JSObject JSValue -> Result (String, Node.Node)
parseNode n a = do
let name = n
mtotal <- fromObj "total_memory" a
mnode <- fromObj "reserved_memory" a
mfree <- fromObj "free_memory" a
dtotal <- fromObj "total_disk" a
dfree <- fromObj "free_disk" a
offline <- fromObj "offline" a
drained <- fromObj "offline" a
return $ (name, Node.create n mtotal mnode mfree dtotal dfree
(offline || drained))
parseData :: String -> Result Request
parseData body = do
decoded <- fromJResult $ decodeStrict body
let obj = decoded
-- request parser
request <- fromObj "request" obj
rname <- fromObj "name" request
-- existing node parsing
nlist <- fromObj "nodes" obj
let ndata = fromJSObject nlist
nobj <- (mapM (\(x,y) -> asJSObject y >>= parseNode x)) ndata
let (ktn, nl) = assignIndices Node.setIdx nobj
-- existing instance parsing
ilist <- fromObj "instances" obj
let idata = fromJSObject ilist
iobj <- (mapM (\(x,y) -> asJSObject y >>= parseInstance ktn x)) idata
let (kti, il) = assignIndices Instance.setIdx iobj
optype <- fromObj "type" request
rqtype <-
case optype of
"allocate" ->
do
inew <- parseBaseInstance rname request
let (iname, io) = inew
return $ Allocate iname io
"relocate" ->
do
ridx <- lookupNode kti rname rname
return $ Relocate ridx
other -> fail $ ("Invalid request type '" ++ other ++ "'")
return $ Request rqtype nl il (swapPairs ktn) (swapPairs kti)
formatResponse :: Bool -> String -> [String] -> String
formatResponse success info nodes =
let
e_success = ("success", JSBool success)
e_info = ("info", JSString . toJSString $ info)
e_nodes = ("nodes", JSArray $ map (JSString . toJSString) nodes)
in encodeStrict $ makeObj [e_success, e_info, e_nodes]