Revision 2060348b Ganeti/HTools/Node.hs
b/Ganeti/HTools/Node.hs | ||
---|---|---|
27 | 27 |
|
28 | 28 |
module Ganeti.HTools.Node |
29 | 29 |
( Node(failN1, name, idx, |
30 |
t_mem, n_mem, f_mem, r_mem, x_mem,
|
|
31 |
t_dsk, f_dsk,
|
|
32 |
t_cpu, u_cpu,
|
|
33 |
p_mem, p_dsk, p_rem, p_cpu,
|
|
34 |
m_dsk, m_cpu, lo_dsk, hi_cpu,
|
|
35 |
plist, slist, offline)
|
|
30 |
tMem, nMem, fMem, rMem, xMem,
|
|
31 |
tDsk, fDsk,
|
|
32 |
tCpu, uCpu,
|
|
33 |
pMem, pDsk, pRem, pCpu,
|
|
34 |
mDsk, mCpu, loDsk, hiCpu,
|
|
35 |
pList, sList, offline)
|
|
36 | 36 |
, List |
37 | 37 |
-- * Constructor |
38 | 38 |
, create |
... | ... | |
75 | 75 |
|
76 | 76 |
-- | The node type. |
77 | 77 |
data Node = Node { name :: String -- ^ The node name |
78 |
, t_mem :: Double -- ^ Total memory (MiB)
|
|
79 |
, n_mem :: Int -- ^ Node memory (MiB)
|
|
80 |
, f_mem :: Int -- ^ Free memory (MiB)
|
|
81 |
, x_mem :: Int -- ^ Unaccounted memory (MiB)
|
|
82 |
, t_dsk :: Double -- ^ Total disk space (MiB)
|
|
83 |
, f_dsk :: Int -- ^ Free disk space (MiB)
|
|
84 |
, t_cpu :: Double -- ^ Total CPU count
|
|
85 |
, u_cpu :: Int -- ^ Used VCPU count
|
|
86 |
, plist :: [T.Idx]-- ^ List of primary instance indices
|
|
87 |
, slist :: [T.Idx]-- ^ List of secondary instance indices
|
|
78 |
, tMem :: Double -- ^ Total memory (MiB)
|
|
79 |
, nMem :: Int -- ^ Node memory (MiB)
|
|
80 |
, fMem :: Int -- ^ Free memory (MiB)
|
|
81 |
, xMem :: Int -- ^ Unaccounted memory (MiB)
|
|
82 |
, tDsk :: Double -- ^ Total disk space (MiB)
|
|
83 |
, fDsk :: Int -- ^ Free disk space (MiB)
|
|
84 |
, tCpu :: Double -- ^ Total CPU count
|
|
85 |
, uCpu :: Int -- ^ Used VCPU count
|
|
86 |
, pList :: [T.Idx]-- ^ List of primary instance indices
|
|
87 |
, sList :: [T.Idx]-- ^ List of secondary instance indices
|
|
88 | 88 |
, idx :: T.Ndx -- ^ Internal index for book-keeping |
89 | 89 |
, peers :: PeerMap.PeerMap -- ^ Pnode to instance mapping |
90 | 90 |
, failN1:: Bool -- ^ Whether the node has failed n1 |
91 |
, r_mem :: Int -- ^ Maximum memory needed for
|
|
91 |
, rMem :: Int -- ^ Maximum memory needed for
|
|
92 | 92 |
-- failover by primaries of this node |
93 |
, p_mem :: Double -- ^ Percent of free memory
|
|
94 |
, p_dsk :: Double -- ^ Percent of free disk
|
|
95 |
, p_rem :: Double -- ^ Percent of reserved memory
|
|
96 |
, p_cpu :: Double -- ^ Ratio of virtual to physical CPUs
|
|
97 |
, m_dsk :: Double -- ^ Minimum free disk ratio
|
|
98 |
, m_cpu :: Double -- ^ Max ratio of virt-to-phys CPUs
|
|
99 |
, lo_dsk :: Int -- ^ Autocomputed from m_dsk low disk
|
|
93 |
, pMem :: Double -- ^ Percent of free memory
|
|
94 |
, pDsk :: Double -- ^ Percent of free disk
|
|
95 |
, pRem :: Double -- ^ Percent of reserved memory
|
|
96 |
, pCpu :: Double -- ^ Ratio of virtual to physical CPUs
|
|
97 |
, mDsk :: Double -- ^ Minimum free disk ratio
|
|
98 |
, mCpu :: Double -- ^ Max ratio of virt-to-phys CPUs
|
|
99 |
, loDsk :: Int -- ^ Autocomputed from mDsk low disk
|
|
100 | 100 |
-- threshold |
101 |
, hi_cpu :: Int -- ^ Autocomputed from m_cpu high cpu
|
|
101 |
, hiCpu :: Int -- ^ Autocomputed from mCpu high cpu
|
|
102 | 102 |
-- threshold |
103 | 103 |
, offline :: Bool -- ^ Whether the node should not be used |
104 | 104 |
-- for allocations and skipped from |
... | ... | |
142 | 142 |
Node |
143 | 143 |
{ |
144 | 144 |
name = name_init, |
145 |
t_mem = mem_t_init,
|
|
146 |
n_mem = mem_n_init,
|
|
147 |
f_mem = mem_f_init,
|
|
148 |
t_dsk = dsk_t_init,
|
|
149 |
f_dsk = dsk_f_init,
|
|
150 |
t_cpu = cpu_t_init,
|
|
151 |
u_cpu = 0,
|
|
152 |
plist = [],
|
|
153 |
slist = [],
|
|
145 |
tMem = mem_t_init,
|
|
146 |
nMem = mem_n_init,
|
|
147 |
fMem = mem_f_init,
|
|
148 |
tDsk = dsk_t_init,
|
|
149 |
fDsk = dsk_f_init,
|
|
150 |
tCpu = cpu_t_init,
|
|
151 |
uCpu = 0,
|
|
152 |
pList = [],
|
|
153 |
sList = [],
|
|
154 | 154 |
failN1 = True, |
155 | 155 |
idx = -1, |
156 | 156 |
peers = PeerMap.empty, |
157 |
r_mem = 0,
|
|
158 |
p_mem = fromIntegral mem_f_init / mem_t_init,
|
|
159 |
p_dsk = fromIntegral dsk_f_init / dsk_t_init,
|
|
160 |
p_rem = 0,
|
|
161 |
p_cpu = 0,
|
|
157 |
rMem = 0,
|
|
158 |
pMem = fromIntegral mem_f_init / mem_t_init,
|
|
159 |
pDsk = fromIntegral dsk_f_init / dsk_t_init,
|
|
160 |
pRem = 0,
|
|
161 |
pCpu = 0,
|
|
162 | 162 |
offline = offline_init, |
163 |
x_mem = 0,
|
|
164 |
m_dsk = noLimit,
|
|
165 |
m_cpu = noLimit,
|
|
166 |
lo_dsk = noLimitInt,
|
|
167 |
hi_cpu = noLimitInt
|
|
163 |
xMem = 0,
|
|
164 |
mDsk = noLimit,
|
|
165 |
mCpu = noLimit,
|
|
166 |
loDsk = noLimitInt,
|
|
167 |
hiCpu = noLimitInt
|
|
168 | 168 |
} |
169 | 169 |
|
170 | 170 |
-- | Changes the index. |
... | ... | |
185 | 185 |
|
186 | 186 |
-- | Sets the unnaccounted memory. |
187 | 187 |
setXmem :: Node -> Int -> Node |
188 |
setXmem t val = t { x_mem = val }
|
|
188 |
setXmem t val = t { xMem = val }
|
|
189 | 189 |
|
190 | 190 |
-- | Sets the max disk usage ratio |
191 | 191 |
setMdsk :: Node -> Double -> Node |
192 |
setMdsk t val = t { m_dsk = val,
|
|
193 |
lo_dsk = if val == noLimit
|
|
192 |
setMdsk t val = t { mDsk = val,
|
|
193 |
loDsk = if val == noLimit
|
|
194 | 194 |
then noLimitInt |
195 |
else floor (val * t_dsk t) }
|
|
195 |
else floor (val * tDsk t) }
|
|
196 | 196 |
|
197 | 197 |
-- | Sets the max cpu usage ratio |
198 | 198 |
setMcpu :: Node -> Double -> Node |
199 |
setMcpu t val = t { m_cpu = val, hi_cpu = floor (val * t_cpu t) }
|
|
199 |
setMcpu t val = t { mCpu = val, hiCpu = floor (val * tCpu t) }
|
|
200 | 200 |
|
201 | 201 |
-- | Computes the maximum reserved memory for peers from a peer map. |
202 | 202 |
computeMaxRes :: PeerMap.PeerMap -> PeerMap.Elem |
... | ... | |
207 | 207 |
buildPeers t il = |
208 | 208 |
let mdata = map |
209 | 209 |
(\i_idx -> let inst = Container.find i_idx il |
210 |
in (Instance.pnode inst, Instance.mem inst))
|
|
211 |
(slist t)
|
|
210 |
in (Instance.pNode inst, Instance.mem inst))
|
|
211 |
(sList t)
|
|
212 | 212 |
pmap = PeerMap.accumArray (+) mdata |
213 | 213 |
new_rmem = computeMaxRes pmap |
214 |
new_failN1 = f_mem t <= new_rmem
|
|
215 |
new_prem = fromIntegral new_rmem / t_mem t
|
|
216 |
in t {peers=pmap, failN1 = new_failN1, r_mem = new_rmem, p_rem = new_prem}
|
|
214 |
new_failN1 = fMem t <= new_rmem
|
|
215 |
new_prem = fromIntegral new_rmem / tMem t
|
|
216 |
in t {peers=pmap, failN1 = new_failN1, rMem = new_rmem, pRem = new_prem}
|
|
217 | 217 |
|
218 | 218 |
-- | Assigns an instance to a node as primary without other updates. |
219 | 219 |
setPri :: Node -> T.Idx -> Node |
220 |
setPri t ix = t { plist = ix:plist t }
|
|
220 |
setPri t ix = t { pList = ix:pList t }
|
|
221 | 221 |
|
222 | 222 |
-- | Assigns an instance to a node as secondary without other updates. |
223 | 223 |
setSec :: Node -> T.Idx -> Node |
224 |
setSec t ix = t { slist = ix:slist t }
|
|
224 |
setSec t ix = t { sList = ix:sList t }
|
|
225 | 225 |
|
226 | 226 |
-- | Add primary cpus to a node |
227 | 227 |
addCpus :: Node -> Int -> Node |
228 | 228 |
addCpus t count = |
229 |
let new_count = u_cpu t + count
|
|
230 |
in t { u_cpu = new_count, p_cpu = fromIntegral new_count / t_cpu t }
|
|
229 |
let new_count = uCpu t + count
|
|
230 |
in t { uCpu = new_count, pCpu = fromIntegral new_count / tCpu t }
|
|
231 | 231 |
|
232 | 232 |
-- * Update functions |
233 | 233 |
|
234 | 234 |
-- | Sets the free memory. |
235 | 235 |
setFmem :: Node -> Int -> Node |
236 | 236 |
setFmem t new_mem = |
237 |
let new_n1 = new_mem <= r_mem t
|
|
238 |
new_mp = fromIntegral new_mem / t_mem t
|
|
237 |
let new_n1 = new_mem <= rMem t
|
|
238 |
new_mp = fromIntegral new_mem / tMem t
|
|
239 | 239 |
in |
240 |
t { f_mem = new_mem, failN1 = new_n1, p_mem = new_mp }
|
|
240 |
t { fMem = new_mem, failN1 = new_n1, pMem = new_mp }
|
|
241 | 241 |
|
242 | 242 |
-- | Removes a primary instance. |
243 | 243 |
removePri :: Node -> Instance.Instance -> Node |
244 | 244 |
removePri t inst = |
245 | 245 |
let iname = Instance.idx inst |
246 |
new_plist = delete iname (plist t)
|
|
247 |
new_mem = f_mem t + Instance.mem inst
|
|
248 |
new_dsk = f_dsk t + Instance.dsk inst
|
|
249 |
new_mp = fromIntegral new_mem / t_mem t
|
|
250 |
new_dp = fromIntegral new_dsk / t_dsk t
|
|
251 |
new_failn1 = new_mem <= r_mem t
|
|
252 |
new_ucpu = u_cpu t - Instance.vcpus inst
|
|
253 |
new_rcpu = fromIntegral new_ucpu / t_cpu t
|
|
254 |
in t {plist = new_plist, f_mem = new_mem, f_dsk = new_dsk,
|
|
255 |
failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp,
|
|
256 |
u_cpu = new_ucpu, p_cpu = new_rcpu}
|
|
246 |
new_plist = delete iname (pList t)
|
|
247 |
new_mem = fMem t + Instance.mem inst
|
|
248 |
new_dsk = fDsk t + Instance.dsk inst
|
|
249 |
new_mp = fromIntegral new_mem / tMem t
|
|
250 |
new_dp = fromIntegral new_dsk / tDsk t
|
|
251 |
new_failn1 = new_mem <= rMem t
|
|
252 |
new_ucpu = uCpu t - Instance.vcpus inst
|
|
253 |
new_rcpu = fromIntegral new_ucpu / tCpu t
|
|
254 |
in t {pList = new_plist, fMem = new_mem, fDsk = new_dsk,
|
|
255 |
failN1 = new_failn1, pMem = new_mp, pDsk = new_dp,
|
|
256 |
uCpu = new_ucpu, pCpu = new_rcpu}
|
|
257 | 257 |
|
258 | 258 |
-- | Removes a secondary instance. |
259 | 259 |
removeSec :: Node -> Instance.Instance -> Node |
260 | 260 |
removeSec t inst = |
261 | 261 |
let iname = Instance.idx inst |
262 |
pnode = Instance.pnode inst
|
|
263 |
new_slist = delete iname (slist t)
|
|
264 |
new_dsk = f_dsk t + Instance.dsk inst
|
|
262 |
pnode = Instance.pNode inst
|
|
263 |
new_slist = delete iname (sList t)
|
|
264 |
new_dsk = fDsk t + Instance.dsk inst
|
|
265 | 265 |
old_peers = peers t |
266 | 266 |
old_peem = PeerMap.find pnode old_peers |
267 | 267 |
new_peem = old_peem - Instance.mem inst |
268 | 268 |
new_peers = PeerMap.add pnode new_peem old_peers |
269 |
old_rmem = r_mem t
|
|
269 |
old_rmem = rMem t
|
|
270 | 270 |
new_rmem = if old_peem < old_rmem then |
271 | 271 |
old_rmem |
272 | 272 |
else |
273 | 273 |
computeMaxRes new_peers |
274 |
new_prem = fromIntegral new_rmem / t_mem t
|
|
275 |
new_failn1 = f_mem t <= new_rmem
|
|
276 |
new_dp = fromIntegral new_dsk / t_dsk t
|
|
277 |
in t {slist = new_slist, f_dsk = new_dsk, peers = new_peers,
|
|
278 |
failN1 = new_failn1, r_mem = new_rmem, p_dsk = new_dp,
|
|
279 |
p_rem = new_prem}
|
|
274 |
new_prem = fromIntegral new_rmem / tMem t
|
|
275 |
new_failn1 = fMem t <= new_rmem
|
|
276 |
new_dp = fromIntegral new_dsk / tDsk t
|
|
277 |
in t {sList = new_slist, fDsk = new_dsk, peers = new_peers,
|
|
278 |
failN1 = new_failn1, rMem = new_rmem, pDsk = new_dp,
|
|
279 |
pRem = new_prem}
|
|
280 | 280 |
|
281 | 281 |
-- | Adds a primary instance. |
282 | 282 |
addPri :: Node -> Instance.Instance -> T.OpResult Node |
283 | 283 |
addPri t inst = |
284 | 284 |
let iname = Instance.idx inst |
285 |
new_mem = f_mem t - Instance.mem inst
|
|
286 |
new_dsk = f_dsk t - Instance.dsk inst
|
|
287 |
new_failn1 = new_mem <= r_mem t
|
|
288 |
new_ucpu = u_cpu t + Instance.vcpus inst
|
|
289 |
new_pcpu = fromIntegral new_ucpu / t_cpu t
|
|
290 |
new_dp = fromIntegral new_dsk / t_dsk t
|
|
291 |
l_cpu = m_cpu t
|
|
285 |
new_mem = fMem t - Instance.mem inst
|
|
286 |
new_dsk = fDsk t - Instance.dsk inst
|
|
287 |
new_failn1 = new_mem <= rMem t
|
|
288 |
new_ucpu = uCpu t + Instance.vcpus inst
|
|
289 |
new_pcpu = fromIntegral new_ucpu / tCpu t
|
|
290 |
new_dp = fromIntegral new_dsk / tDsk t
|
|
291 |
l_cpu = mCpu t
|
|
292 | 292 |
in if new_mem <= 0 then T.OpFail T.FailMem |
293 |
else if new_dsk <= 0 || m_dsk t > new_dp then T.OpFail T.FailDisk
|
|
293 |
else if new_dsk <= 0 || mDsk t > new_dp then T.OpFail T.FailDisk
|
|
294 | 294 |
else if new_failn1 && not (failN1 t) then T.OpFail T.FailMem |
295 | 295 |
else if l_cpu >= 0 && l_cpu < new_pcpu then T.OpFail T.FailCPU |
296 | 296 |
else |
297 |
let new_plist = iname:plist t
|
|
298 |
new_mp = fromIntegral new_mem / t_mem t
|
|
299 |
r = t { plist = new_plist, f_mem = new_mem, f_dsk = new_dsk,
|
|
300 |
failN1 = new_failn1, p_mem = new_mp, p_dsk = new_dp,
|
|
301 |
u_cpu = new_ucpu, p_cpu = new_pcpu }
|
|
297 |
let new_plist = iname:pList t
|
|
298 |
new_mp = fromIntegral new_mem / tMem t
|
|
299 |
r = t { pList = new_plist, fMem = new_mem, fDsk = new_dsk,
|
|
300 |
failN1 = new_failn1, pMem = new_mp, pDsk = new_dp,
|
|
301 |
uCpu = new_ucpu, pCpu = new_pcpu }
|
|
302 | 302 |
in T.OpGood r |
303 | 303 |
|
304 | 304 |
-- | Adds a secondary instance. |
... | ... | |
306 | 306 |
addSec t inst pdx = |
307 | 307 |
let iname = Instance.idx inst |
308 | 308 |
old_peers = peers t |
309 |
old_mem = f_mem t
|
|
310 |
new_dsk = f_dsk t - Instance.dsk inst
|
|
309 |
old_mem = fMem t
|
|
310 |
new_dsk = fDsk t - Instance.dsk inst
|
|
311 | 311 |
new_peem = PeerMap.find pdx old_peers + Instance.mem inst |
312 | 312 |
new_peers = PeerMap.add pdx new_peem old_peers |
313 |
new_rmem = max (r_mem t) new_peem
|
|
314 |
new_prem = fromIntegral new_rmem / t_mem t
|
|
313 |
new_rmem = max (rMem t) new_peem
|
|
314 |
new_prem = fromIntegral new_rmem / tMem t
|
|
315 | 315 |
new_failn1 = old_mem <= new_rmem |
316 |
new_dp = fromIntegral new_dsk / t_dsk t
|
|
317 |
in if new_dsk <= 0 || m_dsk t > new_dp then T.OpFail T.FailDisk
|
|
316 |
new_dp = fromIntegral new_dsk / tDsk t
|
|
317 |
in if new_dsk <= 0 || mDsk t > new_dp then T.OpFail T.FailDisk
|
|
318 | 318 |
else if new_failn1 && not (failN1 t) then T.OpFail T.FailMem |
319 |
else let new_slist = iname:slist t
|
|
320 |
r = t { slist = new_slist, f_dsk = new_dsk,
|
|
319 |
else let new_slist = iname:sList t
|
|
320 |
r = t { sList = new_slist, fDsk = new_dsk,
|
|
321 | 321 |
peers = new_peers, failN1 = new_failn1, |
322 |
r_mem = new_rmem, p_dsk = new_dp,
|
|
323 |
p_rem = new_prem }
|
|
322 |
rMem = new_rmem, pDsk = new_dp,
|
|
323 |
pRem = new_prem }
|
|
324 | 324 |
in T.OpGood r |
325 | 325 |
|
326 | 326 |
-- * Stats functions |
... | ... | |
328 | 328 |
-- | Computes the amount of available disk on a given node |
329 | 329 |
availDisk :: Node -> Int |
330 | 330 |
availDisk t = |
331 |
let _f = f_dsk t
|
|
332 |
_l = lo_dsk t
|
|
331 |
let _f = fDsk t
|
|
332 |
_l = loDsk t
|
|
333 | 333 |
in |
334 | 334 |
if _l == noLimitInt |
335 | 335 |
then _f |
... | ... | |
342 | 342 |
-- | String converter for the node list functionality. |
343 | 343 |
list :: Int -> Node -> String |
344 | 344 |
list mname t = |
345 |
let pl = length $ plist t
|
|
346 |
sl = length $ slist t
|
|
347 |
mp = p_mem t
|
|
348 |
dp = p_dsk t
|
|
349 |
cp = p_cpu t
|
|
345 |
let pl = length $ pList t
|
|
346 |
sl = length $ sList t
|
|
347 |
mp = pMem t
|
|
348 |
dp = pDsk t
|
|
349 |
cp = pCpu t
|
|
350 | 350 |
off = offline t |
351 | 351 |
fn = failN1 t |
352 |
tmem = t_mem t
|
|
353 |
nmem = n_mem t
|
|
354 |
xmem = x_mem t
|
|
355 |
fmem = f_mem t
|
|
352 |
tmem = tMem t
|
|
353 |
nmem = nMem t
|
|
354 |
xmem = xMem t
|
|
355 |
fmem = fMem t
|
|
356 | 356 |
imem = truncate tmem - nmem - xmem - fmem |
357 | 357 |
in |
358 | 358 |
if off |
... | ... | |
362 | 362 |
printf " %c %-*s %5.0f %5d %5d %5d %5d %5d %5.0f %5d\ |
363 | 363 |
\ %4.0f %4d %3d %3d %6.4f %6.4f %5.2f" |
364 | 364 |
(if off then '-' else if fn then '*' else ' ') |
365 |
mname (name t) tmem nmem imem xmem fmem (r_mem t)
|
|
366 |
(t_dsk t / 1024) (f_dsk t `div` 1024)
|
|
367 |
(t_cpu t) (u_cpu t)
|
|
365 |
mname (name t) tmem nmem imem xmem fmem (rMem t)
|
|
366 |
(tDsk t / 1024) (fDsk t `div` 1024)
|
|
367 |
(tCpu t) (uCpu t)
|
|
368 | 368 |
pl sl mp dp cp |
Also available in: Unified diff