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