Statistics
| Branch: | Tag: | Revision:

root / hscan.hs @ e2fa2baf

History | View | Annotate | Download (6.8 kB)

1 1b7a5835 Iustin Pop
{-| Scan clusters via RAPI and write instance/node data files.
2 1b7a5835 Iustin Pop
3 1b7a5835 Iustin Pop
-}
4 1b7a5835 Iustin Pop
5 e2fa2baf Iustin Pop
{-
6 e2fa2baf Iustin Pop
7 e2fa2baf Iustin Pop
Copyright (C) 2009 Google Inc.
8 e2fa2baf Iustin Pop
9 e2fa2baf Iustin Pop
This program is free software; you can redistribute it and/or modify
10 e2fa2baf Iustin Pop
it under the terms of the GNU General Public License as published by
11 e2fa2baf Iustin Pop
the Free Software Foundation; either version 2 of the License, or
12 e2fa2baf Iustin Pop
(at your option) any later version.
13 e2fa2baf Iustin Pop
14 e2fa2baf Iustin Pop
This program is distributed in the hope that it will be useful, but
15 e2fa2baf Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
16 e2fa2baf Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 e2fa2baf Iustin Pop
General Public License for more details.
18 e2fa2baf Iustin Pop
19 e2fa2baf Iustin Pop
You should have received a copy of the GNU General Public License
20 e2fa2baf Iustin Pop
along with this program; if not, write to the Free Software
21 e2fa2baf Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 e2fa2baf Iustin Pop
02110-1301, USA.
23 e2fa2baf Iustin Pop
24 e2fa2baf Iustin Pop
-}
25 e2fa2baf Iustin Pop
26 1b7a5835 Iustin Pop
module Main (main) where
27 1b7a5835 Iustin Pop
28 1b7a5835 Iustin Pop
import Data.List
29 1b7a5835 Iustin Pop
import Data.Function
30 1b7a5835 Iustin Pop
import Monad
31 1b7a5835 Iustin Pop
import System
32 1b7a5835 Iustin Pop
import System.IO
33 1b7a5835 Iustin Pop
import System.FilePath
34 1b7a5835 Iustin Pop
import System.Console.GetOpt
35 1b7a5835 Iustin Pop
import qualified System
36 1b7a5835 Iustin Pop
37 1b7a5835 Iustin Pop
import Text.Printf (printf)
38 1b7a5835 Iustin Pop
39 1b7a5835 Iustin Pop
import qualified Ganeti.HTools.Container as Container
40 1b7a5835 Iustin Pop
import qualified Ganeti.HTools.Cluster as Cluster
41 1b7a5835 Iustin Pop
import qualified Ganeti.HTools.Node as Node
42 1b7a5835 Iustin Pop
import qualified Ganeti.HTools.Instance as Instance
43 209b3711 Iustin Pop
import qualified Ganeti.HTools.CLI as CLI
44 040afc35 Iustin Pop
import qualified Ganeti.HTools.Rapi as Rapi
45 e4c5beaf Iustin Pop
import qualified Ganeti.HTools.Loader as Loader
46 e4c5beaf Iustin Pop
import Ganeti.HTools.Types
47 1b7a5835 Iustin Pop
48 1b7a5835 Iustin Pop
-- | Command line options structure.
49 1b7a5835 Iustin Pop
data Options = Options
50 1b7a5835 Iustin Pop
    { optShowNodes :: Bool     -- ^ Whether to show node status
51 1b7a5835 Iustin Pop
    , optOutPath   :: FilePath -- ^ Path to the output directory
52 1b7a5835 Iustin Pop
    , optVerbose   :: Int      -- ^ Verbosity level
53 1b7a5835 Iustin Pop
    , optNoHeader  :: Bool     -- ^ Do not show a header line
54 209b3711 Iustin Pop
    , optShowVer   :: Bool     -- ^ Just show the program version
55 209b3711 Iustin Pop
    , optShowHelp  :: Bool     -- ^ Just show the help
56 1b7a5835 Iustin Pop
    } deriving Show
57 1b7a5835 Iustin Pop
58 75d1edf8 Iustin Pop
instance CLI.CLIOptions Options where
59 75d1edf8 Iustin Pop
    showVersion = optShowVer
60 75d1edf8 Iustin Pop
    showHelp    = optShowHelp
61 75d1edf8 Iustin Pop
62 1b7a5835 Iustin Pop
-- | Default values for the command line options.
63 1b7a5835 Iustin Pop
defaultOptions :: Options
64 1b7a5835 Iustin Pop
defaultOptions  = Options
65 1b7a5835 Iustin Pop
 { optShowNodes = False
66 1b7a5835 Iustin Pop
 , optOutPath   = "."
67 1b7a5835 Iustin Pop
 , optVerbose   = 0
68 1b7a5835 Iustin Pop
 , optNoHeader  = False
69 209b3711 Iustin Pop
 , optShowVer   = False
70 209b3711 Iustin Pop
 , optShowHelp  = False
71 1b7a5835 Iustin Pop
 }
