Statistics
| Branch: | Tag: | Revision:

root / Ganeti / HTools / Node.hs @ 306cccd5

History | View | Annotate | Download (18.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 e2fa2baf Iustin Pop
{-
8 e2fa2baf Iustin Pop
9 50811e2c Iustin Pop
Copyright (C) 2009, 2010 Google Inc.
10 e2fa2baf Iustin Pop
11 e2fa2baf Iustin Pop
This program is free software; you can redistribute it and/or modify
12 e2fa2baf Iustin Pop
it under the terms of the GNU General Public License as published by
13 e2fa2baf Iustin Pop
the Free Software Foundation; either version 2 of the License, or
14 e2fa2baf Iustin Pop
(at your option) any later version.
15 e2fa2baf Iustin Pop
16 e2fa2baf Iustin Pop
This program is distributed in the hope that it will be useful, but
17 e2fa2baf Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
18 e2fa2baf Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 e2fa2baf Iustin Pop
General Public License for more details.
20 e2fa2baf Iustin Pop
21 e2fa2baf Iustin Pop
You should have received a copy of the GNU General Public License
22 e2fa2baf Iustin Pop
along with this program; if not, write to the Free Software
23 e2fa2baf Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 e2fa2baf Iustin Pop
02110-1301, USA.
25 e2fa2baf Iustin Pop
26 e2fa2baf Iustin Pop
-}
27 e2fa2baf Iustin Pop
28 669d7e3d Iustin Pop
module Ganeti.HTools.Node
29 aa8d2e71 Iustin Pop
    ( Node(..)
30 262a08a2 Iustin Pop
    , List
31 e4f08c46 Iustin Pop
    -- * Constructor
32 e4f08c46 Iustin Pop
    , create
33 e4f08c46 Iustin Pop
    -- ** Finalization after data loading
34 e4f08c46 Iustin Pop
    , buildPeers
35 e4f08c46 Iustin Pop
    , setIdx
36 8bcdde0c Iustin Pop
    , setAlias
37 c2c1ef0c Iustin Pop
    , setOffline
38 8c5b0a0d Iustin Pop
    , setXmem
39 53f00b20 Iustin Pop
    , setFmem
40 9188aeef Iustin Pop
    , setPri
41 9188aeef Iustin Pop
    , setSec
42 844eff86 Iustin Pop
    , setMdsk
43 844eff86 Iustin Pop
    , setMcpu
44 1e3dccc8 Iustin Pop
    -- * Tag maps
45 1e3dccc8 Iustin Pop
    , addTags
46 1e3dccc8 Iustin Pop
    , delTags
47 1e3dccc8 Iustin Pop
    , rejectAddTags
48 e4f08c46 Iustin Pop
    -- * Instance (re)location
49 e4f08c46 Iustin Pop
    , removePri
50 e4f08c46 Iustin Pop
    , removeSec
51 e4f08c46 Iustin Pop
    , addPri
52 3e3c9393 Iustin Pop
    , addPriEx
53 e4f08c46 Iustin Pop
    , addSec
54 3e3c9393 Iustin Pop
    , addSecEx
55 fe3d6f02 Iustin Pop
    -- * Stats
56 fe3d6f02 Iustin Pop
    , availDisk
57 1e3dccc8 Iustin Pop
    , availMem
58 1e3dccc8 Iustin Pop
    , availCpu
59 1e4b5230 Iustin Pop
    , conflictingPrimaries
60 e4f08c46 Iustin Pop
    -- * Formatting
61 76354e11 Iustin Pop
    , defaultFields
62 76354e11 Iustin Pop
    , showHeader
63 76354e11 Iustin Pop
    , showField
64 e4f08c46 Iustin Pop
    , list
65 040afc35 Iustin Pop
    -- * Misc stuff
66 040afc35 Iustin Pop
    , AssocList
67 1fe81531 Iustin Pop
    , AllocElement
68 040afc35 Iustin Pop
    , noSecondary
69 e4f08c46 Iustin Pop
    ) where
70 e4f08c46 Iustin Pop
71 e4f08c46 Iustin Pop
import Data.List
72 5f0b9579 Iustin Pop
import qualified Data.Map as Map
73 1e4b5230 Iustin Pop
import qualified Data.Foldable as Foldable
74 e4f08c46 Iustin Pop
import Text.Printf (printf)
75 e4f08c46 Iustin Pop
76 669d7e3d Iustin Pop
import qualified Ganeti.HTools.Container as Container
77 669d7e3d Iustin Pop
import qualified Ganeti.HTools.Instance as Instance
78 12e6776a Iustin Pop
import qualified Ganeti.HTools.PeerMap as P
79 e4f08c46 Iustin Pop
80 262a08a2 Iustin Pop
import qualified Ganeti.HTools.Types as T
81 262a08a2 Iustin Pop
82 9188aeef Iustin Pop
-- * Type declarations
83 9188aeef Iustin Pop
84 5f0b9579 Iustin Pop
-- | The tag map type
85 5f0b9579 Iustin Pop
type TagMap = Map.Map String Int
86 5f0b9579 Iustin Pop
87 9188aeef Iustin Pop
-- | The node type.
88 12e6776a Iustin Pop
data Node = Node
89 12e6776a Iustin Pop
    { name     :: String    -- ^ The node name
90 8bcdde0c Iustin Pop
    , alias    :: String    -- ^ The shortened name (for display purposes)
91 12e6776a Iustin Pop
    , tMem     :: Double    -- ^ Total memory (MiB)
92 12e6776a Iustin Pop
    , nMem     :: Int       -- ^ Node memory (MiB)
93 12e6776a Iustin Pop
    , fMem     :: Int       -- ^ Free memory (MiB)
94 12e6776a Iustin Pop
    , xMem     :: Int       -- ^ Unaccounted memory (MiB)
95 12e6776a Iustin Pop
    , tDsk     :: Double    -- ^ Total disk space (MiB)
96 12e6776a Iustin Pop
    , fDsk     :: Int       -- ^ Free disk space (MiB)
97 12e6776a Iustin Pop
    , tCpu     :: Double    -- ^ Total CPU count
98 12e6776a Iustin Pop
    , uCpu     :: Int       -- ^ Used VCPU count
99 12e6776a Iustin Pop
    , pList    :: [T.Idx]   -- ^ List of primary instance indices
100 12e6776a Iustin Pop
    , sList    :: [T.Idx]   -- ^ List of secondary instance indices
101 12e6776a Iustin Pop
    , idx      :: T.Ndx     -- ^ Internal index for book-keeping
102 12e6776a Iustin Pop
    , peers    :: P.PeerMap -- ^ Pnode to instance mapping
103 12e6776a Iustin Pop
    , failN1   :: Bool      -- ^ Whether the node has failed n1
104 12e6776a Iustin Pop
    , rMem     :: Int       -- ^ Maximum memory needed for failover by
105 12e6776a Iustin Pop
                            -- primaries of this node
106 12e6776a Iustin Pop
    , pMem     :: Double    -- ^ Percent of free memory
107 12e6776a Iustin Pop
    , pDsk     :: Double    -- ^ Percent of free disk
108 12e6776a Iustin Pop
    , pRem     :: Double    -- ^ Percent of reserved memory
109 12e6776a Iustin Pop
    , pCpu     :: Double    -- ^ Ratio of virtual to physical CPUs
110 12e6776a Iustin Pop
    , mDsk     :: Double    -- ^ Minimum free disk ratio
111 12e6776a Iustin Pop
    , mCpu     :: Double    -- ^ Max ratio of virt-to-phys CPUs
112 12e6776a Iustin Pop
    , loDsk    :: Int       -- ^ Autocomputed from mDsk low disk
113 12e6776a Iustin Pop
                            -- threshold
114 12e6776a Iustin Pop
    , hiCpu    :: Int       -- ^ Autocomputed from mCpu high cpu
115 12e6776a Iustin Pop
                            -- threshold
116 12e6776a Iustin Pop
    , offline  :: Bool      -- ^ Whether the node should not be used
117 12e6776a Iustin Pop
                            -- for allocations and skipped from score
118 12e6776a Iustin Pop
                            -- computations
119 12e6776a Iustin Pop
    , utilPool :: T.DynUtil -- ^ Total utilisation capacity
120 12e6776a Iustin Pop
    , utilLoad :: T.DynUtil -- ^ Sum of instance utilisation
121 5f0b9579 Iustin Pop
    , pTags    :: TagMap    -- ^ Map of primary instance tags and their count
122 50811e2c Iustin Pop
    } deriving (Show, Eq)
123 e4f08c46 Iustin Pop
124 262a08a2 Iustin Pop
instance T.Element Node where
125 262a08a2 Iustin Pop
    nameOf = name
126 262a08a2 Iustin Pop
    idxOf = idx
127 3e4480e0 Iustin Pop
    setAlias = setAlias
128 262a08a2 Iustin Pop
    setIdx = setIdx
129 c854092b Iustin Pop
    allNames n = [name n, alias n]
130 262a08a2 Iustin Pop
131 9188aeef Iustin Pop
-- | A simple name for the int, node association list.
132 608efcce Iustin Pop
type AssocList = [(T.Ndx, Node)]
133 040afc35 Iustin Pop
134 9188aeef Iustin Pop
-- | A simple name for a node map.
135 262a08a2 Iustin Pop
type List = Container.Container Node
136 262a08a2 Iustin Pop
137 1fe81531 Iustin Pop
-- | A simple name for an allocation element (here just for logistic
138 1fe81531 Iustin Pop
-- reasons)
139 1fe81531 Iustin Pop
type AllocElement = (List, Instance.Instance, [Node])
140 1fe81531 Iustin Pop
141 9188aeef Iustin Pop
-- | Constant node index for a non-moveable instance.
142 608efcce Iustin Pop
noSecondary :: T.Ndx
143 040afc35 Iustin Pop
noSecondary = -1
144 040afc35 Iustin Pop
145 5f0b9579 Iustin Pop
-- * Helper functions
146 5f0b9579 Iustin Pop
147 5f0b9579 Iustin Pop
-- | Add a tag to a tagmap
148 5f0b9579 Iustin Pop
addTag :: TagMap -> String -> TagMap
149 5f0b9579 Iustin Pop
addTag t s = Map.insertWith (+) s 1 t
150 5f0b9579 Iustin Pop
151 5f0b9579 Iustin Pop
-- | Add multiple tags
152 5f0b9579 Iustin Pop
addTags :: TagMap -> [String] -> TagMap
153 5f0b9579 Iustin Pop
addTags = foldl' addTag
154 5f0b9579 Iustin Pop
155 5f0b9579 Iustin Pop
-- | Adjust or delete a tag from a tagmap
156 5f0b9579 Iustin Pop
delTag :: TagMap -> String -> TagMap
157 5f0b9579 Iustin Pop
delTag t s = Map.update (\v -> if v > 1
158 5f0b9579 Iustin Pop
                               then Just (v-1)
159 5f0b9579 Iustin Pop
                               else Nothing)
160 5f0b9579 Iustin Pop
             s t
161 5f0b9579 Iustin Pop
162 5f0b9579 Iustin Pop
-- | Remove multiple tags
163 5f0b9579 Iustin Pop
delTags :: TagMap -> [String] -> TagMap
164 5f0b9579 Iustin Pop
delTags = foldl' delTag
165 5f0b9579 Iustin Pop
166 5f0b9579 Iustin Pop
-- | Check if we can add a list of tags to a tagmap
167 5f0b9579 Iustin Pop
rejectAddTags :: TagMap -> [String] -> Bool
168 5182e970 Iustin Pop
rejectAddTags t = any (`Map.member` t)
169 5f0b9579 Iustin Pop
170 1e4b5230 Iustin Pop
-- | Check how many primary instances have conflicting tags. The
171 1e4b5230 Iustin Pop
-- algorithm to compute this is to sum the count of all tags, then
172 1e4b5230 Iustin Pop
-- subtract the size of the tag map (since each tag has at least one,
173 1e4b5230 Iustin Pop
-- non-conflicting instance); this is equivalent to summing the
174 1e4b5230 Iustin Pop
-- values in the tag map minus one.
175 1e4b5230 Iustin Pop
conflictingPrimaries :: Node -> Int
176 1e4b5230 Iustin Pop
conflictingPrimaries (Node { pTags = t }) = Foldable.sum t - Map.size t
177 1e4b5230 Iustin Pop
178 9188aeef Iustin Pop
-- * Initialization functions
179 e4f08c46 Iustin Pop
180 9188aeef Iustin Pop
-- | Create a new node.
181 9188aeef Iustin Pop
--
182 9188aeef Iustin Pop
-- The index and the peers maps are empty, and will be need to be
183 9188aeef Iustin Pop
-- update later via the 'setIdx' and 'buildPeers' functions.
184 1a82215d Iustin Pop
create :: String -> Double -> Int -> Int -> Double
185 1a82215d Iustin Pop
       -> Int -> Double -> Bool -> Node
186 2727257a Iustin Pop
create name_init mem_t_init mem_n_init mem_f_init
187 1a82215d Iustin Pop
       dsk_t_init dsk_f_init cpu_t_init offline_init =
188 8bcdde0c Iustin Pop
    Node { name = name_init
189 8bcdde0c Iustin Pop
         , alias = name_init
190 2180829f Iustin Pop
         , tMem = mem_t_init
191 2180829f Iustin Pop
         , nMem = mem_n_init
192 2180829f Iustin Pop
         , fMem = mem_f_init
193 2180829f Iustin Pop
         , tDsk = dsk_t_init
194 2180829f Iustin Pop
         , fDsk = dsk_f_init
195 2180829f Iustin Pop
         , tCpu = cpu_t_init
196 2180829f Iustin Pop
         , uCpu = 0
197 2180829f Iustin Pop
         , pList = []
198 2180829f Iustin Pop
         , sList = []
199 2180829f Iustin Pop
         , failN1 = True
200 2180829f Iustin Pop
         , idx = -1
201 12e6776a Iustin Pop
         , peers = P.empty
202 2180829f Iustin Pop
         , rMem = 0
203 2180829f Iustin Pop
         , pMem = fromIntegral mem_f_init / mem_t_init
204 2180829f Iustin Pop
         , pDsk = fromIntegral dsk_f_init / dsk_t_init
205 2180829f Iustin Pop
         , pRem = 0
206 2180829f Iustin Pop
         , pCpu = 0
207 2180829f Iustin Pop
         , offline = offline_init
208 2180829f Iustin Pop
         , xMem = 0
209 f4c0b8c5 Iustin Pop
         , mDsk = T.defReservedDiskRatio
210 f4c0b8c5 Iustin Pop
         , mCpu = T.defVcpuRatio
211 f4c0b8c5 Iustin Pop
         , loDsk = mDskToloDsk T.defReservedDiskRatio dsk_t_init
212 f4c0b8c5 Iustin Pop
         , hiCpu = mCpuTohiCpu T.defVcpuRatio cpu_t_init
213 ee9724b9 Iustin Pop
         , utilPool = T.baseUtil
214 2180829f Iustin Pop
         , utilLoad = T.zeroUtil
215 5f0b9579 Iustin Pop
         , pTags = Map.empty
216 2180829f Iustin Pop
         }
217 e4f08c46 Iustin Pop
218 3ed46bb7 Iustin Pop
-- | Conversion formula from mDsk\/tDsk to loDsk
219 f4c0b8c5 Iustin Pop
mDskToloDsk :: Double -> Double -> Int
220 f4c0b8c5 Iustin Pop
mDskToloDsk mval tdsk = floor (mval * tdsk)
221 f4c0b8c5 Iustin Pop
222 3ed46bb7 Iustin Pop
-- | Conversion formula from mCpu\/tCpu to hiCpu
223 f4c0b8c5 Iustin Pop
mCpuTohiCpu :: Double -> Double -> Int
224 f4c0b8c5 Iustin Pop
mCpuTohiCpu mval tcpu = floor (mval * tcpu)
225 f4c0b8c5 Iustin Pop
226 e4f08c46 Iustin Pop
-- | Changes the index.
227 9188aeef Iustin Pop
--
228 e4f08c46 Iustin Pop
-- This is used only during the building of the data structures.
229 608efcce Iustin Pop
setIdx :: Node -> T.Ndx -> Node
230 e4f08c46 Iustin Pop
setIdx t i = t {idx = i}
231 e4f08c46 Iustin Pop
232 8bcdde0c Iustin Pop
-- | Changes the alias.
233 8bcdde0c Iustin Pop
--
234 8bcdde0c Iustin Pop
-- This is used only during the building of the data structures.
235 8bcdde0c Iustin Pop
setAlias :: Node -> String -> Node
236 8bcdde0c Iustin Pop
setAlias t s = t { alias = s }
237 497e30a1 Iustin Pop
238 9188aeef Iustin Pop
-- | Sets the offline attribute.
239 c2c1ef0c Iustin Pop
setOffline :: Node -> Bool -> Node
240 c2c1ef0c Iustin Pop
setOffline t val = t { offline = val }
241 c2c1ef0c Iustin Pop
242 9188aeef Iustin Pop
-- | Sets the unnaccounted memory.
243 8c5b0a0d Iustin Pop
setXmem :: Node -> Int -> Node
244 2060348b Iustin Pop
setXmem t val = t { xMem = val }
245 8c5b0a0d Iustin Pop
246 844eff86 Iustin Pop
-- | Sets the max disk usage ratio
247 844eff86 Iustin Pop
setMdsk :: Node -> Double -> Node
248 f4c0b8c5 Iustin Pop
setMdsk t val = t { mDsk = val, loDsk = mDskToloDsk val (tDsk t) }
249 844eff86 Iustin Pop
250 844eff86 Iustin Pop
-- | Sets the max cpu usage ratio
251 844eff86 Iustin Pop
setMcpu :: Node -> Double -> Node
252 f4c0b8c5 Iustin Pop
setMcpu t val = t { mCpu = val, hiCpu = mCpuTohiCpu val (tCpu t) }
253 844eff86 Iustin Pop
254 e4f08c46 Iustin Pop
-- | Computes the maximum reserved memory for peers from a peer map.
255 12e6776a Iustin Pop
computeMaxRes :: P.PeerMap -> P.Elem
256 12e6776a Iustin Pop
computeMaxRes = P.maxElem
257 e4f08c46 Iustin Pop
258 e4f08c46 Iustin Pop
-- | Builds the peer map for a given node.
259 9cf4267a Iustin Pop
buildPeers :: Node -> Instance.List -> Node
260 9cf4267a Iustin Pop
buildPeers t il =
261 e4f08c46 Iustin Pop
    let mdata = map
262 e4f08c46 Iustin Pop
                (\i_idx -> let inst = Container.find i_idx il
263 2060348b Iustin Pop
                           in (Instance.pNode inst, Instance.mem inst))
264 2060348b Iustin Pop
                (sList t)
265 12e6776a Iustin Pop
        pmap = P.accumArray (+) mdata
266 e4f08c46 Iustin Pop
        new_rmem = computeMaxRes pmap
267 2060348b Iustin Pop
        new_failN1 = fMem t <= new_rmem
268 2060348b Iustin Pop
        new_prem = fromIntegral new_rmem / tMem t
269 2060348b Iustin Pop
    in t {peers=pmap, failN1 = new_failN1, rMem = new_rmem, pRem = new_prem}
270 e4f08c46 Iustin Pop
271 a488a217 Iustin Pop
-- | Assigns an instance to a node as primary and update the used VCPU
272 5f0b9579 Iustin Pop
-- count, utilisation data and tags map.
273 a488a217 Iustin Pop
setPri :: Node -> Instance.Instance -> Node
274 aa8d2e71 Iustin Pop
setPri t inst = t { pList = Instance.idx inst:pList t
275 a488a217 Iustin Pop
                  , uCpu = new_count
276 aa8d2e71 Iustin Pop
                  , pCpu = fromIntegral new_count / tCpu t
277 aa8d2e71 Iustin Pop
                  , utilLoad = utilLoad t `T.addUtil` Instance.util inst
278 5f0b9579 Iustin Pop
                  , pTags = addTags (pTags t) (Instance.tags inst)
279 aa8d2e71 Iustin Pop
                  }
280 a488a217 Iustin Pop
    where new_count = uCpu t + Instance.vcpus inst
281 9188aeef Iustin Pop
282 9188aeef Iustin Pop
-- | Assigns an instance to a node as secondary without other updates.
283 a488a217 Iustin Pop
setSec :: Node -> Instance.Instance -> Node
284 aa8d2e71 Iustin Pop
setSec t inst = t { sList = Instance.idx inst:sList t
285 aa8d2e71 Iustin Pop
                  , utilLoad = old_load { T.dskWeight = T.dskWeight old_load +
286 aa8d2e71 Iustin Pop
                                          T.dskWeight (Instance.util inst) }
287 aa8d2e71 Iustin Pop
                  }
288 aa8d2e71 Iustin Pop
    where old_load = utilLoad t
289 1a82215d Iustin Pop
290 9188aeef Iustin Pop
-- * Update functions
291 9188aeef Iustin Pop
292 9188aeef Iustin Pop
-- | Sets the free memory.
293 9188aeef Iustin Pop
setFmem :: Node -> Int -> Node
294 9188aeef Iustin Pop
setFmem t new_mem =
295 2060348b Iustin Pop
    let new_n1 = new_mem <= rMem t
296 2060348b Iustin Pop
        new_mp = fromIntegral new_mem / tMem t
297 bbd8efd2 Iustin Pop
    in t { fMem = new_mem, failN1 = new_n1, pMem = new_mp }
298 9188aeef Iustin Pop
299 e4f08c46 Iustin Pop
-- | Removes a primary instance.
300 e4f08c46 Iustin Pop
removePri :: Node -> Instance.Instance -> Node
301 e4f08c46 Iustin Pop
removePri t inst =
302 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
303 2060348b Iustin Pop
        new_plist = delete iname (pList t)
304 2060348b Iustin Pop
        new_mem = fMem t + Instance.mem inst
305 2060348b Iustin Pop
        new_dsk = fDsk t + Instance.dsk inst
306 2060348b Iustin Pop
        new_mp = fromIntegral new_mem / tMem t
307 2060348b Iustin Pop
        new_dp = fromIntegral new_dsk / tDsk t
308 2060348b Iustin Pop
        new_failn1 = new_mem <= rMem t
309 2060348b Iustin Pop
        new_ucpu = uCpu t - Instance.vcpus inst
310 2060348b Iustin Pop
        new_rcpu = fromIntegral new_ucpu / tCpu t
311 aa8d2e71 Iustin Pop
        new_load = utilLoad t `T.subUtil` Instance.util inst
312 bbd8efd2 Iustin Pop
    in t { pList = new_plist, fMem = new_mem, fDsk = new_dsk
313 bbd8efd2 Iustin Pop
         , failN1 = new_failn1, pMem = new_mp, pDsk = new_dp
314 5f0b9579 Iustin Pop
         , uCpu = new_ucpu, pCpu = new_rcpu, utilLoad = new_load
315 5f0b9579 Iustin Pop
         , pTags = delTags (pTags t) (Instance.tags inst) }
316 e4f08c46 Iustin Pop
317 e4f08c46 Iustin Pop
-- | Removes a secondary instance.
318 e4f08c46 Iustin Pop
removeSec :: Node -> Instance.Instance -> Node
319 e4f08c46 Iustin Pop
removeSec t inst =
320 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
321 2060348b Iustin Pop
        pnode = Instance.pNode inst
322 2060348b Iustin Pop
        new_slist = delete iname (sList t)
323 2060348b Iustin Pop
        new_dsk = fDsk t + Instance.dsk inst
324 e4f08c46 Iustin Pop
        old_peers = peers t
325 12e6776a Iustin Pop
        old_peem = P.find pnode old_peers
326 9f6dcdea Iustin Pop
        new_peem =  old_peem - Instance.mem inst
327 124b7cd7 Iustin Pop
        new_peers = if new_peem > 0
328 124b7cd7 Iustin Pop
                    then P.add pnode new_peem old_peers
329 124b7cd7 Iustin Pop
                    else P.remove pnode old_peers
330 2060348b Iustin Pop
        old_rmem = rMem t
331 bbd8efd2 Iustin Pop
        new_rmem = if old_peem < old_rmem
332 bbd8efd2 Iustin Pop
                   then old_rmem
333 bbd8efd2 Iustin Pop
                   else computeMaxRes new_peers
334 2060348b Iustin Pop
        new_prem = fromIntegral new_rmem / tMem t
335 2060348b Iustin Pop
        new_failn1 = fMem t <= new_rmem
336 2060348b Iustin Pop
        new_dp = fromIntegral new_dsk / tDsk t
337 aa8d2e71 Iustin Pop
        old_load = utilLoad t
338 aa8d2e71 Iustin Pop
        new_load = old_load { T.dskWeight = T.dskWeight old_load -
339 aa8d2e71 Iustin Pop
                                            T.dskWeight (Instance.util inst) }
340 bbd8efd2 Iustin Pop
    in t { sList = new_slist, fDsk = new_dsk, peers = new_peers
341 bbd8efd2 Iustin Pop
         , failN1 = new_failn1, rMem = new_rmem, pDsk = new_dp
342 bbd8efd2 Iustin Pop
         , pRem = new_prem, utilLoad = new_load }
343 e4f08c46 Iustin Pop
344 3e3c9393 Iustin Pop
-- | Adds a primary instance (basic version).
345 f2280553 Iustin Pop
addPri :: Node -> Instance.Instance -> T.OpResult Node
346 3e3c9393 Iustin Pop
addPri = addPriEx False
347 3e3c9393 Iustin Pop
348 3e3c9393 Iustin Pop
-- | Adds a primary instance (extended version).
349 3e3c9393 Iustin Pop
addPriEx :: Bool               -- ^ Whether to override the N+1 and
350 3e3c9393 Iustin Pop
                               -- other /soft/ checks, useful if we
351 3e3c9393 Iustin Pop
                               -- come from a worse status
352 3e3c9393 Iustin Pop
                               -- (e.g. offline)
353 3e3c9393 Iustin Pop
         -> Node               -- ^ The target node
354 3e3c9393 Iustin Pop
         -> Instance.Instance  -- ^ The instance to add
355 3e3c9393 Iustin Pop
         -> T.OpResult Node    -- ^ The result of the operation,
356 3e3c9393 Iustin Pop
                               -- either the new version of the node
357 3e3c9393 Iustin Pop
                               -- or a failure mode
358 3e3c9393 Iustin Pop
addPriEx force t inst =
359 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
360 2060348b Iustin Pop
        new_mem = fMem t - Instance.mem inst
361 2060348b Iustin Pop
        new_dsk = fDsk t - Instance.dsk inst
362 2060348b Iustin Pop
        new_failn1 = new_mem <= rMem t
363 2060348b Iustin Pop
        new_ucpu = uCpu t + Instance.vcpus inst
364 2060348b Iustin Pop
        new_pcpu = fromIntegral new_ucpu / tCpu t
365 2060348b Iustin Pop
        new_dp = fromIntegral new_dsk / tDsk t
366 2060348b Iustin Pop
        l_cpu = mCpu t
367 aa8d2e71 Iustin Pop
        new_load = utilLoad t `T.addUtil` Instance.util inst
368 5f0b9579 Iustin Pop
        inst_tags = Instance.tags inst
369 5f0b9579 Iustin Pop
        old_tags = pTags t
370 3e3c9393 Iustin Pop
        strict = not force
371 a4a6e623 Iustin Pop
    in case () of
372 a4a6e623 Iustin Pop
         _ | new_mem <= 0 -> T.OpFail T.FailMem
373 3e3c9393 Iustin Pop
           | new_dsk <= 0 -> T.OpFail T.FailDisk
374 3e3c9393 Iustin Pop
           | mDsk t > new_dp && strict -> T.OpFail T.FailDisk
375 3e3c9393 Iustin Pop
           | new_failn1 && not (failN1 t) && strict -> T.OpFail T.FailMem
376 3e3c9393 Iustin Pop
           | l_cpu >= 0 && l_cpu < new_pcpu && strict -> T.OpFail T.FailCPU
377 a4a6e623 Iustin Pop
           | rejectAddTags old_tags inst_tags -> T.OpFail T.FailTags
378 a4a6e623 Iustin Pop
           | otherwise ->
379 a4a6e623 Iustin Pop
               let new_plist = iname:pList t
380 a4a6e623 Iustin Pop
                   new_mp = fromIntegral new_mem / tMem t
381 a4a6e623 Iustin Pop
                   r = t { pList = new_plist, fMem = new_mem, fDsk = new_dsk
382 a4a6e623 Iustin Pop
                         , failN1 = new_failn1, pMem = new_mp, pDsk = new_dp
383 a4a6e623 Iustin Pop
                         , uCpu = new_ucpu, pCpu = new_pcpu
384 a4a6e623 Iustin Pop
                         , utilLoad = new_load
385 a4a6e623 Iustin Pop
                         , pTags = addTags old_tags inst_tags }
386 a4a6e623 Iustin Pop
               in T.OpGood r
387 e4f08c46 Iustin Pop
388 3e3c9393 Iustin Pop
-- | Adds a secondary instance (basic version).
389 f2280553 Iustin Pop
addSec :: Node -> Instance.Instance -> T.Ndx -> T.OpResult Node
390 3e3c9393 Iustin Pop
addSec = addSecEx False
391 3e3c9393 Iustin Pop
392 3e3c9393 Iustin Pop
-- | Adds a secondary instance (extended version).
393 3e3c9393 Iustin Pop
addSecEx :: Bool -> Node -> Instance.Instance -> T.Ndx -> T.OpResult Node
394 3e3c9393 Iustin Pop
addSecEx force t inst pdx =
395 e4f08c46 Iustin Pop
    let iname = Instance.idx inst
396 e4f08c46 Iustin Pop
        old_peers = peers t
397 2060348b Iustin Pop
        old_mem = fMem t
398 2060348b Iustin Pop
        new_dsk = fDsk t - Instance.dsk inst
399 12e6776a Iustin Pop
        new_peem = P.find pdx old_peers + Instance.mem inst
400 12e6776a Iustin Pop
        new_peers = P.add pdx new_peem old_peers
401 2060348b Iustin Pop
        new_rmem = max (rMem t) new_peem
402 2060348b Iustin Pop
        new_prem = fromIntegral new_rmem / tMem t
403 c43c3354 Iustin Pop
        new_failn1 = old_mem <= new_rmem
404 2060348b Iustin Pop
        new_dp = fromIntegral new_dsk / tDsk t
405 aa8d2e71 Iustin Pop
        old_load = utilLoad t
406 aa8d2e71 Iustin Pop
        new_load = old_load { T.dskWeight = T.dskWeight old_load +
407 aa8d2e71 Iustin Pop
                                            T.dskWeight (Instance.util inst) }
408 3e3c9393 Iustin Pop
        strict = not force
409 a4a6e623 Iustin Pop
    in case () of
410 3e3c9393 Iustin Pop
         _ | new_dsk <= 0 -> T.OpFail T.FailDisk
411 3e3c9393 Iustin Pop
           | mDsk t > new_dp && strict -> T.OpFail T.FailDisk
412 74e89a14 Iustin Pop
           | Instance.mem inst >= old_mem && strict -> T.OpFail T.FailMem
413 3e3c9393 Iustin Pop
           | new_failn1 && not (failN1 t) && strict -> T.OpFail T.FailMem
414 a4a6e623 Iustin Pop
           | otherwise ->
415 a4a6e623 Iustin Pop
               let new_slist = iname:sList t
416 a4a6e623 Iustin Pop
                   r = t { sList = new_slist, fDsk = new_dsk
417 a4a6e623 Iustin Pop
                         , peers = new_peers, failN1 = new_failn1
418 a4a6e623 Iustin Pop
                         , rMem = new_rmem, pDsk = new_dp
419 a4a6e623 Iustin Pop
                         , pRem = new_prem, utilLoad = new_load }
420 a4a6e623 Iustin Pop
               in T.OpGood r
421 e4f08c46 Iustin Pop
422 fe3d6f02 Iustin Pop
-- * Stats functions
423 fe3d6f02 Iustin Pop
424 fe3d6f02 Iustin Pop
-- | Computes the amount of available disk on a given node
425 fe3d6f02 Iustin Pop
availDisk :: Node -> Int
426 fe3d6f02 Iustin Pop
availDisk t =
427 2060348b Iustin Pop
    let _f = fDsk t
428 2060348b Iustin Pop
        _l = loDsk t
429 f4c0b8c5 Iustin Pop
    in if _f < _l
430 f4c0b8c5 Iustin Pop
       then 0
431 f4c0b8c5 Iustin Pop
       else _f - _l
432 fe3d6f02 Iustin Pop
433 1e3dccc8 Iustin Pop
-- | Computes the amount of available memory on a given node
434 1e3dccc8 Iustin Pop
availMem :: Node -> Int
435 1e3dccc8 Iustin Pop
availMem t =
436 1e3dccc8 Iustin Pop
    let _f = fMem t
437 1e3dccc8 Iustin Pop
        _l = rMem t
438 1e3dccc8 Iustin Pop
    in if _f < _l
439 1e3dccc8 Iustin Pop
       then 0
440 1e3dccc8 Iustin Pop
       else _f - _l
441 1e3dccc8 Iustin Pop
442 1e3dccc8 Iustin Pop
-- | Computes the amount of available memory on a given node
443 1e3dccc8 Iustin Pop
availCpu :: Node -> Int
444 1e3dccc8 Iustin Pop
availCpu t =
445 1e3dccc8 Iustin Pop
    let _u = uCpu t
446 1e3dccc8 Iustin Pop
        _l = hiCpu t
447 1e3dccc8 Iustin Pop
    in if _l >= _u
448 1e3dccc8 Iustin Pop
       then _l - _u
449 1e3dccc8 Iustin Pop
       else 0
450 1e3dccc8 Iustin Pop
451 9188aeef Iustin Pop
-- * Display functions
452 01f6a5d2 Iustin Pop
453 c5f7412e Iustin Pop
showField :: Node -> String -> String
454 c5f7412e Iustin Pop
showField t field =
455 c5f7412e Iustin Pop
    case field of
456 16f08e82 Iustin Pop
      "idx"  -> printf "%4d" $ idx t
457 3e4480e0 Iustin Pop
      "name" -> alias t
458 3e4480e0 Iustin Pop
      "fqdn" -> name t
459 c5f7412e Iustin Pop
      "status" -> if offline t then "-"
460 c5f7412e Iustin Pop
                  else if failN1 t then "*" else " "
461 c5f7412e Iustin Pop
      "tmem" -> printf "%5.0f" $ tMem t
462 c5f7412e Iustin Pop
      "nmem" -> printf "%5d" $ nMem t
463 c5f7412e Iustin Pop
      "xmem" -> printf "%5d" $ xMem t
464 c5f7412e Iustin Pop
      "fmem" -> printf "%5d" $ fMem t
465 c5f7412e Iustin Pop
      "imem" -> printf "%5d" imem
466 c5f7412e Iustin Pop
      "rmem" -> printf "%5d" $ rMem t
467 76354e11 Iustin Pop
      "amem" -> printf "%5d" $ fMem t - rMem t
468 c5f7412e Iustin Pop
      "tdsk" -> printf "%5.0f" $ tDsk t / 1024
469 c5f7412e Iustin Pop
      "fdsk" -> printf "%5d" $ fDsk t `div` 1024
470 c5f7412e Iustin Pop
      "tcpu" -> printf "%4.0f" $ tCpu t
471 c5f7412e Iustin Pop
      "ucpu" -> printf "%4d" $ uCpu t
472 16f08e82 Iustin Pop
      "pcnt" -> printf "%3d" $ length (pList t)
473 16f08e82 Iustin Pop
      "scnt" -> printf "%3d" $ length (sList t)
474 16f08e82 Iustin Pop
      "plist" -> show $ pList t
475 16f08e82 Iustin Pop
      "slist" -> show $ sList t
476 c5f7412e Iustin Pop
      "pfmem" -> printf "%6.4f" $ pMem t
477 c5f7412e Iustin Pop
      "pfdsk" -> printf "%6.4f" $ pDsk t
478 c5f7412e Iustin Pop
      "rcpu"  -> printf "%5.2f" $ pCpu t
479 c5f7412e Iustin Pop
      "cload" -> printf "%5.3f" uC
480 c5f7412e Iustin Pop
      "mload" -> printf "%5.3f" uM
481 c5f7412e Iustin Pop
      "dload" -> printf "%5.3f" uD
482 c5f7412e Iustin Pop
      "nload" -> printf "%5.3f" uN
483 b2999982 Iustin Pop
      "ptags" -> intercalate "," . map (\(k, v) -> printf "%s=%d" k v) .
484 b2999982 Iustin Pop
                 Map.toList $ pTags t
485 16f08e82 Iustin Pop
      "peermap" -> show $ peers t
486 82ea2874 Iustin Pop
      _ -> T.unknownField
487 c5f7412e Iustin Pop
    where
488 c5f7412e Iustin Pop
      T.DynUtil { T.cpuWeight = uC, T.memWeight = uM,
489 c5f7412e Iustin Pop
                  T.dskWeight = uD, T.netWeight = uN } = utilLoad t
490 c5f7412e Iustin Pop
      imem = truncate (tMem t) - nMem t - xMem t - fMem t
491 c5f7412e Iustin Pop
492 76354e11 Iustin Pop
-- | Returns the header and numeric propery of a field
493 76354e11 Iustin Pop
showHeader :: String -> (String, Bool)
494 76354e11 Iustin Pop
showHeader field =
495 76354e11 Iustin Pop
    case field of
496 16f08e82 Iustin Pop
      "idx" -> ("Index", True)
497 76354e11 Iustin Pop
      "name" -> ("Name", False)
498 3e4480e0 Iustin Pop
      "fqdn" -> ("Name", False)
499 76354e11 Iustin Pop
      "status" -> ("F", False)
500 76354e11 Iustin Pop
      "tmem" -> ("t_mem", True)
501 76354e11 Iustin Pop
      "nmem" -> ("n_mem", True)
502 76354e11 Iustin Pop
      "xmem" -> ("x_mem", True)
503 76354e11 Iustin Pop
      "fmem" -> ("f_mem", True)
504 76354e11 Iustin Pop
      "imem" -> ("i_mem", True)
505 76354e11 Iustin Pop
      "rmem" -> ("r_mem", True)
506 76354e11 Iustin Pop
      "amem" -> ("a_mem", True)
507 76354e11 Iustin Pop
      "tdsk" -> ("t_dsk", True)
508 76354e11 Iustin Pop
      "fdsk" -> ("f_dsk", True)
509 76354e11 Iustin Pop
      "tcpu" -> ("pcpu", True)
510 76354e11 Iustin Pop
      "ucpu" -> ("vcpu", True)
511 16f08e82 Iustin Pop
      "pcnt" -> ("pcnt", True)
512 16f08e82 Iustin Pop
      "scnt" -> ("scnt", True)
513 16f08e82 Iustin Pop
      "plist" -> ("primaries", True)
514 16f08e82 Iustin Pop
      "slist" -> ("secondaries", True)
515 76354e11 Iustin Pop
      "pfmem" -> ("p_fmem", True)
516 76354e11 Iustin Pop
      "pfdsk" -> ("p_fdsk", True)
517 76354e11 Iustin Pop
      "rcpu"  -> ("r_cpu", True)
518 76354e11 Iustin Pop
      "cload" -> ("lCpu", True)
519 76354e11 Iustin Pop
      "mload" -> ("lMem", True)
520 76354e11 Iustin Pop
      "dload" -> ("lDsk", True)
521 76354e11 Iustin Pop
      "nload" -> ("lNet", True)
522 b2999982 Iustin Pop
      "ptags" -> ("PrimaryTags", False)
523 16f08e82 Iustin Pop
      "peermap" -> ("PeerMap", False)
524 82ea2874 Iustin Pop
      _ -> (T.unknownField, False)
525 c5f7412e Iustin Pop
526 e4f08c46 Iustin Pop
-- | String converter for the node list functionality.
527 76354e11 Iustin Pop
list :: [String] -> Node -> [String]
528 76354e11 Iustin Pop
list fields t = map (showField t) fields
529 76354e11 Iustin Pop
530 76354e11 Iustin Pop
531 76354e11 Iustin Pop
defaultFields :: [String]
532 76354e11 Iustin Pop
defaultFields =
533 76354e11 Iustin Pop
    [ "status", "name", "tmem", "nmem", "imem", "xmem", "fmem"
534 16f08e82 Iustin Pop
    , "rmem", "tdsk", "fdsk", "tcpu", "ucpu", "pcnt", "scnt"
535 76354e11 Iustin Pop
    , "pfmem", "pfdsk", "rcpu"
536 76354e11 Iustin Pop
    , "cload", "mload", "dload", "nload" ]