1 {-| Parsing data from text-files
3 This module holds the code for loading the cluster state from text
4 files, as produced by gnt-node and gnt-instance list.
10 Copyright (C) 2009 Google Inc.
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 module Ganeti.HTools.Text
37 import Ganeti.HTools.Utils
38 import Ganeti.HTools.Loader
39 import Ganeti.HTools.Types
40 import qualified Ganeti.HTools.Node as Node
41 import qualified Ganeti.HTools.Instance as Instance
43 -- | Load a node from a field list.
44 loadNode :: (Monad m) => [String] -> m (String, Node.Node)
45 loadNode [name, tm, nm, fm, td, fd, tc, fo] = do
47 if any (== "?") [tm,nm,fm,td,fd,tc] || fo == "Y" then
48 return $ Node.create name 0 0 0 0 0 0 True
50 vtm <- tryRead name tm
51 vnm <- tryRead name nm
52 vfm <- tryRead name fm
53 vtd <- tryRead name td
54 vfd <- tryRead name fd
55 vtc <- tryRead name tc
56 return $ Node.create name vtm vnm vfm vtd vfd vtc False
57 return (name, new_node)
58 loadNode s = fail $ "Invalid/incomplete node data: '" ++ show s ++ "'"
60 -- | Load an instance from a field list.
61 loadInst :: (Monad m) =>
62 [(String, Ndx)] -> [String] -> m (String, Instance.Instance)
63 loadInst ktn [name, mem, dsk, vcpus, status, pnode, snode, tags] = do
64 pidx <- lookupNode ktn name pnode
65 sidx <- (if null snode then return Node.noSecondary
66 else lookupNode ktn name snode)
67 vmem <- tryRead name mem
68 vdsk <- tryRead name dsk
69 vvcpus <- tryRead name vcpus
70 when (sidx == pidx) $ fail $ "Instance " ++ name ++
71 " has same primary and secondary node - " ++ pnode
72 let vtags = sepSplit ',' tags
73 newinst = Instance.create name vmem vdsk vvcpus status vtags pidx sidx
74 return (name, newinst)
75 loadInst _ s = fail $ "Invalid/incomplete instance data: '" ++ show s ++ "'"
77 -- | Convert newline and delimiter-separated text.
79 -- This function converts a text in tabular format as generated by
80 -- @gnt-instance list@ and @gnt-node list@ to a list of objects using
81 -- a supplied conversion function.
82 loadTabular :: (Monad m, Element a) =>
83 [String] -> ([String] -> m (String, a))
84 -> m ([(String, Int)], [(Int, a)])
85 loadTabular lines_data convert_fn = do
86 let rows = map (sepSplit '|') lines_data
87 kerows <- mapM convert_fn rows
88 return $ assignIndices kerows
90 -- | Builds the cluster data from text input.
91 loadData :: String -- ^ Path to the text file
92 -> IO (Result (Node.AssocList, Instance.AssocList, [String]))
93 loadData afile = do -- IO monad
94 fdata <- readFile afile
95 let flines = lines fdata
96 (nlines, ilines) = break null flines
98 ifixed <- case ilines of
99 [] -> Bad "Invalid format of the input file (no instance data)"
101 {- node file: name t_mem n_mem f_mem t_disk f_disk -}
102 (ktn, nl) <- loadTabular nlines loadNode
103 {- instance file: name mem disk status pnode snode -}
104 (_, il) <- loadTabular ifixed (loadInst ktn)