72 1b7a5835 Iustin Pop
73 1b7a5835 Iustin Pop
-- | Options list and functions
74 1b7a5835 Iustin Pop
options :: [OptDescr (Options -> Options)]
75 1b7a5835 Iustin Pop
options =
76 1b7a5835 Iustin Pop
    [ Option ['p']     ["print-nodes"]
77 1b7a5835 Iustin Pop
      (NoArg (\ opts -> opts { optShowNodes = True }))
78 1b7a5835 Iustin Pop
      "print the final node list"
79 1b7a5835 Iustin Pop
    , Option ['d']     ["output-dir"]
80 1b7a5835 Iustin Pop
      (ReqArg (\ d opts -> opts { optOutPath = d }) "PATH")
81 1b7a5835 Iustin Pop
      "directory in which to write output files"
82 1b7a5835 Iustin Pop
    , Option ['v']     ["verbose"]
83 1b7a5835 Iustin Pop
      (NoArg (\ opts -> opts { optVerbose = (optVerbose opts) + 1 }))
84 1b7a5835 Iustin Pop
      "increase the verbosity level"
85 1b7a5835 Iustin Pop
    , Option []        ["no-headers"]
86 1b7a5835 Iustin Pop
      (NoArg (\ opts -> opts { optNoHeader = True }))
87 1b7a5835 Iustin Pop
      "do not show a header line"
88 209b3711 Iustin Pop
    , Option ['V']     ["version"]
89 209b3711 Iustin Pop
      (NoArg (\ opts -> opts { optShowVer = True}))
90 209b3711 Iustin Pop
      "show the version of the program"
91 209b3711 Iustin Pop
    , Option ['h']     ["help"]
92 209b3711 Iustin Pop
      (NoArg (\ opts -> opts { optShowHelp = True}))
93 209b3711 Iustin Pop
      "show help"
94 1b7a5835 Iustin Pop
    ]
95 1b7a5835 Iustin Pop
96 1b7a5835 Iustin Pop
-- | Generate node file data from node objects
97 262a08a2 Iustin Pop
serializeNodes :: Node.List -> String -> String
98 dbd6700b Iustin Pop
serializeNodes nl csf =
99 dbd6700b Iustin Pop
    let nodes = Container.elems nl
100 1b7a5835 Iustin Pop
        nlines = map
101 1b7a5835 Iustin Pop
                 (\node ->
102 dbd6700b Iustin Pop
                      let name = Node.name node ++ csf
103 670b57ad Iustin Pop
                          t_mem = (truncate $ Node.t_mem node)::Int
104 670b57ad Iustin Pop
                          t_dsk = (truncate $ Node.t_dsk node)::Int
105 1b7a5835 Iustin Pop
                      in
106 00b15752 Iustin Pop
                        printf "%s|%d|%d|%d|%d|%d|%c" name
107 04be800a Iustin Pop
                                   t_mem (Node.n_mem node) (Node.f_mem node)
108 00b15752 Iustin Pop
                                   t_dsk (Node.f_dsk node)
109 00b15752 Iustin Pop
                                   (if Node.offline node then 'Y' else 'N')
110 00b15752 Iustin Pop
                 )
111 1b7a5835 Iustin Pop
                 nodes
112 1b7a5835 Iustin Pop
    in unlines nlines
113 1b7a5835 Iustin Pop
114 1b7a5835 Iustin Pop
-- | Generate instance file data from instance objects
115 262a08a2 Iustin Pop
serializeInstances :: Node.List -> Instance.List
116 db1bcfe8 Iustin Pop
                   -> String -> String
117 db1bcfe8 Iustin Pop
serializeInstances nl il csf =
118 db1bcfe8 Iustin Pop
    let instances = Container.elems il
119 1b7a5835 Iustin Pop
        nlines = map
120 1b7a5835 Iustin Pop
                 (\inst ->
121 1b7a5835 Iustin Pop
                      let
122 dbd6700b Iustin Pop
                          iname = Instance.name inst ++ csf
123 262a08a2 Iustin Pop
                          pnode = Container.nameOf nl $ Instance.pnode inst
124 262a08a2 Iustin Pop
                          snode = Container.nameOf nl $ Instance.snode inst
125 1b7a5835 Iustin Pop
                      in
126 f82f1f39 Iustin Pop
                        printf "%s|%d|%d|%s|%s|%s"
127 1b7a5835 Iustin Pop
                               iname (Instance.mem inst) (Instance.dsk inst)
128 f82f1f39 Iustin Pop
                               (Instance.run_st inst)
129 1b7a5835 Iustin Pop
                               pnode snode
130 1b7a5835 Iustin Pop
                 )
131 1b7a5835 Iustin Pop
                 instances
132 1b7a5835 Iustin Pop
    in unlines nlines
