1 {-| Scan clusters via RAPI and write instance/node data files.
7 Copyright (C) 2009 Google Inc.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 module Main (main) where
33 import System.FilePath
34 import qualified System
36 import Text.Printf (printf)
38 import qualified Ganeti.HTools.Container as Container
39 import qualified Ganeti.HTools.Cluster as Cluster
40 import qualified Ganeti.HTools.Node as Node
41 import qualified Ganeti.HTools.Instance as Instance
42 import qualified Ganeti.HTools.Rapi as Rapi
43 import qualified Ganeti.HTools.Loader as Loader
45 import Ganeti.HTools.CLI
46 import Ganeti.HTools.Types
48 -- | Options list and functions
59 -- | Serialize a single node
60 serializeNode :: String -> Node.Node -> String
61 serializeNode csf node =
62 printf "%s|%.0f|%d|%d|%.0f|%d|%.0f|%c" (Node.name node ++ csf)
63 (Node.tMem node) (Node.nMem node) (Node.fMem node)
64 (Node.tDsk node) (Node.fDsk node) (Node.tCpu node)
65 (if Node.offline node then 'Y' else 'N')
67 -- | Generate node file data from node objects
68 serializeNodes :: String -> Node.List -> String
70 unlines . map (serializeNode csf) . Container.elems
72 -- | Serialize a single instance
73 serializeInstance :: String -> Node.List -> Instance.Instance -> String
74 serializeInstance csf nl inst =
76 iname = Instance.name inst ++ csf
77 pnode = Container.nameOf nl (Instance.pNode inst) ++ csf
78 sidx = Instance.sNode inst
79 snode = (if sidx == Node.noSecondary
81 else Container.nameOf nl sidx ++ csf)
83 printf "%s|%d|%d|%d|%s|%s|%s"
84 iname (Instance.mem inst) (Instance.dsk inst)
85 (Instance.vcpus inst) (Instance.runSt inst)
88 -- | Generate instance file data from instance objects
89 serializeInstances :: String -> Node.List -> Instance.List -> String
90 serializeInstances csf nl =
91 unlines . map (serializeInstance csf nl) . Container.elems
93 -- | Return a one-line summary of cluster state
94 printCluster :: Node.List -> Instance.List
97 let (bad_nodes, bad_instances) = Cluster.computeBadItems nl il
98 ccv = Cluster.compCV nl
99 nodes = Container.elems nl
100 insts = Container.elems il
101 t_ram = sum . map Node.tMem $ nodes
102 t_dsk = sum . map Node.tDsk $ nodes
103 f_ram = sum . map Node.fMem $ nodes
104 f_dsk = sum . map Node.fDsk $ nodes
106 printf "%5d %5d %5d %5d %6.0f %6d %6.0f %6d %.8f"
107 (length nodes) (length insts)
108 (length bad_nodes) (length bad_instances)
110 (t_dsk / 1024) (f_dsk `div` 1024)
114 -- | Replace slashes with underscore for saving to filesystem
116 fixSlash :: String -> String
117 fixSlash = map (\x -> if x == '/' then '_' else x)
122 cmd_args <- System.getArgs
123 (opts, clusters) <- parseOpts cmd_args "hscan" options
125 let odir = optOutPath opts
126 nlen = maximum . map length $ clusters
128 unless (optNoHeaders opts) $
129 printf "%-*s %5s %5s %5s %5s %6s %6s %6s %6s %10s\n" nlen
130 "Name" "Nodes" "Inst" "BNode" "BInst" "t_mem" "f_mem"
131 "t_disk" "f_disk" "Score"
135 printf "%-*s " nlen name
137 input_data <- Rapi.loadData name
138 let ldresult = input_data >>= Loader.mergeData []
140 Bad err -> printf "\nError: failed to load data. \
143 let (nl, il, csf) = x
144 (_, fix_nl) = Loader.checkData nl il
145 putStrLn $ printCluster fix_nl il
146 when (optShowNodes opts) $
147 putStr $ Cluster.printNodes fix_nl
148 let ndata = serializeNodes csf nl
149 idata = serializeInstances csf nl il
150 oname = odir </> fixSlash name
151 writeFile (oname <.> "nodes") ndata
152 writeFile (oname <.> "instances") idata)