Statistics
| Branch: | Tag: | Revision:

root / Ganeti / HTools / Node.hs @ 00b15752

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