Revision efe98965 htools/Ganeti/HTools/Loader.hs
b/htools/Ganeti/HTools/Loader.hs | ||
---|---|---|
40 | 40 |
, Request(..) |
41 | 41 |
, ClusterData(..) |
42 | 42 |
, emptyCluster |
43 |
, compareNameComponent |
|
44 |
, prefixMatch |
|
45 |
, LookupResult(..) |
|
46 |
, MatchPriority(..) |
|
43 | 47 |
) where |
44 | 48 |
|
45 | 49 |
import Data.List |
50 |
import Data.Function |
|
46 | 51 |
import qualified Data.Map as M |
47 | 52 |
import Text.Printf (printf) |
48 | 53 |
|
... | ... | |
52 | 57 |
import qualified Ganeti.HTools.Group as Group |
53 | 58 |
|
54 | 59 |
import Ganeti.HTools.Types |
60 |
import Ganeti.HTools.Utils |
|
55 | 61 |
|
56 | 62 |
-- * Constants |
57 | 63 |
|
... | ... | |
94 | 100 |
, cdTags :: [String] -- ^ The cluster tags |
95 | 101 |
} deriving (Show, Read) |
96 | 102 |
|
103 |
-- | The priority of a match in a lookup result. |
|
104 |
data MatchPriority = ExactMatch |
|
105 |
| MultipleMatch |
|
106 |
| PartialMatch |
|
107 |
| FailMatch |
|
108 |
deriving (Show, Read, Enum, Eq, Ord) |
|
109 |
|
|
110 |
-- | The result of a name lookup in a list. |
|
111 |
data LookupResult = LookupResult |
|
112 |
{ lrMatchPriority :: MatchPriority -- ^ The result type |
|
113 |
-- | Matching value (for ExactMatch, PartialMatch), Lookup string otherwise |
|
114 |
, lrContent :: String |
|
115 |
} deriving (Show, Read) |
|
116 |
|
|
117 |
-- | Lookup results have an absolute preference ordering. |
|
118 |
instance Eq LookupResult where |
|
119 |
(==) = (==) `on` lrMatchPriority |
|
120 |
|
|
121 |
instance Ord LookupResult where |
|
122 |
compare = compare `on` lrMatchPriority |
|
123 |
|
|
97 | 124 |
-- | An empty cluster. |
98 | 125 |
emptyCluster :: ClusterData |
99 | 126 |
emptyCluster = ClusterData Container.empty Container.empty Container.empty [] |
... | ... | |
121 | 148 |
Nothing -> fail $ "Unknown group '" ++ gname ++ "' for node " ++ nname |
122 | 149 |
Just idx -> return idx |
123 | 150 |
|
151 |
-- | Check for prefix matches in names. |
|
152 |
-- Implemented in Ganeti core utils.text.MatchNameComponent |
|
153 |
-- as the regexp r"^%s(\..*)?$" % re.escape(key) |
|
154 |
prefixMatch :: String -- ^ Lookup |
|
155 |
-> String -- ^ Full name |
|
156 |
-> Bool -- ^ Whether there is a prefix match |
|
157 |
prefixMatch lkp = isPrefixOf (lkp ++ ".") |
|
158 |
|
|
159 |
-- | Is the lookup priority a "good" one? |
|
160 |
goodMatchPriority :: MatchPriority -> Bool |
|
161 |
goodMatchPriority ExactMatch = True |
|
162 |
goodMatchPriority PartialMatch = True |
|
163 |
goodMatchPriority _ = False |
|
164 |
|
|
165 |
-- | Is the lookup result an actual match? |
|
166 |
goodLookupResult :: LookupResult -> Bool |
|
167 |
goodLookupResult = goodMatchPriority . lrMatchPriority |
|
168 |
|
|
169 |
-- | Compares a canonical name and a lookup string. |
|
170 |
compareNameComponent :: String -- ^ Canonical (target) name |
|
171 |
-> String -- ^ Partial (lookup) name |
|
172 |
-> LookupResult -- ^ Result of the lookup |
|
173 |
compareNameComponent cnl lkp = |
|
174 |
select (LookupResult FailMatch lkp) |
|
175 |
[ (cnl == lkp , LookupResult ExactMatch cnl) |
|
176 |
, (prefixMatch lkp cnl , LookupResult PartialMatch cnl) |
|
177 |
] |
|
178 |
|
|
179 |
-- | Lookup a string and choose the best result. |
|
180 |
chooseLookupResult :: String -- ^ Lookup key |
|
181 |
-> String -- ^ String to compare to the lookup key |
|
182 |
-> LookupResult -- ^ Previous result |
|
183 |
-> LookupResult -- ^ New result |
|
184 |
chooseLookupResult lkp cstr old = |
|
185 |
-- default: use class order to pick the minimum result |
|
186 |
select (min new old) |
|
187 |
-- special cases: |
|
188 |
-- short circuit if the new result is an exact match |
|
189 |
[ ((lrMatchPriority new) == ExactMatch, new) |
|
190 |
-- if both are partial matches generate a multiple match |
|
191 |
, (partial2, LookupResult MultipleMatch lkp) |
|
192 |
] where new = compareNameComponent cstr lkp |
|
193 |
partial2 = all ((PartialMatch==) . lrMatchPriority) [old, new] |
|
194 |
|
|
195 |
-- | Find the canonical name for a lookup string in a list of names. |
|
196 |
lookupName :: [String] -- ^ List of keys |
|
197 |
-> String -- ^ Lookup string |
|
198 |
-> LookupResult -- ^ Result of the lookup |
|
199 |
lookupName l s = foldr (chooseLookupResult s) |
|
200 |
(LookupResult FailMatch s) l |
|
201 |
|
|
124 | 202 |
-- | Given a list of elements (and their names), assign indices to them. |
125 | 203 |
assignIndices :: (Element a) => |
126 | 204 |
[(String, a)] |
Also available in: Unified diff