module Ganeti.HTools.Cluster.Moves
( applyMoveEx
, setInstanceLocationScore
, move
) where
import qualified Data.Set as Set
import Ganeti.HTools.Types
import qualified Ganeti.HTools.Container as Container
import qualified Ganeti.HTools.Instance as Instance
import qualified Ganeti.HTools.Node as Node
instanceNodes :: Node.List -> Instance.Instance ->
(Ndx, Ndx, Node.Node, Node.Node)
instanceNodes nl inst =
let old_pdx = Instance.pNode inst
old_sdx = Instance.sNode inst
old_p = Container.find old_pdx nl
old_s = Container.find old_sdx nl
in (old_pdx, old_sdx, old_p, old_s)
setInstanceLocationScore :: Instance.Instance
-> Node.Node
-> Node.Node
-> Instance.Instance
setInstanceLocationScore t p s =
t { Instance.locationScore =
Set.size $ Node.locationTags p `Set.intersection` Node.locationTags s }
applyMoveEx :: Bool
-> Node.List -> Instance.Instance
-> IMove -> OpResult (Node.List, Instance.Instance, Ndx, Ndx)
applyMoveEx force nl inst Failover =
let (old_pdx, old_sdx, old_p, old_s) = instanceNodes nl inst
int_p = Node.removePri old_p inst
int_s = Node.removeSec old_s inst
new_nl = do
Node.checkMigration old_p old_s
new_p <- Node.addPriEx (Node.offline old_p || force) int_s inst
new_s <- Node.addSecExEx (Node.offline old_p) (Node.offline old_p)
int_p inst old_sdx
let new_inst = Instance.setBoth inst old_sdx old_pdx
return (Container.addTwo old_pdx new_s old_sdx new_p nl,
new_inst, old_sdx, old_pdx)
in new_nl
applyMoveEx force nl inst (FailoverToAny new_pdx) = do
let (old_pdx, old_sdx, old_pnode, _) = instanceNodes nl inst
new_pnode = Container.find new_pdx nl
force_failover = Node.offline old_pnode || force
Node.checkMigration old_pnode new_pnode
new_pnode' <- Node.addPriEx force_failover new_pnode inst
let old_pnode' = Node.removePri old_pnode inst
inst' = Instance.setPri inst new_pdx
nl' = Container.addTwo old_pdx old_pnode' new_pdx new_pnode' nl
return (nl', inst', new_pdx, old_sdx)
applyMoveEx force nl inst (ReplacePrimary new_pdx) =
let (old_pdx, old_sdx, old_p, old_s) = instanceNodes nl inst
tgt_n = Container.find new_pdx nl
int_p = Node.removePri old_p inst
int_s = Node.removeSec old_s inst
new_inst = Instance.setPri (setInstanceLocationScore inst tgt_n int_s)
new_pdx
force_p = Node.offline old_p || force
new_nl = do
Node.checkMigration old_p old_s
Node.checkMigration old_s tgt_n
tmp_s <- Node.addPriEx force_p int_s new_inst
let tmp_s' = Node.removePri tmp_s new_inst
new_p <- Node.addPriEx force_p tgt_n new_inst
new_s <- Node.addSecEx force_p tmp_s' new_inst new_pdx
return (Container.add new_pdx new_p $
Container.addTwo old_pdx int_p old_sdx new_s nl,
new_inst, new_pdx, old_sdx)
in new_nl
applyMoveEx force nl inst (ReplaceSecondary new_sdx) =
let old_pdx = Instance.pNode inst
old_sdx = Instance.sNode inst
old_s = Container.find old_sdx nl
tgt_n = Container.find new_sdx nl
pnode = Container.find old_pdx nl
pnode' = Node.removePri pnode inst
int_s = Node.removeSec old_s inst
force_s = Node.offline old_s || force
new_inst = Instance.setSec (setInstanceLocationScore inst pnode tgt_n)
new_sdx
new_nl = do
new_s <- Node.addSecEx force_s tgt_n new_inst old_pdx
pnode'' <- Node.addPriEx True pnode' new_inst
return (Container.add old_pdx pnode'' $
Container.addTwo new_sdx new_s old_sdx int_s nl,
new_inst, old_pdx, new_sdx)
in new_nl
applyMoveEx force nl inst (ReplaceAndFailover new_pdx) =
let (old_pdx, old_sdx, old_p, old_s) = instanceNodes nl inst
tgt_n = Container.find new_pdx nl
int_p = Node.removePri old_p inst
int_s = Node.removeSec old_s inst
new_inst = Instance.setBoth (setInstanceLocationScore inst tgt_n int_p)
new_pdx old_pdx
force_s = Node.offline old_s || force
new_nl = do
Node.checkMigration old_p tgt_n
new_p <- Node.addPriEx force tgt_n new_inst
new_s <- Node.addSecEx force_s int_p new_inst new_pdx
return (Container.add new_pdx new_p $
Container.addTwo old_pdx new_s old_sdx int_s nl,
new_inst, new_pdx, old_pdx)
in new_nl
applyMoveEx force nl inst (FailoverAndReplace new_sdx) =
let (old_pdx, old_sdx, old_p, old_s) = instanceNodes nl inst
tgt_n = Container.find new_sdx nl
int_p = Node.removePri old_p inst
int_s = Node.removeSec old_s inst
force_p = Node.offline old_p || force
new_inst = Instance.setBoth (setInstanceLocationScore inst int_s tgt_n)
old_sdx new_sdx
new_nl = do
Node.checkMigration old_p old_s
new_p <- Node.addPriEx force_p int_s new_inst
new_s <- Node.addSecEx force_p tgt_n new_inst old_sdx
return (Container.add new_sdx new_s $
Container.addTwo old_sdx new_p old_pdx int_p nl,
new_inst, old_sdx, new_sdx)
in new_nl
move :: (Node.List, Instance.List)
-> (Idx, IMove)
-> OpResult (Node.List, Instance.List)
move (nl, il) (idx, mv) = do
let inst = Container.find idx il
(nl', inst', _, _) <- applyMoveEx True nl inst mv
return (nl', Container.add idx inst' il)