Statistics
| Branch: | Tag: | Revision:

root / Ganeti / HTools / Node.hs @ 8c2ebac8

History | View | Annotate | Download (9 kB)

1 e4f08c46 Iustin Pop
{-| Module describing a node.
2 e4f08c46 Iustin Pop
3 e4f08c46 Iustin Pop
    All updates are functional (copy-based) and return a new node with
4 e4f08c46 Iustin Pop
    updated value.
5 e4f08c46 Iustin Pop
-}
6 e4f08c46 Iustin Pop
7 669d7e3d Iustin Pop
module Ganeti.HTools.Node
8 e4f08c46 Iustin Pop
    (
9 2727257a Iustin Pop
      Node(failN1, name, idx, t_mem, n_mem, f_mem, t_dsk, f_dsk,
10 04be800a Iustin Pop
           p_mem, p_dsk, p_rem,
11 7847a037 Iustin Pop
           plist, slist, offline)
12 e4f08c46 Iustin Pop
    -- * Constructor
13 e4f08c46 Iustin Pop
    , create
14 e4f08c46 Iustin Pop
    -- ** Finalization after data loading
15 e4f08c46 Iustin Pop
    , buildPeers
16 e4f08c46 Iustin Pop
    , setIdx
17 497e30a1 Iustin Pop
    , setName
18 c2c1ef0c Iustin Pop
    , setOffline
19 8c5b0a0d Iustin Pop
    , setXmem
20 53f00b20 Iustin Pop
    , setFmem
21 e4f08c46 Iustin Pop
    -- * Instance (re)location
22 e4f08c46 Iustin Pop
    , removePri
23 e4f08c46 Iustin Pop
    , removeSec
24 e4f08c46 Iustin Pop
    , addPri
25 e4f08c46 Iustin Pop
    , addSec
26 01f6a5d2 Iustin Pop
    , setPri
27 01f6a5d2 Iustin Pop
    , setSec
28 e4f08c46 Iustin Pop
    -- * Formatting
29 e4f08c46 Iustin Pop
    , list
30 040afc35 Iustin Pop
    -- * Misc stuff
31 040afc35 Iustin Pop
    , AssocList
32 040afc35 Iustin Pop
    , noSecondary
33 e4f08c46 Iustin Pop
    ) where
34 e4f08c46 Iustin Pop
35 e4f08c46 Iustin Pop
import Data.List
36 e4f08c46 Iustin Pop
import Text.Printf (printf)
37 e4f08c46 Iustin Pop
38 669d7e3d Iustin Pop
import qualified Ganeti.HTools.Container as Container
39 669d7e3d Iustin Pop
import qualified Ganeti.HTools.Instance as Instance
40 669d7e3d Iustin Pop
import qualified Ganeti.HTools.PeerMap as PeerMap
41 e4f08c46 Iustin Pop
42 2727257a Iustin Pop
data Node = Node { name  :: String -- ^ the node name
43 2727257a Iustin Pop
                 , t_mem :: Double -- ^ total memory (MiB)
44 04be800a Iustin Pop
                 , n_mem :: Int    -- ^ node memory (MiB)
45 38f63ae6 Iustin Pop
                 , f_mem :: Int    -- ^ free memory (MiB)
46 8c5b0a0d Iustin Pop
                 , x_mem :: Int    -- ^ unaccounted memory (MiB)
47 38f63ae6 Iustin Pop
                 , t_dsk :: Double -- ^ total disk space (MiB)
48 38f63ae6 Iustin Pop
                 , f_dsk :: Int    -- ^ free disk space (MiB)
49 38f63ae6 Iustin Pop
                 , plist :: [Int]  -- ^ list of primary instance indices
50 38f63ae6 Iustin Pop
                 , slist :: [Int]  -- ^ list of secondary instance indices
51 c622fa7c Iustin Pop
                 , idx :: Int      -- ^ internal index for book-keeping
52 80d0d2f1 Iustin Pop
                 , peers :: PeerMap.PeerMap -- ^ pnode to instance mapping
53 80d0d2f1 Iustin Pop
                 , failN1:: Bool   -- ^ whether the node has failed n1
54 80d0d2f1 Iustin Pop
                 , r_mem :: Int    -- ^ maximum memory needed for
55 80d0d2f1 Iustin Pop
                                   -- failover by primaries of this node
56 80d0d2f1 Iustin Pop
                 , p_mem :: Double -- ^ percent of free memory
57 80d0d2f1 Iustin Pop
                 , p_dsk :: Double -- ^ percent of free disk
58 80d0d2f1 Iustin Pop
                 , p_rem :: Double -- ^ percent of reserved memory
59 c2c1ef0c Iustin Pop
                 , offline :: Bool -- ^ whether the node should not be used
60 c2c1ef0c Iustin Pop
                                   -- for allocations and skipped from
61 c2c1ef0c Iustin Pop
                                   -- score computations
62 e4f08c46 Iustin Pop
  } deriving (Show)
