Parse node group networks
[ganeti-github.git] / src / Ganeti / HTools / Types.hs
1 {-# LANGUAGE TemplateHaskell #-}
2
3 {-| Some common types.
4
5 -}
6
7 {-
8
9 Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 02110-1301, USA.
25
26 -}
27
28 module Ganeti.HTools.Types
29 ( Idx
30 , Ndx
31 , Gdx
32 , NameAssoc
33 , Score
34 , Weight
35 , GroupID
36 , defaultGroupID
37 , AllocPolicy(..)
38 , allocPolicyFromRaw
39 , allocPolicyToRaw
40 , NetworkID
41 , InstanceStatus(..)
42 , instanceStatusFromRaw
43 , instanceStatusToRaw
44 , RSpec(..)
45 , AllocInfo(..)
46 , AllocStats
47 , DynUtil(..)
48 , zeroUtil
49 , baseUtil
50 , addUtil
51 , subUtil
52 , defReservedDiskRatio
53 , unitMem
54 , unitCpu
55 , unitDsk
56 , unknownField
57 , Placement
58 , IMove(..)
59 , DiskTemplate(..)
60 , diskTemplateToRaw
61 , diskTemplateFromRaw
62 , MirrorType(..)
63 , templateMirrorType
64 , MoveJob
65 , JobSet
66 , Element(..)
67 , FailMode(..)
68 , FailStats
69 , OpResult
70 , opToResult
71 , EvacMode(..)
72 , ISpec(..)
73 , MinMaxISpecs(..)
74 , IPolicy(..)
75 , defIPolicy
76 , rspecFromISpec
77 , AutoRepairType(..)
78 , autoRepairTypeToRaw
79 , autoRepairTypeFromRaw
80 , AutoRepairResult(..)
81 , autoRepairResultToRaw
82 , autoRepairResultFromRaw
83 , AutoRepairPolicy(..)
84 , AutoRepairSuspendTime(..)
85 , AutoRepairData(..)
86 , AutoRepairStatus(..)
87 ) where
88
89 import qualified Data.Map as M
90 import System.Time (ClockTime)
91
92 import qualified Ganeti.Constants as C
93 import qualified Ganeti.THH as THH
94 import Ganeti.BasicTypes
95 import Ganeti.Types
96
97 -- | The instance index type.
98 type Idx = Int
99
100 -- | The node index type.
101 type Ndx = Int
102
103 -- | The group index type.
104 type Gdx = Int
105
106 -- | The type used to hold name-to-idx mappings.
107 type NameAssoc = M.Map String Int
108
109 -- | A separate name for the cluster score type.
110 type Score = Double
111
112 -- | A separate name for a weight metric.
113 type Weight = Double
114
115 -- | The Group UUID type.
116 type GroupID = String
117
118 -- | Default group UUID (just a string, not a real UUID).
119 defaultGroupID :: GroupID
120 defaultGroupID = "00000000-0000-0000-0000-000000000000"
121
122 -- | Mirroring type.
123 data MirrorType = MirrorNone -- ^ No mirroring/movability
124 | MirrorInternal -- ^ DRBD-type mirroring
125 | MirrorExternal -- ^ Shared-storage type mirroring
126 deriving (Eq, Show)
127
128 -- | Correspondence between disk template and mirror type.
129 templateMirrorType :: DiskTemplate -> MirrorType
130 templateMirrorType DTDiskless = MirrorExternal
131 templateMirrorType DTFile = MirrorNone
132 templateMirrorType DTSharedFile = MirrorExternal
133 templateMirrorType DTPlain = MirrorNone
134 templateMirrorType DTBlock = MirrorExternal
135 templateMirrorType DTDrbd8 = MirrorInternal
136 templateMirrorType DTRbd = MirrorExternal
137 templateMirrorType DTExt = MirrorExternal
138
139 -- | The resource spec type.
140 data RSpec = RSpec
141 { rspecCpu :: Int -- ^ Requested VCPUs
142 , rspecMem :: Int -- ^ Requested memory
143 , rspecDsk :: Int -- ^ Requested disk
144 } deriving (Show, Eq)
145
146 -- | Allocation stats type. This is used instead of 'RSpec' (which was
147 -- used at first), because we need to track more stats. The actual
148 -- data can refer either to allocated, or available, etc. values
149 -- depending on the context. See also
150 -- 'Cluster.computeAllocationDelta'.
151 data AllocInfo = AllocInfo
152 { allocInfoVCpus :: Int -- ^ VCPUs
153 , allocInfoNCpus :: Double -- ^ Normalised CPUs
154 , allocInfoMem :: Int -- ^ Memory
155 , allocInfoDisk :: Int -- ^ Disk
156 } deriving (Show, Eq)
157
158 -- | Currently used, possibly to allocate, unallocable.
159 type AllocStats = (AllocInfo, AllocInfo, AllocInfo)
160
161 -- | The network UUID type.
162 type NetworkID = String
163
164 -- | Instance specification type.
165 $(THH.buildObject "ISpec" "iSpec"
166 [ THH.renameField "MemorySize" $ THH.simpleField C.ispecMemSize [t| Int |]
167 , THH.renameField "CpuCount" $ THH.simpleField C.ispecCpuCount [t| Int |]
168 , THH.renameField "DiskSize" $ THH.simpleField C.ispecDiskSize [t| Int |]
169 , THH.renameField "DiskCount" $ THH.simpleField C.ispecDiskCount [t| Int |]
170 , THH.renameField "NicCount" $ THH.simpleField C.ispecNicCount [t| Int |]
171 , THH.renameField "SpindleUse" $ THH.simpleField C.ispecSpindleUse [t| Int |]
172 ])
173
174 -- | The default minimum ispec.
175 defMinISpec :: ISpec
176 defMinISpec = ISpec { iSpecMemorySize = C.ispecsMinmaxDefaultsMinMemorySize
177 , iSpecCpuCount = C.ispecsMinmaxDefaultsMinCpuCount
178 , iSpecDiskSize = C.ispecsMinmaxDefaultsMinDiskSize
179 , iSpecDiskCount = C.ispecsMinmaxDefaultsMinDiskCount
180 , iSpecNicCount = C.ispecsMinmaxDefaultsMinNicCount
181 , iSpecSpindleUse = C.ispecsMinmaxDefaultsMinSpindleUse
182 }
183
184 -- | The default standard ispec.
185 defStdISpec :: ISpec
186 defStdISpec = ISpec { iSpecMemorySize = C.ipolicyDefaultsStdMemorySize
187 , iSpecCpuCount = C.ipolicyDefaultsStdCpuCount
188 , iSpecDiskSize = C.ipolicyDefaultsStdDiskSize
189 , iSpecDiskCount = C.ipolicyDefaultsStdDiskCount
190 , iSpecNicCount = C.ipolicyDefaultsStdNicCount
191 , iSpecSpindleUse = C.ipolicyDefaultsStdSpindleUse
192 }
193
194 -- | The default max ispec.
195 defMaxISpec :: ISpec
196 defMaxISpec = ISpec { iSpecMemorySize = C.ispecsMinmaxDefaultsMaxMemorySize
197 , iSpecCpuCount = C.ispecsMinmaxDefaultsMaxCpuCount
198 , iSpecDiskSize = C.ispecsMinmaxDefaultsMaxDiskSize
199 , iSpecDiskCount = C.ispecsMinmaxDefaultsMaxDiskCount
200 , iSpecNicCount = C.ispecsMinmaxDefaultsMaxNicCount
201 , iSpecSpindleUse = C.ispecsMinmaxDefaultsMaxSpindleUse
202 }
203
204 -- | Minimum and maximum instance specs type.
205 $(THH.buildObject "MinMaxISpecs" "minMaxISpecs"
206 [ THH.renameField "MinSpec" $ THH.simpleField "min" [t| ISpec |]
207 , THH.renameField "MaxSpec" $ THH.simpleField "max" [t| ISpec |]
208 ])
209
210 -- | Defult minimum and maximum instance specs.
211 defMinMaxISpecs :: [MinMaxISpecs]
212 defMinMaxISpecs = [MinMaxISpecs { minMaxISpecsMinSpec = defMinISpec
213 , minMaxISpecsMaxSpec = defMaxISpec
214 }]
215
216 -- | Instance policy type.
217 $(THH.buildObject "IPolicy" "iPolicy"
218 [ THH.renameField "MinMaxISpecs" $
219 THH.simpleField C.ispecsMinmax [t| [MinMaxISpecs] |]
220 , THH.renameField "StdSpec" $ THH.simpleField C.ispecsStd [t| ISpec |]
221 , THH.renameField "DiskTemplates" $
222 THH.simpleField C.ipolicyDts [t| [DiskTemplate] |]
223 , THH.renameField "VcpuRatio" $
224 THH.simpleField C.ipolicyVcpuRatio [t| Double |]
225 , THH.renameField "SpindleRatio" $
226 THH.simpleField C.ipolicySpindleRatio [t| Double |]
227 ])
228
229 -- | Converts an ISpec type to a RSpec one.
230 rspecFromISpec :: ISpec -> RSpec
231 rspecFromISpec ispec = RSpec { rspecCpu = iSpecCpuCount ispec
232 , rspecMem = iSpecMemorySize ispec
233 , rspecDsk = iSpecDiskSize ispec
234 }
235
236 -- | The default instance policy.
237 defIPolicy :: IPolicy
238 defIPolicy = IPolicy { iPolicyMinMaxISpecs = defMinMaxISpecs
239 , iPolicyStdSpec = defStdISpec
240 -- hardcoding here since Constants.hs exports the
241 -- string values, not the actual type; and in
242 -- htools, we are mostly looking at DRBD
243 , iPolicyDiskTemplates = [minBound..maxBound]
244 , iPolicyVcpuRatio = C.ipolicyDefaultsVcpuRatio
245 , iPolicySpindleRatio = C.ipolicyDefaultsSpindleRatio
246 }
247
248 -- | The dynamic resource specs of a machine (i.e. load or load
249 -- capacity, as opposed to size).
250 data DynUtil = DynUtil
251 { cpuWeight :: Weight -- ^ Standardised CPU usage
252 , memWeight :: Weight -- ^ Standardised memory load
253 , dskWeight :: Weight -- ^ Standardised disk I\/O usage
254 , netWeight :: Weight -- ^ Standardised network usage
255 } deriving (Show, Eq)
256
257 -- | Initial empty utilisation.
258 zeroUtil :: DynUtil
259 zeroUtil = DynUtil { cpuWeight = 0, memWeight = 0
260 , dskWeight = 0, netWeight = 0 }
261
262 -- | Base utilisation (used when no actual utilisation data is
263 -- supplied).
264 baseUtil :: DynUtil
265 baseUtil = DynUtil { cpuWeight = 1, memWeight = 1
266 , dskWeight = 1, netWeight = 1 }
267
268 -- | Sum two utilisation records.
269 addUtil :: DynUtil -> DynUtil -> DynUtil
270 addUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
271 DynUtil (a1+b1) (a2+b2) (a3+b3) (a4+b4)
272
273 -- | Substracts one utilisation record from another.
274 subUtil :: DynUtil -> DynUtil -> DynUtil
275 subUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
276 DynUtil (a1-b1) (a2-b2) (a3-b3) (a4-b4)
277
278 -- | The description of an instance placement. It contains the
279 -- instance index, the new primary and secondary node, the move being
280 -- performed and the score of the cluster after the move.
281 type Placement = (Idx, Ndx, Ndx, IMove, Score)
282
283 -- | An instance move definition.
284 data IMove = Failover -- ^ Failover the instance (f)
285 | FailoverToAny Ndx -- ^ Failover to a random node
286 -- (fa:np), for shared storage
287 | ReplacePrimary Ndx -- ^ Replace primary (f, r:np, f)
288 | ReplaceSecondary Ndx -- ^ Replace secondary (r:ns)
289 | ReplaceAndFailover Ndx -- ^ Replace secondary, failover (r:np, f)
290 | FailoverAndReplace Ndx -- ^ Failover, replace secondary (f, r:ns)
291 deriving (Show)
292
293 -- | Formatted solution output for one move (involved nodes and
294 -- commands.
295 type MoveJob = ([Ndx], Idx, IMove, [String])
296
297 -- | Unknown field in table output.
298 unknownField :: String
299 unknownField = "<unknown field>"
300
301 -- | A list of command elements.
302 type JobSet = [MoveJob]
303
304 -- | Default max disk usage ratio.
305 defReservedDiskRatio :: Double
306 defReservedDiskRatio = 0
307
308 -- | Base memory unit.
309 unitMem :: Int
310 unitMem = 64
311
312 -- | Base disk unit.
313 unitDsk :: Int
314 unitDsk = 256
315
316 -- | Base vcpus unit.
317 unitCpu :: Int
318 unitCpu = 1
319
320 -- | Reason for an operation's falure.
321 data FailMode = FailMem -- ^ Failed due to not enough RAM
322 | FailDisk -- ^ Failed due to not enough disk
323 | FailCPU -- ^ Failed due to not enough CPU capacity
324 | FailN1 -- ^ Failed due to not passing N1 checks
325 | FailTags -- ^ Failed due to tag exclusion
326 deriving (Eq, Enum, Bounded, Show)
327
328 -- | List with failure statistics.
329 type FailStats = [(FailMode, Int)]
330
331 -- | Either-like data-type customized for our failure modes.
332 --
333 -- The failure values for this monad track the specific allocation
334 -- failures, so this is not a general error-monad (compare with the
335 -- 'Result' data type). One downside is that this type cannot encode a
336 -- generic failure mode, hence our way to build a FailMode from string
337 -- will instead raise an exception.
338 type OpResult = GenericResult FailMode
339
340 -- | 'FromString' instance for 'FailMode' designed to catch unintended
341 -- use as a general monad.
342 instance FromString FailMode where
343 mkFromString v = error $ "Programming error: OpResult used as generic monad"
344 ++ v
345
346 -- | Conversion from 'OpResult' to 'Result'.
347 opToResult :: OpResult a -> Result a
348 opToResult (Bad f) = Bad $ show f
349 opToResult (Ok v) = Ok v
350
351 -- | A generic class for items that have updateable names and indices.
352 class Element a where
353 -- | Returns the name of the element
354 nameOf :: a -> String
355 -- | Returns all the known names of the element
356 allNames :: a -> [String]
357 -- | Returns the index of the element
358 idxOf :: a -> Int
359 -- | Updates the alias of the element
360 setAlias :: a -> String -> a
361 -- | Compute the alias by stripping a given suffix (domain) from
362 -- the name
363 computeAlias :: String -> a -> a
364 computeAlias dom e = setAlias e alias
365 where alias = take (length name - length dom) name
366 name = nameOf e
367 -- | Updates the index of the element
368 setIdx :: a -> Int -> a
369
370 -- | The iallocator node-evacuate evac_mode type.
371 $(THH.declareSADT "EvacMode"
372 [ ("ChangePrimary", 'C.iallocatorNevacPri)
373 , ("ChangeSecondary", 'C.iallocatorNevacSec)
374 , ("ChangeAll", 'C.iallocatorNevacAll)
375 ])
376 $(THH.makeJSONInstance ''EvacMode)
377
378 -- | The repair modes for the auto-repair tool.
379 $(THH.declareSADT "AutoRepairType"
380 -- Order is important here: from least destructive to most.
381 [ ("ArFixStorage", 'C.autoRepairFixStorage)
382 , ("ArMigrate", 'C.autoRepairMigrate)
383 , ("ArFailover", 'C.autoRepairFailover)
384 , ("ArReinstall", 'C.autoRepairReinstall)
385 ])
386
387 -- | The possible auto-repair results.
388 $(THH.declareSADT "AutoRepairResult"
389 -- Order is important here: higher results take precedence when an object
390 -- has several result annotations attached.
391 [ ("ArEnoperm", 'C.autoRepairEnoperm)
392 , ("ArSuccess", 'C.autoRepairSuccess)
393 , ("ArFailure", 'C.autoRepairFailure)
394 ])
395
396 -- | The possible auto-repair policy for a given instance.
397 data AutoRepairPolicy
398 = ArEnabled AutoRepairType -- ^ Auto-repair explicitly enabled
399 | ArSuspended AutoRepairSuspendTime -- ^ Suspended temporarily, or forever
400 | ArNotEnabled -- ^ Auto-repair not explicitly enabled
401 deriving (Eq, Show)
402
403 -- | The suspend timeout for 'ArSuspended'.
404 data AutoRepairSuspendTime = Forever -- ^ Permanently suspended
405 | Until ClockTime -- ^ Suspended up to a certain time
406 deriving (Eq, Show)
407
408 -- | The possible auto-repair states for any given instance.
409 data AutoRepairStatus
410 = ArHealthy (Maybe AutoRepairData) -- ^ No problems detected with the instance
411 | ArNeedsRepair AutoRepairData -- ^ Instance has problems, no action taken
412 | ArPendingRepair AutoRepairData -- ^ Repair jobs ongoing for the instance
413 | ArFailedRepair AutoRepairData -- ^ Some repair jobs for the instance failed
414 deriving (Eq, Show)
415
416 -- | The data accompanying a repair operation (future, pending, or failed).
417 data AutoRepairData = AutoRepairData { arType :: AutoRepairType
418 , arUuid :: String
419 , arTime :: ClockTime
420 , arJobs :: [JobId]
421 , arResult :: Maybe AutoRepairResult
422 , arTag :: String
423 }
424 deriving (Eq, Show)