Add two functions for checking cluster consistency
[ganeti-local] / Ganeti / HTools / Types.hs
1 {-| Some common types.
2
3 -}
4
5 {-
6
7 Copyright (C) 2009, 2010 Google Inc.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA.
23
24 -}
25
26 module Ganeti.HTools.Types
27     ( Idx
28     , Ndx
29     , NameAssoc
30     , Score
31     , Weight
32     , GroupID
33     , RSpec(..)
34     , DynUtil(..)
35     , zeroUtil
36     , baseUtil
37     , addUtil
38     , subUtil
39     , defVcpuRatio
40     , defReservedDiskRatio
41     , unitMem
42     , unitCpu
43     , unitDsk
44     , unknownField
45     , Placement
46     , IMove(..)
47     , MoveJob
48     , JobSet
49     , Result(..)
50     , Element(..)
51     , FailMode(..)
52     , FailStats
53     , OpResult(..)
54     , connTimeout
55     , queryTimeout
56     ) where
57
58 -- | The instance index type.
59 type Idx = Int
60
61 -- | The node index type.
62 type Ndx = Int
63
64 -- | The type used to hold name-to-idx mappings.
65 type NameAssoc = [(String, Int)]
66
67 -- | A separate name for the cluster score type.
68 type Score = Double
69
70 -- | A separate name for a weight metric.
71 type Weight = Double
72
73 -- | The Group UUID type
74 type GroupID = String
75
76 -- | The resource spec type.
77 data RSpec = RSpec
78     { rspecCpu  :: Int  -- ^ Requested VCPUs
79     , rspecMem  :: Int  -- ^ Requested memory
80     , rspecDsk  :: Int  -- ^ Requested disk
81     } deriving (Show, Eq)
82
83 -- | The dynamic resource specs of a machine (i.e. load or load
84 -- capacity, as opposed to size).
85 data DynUtil = DynUtil
86     { cpuWeight :: Weight -- ^ Standardised CPU usage
87     , memWeight :: Weight -- ^ Standardised memory load
88     , dskWeight :: Weight -- ^ Standardised disk I\/O usage
89     , netWeight :: Weight -- ^ Standardised network usage
90     } deriving (Show, Eq)
91
92 -- | Initial empty utilisation
93 zeroUtil :: DynUtil
94 zeroUtil = DynUtil { cpuWeight = 0, memWeight = 0
95                    , dskWeight = 0, netWeight = 0 }
96
97 baseUtil :: DynUtil
98 baseUtil = DynUtil { cpuWeight = 1, memWeight = 1
99                    , dskWeight = 1, netWeight = 1 }
100
101 addUtil :: DynUtil -> DynUtil -> DynUtil
102 addUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
103     DynUtil (a1+b1) (a2+b2) (a3+b3) (a4+b4)
104
105 subUtil :: DynUtil -> DynUtil -> DynUtil
106 subUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
107     DynUtil (a1-b1) (a2-b2) (a3-b3) (a4-b4)
108
109 -- | The description of an instance placement. It contains the
110 -- instance index, the new primary and secondary node, the move being
111 -- performed and the score of the cluster after the move.
112 type Placement = (Idx, Ndx, Ndx, IMove, Score)
113
114 -- | An instance move definition
115 data IMove = Failover                -- ^ Failover the instance (f)
116            | ReplacePrimary Ndx      -- ^ Replace primary (f, r:np, f)
117            | ReplaceSecondary Ndx    -- ^ Replace secondary (r:ns)
118            | ReplaceAndFailover Ndx  -- ^ Replace secondary, failover (r:np, f)
119            | FailoverAndReplace Ndx  -- ^ Failover, replace secondary (f, r:ns)
120              deriving (Show)
121
122 -- | Formatted solution output for one move (involved nodes and
123 -- commands
124 type MoveJob = ([Ndx], Idx, IMove, [String])
125
126 -- | Unknown field in table output
127 unknownField :: String
128 unknownField = "<unknown field>"
129
130 -- | A list of command elements
131 type JobSet = [MoveJob]
132
133 -- | Connection timeout (when using non-file methods).
134 connTimeout :: Int
135 connTimeout = 15
136
137 -- | The default timeout for queries (when using non-file methods).
138 queryTimeout :: Int
139 queryTimeout = 60
140
141 -- | Default vcpu-to-pcpu ratio (randomly chosen value).
142 defVcpuRatio :: Double
143 defVcpuRatio = 64
144
145 -- | Default max disk usage ratio.
146 defReservedDiskRatio :: Double
147 defReservedDiskRatio = 0
148
149 -- | Base memory unit.
150 unitMem :: Int
151 unitMem = 64
152
153 -- | Base disk unit.
154 unitDsk :: Int
155 unitDsk = 256
156
157 -- | Base vcpus unit.
158 unitCpu :: Int
159 unitCpu = 1
160
161 {-|
162
163 This is similar to the JSON library Result type - *very* similar, but
164 we want to use it in multiple places, so we abstract it into a
165 mini-library here
166
167 -}
168 data Result a
169     = Bad String
170     | Ok a
171     deriving (Show)
172
173 instance Monad Result where
174     (>>=) (Bad x) _ = Bad x
175     (>>=) (Ok x) fn = fn x
176     return = Ok
177     fail = Bad
178
179 -- | Reason for an operation's falure
180 data FailMode = FailMem  -- ^ Failed due to not enough RAM
181               | FailDisk -- ^ Failed due to not enough disk
182               | FailCPU  -- ^ Failed due to not enough CPU capacity
183               | FailN1   -- ^ Failed due to not passing N1 checks
184               | FailTags -- ^ Failed due to tag exclusion
185                 deriving (Eq, Enum, Bounded, Show)
186
187 -- | List with failure statistics
188 type FailStats = [(FailMode, Int)]
189
190 -- | Either-like data-type customized for our failure modes
191 data OpResult a = OpFail FailMode -- ^ Failed operation
192                 | OpGood a        -- ^ Success operation
193                   deriving (Show)
194
195 instance Monad OpResult where
196     (OpGood x) >>= fn = fn x
197     (OpFail y) >>= _ = OpFail y
198     return = OpGood
199
200 -- | A generic class for items that have updateable names and indices.
201 class Element a where
202     -- | Returns the name of the element
203     nameOf  :: a -> String
204     -- | Returns all the known names of the element
205     allNames :: a -> [String]
206     -- | Returns the index of the element
207     idxOf   :: a -> Int
208     -- | Updates the alias of the element
209     setAlias :: a -> String -> a
210     -- | Compute the alias by stripping a given suffix (domain) from
211     -- | the name
212     computeAlias :: String -> a -> a
213     computeAlias dom e = setAlias e alias
214         where alias = take (length name - length dom) name
215               name = nameOf e
216     -- | Updates the index of the element
217     setIdx  :: a -> Int -> a