module Ganeti.HTools.Types
( Idx
, Ndx
, Gdx
, NameAssoc
, Score
, Weight
, GroupID
, AllocPolicy(..)
, apolFromString
, apolToString
, RSpec(..)
, DynUtil(..)
, zeroUtil
, baseUtil
, addUtil
, subUtil
, defVcpuRatio
, defReservedDiskRatio
, unitMem
, unitCpu
, unitDsk
, unknownField
, Placement
, IMove(..)
, DiskTemplate(..)
, dtToString
, dtFromString
, MoveJob
, JobSet
, Result(..)
, isOk
, isBad
, eitherToResult
, Element(..)
, FailMode(..)
, FailStats
, OpResult(..)
, opToResult
, connTimeout
, queryTimeout
, EvacMode(..)
) where
import qualified Data.Map as M
import qualified Text.JSON as JSON
import qualified Ganeti.Constants as C
type Idx = Int
type Ndx = Int
type Gdx = Int
type NameAssoc = M.Map String Int
type Score = Double
type Weight = Double
type GroupID = String
data AllocPolicy
= AllocPreferred
| AllocLastResort
| AllocUnallocable
deriving (Show, Read, Eq, Ord, Enum, Bounded)
apolFromString :: (Monad m) => String -> m AllocPolicy
apolFromString s =
case () of
_ | s == C.allocPolicyPreferred -> return AllocPreferred
| s == C.allocPolicyLastResort -> return AllocLastResort
| s == C.allocPolicyUnallocable -> return AllocUnallocable
| otherwise -> fail $ "Invalid alloc policy mode: " ++ s
apolToString :: AllocPolicy -> String
apolToString AllocPreferred = C.allocPolicyPreferred
apolToString AllocLastResort = C.allocPolicyLastResort
apolToString AllocUnallocable = C.allocPolicyUnallocable
instance JSON.JSON AllocPolicy where
showJSON = JSON.showJSON . apolToString
readJSON s = case JSON.readJSON s of
JSON.Ok s' -> apolFromString s'
JSON.Error e -> JSON.Error $
"Can't parse alloc_policy: " ++ e
data RSpec = RSpec
{ rspecCpu :: Int
, rspecMem :: Int
, rspecDsk :: Int
} deriving (Show, Read, Eq)
data DynUtil = DynUtil
{ cpuWeight :: Weight
, memWeight :: Weight
, dskWeight :: Weight
, netWeight :: Weight
} deriving (Show, Read, Eq)
zeroUtil :: DynUtil
zeroUtil = DynUtil { cpuWeight = 0, memWeight = 0
, dskWeight = 0, netWeight = 0 }
baseUtil :: DynUtil
baseUtil = DynUtil { cpuWeight = 1, memWeight = 1
, dskWeight = 1, netWeight = 1 }
addUtil :: DynUtil -> DynUtil -> DynUtil
addUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
DynUtil (a1+b1) (a2+b2) (a3+b3) (a4+b4)
subUtil :: DynUtil -> DynUtil -> DynUtil
subUtil (DynUtil a1 a2 a3 a4) (DynUtil b1 b2 b3 b4) =
DynUtil (a1b1) (a2b2) (a3b3) (a4b4)
type Placement = (Idx, Ndx, Ndx, IMove, Score)
data IMove = Failover
| ReplacePrimary Ndx
| ReplaceSecondary Ndx
| ReplaceAndFailover Ndx
| FailoverAndReplace Ndx
deriving (Show, Read)
data DiskTemplate = DTDiskless
| DTFile
| DTSharedFile
| DTPlain
| DTBlock
| DTDrbd8
deriving (Show, Read, Eq, Enum, Bounded)
dtToString :: DiskTemplate -> String
dtToString DTDiskless = C.dtDiskless
dtToString DTFile = C.dtFile
dtToString DTSharedFile = C.dtSharedFile
dtToString DTPlain = C.dtPlain
dtToString DTBlock = C.dtBlock
dtToString DTDrbd8 = C.dtDrbd8
dtFromString :: (Monad m) => String -> m DiskTemplate
dtFromString s =
case () of
_ | s == C.dtDiskless -> return DTDiskless
| s == C.dtFile -> return DTFile
| s == C.dtSharedFile -> return DTSharedFile
| s == C.dtPlain -> return DTPlain
| s == C.dtBlock -> return DTBlock
| s == C.dtDrbd8 -> return DTDrbd8
| otherwise -> fail $ "Invalid disk template: " ++ s
instance JSON.JSON DiskTemplate where
showJSON = JSON.showJSON . dtToString
readJSON s = case JSON.readJSON s of
JSON.Ok s' -> dtFromString s'
JSON.Error e -> JSON.Error $
"Can't parse disk_template as string: " ++ e
type MoveJob = ([Ndx], Idx, IMove, [String])
unknownField :: String
unknownField = "<unknown field>"
type JobSet = [MoveJob]
connTimeout :: Int
connTimeout = 15
queryTimeout :: Int
queryTimeout = 60
defVcpuRatio :: Double
defVcpuRatio = 64
defReservedDiskRatio :: Double
defReservedDiskRatio = 0
unitMem :: Int
unitMem = 64
unitDsk :: Int
unitDsk = 256
unitCpu :: Int
unitCpu = 1
data Result a
= Bad String
| Ok a
deriving (Show, Read, Eq)
instance Monad Result where
(>>=) (Bad x) _ = Bad x
(>>=) (Ok x) fn = fn x
return = Ok
fail = Bad
isOk :: Result a -> Bool
isOk (Ok _) = True
isOk _ = False
isBad :: Result a -> Bool
isBad = not . isOk
eitherToResult :: Either String a -> Result a
eitherToResult (Left s) = Bad s
eitherToResult (Right v) = Ok v
data FailMode = FailMem
| FailDisk
| FailCPU
| FailN1
| FailTags
deriving (Eq, Enum, Bounded, Show, Read)
type FailStats = [(FailMode, Int)]
data OpResult a = OpFail FailMode
| OpGood a
deriving (Show, Read)
instance Monad OpResult where
(OpGood x) >>= fn = fn x
(OpFail y) >>= _ = OpFail y
return = OpGood
opToResult :: OpResult a -> Result a
opToResult (OpFail f) = Bad $ show f
opToResult (OpGood v) = Ok v
class Element a where
nameOf :: a -> String
allNames :: a -> [String]
idxOf :: a -> Int
setAlias :: a -> String -> a
computeAlias :: String -> a -> a
computeAlias dom e = setAlias e alias
where alias = take (length name length dom) name
name = nameOf e
setIdx :: a -> Int -> a
data EvacMode = ChangePrimary
| ChangeSecondary
| ChangeAll
deriving (Show, Read)
instance JSON.JSON EvacMode where
showJSON mode = case mode of
ChangeAll -> JSON.showJSON C.iallocatorNevacAll
ChangePrimary -> JSON.showJSON C.iallocatorNevacPri
ChangeSecondary -> JSON.showJSON C.iallocatorNevacSec
readJSON v =
case JSON.readJSON v of
JSON.Ok s | s == C.iallocatorNevacAll -> return ChangeAll
| s == C.iallocatorNevacPri -> return ChangePrimary
| s == C.iallocatorNevacSec -> return ChangeSecondary
| otherwise -> fail $ "Invalid evacuate mode " ++ s
JSON.Error e -> JSON.Error $
"Can't parse evacuate mode as string: " ++ e