Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / Types.hs @ c22d4dd4

History | View | Annotate | Download (12.2 kB)

1
{-# LANGUAGE TemplateHaskell #-}
2

    
3
{-| Some common types.
4

    
5
-}
6

    
7
{-
8

    
9
Copyright (C) 2009, 2010, 2011, 2012 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
  , InstanceStatus(..)
41
  , instanceStatusFromRaw
42
  , instanceStatusToRaw
43
  , RSpec(..)
44
  , AllocInfo(..)
45
  , AllocStats
46
  , DynUtil(..)
47
  , zeroUtil
48
  , baseUtil
49
  , addUtil
50
  , subUtil
51
  , defReservedDiskRatio
52
  , unitMem
53
  , unitCpu
54
  , unitDsk
55
  , unknownField
56
  , Placement
57
  , IMove(..)
58
  , DiskTemplate(..)
59
  , diskTemplateToRaw
60
  , diskTemplateFromRaw
61
  , MoveJob
62
  , JobSet
63
  , Result(..)
64
  , isOk
65
  , isBad
66
  , eitherToResult
67
  , annotateResult
68
  , Element(..)
69
  , FailMode(..)
70
  , FailStats
71
  , OpResult(..)
72
  , opToResult
73
  , connTimeout
74
  , queryTimeout
75
  , EvacMode(..)
76
  , ISpec(..)
77
  , IPolicy(..)
78
  , defIPolicy
79
  , rspecFromISpec
80
  ) where
81

    
82
import qualified Data.Map as M
83
import Text.JSON (makeObj, readJSON, showJSON)
84

    
85
import qualified Ganeti.Constants as C
86
import qualified Ganeti.THH as THH
87
import Ganeti.BasicTypes
88
import Ganeti.HTools.JSON
89

    
90
-- | The instance index type.
91
type Idx = Int
92

    
93
-- | The node index type.
94
type Ndx = Int
95

    
96
-- | The group index type.
97
type Gdx = Int
98

    
99
-- | The type used to hold name-to-idx mappings.
100
type NameAssoc = M.Map String Int
101

    
102
-- | A separate name for the cluster score type.
103
type Score = Double
104

    
105
-- | A separate name for a weight metric.
106
type Weight = Double
107

    
108
-- | The Group UUID type.
109
type GroupID = String
110

    
111
-- | Default group UUID (just a string, not a real UUID).
112
defaultGroupID :: GroupID
113
defaultGroupID = "00000000-0000-0000-0000-000000000000"
114

    
115
-- | Instance disk template type.
116
$(THH.declareSADT "DiskTemplate"
117
       [ ("DTDiskless",   'C.dtDiskless)
118
       , ("DTFile",       'C.dtFile)
119
       , ("DTSharedFile", 'C.dtSharedFile)
120
       , ("DTPlain",      'C.dtPlain)
121
       , ("DTBlock",      'C.dtBlock)
122
       , ("DTDrbd8",      'C.dtDrbd8)
123
       , ("DTRbd",        'C.dtRbd)
124
       ])
125
$(THH.makeJSONInstance ''DiskTemplate)
126

    
127
-- | The Group allocation policy type.
128
--
129
-- Note that the order of constructors is important as the automatic
130
-- Ord instance will order them in the order they are defined, so when
131
-- changing this data type be careful about the interaction with the
132
-- desired sorting order.
133
$(THH.declareSADT "AllocPolicy"
134
       [ ("AllocPreferred",   'C.allocPolicyPreferred)
135
       , ("AllocLastResort",  'C.allocPolicyLastResort)
136
       , ("AllocUnallocable", 'C.allocPolicyUnallocable)
137
       ])
138
$(THH.makeJSONInstance ''AllocPolicy)
139

    
140
-- | The Instance real state type.
141
$(THH.declareSADT "InstanceStatus"
142
       [ ("AdminDown", 'C.inststAdmindown)
143
       , ("AdminOffline", 'C.inststAdminoffline)
144
       , ("ErrorDown", 'C.inststErrordown)
145
       , ("ErrorUp", 'C.inststErrorup)
146
       , ("NodeDown", 'C.inststNodedown)
147
       , ("NodeOffline", 'C.inststNodeoffline)
148
       , ("Running", 'C.inststRunning)
149
       , ("WrongNode", 'C.inststWrongnode)
150
       ])
151
$(THH.makeJSONInstance ''InstanceStatus)
152

    
153
-- | The resource spec type.
154
data RSpec = RSpec
155
  { rspecCpu  :: Int  -- ^ Requested VCPUs
156
  , rspecMem  :: Int  -- ^ Requested memory
157
  , rspecDsk  :: Int  -- ^ Requested disk
158
  } deriving (Show, Read, Eq)
159

    
160
-- | Allocation stats type. This is used instead of 'RSpec' (which was
161
-- used at first), because we need to track more stats. The actual
162
-- data can refer either to allocated, or available, etc. values
163
-- depending on the context. See also
164
-- 'Cluster.computeAllocationDelta'.
165
data AllocInfo = AllocInfo
166
  { allocInfoVCpus :: Int    -- ^ VCPUs
167
  , allocInfoNCpus :: Double -- ^ Normalised CPUs
168
  , allocInfoMem   :: Int    -- ^ Memory
169
  , allocInfoDisk  :: Int    -- ^ Disk
170
  } deriving (Show, Read, Eq)
171

    
172
-- | Currently used, possibly to allocate, unallocable.
173
type AllocStats = (AllocInfo, AllocInfo, AllocInfo)
174

    
175
-- | Instance specification type.
176
$(THH.buildObject "ISpec" "iSpec"
177
  [ THH.renameField "MemorySize" $ THH.simpleField C.ispecMemSize   [t| Int |]
178
  , THH.renameField "CpuCount"   $ THH.simpleField C.ispecCpuCount  [t| Int |]
179
  , THH.renameField "DiskSize"   $ THH.simpleField C.ispecDiskSize  [t| Int |]
180
  , THH.renameField "DiskCount"  $ THH.simpleField C.ispecDiskCount [t| Int |]
181
  , THH.renameField "NicCount"   $ THH.simpleField C.ispecNicCount  [t| Int |]
182
  ])
183

    
184
-- | The default minimum ispec.
185
defMinISpec :: ISpec
186
defMinISpec = ISpec { iSpecMemorySize = C.ipolicyDefaultsMinMemorySize
187
                    , iSpecCpuCount   = C.ipolicyDefaultsMinCpuCount
188
                    , iSpecDiskSize   = C.ipolicyDefaultsMinDiskSize
189
                    , iSpecDiskCount  = C.ipolicyDefaultsMinDiskCount
190
                    , iSpecNicCount   = C.ipolicyDefaultsMinNicCount
191
                    }
192

    
193
-- | The default standard ispec.
194
defStdISpec :: ISpec
195
defStdISpec = ISpec { iSpecMemorySize = C.ipolicyDefaultsStdMemorySize
196
                    , iSpecCpuCount   = C.ipolicyDefaultsStdCpuCount
197
                    , iSpecDiskSize   = C.ipolicyDefaultsStdDiskSize
198
                    , iSpecDiskCount  = C.ipolicyDefaultsStdDiskCount
199
                    , iSpecNicCount   = C.ipolicyDefaultsStdNicCount
200
                    }
201

    
202
-- | The default max ispec.
203
defMaxISpec :: ISpec
204
defMaxISpec = ISpec { iSpecMemorySize = C.ipolicyDefaultsMaxMemorySize
205
                    , iSpecCpuCount   = C.ipolicyDefaultsMaxCpuCount
206
                    , iSpecDiskSize   = C.ipolicyDefaultsMaxDiskSize
207
                    , iSpecDiskCount  = C.ipolicyDefaultsMaxDiskCount
208
                    , iSpecNicCount   = C.ipolicyDefaultsMaxNicCount
209
                    }
210

    
211
-- | Instance policy type.
212
$(THH.buildObject "IPolicy" "iPolicy"
213
  [ THH.renameField "StdSpec" $ THH.simpleField C.ispecsStd [t| ISpec |]
214
  , THH.renameField "MinSpec" $ THH.simpleField C.ispecsMin [t| ISpec |]
215
  , THH.renameField "MaxSpec" $ THH.simpleField C.ispecsMax [t| ISpec |]
216
  , THH.renameField "DiskTemplates" $
217
      THH.simpleField C.ipolicyDts [t| [DiskTemplate] |]
218
  , THH.renameField "VcpuRatio" $
219
      THH.simpleField C.ipolicyVcpuRatio [t| Double |]
220
  , THH.renameField "SpindleRatio" $
221
      THH.simpleField C.ipolicySpindleRatio [t| Double |]
222
  ])
223

    
224
-- | Converts an ISpec type to a RSpec one.
225
rspecFromISpec :: ISpec -> RSpec
226
rspecFromISpec ispec = RSpec { rspecCpu = iSpecCpuCount ispec
227
                             , rspecMem = iSpecMemorySize ispec
228
                             , rspecDsk = iSpecDiskSize ispec
229
                             }
230

    
231
-- | The default instance policy.
232
defIPolicy :: IPolicy
233
defIPolicy = IPolicy { iPolicyStdSpec = defStdISpec
234
                     , iPolicyMinSpec = defMinISpec
235
                     , iPolicyMaxSpec = defMaxISpec
236
                     -- hardcoding here since Constants.hs exports the
237
                     -- string values, not the actual type; and in
238
                     -- htools, we are mostly looking at DRBD
239
                     , iPolicyDiskTemplates = [DTDrbd8, DTPlain]
240
                     , iPolicyVcpuRatio = C.ipolicyDefaultsVcpuRatio
241
                     , iPolicySpindleRatio = C.ipolicyDefaultsSpindleRatio
242
                     }
243

    
244
-- | The dynamic resource specs of a machine (i.e. load or load
245
-- capacity, as opposed to size).
246
data DynUtil = DynUtil
247
  { cpuWeight :: Weight -- ^ Standardised CPU usage
248
  , memWeight :: Weight -- ^ Standardised memory load
249
  , dskWeight :: Weight -- ^ Standardised disk I\/O usage
250
  , netWeight :: Weight -- ^ Standardised network usage
251
  } deriving (Show, Read, Eq)
252

    
253
-- | Initial empty utilisation.
254
zeroUtil :: DynUtil
255
zeroUtil = DynUtil { cpuWeight = 0, memWeight = 0
256
                   , dskWeight = 0, netWeight = 0 }
257

    
258
-- | Base utilisation (used when no actual utilisation data is
259
-- supplied).
260
baseUtil :: DynUtil
261
baseUtil = DynUtil { cpuWeight = 1, memWeight = 1
262
                   , dskWeight = 1, netWeight = 1 }
263

    
264
-- | Sum two utilisation records.
265
addUtil :: DynUtil -> DynUtil -> DynUtil
266
addUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
267
  DynUtil (a1+b1) (a2+b2) (a3+b3) (a4+b4)
268

    
269
-- | Substracts one utilisation record from another.
270
subUtil :: DynUtil -> DynUtil -> DynUtil
271
subUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
272
  DynUtil (a1-b1) (a2-b2) (a3-b3) (a4-b4)
273

    
274
-- | The description of an instance placement. It contains the
275
-- instance index, the new primary and secondary node, the move being
276
-- performed and the score of the cluster after the move.
277
type Placement = (Idx, Ndx, Ndx, IMove, Score)
278

    
279
-- | An instance move definition.
280
data IMove = Failover                -- ^ Failover the instance (f)
281
           | ReplacePrimary Ndx      -- ^ Replace primary (f, r:np, f)
282
           | ReplaceSecondary Ndx    -- ^ Replace secondary (r:ns)
283
           | ReplaceAndFailover Ndx  -- ^ Replace secondary, failover (r:np, f)
284
           | FailoverAndReplace Ndx  -- ^ Failover, replace secondary (f, r:ns)
285
             deriving (Show, Read)
286

    
287
-- | Formatted solution output for one move (involved nodes and
288
-- commands.
289
type MoveJob = ([Ndx], Idx, IMove, [String])
290

    
291
-- | Unknown field in table output.
292
unknownField :: String
293
unknownField = "<unknown field>"
294

    
295
-- | A list of command elements.
296
type JobSet = [MoveJob]
297

    
298
-- | Connection timeout (when using non-file methods).
299
connTimeout :: Int
300
connTimeout = 15
301

    
302
-- | The default timeout for queries (when using non-file methods).
303
queryTimeout :: Int
304
queryTimeout = 60
305

    
306
-- | Default max disk usage ratio.
307
defReservedDiskRatio :: Double
308
defReservedDiskRatio = 0
309

    
310
-- | Base memory unit.
311
unitMem :: Int
312
unitMem = 64
313

    
314
-- | Base disk unit.
315
unitDsk :: Int
316
unitDsk = 256
317

    
318
-- | Base vcpus unit.
319
unitCpu :: Int
320
unitCpu = 1
321

    
322
-- | Reason for an operation's falure.
323
data FailMode = FailMem  -- ^ Failed due to not enough RAM
324
              | FailDisk -- ^ Failed due to not enough disk
325
              | FailCPU  -- ^ Failed due to not enough CPU capacity
326
              | FailN1   -- ^ Failed due to not passing N1 checks
327
              | FailTags -- ^ Failed due to tag exclusion
328
                deriving (Eq, Enum, Bounded, Show, Read)
329

    
330
-- | List with failure statistics.
331
type FailStats = [(FailMode, Int)]
332

    
333
-- | Either-like data-type customized for our failure modes.
334
--
335
-- The failure values for this monad track the specific allocation
336
-- failures, so this is not a general error-monad (compare with the
337
-- 'Result' data type). One downside is that this type cannot encode a
338
-- generic failure mode, hence 'fail' for this monad is not defined
339
-- and will cause an exception.
340
data OpResult a = OpFail FailMode -- ^ Failed operation
341
                | OpGood a        -- ^ Success operation
342
                  deriving (Show, Read)
343

    
344
instance Monad OpResult where
345
  (OpGood x) >>= fn = fn x
346
  (OpFail y) >>= _ = OpFail y
347
  return = OpGood
348

    
349
-- | Conversion from 'OpResult' to 'Result'.
350
opToResult :: OpResult a -> Result a
351
opToResult (OpFail f) = Bad $ show f
352
opToResult (OpGood v) = Ok v
353

    
354
-- | A generic class for items that have updateable names and indices.
355
class Element a where
356
  -- | Returns the name of the element
357
  nameOf  :: a -> String
358
  -- | Returns all the known names of the element
359
  allNames :: a -> [String]
360
  -- | Returns the index of the element
361
  idxOf   :: a -> Int
362
  -- | Updates the alias of the element
363
  setAlias :: a -> String -> a
364
  -- | Compute the alias by stripping a given suffix (domain) from
365
  -- the name
366
  computeAlias :: String -> a -> a
367
  computeAlias dom e = setAlias e alias
368
    where alias = take (length name - length dom) name
369
          name = nameOf e
370
  -- | Updates the index of the element
371
  setIdx  :: a -> Int -> a
372

    
373
-- | The iallocator node-evacuate evac_mode type.
374
$(THH.declareSADT "EvacMode"
375
       [ ("ChangePrimary",   'C.iallocatorNevacPri)
376
       , ("ChangeSecondary", 'C.iallocatorNevacSec)
377
       , ("ChangeAll",       'C.iallocatorNevacAll)
378
       ])
379
$(THH.makeJSONInstance ''EvacMode)