63 e4f08c46 Iustin Pop
64 040afc35 Iustin Pop
-- | A simple name for the int, node association list
65 040afc35 Iustin Pop
type AssocList = [(Int, Node)]
66 040afc35 Iustin Pop
67 040afc35 Iustin Pop
-- | Constant node index for a non-moveable instance
68 040afc35 Iustin Pop
noSecondary :: Int
69 040afc35 Iustin Pop
noSecondary = -1
70 040afc35 Iustin Pop
71 e4f08c46 Iustin Pop
{- | Create a new node.
72 e4f08c46 Iustin Pop
73 e4f08c46 Iustin Pop
The index and the peers maps are empty, and will be need to be update
74 e4f08c46 Iustin Pop
later via the 'setIdx' and 'buildPeers' functions.
75 e4f08c46 Iustin Pop
76 e4f08c46 Iustin Pop
-}
77 2727257a Iustin Pop
create :: String -> Double -> Int -> Int -> Double -> Int -> Bool -> Node
78 2727257a Iustin Pop
create name_init mem_t_init mem_n_init mem_f_init
79 2727257a Iustin Pop
       dsk_t_init dsk_f_init offline_init =
80 47a8bade Iustin Pop
    Node
81 47a8bade Iustin Pop
    {
82 2727257a Iustin Pop
      name  = name_init,
83 47a8bade Iustin Pop
      t_mem = mem_t_init,
84 04be800a Iustin Pop
      n_mem = mem_n_init,
85 47a8bade Iustin Pop
      f_mem = mem_f_init,
86 47a8bade Iustin Pop
      t_dsk = dsk_t_init,
87 47a8bade Iustin Pop
      f_dsk = dsk_f_init,
88 47a8bade Iustin Pop
      plist = [],
89 47a8bade Iustin Pop
      slist = [],
90 47a8bade Iustin Pop
      failN1 = True,
91 47a8bade Iustin Pop
      idx = -1,
92 47a8bade Iustin Pop
      peers = PeerMap.empty,
93 47a8bade Iustin Pop
      r_mem = 0,
94 47a8bade Iustin Pop
      p_mem = (fromIntegral mem_f_init) / mem_t_init,
95 47a8bade Iustin Pop
      p_dsk = (fromIntegral dsk_f_init) / dsk_t_init,
96 47a8bade Iustin Pop
      p_rem = 0,
97 00b15752 Iustin Pop
      offline = offline_init,
98 8c5b0a0d Iustin Pop
      x_mem = 0
99 47a8bade Iustin Pop
    }
