Abstract instance running states into a list
[ganeti-local] / 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 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     , setPri
37     , setSec
38     , setBoth
39     , setMovable
40     , specOf
41     , shrinkByType
42     , runningStates
43     ) where
44
45 import qualified Ganeti.HTools.Types as T
46 import qualified Ganeti.HTools.Container as Container
47
48 -- * Type declarations
49
50 -- | The instance type
51 data Instance = Instance { name :: String    -- ^ The instance name
52                          , mem :: Int        -- ^ Memory of the instance
53                          , dsk :: Int        -- ^ Disk size of instance
54                          , vcpus :: Int      -- ^ Number of VCPUs
55                          , running :: Bool   -- ^ Is the instance running?
56                          , runSt :: String   -- ^ Original (text) run status
57                          , pNode :: T.Ndx    -- ^ Original primary node
58                          , sNode :: T.Ndx    -- ^ Original secondary node
59                          , idx :: T.Idx      -- ^ Internal index
60                          , util :: T.DynUtil -- ^ Dynamic resource usage
61                          , movable :: Bool   -- ^ Can the instance be moved?
62                          , tags :: [String]  -- ^ List of instance tags
63                          } deriving (Show)
64
65 instance T.Element Instance where
66     nameOf  = name
67     idxOf   = idx
68     setName = setName
69     setIdx  = setIdx
70
71 -- | Base memory unit.
72 unitMem :: Int
73 unitMem = 64
74 -- | Base disk unit.
75 unitDsk :: Int
76 unitDsk = 256
77 -- | Base vcpus unit.
78 unitCpu :: Int
79 unitCpu = 1
80
81 -- | Running instance states.
82 runningStates :: [String]
83 runningStates = ["running", "ERROR_up"]
84
85 -- | A simple name for the int, instance association list.
86 type AssocList = [(T.Idx, Instance)]
87
88 -- | A simple name for an instance map.
89 type List = Container.Container Instance
90
91 -- * Initialization
92
93 -- | Create an instance.
94 --
95 -- Some parameters are not initialized by function, and must be set
96 -- later (via 'setIdx' for example).
97 create :: String -> Int -> Int -> Int -> String
98        -> [String] -> T.Ndx -> T.Ndx -> Instance
99 create name_init mem_init dsk_init vcpus_init run_init tags_init pn sn =
100     Instance { name = name_init
101              , mem = mem_init
102              , dsk = dsk_init
103              , vcpus = vcpus_init
104              , running = run_init `elem` runningStates
105              , runSt = run_init
106              , pNode = pn
107              , sNode = sn
108              , idx = -1
109              , util = T.baseUtil
110              , tags = tags_init
111              , movable = True
112              }
113
114 -- | Changes the index.
115 --
116 -- This is used only during the building of the data structures.
117 setIdx :: Instance -- ^ The original instance
118        -> T.Idx    -- ^ New index
119        -> Instance -- ^ The modified instance
120 setIdx t i = t { idx = i }
121
122 -- | Changes the name.
123 --
124 -- This is used only during the building of the data structures.
125 setName :: Instance -- ^ The original instance
126         -> String   -- ^ New name
127         -> Instance -- ^ The modified instance
128 setName t s = t { name = s }
129
130 -- * Update functions
131
132 -- | Changes the primary node of the instance.
133 setPri :: Instance  -- ^ the original instance
134         -> T.Ndx    -- ^ the new primary node
135         -> Instance -- ^ the modified instance
136 setPri t p = t { pNode = p }
137
138 -- | Changes the secondary node of the instance.
139 setSec :: Instance  -- ^ the original instance
140         -> T.Ndx    -- ^ the new secondary node
141         -> Instance -- ^ the modified instance
142 setSec t s = t { sNode = s }
143
144 -- | Changes both nodes of the instance.
145 setBoth :: Instance  -- ^ the original instance
146          -> T.Ndx    -- ^ new primary node index
147          -> T.Ndx    -- ^ new secondary node index
148          -> Instance -- ^ the modified instance
149 setBoth t p s = t { pNode = p, sNode = s }
150
151 setMovable :: Instance -- ^ The original instance
152            -> Bool     -- ^ New movable flag
153            -> Instance -- ^ The modified instance
154 setMovable t m = t { movable = m }
155
156 -- | Try to shrink the instance based on the reason why we can't
157 -- allocate it.
158 shrinkByType :: Instance -> T.FailMode -> T.Result Instance
159 shrinkByType inst T.FailMem = let v = mem inst - unitMem
160                               in if v < unitMem
161                                  then T.Bad "out of memory"
162                                  else T.Ok inst { mem = v }
163 shrinkByType inst T.FailDisk = let v = dsk inst - unitDsk
164                                in if v < unitDsk
165                                   then T.Bad "out of disk"
166                                   else T.Ok inst { dsk = v }
167 shrinkByType inst T.FailCPU = let v = vcpus inst - unitCpu
168                               in if v < unitCpu
169                                  then T.Bad "out of vcpus"
170                                  else T.Ok inst { vcpus = v }
171 shrinkByType _ f = T.Bad $ "Unhandled failure mode " ++ show f
172
173 -- | Return the spec of an instance.
174 specOf :: Instance -> T.RSpec
175 specOf Instance { mem = m, dsk = d, vcpus = c } =
176     T.RSpec { T.rspecCpu = c, T.rspecMem = m, T.rspecDsk = d }