Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / Program / Hroller.hs @ 1a9eb17e

History | View | Annotate | Download (4 kB)

1
{-| Cluster rolling maintenance helper.
2

    
3
-}
4

    
5
{-
6

    
7
Copyright (C) 2012 Google Inc.
8

    
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.
13

    
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.
18

    
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
22
02110-1301, USA.
23

    
24
-}
25

    
26
module Ganeti.HTools.Program.Hroller
27
  ( main
28
  , options
29
  , arguments
30
  ) where
31

    
32
import Control.Monad
33
import Data.List
34
import Data.Ord
35

    
36
import qualified Data.IntMap as IntMap
37

    
38
import qualified Ganeti.HTools.Container as Container
39
import qualified Ganeti.HTools.Node as Node
40

    
41
import Ganeti.Common
42
import Ganeti.HTools.CLI
43
import Ganeti.HTools.ExtLoader
44
import Ganeti.HTools.Graph
45
import Ganeti.HTools.Loader
46
import Ganeti.Utils
47

    
48
-- | Options list and functions.
49
options :: IO [OptType]
50
options = do
51
  luxi <- oLuxiSocket
52
  return
53
    [ luxi
54
    , oRapiMaster
55
    , oDataFile
56
    , oIAllocSrc
57
    , oOfflineNode
58
    , oVerbose
59
    , oQuiet
60
    , oNoHeaders
61
    , oSaveCluster
62
    ]
63

    
64
-- | The list of arguments supported by the program.
65
arguments :: [ArgCompletion]
66
arguments = []
67

    
68
-- | Gather statistics for the coloring algorithms.
69
-- Returns a string with a summary on how each algorithm has performed,
70
-- in order of non-decreasing effectiveness, and whether it tied or lost
71
-- with the previous one.
72
getStats :: [(String, ColorVertMap)] -> String
73
getStats colorings = snd . foldr helper (0,"") $ algBySize colorings
74
    where algostat (algo, cmap) = algo ++ ": " ++ size cmap ++ grpsizes cmap
75
          size cmap = show (IntMap.size cmap) ++ " "
76
          grpsizes cmap =
77
            "(" ++ commaJoin (map (show.length) (IntMap.elems cmap)) ++ ")"
78
          algBySize = sortBy (flip (comparing (IntMap.size.snd)))
79
          helper :: (String, ColorVertMap) -> (Int, String) -> (Int, String)
80
          helper el (0, _) = ((IntMap.size.snd) el, algostat el)
81
          helper el (old, str)
82
            | old == elsize = (elsize, str ++ " TIE " ++ algostat el)
83
            | otherwise = (elsize, str ++ " LOOSE " ++ algostat el)
84
              where elsize = (IntMap.size.snd) el
85

    
86
-- | Main function.
87
main :: Options -> [String] -> IO ()
88
main opts args = do
89
  unless (null args) $ exitErr "This program doesn't take any arguments."
90

    
91
  let verbose = optVerbose opts
92

    
93
  -- Load cluster data. The last two arguments, cluster tags and ipolicy, are
94
  -- currently not used by this tool.
95
  ini_cdata@(ClusterData _ fixed_nl ilf _ _) <- loadExternalData opts
96

    
97
  nlf <- setNodeStatus opts fixed_nl
98

    
99
  maybeSaveData (optSaveCluster opts) "original" "before hroller run" ini_cdata
100

    
101
  -- TODO: only online nodes!
102
  -- TODO: filter by node group
103
  -- TODO: fail if instances are running (with option to warn only)
104
  -- TODO: identify master node, and put it last
105

    
106
  nodeGraph <- case Node.mkNodeGraph nlf ilf of
107
                     Nothing -> exitErr "Cannot create node graph"
108
                     Just g -> return g
109

    
110
  when (verbose > 2) . putStrLn $ "Node Graph: " ++ show nodeGraph
111

    
112
  let colorAlgorithms = [ ("LF", colorLF)
113
                        , ("Dsatur", colorDsatur)
114
                        , ("Dcolor", colorDcolor)
115
                        ]
116
      colorings = map (\(v,a) -> (v,(colorVertMap.a) nodeGraph)) colorAlgorithms
117
      smallestColoring =
118
        (snd . minimumBy (comparing (IntMap.size . snd))) colorings
119
      idToName = Node.name  . (`Container.find` nlf)
120
      nodesbycoloring = map (map idToName) $ IntMap.elems smallestColoring
121

    
122
  when (verbose > 1) . putStrLn $ getStats colorings
123

    
124
  unless (optNoHeaders opts) $
125
         putStrLn "'Node Reboot Groups'"
126
  mapM_ (putStrLn . commaJoin) nodesbycoloring