Revision ebf38064 htools/Ganeti/HTools/Loader.hs

b/htools/Ganeti/HTools/Loader.hs
27 27
-}
28 28

  
29 29
module Ganeti.HTools.Loader
30
    ( mergeData
31
    , checkData
32
    , assignIndices
33
    , lookupName
34
    , goodLookupResult
35
    , lookupNode
36
    , lookupInstance
37
    , lookupGroup
38
    , commonSuffix
39
    , RqType(..)
40
    , Request(..)
41
    , ClusterData(..)
42
    , emptyCluster
43
    , compareNameComponent
44
    , prefixMatch
45
    , LookupResult(..)
46
    , MatchPriority(..)
47
    ) where
30
  ( mergeData
31
  , checkData
32
  , assignIndices
33
  , lookupName
34
  , goodLookupResult
35
  , lookupNode
36
  , lookupInstance
37
  , lookupGroup
38
  , commonSuffix
39
  , RqType(..)
40
  , Request(..)
41
  , ClusterData(..)
42
  , emptyCluster
43
  , compareNameComponent
44
  , prefixMatch
45
  , LookupResult(..)
46
  , MatchPriority(..)
47
  ) where
48 48

  
49 49
import Data.List
50 50
import Data.Function
......
74 74

  
75 75
-}
76 76
data RqType
77
    = Allocate Instance.Instance Int -- ^ A new instance allocation
78
    | Relocate Idx Int [Ndx]         -- ^ Choose a new secondary node
79
    | NodeEvacuate [Idx] EvacMode    -- ^ node-evacuate mode
80
    | ChangeGroup [Gdx] [Idx]        -- ^ Multi-relocate mode
77
  = Allocate Instance.Instance Int -- ^ A new instance allocation
78
  | Relocate Idx Int [Ndx]         -- ^ Choose a new secondary node
79
  | NodeEvacuate [Idx] EvacMode    -- ^ node-evacuate mode
80
  | ChangeGroup [Gdx] [Idx]        -- ^ Multi-relocate mode
81 81
    deriving (Show, Read)
82 82

  
83 83
-- | A complete request, as received from Ganeti.
84 84
data Request = Request RqType ClusterData
85
    deriving (Show, Read)
85
               deriving (Show, Read)
86 86

  
87 87
-- | The cluster state.
88 88
data ClusterData = ClusterData
89
    { cdGroups    :: Group.List    -- ^ The node group list
90
    , cdNodes     :: Node.List     -- ^ The node list
91
    , cdInstances :: Instance.List -- ^ The instance list
92
    , cdTags      :: [String]      -- ^ The cluster tags
93
    } deriving (Show, Read)
89
  { cdGroups    :: Group.List    -- ^ The node group list
90
  , cdNodes     :: Node.List     -- ^ The node list
91
  , cdInstances :: Instance.List -- ^ The instance list
92
  , cdTags      :: [String]      -- ^ The cluster tags
93
  } deriving (Show, Read)
94 94

  
95 95
-- | The priority of a match in a lookup result.
96 96
data MatchPriority = ExactMatch
......
101 101

  
102 102
-- | The result of a name lookup in a list.
103 103
data LookupResult = LookupResult
104
    { lrMatchPriority :: MatchPriority -- ^ The result type
105
    -- | Matching value (for ExactMatch, PartialMatch), Lookup string otherwise
106
    , lrContent :: String
107
    } deriving (Show, Read)
104
  { lrMatchPriority :: MatchPriority -- ^ The result type
105
  -- | Matching value (for ExactMatch, PartialMatch), Lookup string otherwise
106
  , lrContent :: String
107
  } deriving (Show, Read)
108 108

  
109 109
-- | Lookup results have an absolute preference ordering.
110 110
instance Eq LookupResult where
......
122 122
-- | Lookups a node into an assoc list.
123 123
lookupNode :: (Monad m) => NameAssoc -> String -> String -> m Ndx
124 124
lookupNode ktn inst node =
125
    case M.lookup node ktn of
126
      Nothing -> fail $ "Unknown node '" ++ node ++ "' for instance " ++ inst
127
      Just idx -> return idx
125
  case M.lookup node ktn of
126
    Nothing -> fail $ "Unknown node '" ++ node ++ "' for instance " ++ inst
127
    Just idx -> return idx
128 128

  
129 129
-- | Lookups an instance into an assoc list.
130 130
lookupInstance :: (Monad m) => NameAssoc -> String -> m Idx
131 131
lookupInstance kti inst =
132
    case M.lookup inst kti of
133
      Nothing -> fail $ "Unknown instance '" ++ inst ++ "'"
134
      Just idx -> return idx
132
  case M.lookup inst kti of
133
    Nothing -> fail $ "Unknown instance '" ++ inst ++ "'"
134
    Just idx -> return idx
135 135

  
136 136
-- | Lookups a group into an assoc list.
137 137
lookupGroup :: (Monad m) => NameAssoc -> String -> String -> m Gdx
138 138
lookupGroup ktg nname gname =
139
    case M.lookup gname ktg of
140
      Nothing -> fail $ "Unknown group '" ++ gname ++ "' for node " ++ nname
141
      Just idx -> return idx
139
  case M.lookup gname ktg of
140
    Nothing -> fail $ "Unknown group '" ++ gname ++ "' for node " ++ nname
