1 {-| Loading data from external sources
3 This module holds the common code for loading the cluster state from external sources.
7 module Ganeti.HTools.Loader
11 import Data.Maybe (isNothing, fromJust)
13 import qualified Ganeti.HTools.Container as Container
14 import qualified Ganeti.HTools.Instance as Instance
15 import qualified Ganeti.HTools.Node as Node
17 import Ganeti.HTools.Types
20 -- | Swap a list of @(a, b)@ into @(b, a)@
21 swapPairs :: [(a, b)] -> [(b, a)]
22 swapPairs = map (\ (a, b) -> (b, a))
24 -- | Lookups a node into an assoc list
25 lookupNode :: (Monad m) => NameAssoc -> String -> String -> m Int
26 lookupNode ktn inst node =
27 case lookup node ktn of
28 Nothing -> fail $ "Unknown node '" ++ node ++ "' for instance " ++ inst
29 Just idx -> return idx
31 assignIndices :: (a -> Int -> a)
33 -> (NameAssoc, [(Int, a)])
34 assignIndices set_fn =
35 unzip . map (\ (idx, (k, v)) -> ((k, idx), (idx, set_fn v idx)))
38 -- | For each instance, add its index to its primary and secondary nodes
39 fixNodes :: [(Int, Node.Node)]
40 -> [(Int, Instance.Instance)]
43 foldl' (\accu (idx, inst) ->
45 assocEqual = (\ (i, _) (j, _) -> i == j)
46 pdx = Instance.pnode inst
47 sdx = Instance.snode inst
48 pold = fromJust $ lookup pdx accu
49 pnew = Node.setPri pold idx
50 ac1 = deleteBy assocEqual (pdx, pold) accu
53 if sdx /= Node.noSecondary then
55 sold = fromJust $ lookup sdx accu
56 snew = Node.setSec sold idx
57 ac3 = deleteBy assocEqual (sdx, sold) ac2
64 -- | Compute the longest common suffix of a NameList list that
65 -- | starts with a dot
66 longestDomain :: NameList -> String
68 longestDomain ((_,x):xs) =
70 onlyStrings = snd $ unzip xs
72 foldr (\ suffix accu -> if all (isSuffixOf suffix) onlyStrings
75 "" $ filter (isPrefixOf ".") (tails x)
77 -- | Remove tails from the (Int, String) lists
78 stripSuffix :: String -> NameList -> NameList
79 stripSuffix suffix lst =
80 let sflen = length suffix in
81 map (\ (key, name) -> (key, take ((length name) - sflen) name)) lst
83 {-| Initializer function that loads the data from a node and list file
84 and massages it into the correct format. -}
85 mergeData :: ([(String, Int)], Node.AssocList,
86 [(String, Int)], Instance.AssocList) -- ^ Data from either
89 -> Result (NodeList, InstanceList, String, NameList, NameList)
90 mergeData (ktn, nl, kti, il) = do
93 il3 = Container.fromAssocList il
94 nl3 = Container.fromAssocList
95 (map (\ (k, v) -> (k, Node.buildPeers v il3 (length nl2))) nl2)
98 common_suffix = longestDomain (xti ++ xtn)
99 stn = stripSuffix common_suffix xtn
100 sti = stripSuffix common_suffix xti
101 return (nl3, il3, common_suffix, stn, sti)