AllocElement: extend with the cluster score
[ganeti-local] / Ganeti / HTools / Text.hs
index fcccbd8..b4f9b72 100644 (file)
@@ -29,10 +29,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 module Ganeti.HTools.Text
     (
       loadData
+    , parseData
     , loadInst
     , loadNode
     , serializeInstances
+    , serializeNode
     , serializeNodes
+    , serializeCluster
     ) where
 
 import Control.Monad
@@ -50,10 +53,11 @@ import qualified Ganeti.HTools.Instance as Instance
 -- | Serialize a single node
 serializeNode :: Node.Node -> String
 serializeNode node =
-    printf "%s|%.0f|%d|%d|%.0f|%d|%.0f|%c" (Node.name node)
+    printf "%s|%.0f|%d|%d|%.0f|%d|%.0f|%c|%s" (Node.name node)
                (Node.tMem node) (Node.nMem node) (Node.fMem node)
                (Node.tDsk node) (Node.fDsk node) (Node.tCpu node)
                (if Node.offline node then 'Y' else 'N')
+               (Node.group node)
 
 -- | Generate node file data from node objects
 serializeNodes :: Node.List -> String
@@ -80,12 +84,22 @@ serializeInstances :: Node.List -> Instance.List -> String
 serializeInstances nl =
     unlines . map (serializeInstance nl) . Container.elems
 
+-- | Generate complete cluster data from node and instance lists
+serializeCluster :: Node.List -> Instance.List -> String
+serializeCluster nl il =
+  let ndata = serializeNodes nl
+      idata = serializeInstances nl il
+  in ndata ++ ['\n'] ++ idata
+
 -- | Load a node from a field list.
 loadNode :: (Monad m) => [String] -> m (String, Node.Node)
-loadNode [name, tm, nm, fm, td, fd, tc, fo] = do
+-- compatibility wrapper for old text files
+loadNode [name, tm, nm, fm, td, fd, tc, fo] =
+  loadNode [name, tm, nm, fm, td, fd, tc, fo, defaultGroupID]
+loadNode [name, tm, nm, fm, td, fd, tc, fo, gu] = do
   new_node <-
       if any (== "?") [tm,nm,fm,td,fd,tc] || fo == "Y" then
-          return $ Node.create name 0 0 0 0 0 0 True
+          return $ Node.create name 0 0 0 0 0 0 True gu
       else do
         vtm <- tryRead name tm
         vnm <- tryRead name nm
@@ -93,13 +107,13 @@ loadNode [name, tm, nm, fm, td, fd, tc, fo] = do
         vtd <- tryRead name td
         vfd <- tryRead name fd
         vtc <- tryRead name tc
-        return $ Node.create name vtm vnm vfm vtd vfd vtc False
+        return $ Node.create name vtm vnm vfm vtd vfd vtc False gu
   return (name, new_node)
 loadNode s = fail $ "Invalid/incomplete node data: '" ++ show s ++ "'"
 
 -- | Load an instance from a field list.
 loadInst :: (Monad m) =>
-            [(String, Ndx)] -> [String] -> m (String, Instance.Instance)
+            NameAssoc -> [String] -> m (String, Instance.Instance)
 loadInst ktn [name, mem, dsk, vcpus, status, pnode, snode, tags] = do
   pidx <- lookupNode ktn name pnode
   sidx <- (if null snode then return Node.noSecondary
@@ -121,25 +135,33 @@ loadInst _ s = fail $ "Invalid/incomplete instance data: '" ++ show s ++ "'"
 -- a supplied conversion function.
 loadTabular :: (Monad m, Element a) =>
                [String] -> ([String] -> m (String, a))
-            -> m ([(String, Int)], [(Int, a)])
+            -> m (NameAssoc, Container.Container a)
 loadTabular lines_data convert_fn = do
   let rows = map (sepSplit '|') lines_data
   kerows <- mapM convert_fn rows
   return $ assignIndices kerows
 
+-- | Load the cluser data from disk.
+readData :: String -- ^ Path to the text file
+         -> IO String
+readData = readFile
+
 -- | Builds the cluster data from text input.
-loadData :: String -- ^ Path to the text file
-         -> IO (Result (Node.AssocList, Instance.AssocList, [String]))
-loadData afile = do -- IO monad
-  fdata <- readFile afile
+parseData :: String -- ^ Text data
+          -> Result (Node.List, Instance.List, [String])
+parseData fdata = do
   let flines = lines fdata
       (nlines, ilines) = break null flines
-  return $ do
-    ifixed <- case ilines of
-                [] -> Bad "Invalid format of the input file (no instance data)"
-                _:xs -> Ok xs
-    {- node file: name t_mem n_mem f_mem t_disk f_disk -}
-    (ktn, nl) <- loadTabular nlines loadNode
-    {- instance file: name mem disk status pnode snode -}
-    (_, il) <- loadTabular ifixed (loadInst ktn)
-    return (nl, il, [])
+  ifixed <- case ilines of
+    [] -> Bad "Invalid format of the input file (no instance data)"
+    _:xs -> Ok xs
+  {- node file: name t_mem n_mem f_mem t_disk f_disk -}
+  (ktn, nl) <- loadTabular nlines loadNode
+  {- instance file: name mem disk status pnode snode -}
+  (_, il) <- loadTabular ifixed (loadInst ktn)
+  return (nl, il, [])
+
+-- | Top level function for data loading
+loadData :: String -- ^ Path to the text file
+         -> IO (Result (Node.List, Instance.List, [String]))
+loadData afile = readData afile >>= return . parseData