htools: return new state from new IAllocator modes
[ganeti-local] / htools / Ganeti / HTools / Instance.hs
1 {-| Module describing an instance.
2
3 The instance data type holds very few fields, the algorithm
4 intelligence is in the "Node" and "Cluster" modules.
5
6 -}
7
8 {-
9
10 Copyright (C) 2009, 2010, 2011 Google Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 02110-1301, USA.
26
27 -}
28
29 module Ganeti.HTools.Instance
30     ( Instance(..)
31     , AssocList
32     , List
33     , create
34     , setIdx
35     , setName
36     , setAlias
37     , setPri
38     , setSec
39     , setBoth
40     , setMovable
41     , specOf
42     , shrinkByType
43     , runningStates
44     , requiredNodes
45     , allNodes
46     ) where
47
48 import qualified Ganeti.HTools.Types as T
49 import qualified Ganeti.HTools.Container as Container
50 import qualified Ganeti.Constants as C
51
52 -- * Type declarations
53
54 -- | The instance type.
55 data Instance = Instance
56     { name         :: String    -- ^ The instance name
57     , alias        :: String    -- ^ The shortened name
58     , mem          :: Int       -- ^ Memory of the instance
59     , dsk          :: Int       -- ^ Disk size of instance
60     , vcpus        :: Int       -- ^ Number of VCPUs
61     , running      :: Bool      -- ^ Is the instance running?
62     , runSt        :: String    -- ^ Original (text) run status
63     , pNode        :: T.Ndx     -- ^ Original primary node
64     , sNode        :: T.Ndx     -- ^ Original secondary node
65     , idx          :: T.Idx     -- ^ Internal index
66     , util         :: T.DynUtil -- ^ Dynamic resource usage
67     , movable      :: Bool      -- ^ Can the instance be moved?
68     , autoBalance  :: Bool      -- ^ Is the instance auto-balanced?
69     , tags         :: [String]  -- ^ List of instance tags
70     , diskTemplate :: T.DiskTemplate -- ^ The disk template of the instance
71     } deriving (Show, Read)
72
73 instance T.Element Instance where
74     nameOf   = name
75     idxOf    = idx
76     setAlias = setAlias
77     setIdx   = setIdx
78     allNames n = [name n, alias n]
79
80 -- | Constant holding the running instance states.
81 runningStates :: [String]
82 runningStates = [C.inststRunning, C.inststErrorup]
83
84 -- | A simple name for the int, instance association list.
85 type AssocList = [(T.Idx, Instance)]
86
87 -- | A simple name for an instance map.
88 type List = Container.Container Instance
89
90 -- * Initialization
91
92 -- | Create an instance.
93 --
94 -- Some parameters are not initialized by function, and must be set
95 -- later (via 'setIdx' for example).
96 create :: String -> Int -> Int -> Int -> String
97        -> [String] -> Bool -> T.Ndx -> T.Ndx -> T.DiskTemplate -> Instance
98 create name_init mem_init dsk_init vcpus_init run_init tags_init
99        auto_balance_init pn sn dt =
100     Instance { name = name_init
101              , alias = name_init
102              , mem = mem_init
103              , dsk = dsk_init
104              , vcpus = vcpus_init
105              , running = run_init `elem` runningStates
106              , runSt = run_init
107              , pNode = pn
108              , sNode = sn
109              , idx = -1
110              , util = T.baseUtil
111              , tags = tags_init
112              , movable = True
113              , autoBalance = auto_balance_init
114              , diskTemplate = dt
115              }
116
117 -- | Changes the index.
118 --
119 -- This is used only during the building of the data structures.
120 setIdx :: Instance -- ^ The original instance
121        -> T.Idx    -- ^ New index
122        -> Instance -- ^ The modified instance
123 setIdx t i = t { idx = i }
124
125 -- | Changes the name.
126 --
127 -- This is used only during the building of the data structures.
128 setName :: Instance -- ^ The original instance
129         -> String   -- ^ New name
130         -> Instance -- ^ The modified instance
131 setName t s = t { name = s, alias = s }
132
133 -- | Changes the alias.
134 --
135 -- This is used only during the building of the data structures.
136 setAlias :: Instance -- ^ The original instance
137          -> String   -- ^ New alias
138          -> Instance -- ^ The modified instance
139 setAlias t s = t { alias = s }
140
141 -- * Update functions
142
143 -- | Changes the primary node of the instance.
144 setPri :: Instance  -- ^ the original instance
145         -> T.Ndx    -- ^ the new primary node
146         -> Instance -- ^ the modified instance
147 setPri t p = t { pNode = p }
148
149 -- | Changes the secondary node of the instance.
150 setSec :: Instance  -- ^ the original instance
151         -> T.Ndx    -- ^ the new secondary node
152         -> Instance -- ^ the modified instance
153 setSec t s = t { sNode = s }
154
155 -- | Changes both nodes of the instance.
156 setBoth :: Instance  -- ^ the original instance
157          -> T.Ndx    -- ^ new primary node index
158          -> T.Ndx    -- ^ new secondary node index
159          -> Instance -- ^ the modified instance
160 setBoth t p s = t { pNode = p, sNode = s }
161
162 setMovable :: Instance -- ^ The original instance
163            -> Bool     -- ^ New movable flag
164            -> Instance -- ^ The modified instance
165 setMovable t m = t { movable = m }
166
167 -- | Try to shrink the instance based on the reason why we can't
168 -- allocate it.
169 shrinkByType :: Instance -> T.FailMode -> T.Result Instance
170 shrinkByType inst T.FailMem = let v = mem inst - T.unitMem
171                               in if v < T.unitMem
172                                  then T.Bad "out of memory"
173                                  else T.Ok inst { mem = v }
174 shrinkByType inst T.FailDisk = let v = dsk inst - T.unitDsk
175                                in if v < T.unitDsk
176                                   then T.Bad "out of disk"
177                                   else T.Ok inst { dsk = v }
178 shrinkByType inst T.FailCPU = let v = vcpus inst - T.unitCpu
179                               in if v < T.unitCpu
180                                  then T.Bad "out of vcpus"
181                                  else T.Ok inst { vcpus = v }
182 shrinkByType _ f = T.Bad $ "Unhandled failure mode " ++ show f
183
184 -- | Return the spec of an instance.
185 specOf :: Instance -> T.RSpec
186 specOf Instance { mem = m, dsk = d, vcpus = c } =
187     T.RSpec { T.rspecCpu = c, T.rspecMem = m, T.rspecDsk = d }
188
189 -- | Computed the number of nodes for a given disk template
190 requiredNodes :: T.DiskTemplate -> Int
191 requiredNodes T.DTDrbd8 = 2
192 requiredNodes _         = 1
193
194 -- | Computes all nodes of an instance.
195 allNodes :: Instance -> [T.Ndx]
196 allNodes inst = case diskTemplate inst of
197                   T.DTDrbd8 -> [pNode inst, sNode inst]
198                   _ -> [pNode inst]