7 Copyright (C) 2009, 2010, 2011 Google Inc.
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.
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.
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
26 module Ganeti.HTools.Types
44 , defReservedDiskRatio
65 import qualified Data.Map as M
66 import qualified Text.JSON as JSON
68 import qualified Ganeti.Constants as C
70 -- | The instance index type.
73 -- | The node index type.
76 -- | The group index type.
79 -- | The type used to hold name-to-idx mappings.
80 type NameAssoc = M.Map String Int
82 -- | A separate name for the cluster score type.
85 -- | A separate name for a weight metric.
88 -- | The Group UUID type.
91 -- | The Group allocation policy type.
93 -- Note that the order of constructors is important as the automatic
94 -- Ord instance will order them in the order they are defined, so when
95 -- changing this data type be careful about the interaction with the
96 -- desired sorting order.
98 = AllocPreferred -- ^ This is the normal status, the group
99 -- should be used normally during allocations
100 | AllocLastResort -- ^ This group should be used only as
101 -- last-resort, after the preferred groups
102 | AllocUnallocable -- ^ This group must not be used for new
104 deriving (Show, Read, Eq, Ord)
106 -- | Convert a string to an alloc policy.
107 apolFromString :: (Monad m) => String -> m AllocPolicy
110 _ | s == C.allocPolicyPreferred -> return AllocPreferred
111 | s == C.allocPolicyLastResort -> return AllocLastResort
112 | s == C.allocPolicyUnallocable -> return AllocUnallocable
113 | otherwise -> fail $ "Invalid alloc policy mode: " ++ s
115 -- | Convert an alloc policy to the Ganeti string equivalent.
116 apolToString :: AllocPolicy -> String
117 apolToString AllocPreferred = C.allocPolicyPreferred
118 apolToString AllocLastResort = C.allocPolicyLastResort
119 apolToString AllocUnallocable = C.allocPolicyUnallocable
121 instance JSON.JSON AllocPolicy where
122 showJSON = JSON.showJSON . apolToString
123 readJSON s = case JSON.readJSON s of
124 JSON.Ok s' -> apolFromString s'
125 JSON.Error e -> JSON.Error $
126 "Can't parse alloc_policy: " ++ e
128 -- | The resource spec type.
130 { rspecCpu :: Int -- ^ Requested VCPUs
131 , rspecMem :: Int -- ^ Requested memory
132 , rspecDsk :: Int -- ^ Requested disk
133 } deriving (Show, Read, Eq)
135 -- | The dynamic resource specs of a machine (i.e. load or load
136 -- capacity, as opposed to size).
137 data DynUtil = DynUtil
138 { cpuWeight :: Weight -- ^ Standardised CPU usage
139 , memWeight :: Weight -- ^ Standardised memory load
140 , dskWeight :: Weight -- ^ Standardised disk I\/O usage
141 , netWeight :: Weight -- ^ Standardised network usage
142 } deriving (Show, Read, Eq)
144 -- | Initial empty utilisation.
146 zeroUtil = DynUtil { cpuWeight = 0, memWeight = 0
147 , dskWeight = 0, netWeight = 0 }
149 -- | Base utilisation (used when no actual utilisation data is
152 baseUtil = DynUtil { cpuWeight = 1, memWeight = 1
153 , dskWeight = 1, netWeight = 1 }
155 -- | Sum two utilisation records.
156 addUtil :: DynUtil -> DynUtil -> DynUtil
157 addUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
158 DynUtil (a1+b1) (a2+b2) (a3+b3) (a4+b4)
160 -- | Substracts one utilisation record from another.
161 subUtil :: DynUtil -> DynUtil -> DynUtil
162 subUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
163 DynUtil (a1-b1) (a2-b2) (a3-b3) (a4-b4)
165 -- | The description of an instance placement. It contains the
166 -- instance index, the new primary and secondary node, the move being
167 -- performed and the score of the cluster after the move.
168 type Placement = (Idx, Ndx, Ndx, IMove, Score)
170 -- | An instance move definition.
171 data IMove = Failover -- ^ Failover the instance (f)
172 | ReplacePrimary Ndx -- ^ Replace primary (f, r:np, f)
173 | ReplaceSecondary Ndx -- ^ Replace secondary (r:ns)
174 | ReplaceAndFailover Ndx -- ^ Replace secondary, failover (r:np, f)
175 | FailoverAndReplace Ndx -- ^ Failover, replace secondary (f, r:ns)
176 deriving (Show, Read)
178 -- | Formatted solution output for one move (involved nodes and
180 type MoveJob = ([Ndx], Idx, IMove, [String])
182 -- | Unknown field in table output.
183 unknownField :: String
184 unknownField = "<unknown field>"
186 -- | A list of command elements.
187 type JobSet = [MoveJob]
189 -- | Connection timeout (when using non-file methods).
193 -- | The default timeout for queries (when using non-file methods).
197 -- | Default vcpu-to-pcpu ratio (randomly chosen value).
198 defVcpuRatio :: Double
201 -- | Default max disk usage ratio.
202 defReservedDiskRatio :: Double
203 defReservedDiskRatio = 0
205 -- | Base memory unit.
213 -- | Base vcpus unit.
219 This is similar to the JSON library Result type - /very/ similar, but
220 we want to use it in multiple places, so we abstract it into a
227 deriving (Show, Read)
229 instance Monad Result where
230 (>>=) (Bad x) _ = Bad x
231 (>>=) (Ok x) fn = fn x
235 -- | Simple checker for whether a 'Result' is OK.
236 isOk :: Result a -> Bool
240 -- | Simple checker for whether a 'Result' is a failure.
241 isBad :: Result a -> Bool
244 -- | Reason for an operation's falure.
245 data FailMode = FailMem -- ^ Failed due to not enough RAM
246 | FailDisk -- ^ Failed due to not enough disk
247 | FailCPU -- ^ Failed due to not enough CPU capacity
248 | FailN1 -- ^ Failed due to not passing N1 checks
249 | FailTags -- ^ Failed due to tag exclusion
250 deriving (Eq, Enum, Bounded, Show, Read)
252 -- | List with failure statistics.
253 type FailStats = [(FailMode, Int)]
255 -- | Either-like data-type customized for our failure modes.
256 data OpResult a = OpFail FailMode -- ^ Failed operation
257 | OpGood a -- ^ Success operation
258 deriving (Show, Read)
260 instance Monad OpResult where
261 (OpGood x) >>= fn = fn x
262 (OpFail y) >>= _ = OpFail y
265 -- | A generic class for items that have updateable names and indices.
266 class Element a where
267 -- | Returns the name of the element
268 nameOf :: a -> String
269 -- | Returns all the known names of the element
270 allNames :: a -> [String]
271 -- | Returns the index of the element
273 -- | Updates the alias of the element
274 setAlias :: a -> String -> a
275 -- | Compute the alias by stripping a given suffix (domain) from
277 computeAlias :: String -> a -> a
278 computeAlias dom e = setAlias e alias
279 where alias = take (length name - length dom) name
281 -- | Updates the index of the element
282 setIdx :: a -> Int -> a
284 -- | The iallocator node-evacuate evac_mode type.
285 data EvacMode = ChangePrimary
288 deriving (Show, Read)