root / Ganeti / HTools / Loader.hs @ 608efcce
History | View | Annotate | Download (5.2 kB)
1 | 040afc35 | Iustin Pop | {-| Loading data from external sources |
---|---|---|---|
2 | 040afc35 | Iustin Pop | |
3 | 040afc35 | Iustin Pop | This module holds the common code for loading the cluster state from external sources. |
4 | 040afc35 | Iustin Pop | |
5 | 040afc35 | Iustin Pop | -} |
6 | 040afc35 | Iustin Pop | |
7 | 040afc35 | Iustin Pop | module Ganeti.HTools.Loader |
8 | 446d8827 | Iustin Pop | ( mergeData |
9 | 446d8827 | Iustin Pop | , checkData |
10 | 446d8827 | Iustin Pop | , assignIndices |
11 | 446d8827 | Iustin Pop | , lookupNode |
12 | ed41c179 | Iustin Pop | , stripSuffix |
13 | 446d8827 | Iustin Pop | ) where |
14 | 040afc35 | Iustin Pop | |
15 | e4c5beaf | Iustin Pop | import Data.List |
16 | 446d8827 | Iustin Pop | import Data.Maybe (fromJust) |
17 | 446d8827 | Iustin Pop | import Text.Printf (printf) |
18 | e4c5beaf | Iustin Pop | |
19 | e4c5beaf | Iustin Pop | import qualified Ganeti.HTools.Container as Container |
20 | e4c5beaf | Iustin Pop | import qualified Ganeti.HTools.Instance as Instance |
21 | e4c5beaf | Iustin Pop | import qualified Ganeti.HTools.Node as Node |
22 | e4c5beaf | Iustin Pop | |
23 | e4c5beaf | Iustin Pop | import Ganeti.HTools.Types |
24 | e4c5beaf | Iustin Pop | |
25 | 040afc35 | Iustin Pop | -- | Lookups a node into an assoc list |
26 | 608efcce | Iustin Pop | lookupNode :: (Monad m) => [(String, Ndx)] -> String -> String -> m Ndx |
27 | 040afc35 | Iustin Pop | lookupNode ktn inst node = |
28 | 040afc35 | Iustin Pop | case lookup node ktn of |
29 | 040afc35 | Iustin Pop | Nothing -> fail $ "Unknown node '" ++ node ++ "' for instance " ++ inst |
30 | 040afc35 | Iustin Pop | Just idx -> return idx |
31 | 040afc35 | Iustin Pop | |
32 | 497e30a1 | Iustin Pop | assignIndices :: (Element a) => |
33 | 497e30a1 | Iustin Pop | [(String, a)] |
34 | 040afc35 | Iustin Pop | -> (NameAssoc, [(Int, a)]) |
35 | 497e30a1 | Iustin Pop | assignIndices = |
36 | 497e30a1 | Iustin Pop | unzip . map (\ (idx, (k, v)) -> ((k, idx), (idx, setIdx v idx))) |
37 | 040afc35 | Iustin Pop | . zip [0..] |
38 | e4c5beaf | Iustin Pop | |
39 | e4c5beaf | Iustin Pop | -- | For each instance, add its index to its primary and secondary nodes |
40 | 608efcce | Iustin Pop | fixNodes :: [(Ndx, Node.Node)] |
41 | 608efcce | Iustin Pop | -> [(Idx, Instance.Instance)] |
42 | 608efcce | Iustin Pop | -> [(Ndx, Node.Node)] |
43 | e4c5beaf | Iustin Pop | fixNodes nl il = |
44 | e4c5beaf | Iustin Pop | foldl' (\accu (idx, inst) -> |
45 | e4c5beaf | Iustin Pop | let |
46 | e4c5beaf | Iustin Pop | assocEqual = (\ (i, _) (j, _) -> i == j) |
47 | e4c5beaf | Iustin Pop | pdx = Instance.pnode inst |
48 | e4c5beaf | Iustin Pop | sdx = Instance.snode inst |
49 | e4c5beaf | Iustin Pop | pold = fromJust $ lookup pdx accu |
50 | e4c5beaf | Iustin Pop | pnew = Node.setPri pold idx |
51 | e4c5beaf | Iustin Pop | ac1 = deleteBy assocEqual (pdx, pold) accu |
52 | e4c5beaf | Iustin Pop | ac2 = (pdx, pnew):ac1 |
53 | e4c5beaf | Iustin Pop | in |
54 | e4c5beaf | Iustin Pop | if sdx /= Node.noSecondary then |
55 | e4c5beaf | Iustin Pop | let |
56 | e4c5beaf | Iustin Pop | sold = fromJust $ lookup sdx accu |
57 | e4c5beaf | Iustin Pop | snew = Node.setSec sold idx |
58 | e4c5beaf | Iustin Pop | ac3 = deleteBy assocEqual (sdx, sold) ac2 |
59 | e4c5beaf | Iustin Pop | ac4 = (sdx, snew):ac3 |
60 | e4c5beaf | Iustin Pop | in ac4 |
61 | e4c5beaf | Iustin Pop | else |
62 | e4c5beaf | Iustin Pop | ac2 |
63 | e4c5beaf | Iustin Pop | ) nl il |
64 | e4c5beaf | Iustin Pop | |
65 | e4c5beaf | Iustin Pop | -- | Compute the longest common suffix of a NameList list that |
66 | e4c5beaf | Iustin Pop | -- | starts with a dot |
67 | 8472a321 | Iustin Pop | longestDomain :: [String] -> String |
68 | e4c5beaf | Iustin Pop | longestDomain [] = "" |
69 | 8472a321 | Iustin Pop | longestDomain (x:xs) = |
70 | 8472a321 | Iustin Pop | foldr (\ suffix accu -> if all (isSuffixOf suffix) xs |
71 | e4c5beaf | Iustin Pop | then suffix |
72 | e4c5beaf | Iustin Pop | else accu) |
73 | e4c5beaf | Iustin Pop | "" $ filter (isPrefixOf ".") (tails x) |
74 | e4c5beaf | Iustin Pop | |
75 | 26b5d395 | Iustin Pop | -- | Remove tail suffix from a string |
76 | 26b5d395 | Iustin Pop | stripSuffix :: Int -> String -> String |
77 | 26b5d395 | Iustin Pop | stripSuffix sflen name = take ((length name) - sflen) name |
78 | e4c5beaf | Iustin Pop | |
79 | e4c5beaf | Iustin Pop | {-| Initializer function that loads the data from a node and list file |
80 | e4c5beaf | Iustin Pop | and massages it into the correct format. -} |
81 | e3a684c5 | Iustin Pop | mergeData :: (Node.AssocList, |
82 | e3a684c5 | Iustin Pop | Instance.AssocList) -- ^ Data from either Text.loadData |
83 | e3a684c5 | Iustin Pop | -- or Rapi.loadData |
84 | 262a08a2 | Iustin Pop | -> Result (Node.List, Instance.List, String) |
85 | e3a684c5 | Iustin Pop | mergeData (nl, il) = do |
86 | e4c5beaf | Iustin Pop | let |
87 | e4c5beaf | Iustin Pop | nl2 = fixNodes nl il |
88 | e4c5beaf | Iustin Pop | il3 = Container.fromAssocList il |
89 | e4c5beaf | Iustin Pop | nl3 = Container.fromAssocList |
90 | e4c5beaf | Iustin Pop | (map (\ (k, v) -> (k, Node.buildPeers v il3 (length nl2))) nl2) |
91 | 8472a321 | Iustin Pop | node_names = map Node.name $ Container.elems nl3 |
92 | 8472a321 | Iustin Pop | inst_names = map Instance.name $ Container.elems il3 |
93 | 8472a321 | Iustin Pop | common_suffix = longestDomain (node_names ++ inst_names) |
94 | 26b5d395 | Iustin Pop | csl = length common_suffix |
95 | 262a08a2 | Iustin Pop | snl = Container.map (\n -> setName n (stripSuffix csl $ nameOf n)) nl3 |
96 | 262a08a2 | Iustin Pop | sil = Container.map (\i -> setName i (stripSuffix csl $ nameOf i)) il3 |
97 | 8472a321 | Iustin Pop | return (snl, sil, common_suffix) |
98 | 446d8827 | Iustin Pop | |
99 | 446d8827 | Iustin Pop | -- | Check cluster data for consistency |
100 | 262a08a2 | Iustin Pop | checkData :: Node.List -> Instance.List |
101 | 262a08a2 | Iustin Pop | -> ([String], Node.List) |
102 | dbd6700b | Iustin Pop | checkData nl il = |
103 | 446d8827 | Iustin Pop | Container.mapAccum |
104 | 446d8827 | Iustin Pop | (\ msgs node -> |
105 | dbd6700b | Iustin Pop | let nname = Node.name node |
106 | 446d8827 | Iustin Pop | nilst = map (flip Container.find $ il) (Node.plist node) |
107 | 446d8827 | Iustin Pop | dilst = filter (not . Instance.running) nilst |
108 | 446d8827 | Iustin Pop | adj_mem = sum . map Instance.mem $ dilst |
109 | 446d8827 | Iustin Pop | delta_mem = (truncate $ Node.t_mem node) |
110 | 446d8827 | Iustin Pop | - (Node.n_mem node) |
111 | 446d8827 | Iustin Pop | - (Node.f_mem node) |
112 | 446d8827 | Iustin Pop | - (nodeImem node il) |
113 | 446d8827 | Iustin Pop | + adj_mem |
114 | 446d8827 | Iustin Pop | delta_dsk = (truncate $ Node.t_dsk node) |
115 | 446d8827 | Iustin Pop | - (Node.f_dsk node) |
116 | 446d8827 | Iustin Pop | - (nodeIdsk node il) |
117 | 446d8827 | Iustin Pop | newn = Node.setFmem (Node.setXmem node delta_mem) |
118 | 446d8827 | Iustin Pop | (Node.f_mem node - adj_mem) |
119 | 446d8827 | Iustin Pop | umsg1 = if delta_mem > 512 || delta_dsk > 1024 |
120 | 446d8827 | Iustin Pop | then [printf "node %s is missing %d MB ram \ |
121 | 446d8827 | Iustin Pop | \and %d GB disk" |
122 | 446d8827 | Iustin Pop | nname delta_mem (delta_dsk `div` 1024)] |
123 | 446d8827 | Iustin Pop | else [] |
124 | 446d8827 | Iustin Pop | in (msgs ++ umsg1, newn) |
125 | 446d8827 | Iustin Pop | ) [] nl |
126 | 446d8827 | Iustin Pop | |
127 | 446d8827 | Iustin Pop | -- | Compute the amount of memory used by primary instances on a node. |
128 | 262a08a2 | Iustin Pop | nodeImem :: Node.Node -> Instance.List -> Int |
129 | 446d8827 | Iustin Pop | nodeImem node il = |
130 | 446d8827 | Iustin Pop | let rfind = flip Container.find $ il |
131 | 446d8827 | Iustin Pop | in sum . map Instance.mem . |
132 | 446d8827 | Iustin Pop | map rfind $ Node.plist node |
133 | 446d8827 | Iustin Pop | |
134 | 446d8827 | Iustin Pop | -- | Compute the amount of disk used by instances on a node (either primary |
135 | 446d8827 | Iustin Pop | -- or secondary). |
136 | 262a08a2 | Iustin Pop | nodeIdsk :: Node.Node -> Instance.List -> Int |
137 | 446d8827 | Iustin Pop | nodeIdsk node il = |
138 | 446d8827 | Iustin Pop | let rfind = flip Container.find $ il |
139 | 446d8827 | Iustin Pop | in sum . map Instance.dsk . |
140 | 446d8827 | Iustin Pop | map rfind $ (Node.plist node) ++ (Node.slist node) |