100 e4f08c46 Iustin Pop
101 e4f08c46 Iustin Pop
-- | Changes the index.
102 e4f08c46 Iustin Pop
-- This is used only during the building of the data structures.
103 e4f08c46 Iustin Pop
setIdx :: Node -> Int -> Node
104 e4f08c46 Iustin Pop
setIdx t i = t {idx = i}
105 e4f08c46 Iustin Pop
106 497e30a1 Iustin Pop
-- | Changes the name
107 497e30a1 Iustin Pop
-- This is used only during the building of the data structures.
108 497e30a1 Iustin Pop
setName t s = t {name = s}
109 497e30a1 Iustin Pop
110 c2c1ef0c Iustin Pop
-- | Sets the offline attribute
111 c2c1ef0c Iustin Pop
setOffline :: Node -> Bool -> Node
112 c2c1ef0c Iustin Pop
setOffline t val = t { offline = val }
113 c2c1ef0c Iustin Pop
114 8c5b0a0d Iustin Pop
-- | Sets the unnaccounted memory
115 8c5b0a0d Iustin Pop
setXmem :: Node -> Int -> Node
116 8c5b0a0d Iustin Pop
setXmem t val = t { x_mem = val }
117 8c5b0a0d Iustin Pop
118 53f00b20 Iustin Pop
-- | Sets the free memory
119 53f00b20 Iustin Pop
setFmem :: Node -> Int -> Node
120 0ee8fd76 Iustin Pop
setFmem t new_mem =
121 0ee8fd76 Iustin Pop
    let new_n1 = computeFailN1 (r_mem t) new_mem (f_dsk t)
122 0ee8fd76 Iustin Pop
        new_mp = (fromIntegral new_mem) / (t_mem t)
123 0ee8fd76 Iustin Pop
    in
124 0ee8fd76 Iustin Pop
      t { f_mem = new_mem, failN1 = new_n1, p_mem = new_mp }
125 53f00b20 Iustin Pop
126 e4f08c46 Iustin Pop
-- | Given the rmem, free memory and disk, computes the failn1 status.
127 e4f08c46 Iustin Pop
computeFailN1 :: Int -> Int -> Int -> Bool
128 962367fe Iustin Pop
computeFailN1 new_rmem new_mem new_dsk =
129 962367fe Iustin Pop
    new_mem <= new_rmem || new_dsk <= 0
130 e4f08c46 Iustin Pop
131 d10b27ef Iustin Pop
-- | Given the new free memory and disk, fail if any of them is below zero.
132 d10b27ef Iustin Pop
failHealth :: Int -> Int -> Bool
133 d10b27ef Iustin Pop
failHealth new_mem new_dsk = new_mem <= 0 || new_dsk <= 0
134 d10b27ef Iustin Pop
135 e4f08c46 Iustin Pop
-- | Computes the maximum reserved memory for peers from a peer map.
136 e4f08c46 Iustin Pop
computeMaxRes :: PeerMap.PeerMap -> PeerMap.Elem
137 e4f08c46 Iustin Pop
computeMaxRes new_peers = PeerMap.maxElem new_peers
138 e4f08c46 Iustin Pop
139 e4f08c46 Iustin Pop
-- | Builds the peer map for a given node.
140 e4f08c46 Iustin Pop
buildPeers :: Node -> Container.Container Instance.Instance -> Int -> Node
141 e4f08c46 Iustin Pop
buildPeers t il num_nodes =
142 e4f08c46 Iustin Pop
    let mdata = map
143 e4f08c46 Iustin Pop
                (\i_idx -> let inst = Container.find i_idx il
144 e4f08c46 Iustin Pop
                           in (Instance.pnode inst, Instance.mem inst))
145 e4f08c46 Iustin Pop
                (slist t)
146 e4f08c46 Iustin Pop
        pmap = PeerMap.accumArray (+) 0 (0, num_nodes - 1) mdata
147 e4f08c46 Iustin Pop
        new_rmem = computeMaxRes pmap
148 962367fe Iustin Pop
        new_failN1 = computeFailN1 new_rmem (f_mem t) (f_dsk t)
149 dfc749e6 Iustin Pop
        new_prem = (fromIntegral new_rmem) / (t_mem t)
150 c622fa7c Iustin Pop
    in t {peers=pmap, failN1 = new_failN1, r_mem = new_rmem, p_rem = new_prem}
151 e4f08c46 Iustin Pop
152 e4f08c46 Iustin Pop
-- | Removes a primary instance.
153 e4f08c46 Iustin Pop
removePri :: Node -> Instance.Instance -> Node
154 e4f08c46 Iustin Pop
removePri t inst =
155 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
156 e4f08c46 Iustin Pop
        new_plist = delete iname (plist t)
157 e4f08c46 Iustin Pop
        new_mem = f_mem t + Instance.mem inst
