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
38 import Ganeti.HTools.Utils
39 import Ganeti.HTools.Loader
40 import Ganeti.HTools.Types
41 import qualified Ganeti.HTools.Node as Node
42 import qualified Ganeti.HTools.Instance as Instance
44 -- | Load a node from a field list.
45 loadNode :: (Monad m) => [String] -> m (String, Node.Node)
46 loadNode [name, tm, nm, fm, td, fd, tc, fo] = do
48 if any (== "?") [tm,nm,fm,td,fd,tc] || fo == "Y" then
49 return $ Node.create name 0 0 0 0 0 0 True
51 vtm <- tryRead name tm
52 vnm <- tryRead name nm
53 vfm <- tryRead name fm
54 vtd <- tryRead name td
55 vfd <- tryRead name fd
56 vtc <- tryRead name tc
57 return $ Node.create name vtm vnm vfm vtd vfd vtc False
58 return (name, new_node)
59 loadNode s = fail $ "Invalid/incomplete node data: '" ++ show s ++ "'"
61 -- | Load an instance from a field list.
62 loadInst :: (Monad m) =>
63 [(String, Ndx)] -> [String] -> m (String, Instance.Instance)
64 loadInst ktn [name, mem, dsk, vcpus, status, pnode, snode, tags] = do
65 pidx <- lookupNode ktn name pnode
66 sidx <- (if null snode then return Node.noSecondary
67 else lookupNode ktn name snode)
68 vmem <- tryRead name mem
69 vdsk <- tryRead name dsk
70 vvcpus <- tryRead name vcpus
71 when (sidx == pidx) $ fail $ "Instance " ++ name ++
72 " has same primary and secondary node - " ++ pnode
73 let vtags = sepSplit ',' tags
74 newinst = Instance.create name vmem vdsk vvcpus status vtags pidx sidx
75 return (name, newinst)
76 loadInst _ s = fail $ "Invalid/incomplete instance data: '" ++ show s ++ "'"
78 -- | Convert newline and delimiter-separated text.
80 -- This function converts a text in tabular format as generated by
81 -- @gnt-instance list@ and @gnt-node list@ to a list of objects using
82 -- a supplied conversion function.
83 loadTabular :: (Monad m, Element a) =>
84 [String] -> ([String] -> m (String, a))
85 -> m ([(String, Int)], [(Int, a)])
86 loadTabular lines_data convert_fn = do
87 let rows = map (sepSplit '|') lines_data
88 kerows <- mapM convert_fn rows
89 return $ assignIndices kerows
91 -- | Builds the cluster data from text input.
92 loadData :: String -- ^ Path to the text file
93 -> IO (Result (Node.AssocList, Instance.AssocList, [String]))
94 loadData afile = do -- IO monad
95 fdata <- readFile afile
96 let flines = lines fdata
97 (nlines, ilines) = break null flines
99 ifixed <- case ilines of
100 [] -> Bad "Invalid format of the input file (no instance data)"
102 {- node file: name t_mem n_mem f_mem t_disk f_disk -}
103 (ktn, nl) <- loadTabular nlines loadNode
104 {- instance file: name mem disk status pnode snode -}
105 (_, il) <- loadTabular ifixed (loadInst ktn)