Revision 00b15752

b/Ganeti/HTools/Cluster.hs
753 753
    let
754 754
    {- node file: name t_mem n_mem f_mem t_disk f_disk -}
755 755
        (ktn, nl) = loadTabular ndata
756
                    (\ (name:tm:nm:fm:td:fd:[]) ->
756
                    (\ (name:tm:nm:fm:td:fd:fo:[]) ->
757 757
                         (name,
758
                          Node.create (read tm) (read nm)
759
                                  (read fm) (read td) (read fd)))
758
                          if any (== "?") [tm,nm,fm,td,fd] || fo == "Y" then
759
                              Node.create 0 0 0 0 0 True
760
                          else
761
                              Node.create (read tm) (read nm) (read fm)
762
                                      (read td) (read fd) False
763
                         ))
760 764
                    Node.setIdx
761 765
    {- instance file: name mem disk status pnode snode -}
762 766
        (kti, il) = loadTabular idata
b/Ganeti/HTools/Node.hs
64 64
later via the 'setIdx' and 'buildPeers' functions.
65 65

  
66 66
-}
67
create :: Double -> Int -> Int -> Double -> Int -> Node
68
create mem_t_init mem_n_init mem_f_init dsk_t_init dsk_f_init =
67
create :: Double -> Int -> Int -> Double -> Int -> Bool -> Node
68
create mem_t_init mem_n_init mem_f_init dsk_t_init dsk_f_init
69
       offline_init =
69 70
    Node
70 71
    {
71 72
      t_mem = mem_t_init,
......
82 83
      p_mem = (fromIntegral mem_f_init) / mem_t_init,
83 84
      p_dsk = (fromIntegral dsk_f_init) / dsk_t_init,
84 85
      p_rem = 0,
85
      offline = False,
86
      offline = offline_init,
86 87
      x_mem = 0
87 88
    }
88 89

  
b/Ganeti/HTools/Rapi.hs
90 90
                  concatEitherElems running $
91 91
                  concatEitherElems pnode snode
92 92

  
93
boolToYN :: Bool -> Either String String
94
boolToYN True = Right "Y"
95
boolToYN _ = Right "N"
96

  
93 97
parseNode :: JSObject JSValue -> Either String String
94 98
parseNode a =
95 99
    let name = getStringElement "name" a
100
        offline = getBoolElement "offline" a
101
        drained = getBoolElement "drained" a
96 102
        mtotal = getIntElement "mtotal" a
97 103
        mnode = getIntElement "mnode" a
98 104
        mfree = getIntElement "mfree" a
99 105
        dtotal = getIntElement "dtotal" a
100 106
        dfree = getIntElement "dfree" a
101 107
    in concatEitherElems name $
102
       concatEitherElems (show `applyEither1` mtotal) $
103
       concatEitherElems (show `applyEither1` mnode) $
104
       concatEitherElems (show `applyEither1` mfree) $
105
       concatEitherElems (show `applyEither1` dtotal)
106
                             (show `applyEither1` dfree)
108
       (case offline of
109
          Right True -> Right "0|0|0|0|0|Y"
110
          _ ->
111
              concatEitherElems (show `applyEither1` mtotal) $
112
              concatEitherElems (show `applyEither1` mnode) $
113
              concatEitherElems (show `applyEither1` mfree) $
114
              concatEitherElems (show `applyEither1` dtotal) $
115
              concatEitherElems (show `applyEither1` dfree)
116
              ((applyEither2 (||) offline drained) `combineEithers` boolToYN)
117
       )
b/Ganeti/HTools/Utils.hs
20 20
    , fromObj
21 21
    , getStringElement
22 22
    , getIntElement
23
    , getBoolElement
23 24
    , getListElement
24 25
    , getObjectElement
25 26
    , asJSObject
......
165 166
getIntElement :: String -> JSObject JSValue -> Either String Int
166 167
getIntElement = fromObj
167 168

  
169
getBoolElement :: String -> JSObject JSValue -> Either String Bool
170
getBoolElement = fromObj
171

  
168 172
getListElement :: String -> JSObject JSValue
169 173
               -> Either String [JSValue]
170 174
getListElement = fromObj
b/README
2 2
=============================
3 3

  
4 4
These are some simple cluster tools for fixing common problems. Right
5
now N+1 and rebalancing are included.
5
now N+1 and rebalancing are included. Starting with version 0.1.0,
6
only Ganeti 2.0 is supported.
6 7

  
7 8

  
8 9
Cluster N+1 solver
......
37 38
more precise information. In case RAPI is not usable for whatever
38 39
reason, the following two commands should be run::
39 40

  
40
    gnt-node list -oname,mtotal,mnode,mfree,dtotal,dfree \
41
    gnt-node list -oname,mtotal,mnode,mfree,dtotal,dfree,offline \
41 42
      --separator '|' --no-headers > nodes
42 43
    gnt-instance list -oname,admin_ram,sda_size,status,pnode,snodes \
43 44
      --separator '|' --no-head > instances
b/hbal.1
247 247
these nodes will not be included in the score calculation (except for
248 248
the percentage of instances on offline nodes)
249 249
.RE
250
Note that hbal will also mark as offline any nodes which are reported
251
by RAPI as such, or that have "?" in file-based input in any numeric
252
fields.
250 253
.RE
251 254

  
252 255
.TP
b/hscan.hs
79 79
                          t_mem = (truncate $ Node.t_mem node)::Int
80 80
                          t_dsk = (truncate $ Node.t_dsk node)::Int
81 81
                      in
82
                        printf "%s|%d|%d|%d|%d|%d" name
82
                        printf "%s|%d|%d|%d|%d|%d|%c" name
83 83
                                   t_mem (Node.n_mem node) (Node.f_mem node)
84
                                   t_dsk (Node.f_dsk node))
84
                                   t_dsk (Node.f_dsk node)
85
                                   (if Node.offline node then 'Y' else 'N')
86
                 )
85 87
                 nodes
86 88
    in unlines nlines
87 89

  

Also available in: Unified diff