158 962367fe Iustin Pop
        new_dsk = f_dsk t + Instance.dsk inst
159 38f63ae6 Iustin Pop
        new_mp = (fromIntegral new_mem) / (t_mem t)
160 38f63ae6 Iustin Pop
        new_dp = (fromIntegral new_dsk) / (t_dsk t)
161 c622fa7c Iustin Pop
        new_failn1 = computeFailN1 (r_mem t) new_mem new_dsk
162 962367fe Iustin Pop
    in t {plist = new_plist, f_mem = new_mem, f_dsk = new_dsk,
163 0335fe4a Iustin Pop
          failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp}
164 e4f08c46 Iustin Pop
165 e4f08c46 Iustin Pop
-- | Removes a secondary instance.
166 e4f08c46 Iustin Pop
removeSec :: Node -> Instance.Instance -> Node
167 e4f08c46 Iustin Pop
removeSec t inst =
168 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
169 e4f08c46 Iustin Pop
        pnode = Instance.pnode inst
170 e4f08c46 Iustin Pop
        new_slist = delete iname (slist t)
171 962367fe Iustin Pop
        new_dsk = f_dsk t + Instance.dsk inst
172 e4f08c46 Iustin Pop
        old_peers = peers t
173 e4f08c46 Iustin Pop
        old_peem = PeerMap.find pnode old_peers
174 e4f08c46 Iustin Pop
        new_peem =  old_peem - (Instance.mem inst)
175 e4f08c46 Iustin Pop
        new_peers = PeerMap.add pnode new_peem old_peers
176 c622fa7c Iustin Pop
        old_rmem = r_mem t
177 e4f08c46 Iustin Pop
        new_rmem = if old_peem < old_rmem then
178 e4f08c46 Iustin Pop
                       old_rmem
179 e4f08c46 Iustin Pop
                   else
180 e4f08c46 Iustin Pop
                       computeMaxRes new_peers
181 dfc749e6 Iustin Pop
        new_prem = (fromIntegral new_rmem) / (t_mem t)
182 962367fe Iustin Pop
        new_failn1 = computeFailN1 new_rmem (f_mem t) new_dsk
183 38f63ae6 Iustin Pop
        new_dp = (fromIntegral new_dsk) / (t_dsk t)
184 962367fe Iustin Pop
    in t {slist = new_slist, f_dsk = new_dsk, peers = new_peers,
185 c622fa7c Iustin Pop
          failN1 = new_failn1, r_mem = new_rmem, p_dsk = new_dp,
186 dfc749e6 Iustin Pop
          p_rem = new_prem}
187 e4f08c46 Iustin Pop
188 e4f08c46 Iustin Pop
-- | Adds a primary instance.
189 e4f08c46 Iustin Pop
addPri :: Node -> Instance.Instance -> Maybe Node
190 e4f08c46 Iustin Pop
addPri t inst =
191 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
192 e4f08c46 Iustin Pop
        new_mem = f_mem t - Instance.mem inst
193 962367fe Iustin Pop
        new_dsk = f_dsk t - Instance.dsk inst
194 c622fa7c Iustin Pop
        new_failn1 = computeFailN1 (r_mem t) new_mem new_dsk in
195 d10b27ef Iustin Pop
      if (failHealth new_mem new_dsk) || (new_failn1 && not (failN1 t)) then
196 e4f08c46 Iustin Pop
        Nothing
197 e4f08c46 Iustin Pop
      else
198 0335fe4a Iustin Pop
        let new_plist = iname:(plist t)
199 38f63ae6 Iustin Pop
            new_mp = (fromIntegral new_mem) / (t_mem t)
200 38f63ae6 Iustin Pop
            new_dp = (fromIntegral new_dsk) / (t_dsk t)
201 0335fe4a Iustin Pop
        in
202 962367fe Iustin Pop
        Just t {plist = new_plist, f_mem = new_mem, f_dsk = new_dsk,
203 0335fe4a Iustin Pop
                failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp}