133 1b7a5835 Iustin Pop
134 1b7a5835 Iustin Pop
-- | Return a one-line summary of cluster state
135 262a08a2 Iustin Pop
printCluster :: Node.List -> Instance.List
136 1b7a5835 Iustin Pop
             -> String
137 dbd6700b Iustin Pop
printCluster nl il =
138 1b7a5835 Iustin Pop
    let (bad_nodes, bad_instances) = Cluster.computeBadItems nl il
139 1b7a5835 Iustin Pop
        ccv = Cluster.compCV nl
140 1b7a5835 Iustin Pop
        nodes = Container.elems nl
141 dbd6700b Iustin Pop
        insts = Container.elems il
142 1b7a5835 Iustin Pop
        t_ram = truncate . sum . map Node.t_mem $ nodes
143 1b7a5835 Iustin Pop
        t_dsk = truncate . sum . map Node.t_dsk $ nodes
144 1b7a5835 Iustin Pop
        f_ram = sum . map Node.f_mem $ nodes
145 1b7a5835 Iustin Pop
        f_dsk = sum . map Node.f_dsk $ nodes
146 1b7a5835 Iustin Pop
    in
147 1b7a5835 Iustin Pop
      printf "%5d %5d %5d %5d %6d %6d %6d %6d %.8f"
148 dbd6700b Iustin Pop
                 (length nodes) (length insts)
149 1b7a5835 Iustin Pop
                 (length bad_nodes) (length bad_instances)
150 1b7a5835 Iustin Pop
                 (t_ram::Integer) f_ram
151 1b7a5835 Iustin Pop
                 ((t_dsk::Integer) `div` 1024) (f_dsk `div` 1024)
152 1b7a5835 Iustin Pop
                 ccv
153 1b7a5835 Iustin Pop
154 1b7a5835 Iustin Pop
155 0944090a Iustin Pop
-- | Replace slashes with underscore for saving to filesystem
156 0944090a Iustin Pop
157 0944090a Iustin Pop
fixSlash :: String -> String
158 0944090a Iustin Pop
fixSlash = map (\x -> if x == '/' then '_' else x)
159 0944090a Iustin Pop
160 1b7a5835 Iustin Pop
-- | Main function.
161 1b7a5835 Iustin Pop
main :: IO ()
162 1b7a5835 Iustin Pop
main = do
163 1b7a5835 Iustin Pop
  cmd_args <- System.getArgs
164 209b3711 Iustin Pop
  (opts, clusters) <- CLI.parseOpts cmd_args "hscan" options
165 75d1edf8 Iustin Pop
                      defaultOptions
166 1b7a5835 Iustin Pop
167 1b7a5835 Iustin Pop
  let odir = optOutPath opts
168 1b7a5835 Iustin Pop
      nlen = maximum . map length $ clusters
169 1b7a5835 Iustin Pop
170 1b7a5835 Iustin Pop
  unless (optNoHeader opts) $
171 1b7a5835 Iustin Pop
         printf "%-*s %5s %5s %5s %5s %6s %6s %6s %6s %10s\n" nlen
172 1b7a5835 Iustin Pop
                "Name" "Nodes" "Inst" "BNode" "BInst" "t_mem" "f_mem"
173 1b7a5835 Iustin Pop
                "t_disk" "f_disk" "Score"
174 1b7a5835 Iustin Pop
175 fd22ce8e Iustin Pop
  mapM_ (\ name ->
176 1b7a5835 Iustin Pop
            do
177 1b7a5835 Iustin Pop
              printf "%-*s " nlen name
178 1b7a5835 Iustin Pop
              hFlush stdout
179 040afc35 Iustin Pop
              input_data <- Rapi.loadData name
180 e4c5beaf Iustin Pop
              let ldresult = input_data >>= Loader.mergeData
181 fd22ce8e Iustin Pop
              (case ldresult of
182 fd22ce8e Iustin Pop
                 Bad err -> printf "\nError: failed to load data. \
183 fd22ce8e Iustin Pop
                                   \Details:\n%s\n" err
184 fd22ce8e Iustin Pop
                 Ok x -> do
185 8472a321 Iustin Pop
                   let (nl, il, csf) = x
186 dbd6700b Iustin Pop
                       (_, fix_nl) = Loader.checkData nl il
187 dbd6700b Iustin Pop
                   putStrLn $ printCluster fix_nl il
188 fd22ce8e Iustin Pop
                   when (optShowNodes opts) $ do
189 dbd6700b Iustin Pop
                           putStr $ Cluster.printNodes fix_nl
190 dbd6700b Iustin Pop
                   let ndata = serializeNodes nl csf
191 db1bcfe8 Iustin Pop
                       idata = serializeInstances nl il csf
192 fd22ce8e Iustin Pop
                       oname = odir </> (fixSlash name)
193 fd22ce8e Iustin Pop
                   writeFile (oname <.> "nodes") ndata
194 fd22ce8e Iustin Pop
                   writeFile (oname <.> "instances") idata)
195 1b7a5835 Iustin Pop
       ) clusters