141
    Just idx -> return idx
142 142

  
143 143
-- | Check for prefix matches in names.
144 144
-- Implemented in Ganeti core utils.text.MatchNameComponent
......
206 206
         -> Instance.Instance
207 207
         -> Node.List
208 208
fixNodes accu inst =
209
    let
210
        pdx = Instance.pNode inst
211
        sdx = Instance.sNode inst
212
        pold = Container.find pdx accu
213
        pnew = Node.setPri pold inst
214
        ac2 = Container.add pdx pnew accu
215
    in
216
      if sdx /= Node.noSecondary
217
      then let sold = Container.find sdx accu
218
               snew = Node.setSec sold inst
219
           in Container.add sdx snew ac2
220
      else ac2
209
  let pdx = Instance.pNode inst
210
      sdx = Instance.sNode inst
211
      pold = Container.find pdx accu
212
      pnew = Node.setPri pold inst
213
      ac2 = Container.add pdx pnew accu
214
  in if sdx /= Node.noSecondary
215
       then let sold = Container.find sdx accu
216
                snew = Node.setSec sold inst
217
            in Container.add sdx snew ac2
218
       else ac2
221 219

  
222 220
-- | Remove non-selected tags from the exclusion list.
223 221
filterExTags :: [String] -> Instance.Instance -> Instance.Instance
224 222
filterExTags tl inst =
225
    let old_tags = Instance.tags inst
226
        new_tags = filter (\tag -> any (`isPrefixOf` tag) tl)
227
                   old_tags
228
    in inst { Instance.tags = new_tags }
223
  let old_tags = Instance.tags inst
224
      new_tags = filter (\tag -> any (`isPrefixOf` tag) tl) old_tags
225
  in inst { Instance.tags = new_tags }
229 226

  
230 227
-- | Update the movable attribute.
231 228
updateMovable :: [String]           -- ^ Selected instances (if not empty)
......
233 230
              -> Instance.Instance  -- ^ Target Instance
234 231
              -> Instance.Instance  -- ^ Target Instance with updated attribute
235 232
updateMovable selinsts exinsts inst =
236
    if Instance.sNode inst == Node.noSecondary ||
237
       Instance.name inst `elem` exinsts ||
238
       not (null selinsts || Instance.name inst `elem` selinsts)
233
  if Instance.sNode inst == Node.noSecondary ||
234
     Instance.name inst `elem` exinsts ||
235
     not (null selinsts || Instance.name inst `elem` selinsts)
239 236
    then Instance.setMovable inst False
240 237
    else inst
241 238

  
......
244 241
longestDomain :: [String] -> String
245 242
longestDomain [] = ""
246 243
longestDomain (x:xs) =
247
      foldr (\ suffix accu -> if all (isSuffixOf suffix) xs
248
                              then suffix
249
                              else accu)
250
      "" $ filter (isPrefixOf ".") (tails x)
244
  foldr (\ suffix accu -> if all (isSuffixOf suffix) xs
245
                            then suffix
246
                            else accu)
247
          "" $ filter (isPrefixOf ".") (tails x)
251 248

  
252 249
-- | Extracts the exclusion tags from the cluster configuration.
253 250
extractExTags :: [String] -> [String]
254 251
extractExTags =
255
    map (drop (length exTagsPrefix)) .
256
    filter (isPrefixOf exTagsPrefix)
252
  map (drop (length exTagsPrefix)) .
253
  filter (isPrefixOf exTagsPrefix)
257 254

  
258 255
-- | Extracts the common suffix from node\/instance names.
259 256
commonSuffix :: Node.List -> Instance.List -> String
260 257
commonSuffix nl il =
261
    let node_names = map Node.name $ Container.elems nl
262
        inst_names = map Instance.name $ Container.elems il
263
    in longestDomain (node_names ++ inst_names)
258
  let node_names = map Node.name $ Container.elems nl
259
      inst_names = map Instance.name $ Container.elems il
260
  in longestDomain (node_names ++ inst_names)
264 261

  
265 262
-- | Initializer function that loads the data from a node and instance
266 263
-- list and massages it into the correct format.
......
328 325
-- | Compute the amount of memory used by primary instances on a node.
329 326
nodeImem :: Node.Node -> Instance.List -> Int
330 327
nodeImem node il =
331
    let rfind = flip Container.find il
332
        il' = map rfind $ Node.pList node
333
        oil' = filter (not . Instance.instanceOffline) il'
334
    in sum . map Instance.mem $ oil'
328
  let rfind = flip Container.find il
329
      il' = map rfind $ Node.pList node
330
      oil' = filter (not . Instance.instanceOffline) il'
331
  in sum . map Instance.mem $ oil'
335 332

  
336 333

  
337 334
-- | Compute the amount of disk used by instances on a node (either primary
338 335
-- or secondary).
339 336
nodeIdsk :: Node.Node -> Instance.List -> Int
340 337
nodeIdsk node il =
341
    let rfind = flip Container.find il
342
    in sum . map (Instance.dsk . rfind)
343
           $ Node.pList node ++ Node.sList node
338
  let rfind = flip Container.find il
339
  in sum . map (Instance.dsk . rfind)
340
       $ Node.pList node ++ Node.sList node

Also available in: Unified diff