204 e4f08c46 Iustin Pop
205 e4f08c46 Iustin Pop
-- | Adds a secondary instance.
206 e4f08c46 Iustin Pop
addSec :: Node -> Instance.Instance -> Int -> Maybe Node
207 e4f08c46 Iustin Pop
addSec t inst pdx =
208 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
209 e4f08c46 Iustin Pop
        old_peers = peers t
210 d10b27ef Iustin Pop
        old_mem = f_mem t
211 962367fe Iustin Pop
        new_dsk = f_dsk t - Instance.dsk inst
212 e4f08c46 Iustin Pop
        new_peem = PeerMap.find pdx old_peers + Instance.mem inst
213 e4f08c46 Iustin Pop
        new_peers = PeerMap.add pdx new_peem old_peers
214 c622fa7c Iustin Pop
        new_rmem = max (r_mem t) new_peem
215 dfc749e6 Iustin Pop
        new_prem = (fromIntegral new_rmem) / (t_mem t)
216 d10b27ef Iustin Pop
        new_failn1 = computeFailN1 new_rmem old_mem new_dsk in
217 d10b27ef Iustin Pop
    if (failHealth old_mem new_dsk) || (new_failn1 && not (failN1 t)) then
218 e4f08c46 Iustin Pop
        Nothing
219 e4f08c46 Iustin Pop
    else
220 0335fe4a Iustin Pop
        let new_slist = iname:(slist t)
221 38f63ae6 Iustin Pop
            new_dp = (fromIntegral new_dsk) / (t_dsk t)
222 0335fe4a Iustin Pop
        in
223 962367fe Iustin Pop
        Just t {slist = new_slist, f_dsk = new_dsk,
224 e4f08c46 Iustin Pop
                peers = new_peers, failN1 = new_failn1,
225 c622fa7c Iustin Pop
                r_mem = new_rmem, p_dsk = new_dp,
226 dfc749e6 Iustin Pop
                p_rem = new_prem}
227 e4f08c46 Iustin Pop
228 01f6a5d2 Iustin Pop
-- | Add a primary instance to a node without other updates
229 01f6a5d2 Iustin Pop
setPri :: Node -> Int -> Node
230 01f6a5d2 Iustin Pop
setPri t idx = t { plist = idx:(plist t) }
231 01f6a5d2 Iustin Pop
232 01f6a5d2 Iustin Pop
-- | Add a secondary instance to a node without other updates
233 01f6a5d2 Iustin Pop
setSec :: Node -> Int -> Node
234 01f6a5d2 Iustin Pop
setSec t idx = t { slist = idx:(slist t) }
235 01f6a5d2 Iustin Pop
236 e4f08c46 Iustin Pop
-- | String converter for the node list functionality.
237 dbd6700b Iustin Pop
list :: Int -> Node -> String
238 dbd6700b Iustin Pop
list mname t =
239 e4f08c46 Iustin Pop
    let pl = plist t
240 e4f08c46 Iustin Pop
        sl = slist t
241 0335fe4a Iustin Pop
        mp = p_mem t
242 0335fe4a Iustin Pop
        dp = p_dsk t
243 352806f7 Iustin Pop
        off = offline t
244 2cf878a5 Iustin Pop
        fn = failN1 t
245 a1c6212e Iustin Pop
        tmem = t_mem t
246 a1c6212e Iustin Pop
        nmem = n_mem t
247 a1c6212e Iustin Pop
        xmem = x_mem t
248 a1c6212e Iustin Pop
        fmem = f_mem t
249 a1c6212e Iustin Pop
        imem = (truncate tmem) - nmem - xmem - fmem
250 e4f08c46 Iustin Pop
    in
251 a1c6212e Iustin Pop
      printf " %c %-*s %5.0f %5d %5d %5d %5d %5d %5.0f %5d %3d %3d %.5f %.5f"
252 352806f7 Iustin Pop
                 (if off then '-' else if fn then '*' else ' ')
253 dbd6700b Iustin Pop
                 mname (name t) tmem nmem imem xmem fmem (r_mem t)
254 ced859f3 Iustin Pop
                 ((t_dsk t) / 1024) ((f_dsk t) `div` 1024)
255 e4f08c46 Iustin Pop
                 (length pl) (length sl)
256 e4f08c46 Iustin Pop
                 mp dp