{-
-Copyright (C) 2009 Google Inc.
+Copyright (C) 2009, 2010 Google Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
module Ganeti.HTools.Luxi
(
loadData
+ , parseData
) where
import qualified Control.Exception as E
queryNodesMsg :: L.LuxiOp
queryNodesMsg =
L.QueryNodes [] ["name", "mtotal", "mnode", "mfree", "dtotal", "dfree",
- "ctotal", "offline", "drained"] False
+ "ctotal", "offline", "drained", "vm_capable",
+ "group.uuid"] False
-- | The input data for instance query.
queryInstancesMsg :: L.LuxiOp
getInstances ktn arr = toArray arr >>= mapM (parseInstance ktn)
-- | Construct an instance from a JSON object.
-parseInstance :: [(String, Ndx)]
+parseInstance :: NameAssoc
-> JSValue
-> Result (String, Instance.Instance)
parseInstance ktn (JSArray [ name, disk, mem, vcpus
-- | Construct a node from a JSON object.
parseNode :: JSValue -> Result (String, Node.Node)
parseNode (JSArray [ name, mtotal, mnode, mfree, dtotal, dfree
- , ctotal, offline, drained ])
+ , ctotal, offline, drained, vm_capable, g_uuid ])
= do
xname <- annotateResult "Parsing new node" (fromJVal name)
let convert v = annotateResult ("Node '" ++ xname ++ "'") (fromJVal v)
xoffline <- convert offline
xdrained <- convert drained
- node <- (if xoffline || xdrained
- then return $ Node.create xname 0 0 0 0 0 0 True
+ xvm_capable <- convert vm_capable
+ xguuid <- convert g_uuid
+ node <- (if xoffline || xdrained || not xvm_capable
+ then return $ Node.create xname 0 0 0 0 0 0 True xguuid
else do
xmtotal <- convert mtotal
xmnode <- convert mnode
xdfree <- convert dfree
xctotal <- convert ctotal
return $ Node.create xname xmtotal xmnode xmfree
- xdtotal xdfree xctotal False)
+ xdtotal xdfree xctotal False xguuid)
return (xname, node)
parseNode v = fail ("Invalid node query result: " ++ show v)
-- * Main loader functionality
-- | Builds the cluster data from an URL.
-loadData :: String -- ^ Unix socket to use as source
- -> IO (Result (Node.AssocList, Instance.AssocList, [String]))
-loadData master =
+readData :: String -- ^ Unix socket to use as source
+ -> IO (Result JSValue, Result JSValue, Result JSValue)
+readData master =
E.bracket
(L.getClient master)
L.closeClient
nodes <- queryNodes s
instances <- queryInstances s
cinfo <- queryClusterInfo s
- return $ do -- Result monad
- node_data <- nodes >>= getNodes
- let (node_names, node_idx) = assignIndices node_data
- inst_data <- instances >>= getInstances node_names
- let (_, inst_idx) = assignIndices inst_data
- ctags <- cinfo >>= getClusterTags
- return (node_idx, inst_idx, ctags)
+ return (nodes, instances, cinfo)
)
+
+parseData :: (Result JSValue, Result JSValue, Result JSValue)
+ -> Result (Node.List, Instance.List, [String])
+parseData (nodes, instances, cinfo) = do
+ node_data <- nodes >>= getNodes
+ let (node_names, node_idx) = assignIndices node_data
+ inst_data <- instances >>= getInstances node_names
+ let (_, inst_idx) = assignIndices inst_data
+ ctags <- cinfo >>= getClusterTags
+ return (node_idx, inst_idx, ctags)
+
+-- | Top level function for data loading
+loadData :: String -- ^ Unix socket to use as source
+ -> IO (Result (Node.List, Instance.List, [String]))
+loadData master = readData master >>= return . parseData