Revision 179c0828

b/htools/Ganeti/HTools/Cluster.hs
139 139
data Table = Table Node.List Instance.List Score [Placement]
140 140
             deriving (Show, Read)
141 141

  
142
-- | Cluster statistics data type.
142 143
data CStats = CStats { csFmem :: Integer -- ^ Cluster free mem
143 144
                     , csFdsk :: Integer -- ^ Cluster free disk
144 145
                     , csAmem :: Integer -- ^ Cluster allocatable mem
......
278 279
                 , (2,  "pri_tags_score")
279 280
                 ]
280 281

  
282
-- | Holds the weights used by 'compCVNodes' for each metric.
281 283
detailedCVWeights :: [Double]
282 284
detailedCVWeights = map fst detailedCVInfo
283 285

  
......
333 335
compCV :: Node.List -> Double
334 336
compCV = compCVNodes . Container.elems
335 337

  
336

  
337 338
-- | Compute online nodes from a 'Node.List'.
338 339
getOnline :: Node.List -> [Node.Node]
339 340
getOnline = filter (not . Node.offline) . Container.elems
......
1314 1315
    in intercalate ", " formatted
1315 1316

  
1316 1317
-- | Convert a placement into a list of OpCodes (basically a job).
1317
iMoveToJob :: Node.List -> Instance.List
1318
          -> Idx -> IMove -> [OpCodes.OpCode]
1318
iMoveToJob :: Node.List        -- ^ The node list; only used for node
1319
                               -- names, so any version is good
1320
                               -- (before or after the operation)
1321
           -> Instance.List    -- ^ The instance list; also used for
1322
                               -- names only
1323
           -> Idx              -- ^ The index of the instance being
1324
                               -- moved
1325
           -> IMove            -- ^ The actual move to be described
1326
           -> [OpCodes.OpCode] -- ^ The list of opcodes equivalent to
1327
                               -- the given move
1319 1328
iMoveToJob nl il idx move =
1320 1329
    let inst = Container.find idx il
1321 1330
        iname = Instance.name inst
b/htools/Ganeti/HTools/Compat.hs
34 34

  
35 35
import qualified Control.Parallel.Strategies
36 36

  
37
-- | Wrapper over the function exported from
38
-- "Control.Parallel.Strategies".
39
--
40
-- This wraps either the old or the new name of the function,
41
-- depending on the detected library version.
37 42
rwhnf :: Control.Parallel.Strategies.Strategy a
38 43
#ifdef PARALLEL3
39 44
rwhnf = Control.Parallel.Strategies.rseq
b/htools/Ganeti/HTools/Container.hs
59 59

  
60 60
import qualified Ganeti.HTools.Types as T
61 61

  
62
-- | Our key type.
63

  
62 64
type Key = IntMap.Key
65

  
66
-- | Our container type.
63 67
type Container = IntMap.IntMap
64 68

  
65 69
-- | Locate a key in the map (must exist).
b/htools/Ganeti/HTools/ExtLoader.hs
55 55
wrapIO :: IO (Result a) -> IO (Result a)
56 56
wrapIO = flip catch (return . Bad . show)
57 57

  
58
-- | Parses a user-supplied utilisation string.
58 59
parseUtilisation :: String -> Result (String, DynUtil)
59 60
parseUtilisation line =
60 61
    case sepSplit ' ' line of
b/htools/Ganeti/HTools/Group.hs
73 73
          , idx         = -1
74 74
          }
75 75

  
76
-- | Sets the group index.
77
--
76 78
-- This is used only during the building of the data structures.
77 79
setIdx :: Group -> T.Gdx -> Group
78 80
setIdx t i = t {idx = i}
b/htools/Ganeti/HTools/IAlloc.hs
237 237
               " were moved successfully"
238 238
    in Ok (info, showJSON (mes, fes, Cluster.esOpCodes es), fin_nl, fin_il)
239 239

  
240
-- | Process a request and return new node lists
240
-- | Process a request and return new node lists.
241 241
processRequest :: Request -> Result IAllocResult
242 242
processRequest request =
243 243
  let Request rqtype (ClusterData gl nl il _) = request
......
251 251
           Cluster.tryNodeEvac gl nl il mode xi >>=
252 252
                  formatNodeEvac gl nl il
253 253

  
254
-- | Reads the request from the data file(s)
254
-- | Reads the request from the data file(s).
255 255
readRequest :: Options -> [String] -> IO Request
256 256
readRequest opts args = do
257 257
  when (null args) $ do
b/htools/Ganeti/HTools/Instance.hs
159 159
         -> Instance -- ^ the modified instance
160 160
setBoth t p s = t { pNode = p, sNode = s }
161 161

  
162
-- | Sets the movable flag on an instance.
162 163
setMovable :: Instance -- ^ The original instance
163 164
           -> Bool     -- ^ New movable flag
164 165
           -> Instance -- ^ The modified instance
......
186 187
specOf Instance { mem = m, dsk = d, vcpus = c } =
187 188
    T.RSpec { T.rspecCpu = c, T.rspecMem = m, T.rspecDsk = d }
188 189

  
189
-- | Computed the number of nodes for a given disk template
190
-- | Computed the number of nodes for a given disk template.
190 191
requiredNodes :: T.DiskTemplate -> Int
191 192
requiredNodes T.DTDrbd8 = 2
192 193
requiredNodes _         = 1
b/htools/Ganeti/HTools/Luxi.hs
88 88
queryGroupsMsg =
89 89
  L.QueryGroups [] ["uuid", "name", "alloc_policy"] False
90 90

  
91
-- | Wraper over callMethod doing node query.
91
-- | Wraper over 'callMethod' doing node query.
92 92
queryNodes :: L.Client -> IO (Result JSValue)
93 93
queryNodes = L.callMethod queryNodesMsg
94 94

  
95
-- | Wraper over callMethod doing instance query.
95
-- | Wraper over 'callMethod' doing instance query.
96 96
queryInstances :: L.Client -> IO (Result JSValue)
97 97
queryInstances = L.callMethod queryInstancesMsg
98 98

  
99
-- | Wrapper over 'callMethod' doing cluster information query.
99 100
queryClusterInfo :: L.Client -> IO (Result JSValue)
100 101
queryClusterInfo = L.callMethod queryClusterInfoMsg
101 102

  
......
167 168

  
168 169
parseNode _ v = fail ("Invalid node query result: " ++ show v)
169 170

  
171
-- | Parses the cluster tags.
170 172
getClusterTags :: JSValue -> Result [String]
171 173
getClusterTags v = do
172 174
  let errmsg = "Parsing cluster info"
173 175
  obj <- annotateResult errmsg $ asJSObject v
174 176
  tryFromObj errmsg (fromJSObject obj) "tags"
175 177

  
178
-- | Parses the cluster groups.
176 179
getGroups :: JSValue -> Result [(String, Group.Group)]
177 180
getGroups arr = toArray arr >>= mapM parseGroup
178 181

  
182
-- | Parses a given group information.
179 183
parseGroup :: JSValue -> Result (String, Group.Group)
180 184
parseGroup (JSArray [ uuid, name, apol ]) = do
181 185
  xname <- annotateResult "Parsing new group" (fromJVal name)
b/htools/Ganeti/HTools/Program/Hail.hs
36 36
import Ganeti.HTools.Loader (Request(..), ClusterData(..))
37 37
import Ganeti.HTools.ExtLoader (maybeSaveData)
38 38

  
39
-- | Options list and functions
39
-- | Options list and functions.
40 40
options :: [OptType]
41 41
options =
42 42
    [ oPrintNodes
b/htools/Ganeti/HTools/Program/Hbal.hs
54 54
import qualified Ganeti.Luxi as L
55 55
import Ganeti.Jobs
56 56

  
57
-- | Options list and functions
57
-- | Options list and functions.
58 58
options :: [OptType]
59 59
options =
60 60
    [ oPrintNodes
......
133 133
                           mg_limit min_gain evac_mode
134 134
        Nothing -> return (ini_tbl, cmd_strs)
135 135

  
136
-- | Formats the solution for the oneline display
136
-- | Formats the solution for the oneline display.
137 137
formatOneline :: Double -> Int -> Double -> String
138 138
formatOneline ini_cv plc_len fin_cv =
139 139
    printf "%.8f %d %.8f %8.3f" ini_cv plc_len fin_cv
140 140
               (if fin_cv == 0 then 1 else ini_cv / fin_cv)
141 141

  
142 142
-- | Polls a set of jobs at a fixed interval until all are finished
143
-- one way or another
143
-- one way or another.
144 144
waitForJobs :: L.Client -> [String] -> IO (Result [JobStatus])
145 145
waitForJobs client jids = do
146 146
  sts <- L.queryJobsStatus client jids
......
153 153
              waitForJobs client jids
154 154
            else return $ Ok s
155 155

  
156
-- | Check that a set of job statuses is all success
156
-- | Check that a set of job statuses is all success.
157 157
checkJobsStatus :: [JobStatus] -> Bool
158 158
checkJobsStatus = all (== JOB_STATUS_SUCCESS)
159 159

  
160
-- | Wrapper over execJobSet checking for early termination
160
-- | Wrapper over execJobSet checking for early termination.
161 161
execWrapper :: String -> Node.List
162 162
           -> Instance.List -> IORef Int -> [JobSet] -> IO Bool
163 163
execWrapper _      _  _  _    [] = return True
......
170 170
     return False
171 171
   else execJobSet master nl il cref alljss)
172 172

  
173
-- | Execute an entire jobset
173
-- | Execute an entire jobset.
174 174
execJobSet :: String -> Node.List
175 175
           -> Instance.List -> IORef Int -> [JobSet] -> IO Bool
176 176
execJobSet _      _  _  _    [] = return True
......
201 201
               hPutStrLn stderr "Aborting."
202 202
               return False)
203 203

  
204
-- | Signal handler for graceful termination
204
-- | Signal handler for graceful termination.
205 205
hangleSigInt :: IORef Int -> IO ()
206 206
hangleSigInt cref = do
207 207
  writeIORef cref 1
208 208
  putStrLn ("Cancel request registered, will exit at" ++
209 209
            " the end of the current job set...")
210 210

  
211
-- | Signal handler for immediate termination
211
-- | Signal handler for immediate termination.
212 212
hangleSigTerm :: IORef Int -> IO ()
213 213
hangleSigTerm cref = do
214 214
  -- update the cref to 2, just for consistency
......
216 216
  putStrLn "Double cancel request, exiting now..."
217 217
  exitImmediately $ ExitFailure 2
218 218

  
219
-- | Runs a job set with handling of signals.
219 220
runJobSet :: String -> Node.List -> Instance.List -> [JobSet] -> IO Bool
220 221
runJobSet master fin_nl il cmd_jobs = do
221 222
  cref <- newIORef 0
b/htools/Ganeti/HTools/Program/Hscan.hs
46 46
import Ganeti.HTools.CLI
47 47
import Ganeti.HTools.Types
48 48

  
49
-- | Options list and functions
49
-- | Options list and functions.
50 50
options :: [OptType]
51 51
options =
52 52
    [ oPrintNodes
......
58 58
    , oShowHelp
59 59
    ]
60 60

  
61
-- | Return a one-line summary of cluster state
61
-- | Return a one-line summary of cluster state.
62 62
printCluster :: Node.List -> Instance.List
63 63
             -> String
64 64
printCluster nl il =
......
79 79
                 ccv
80 80

  
81 81

  
82
-- | Replace slashes with underscore for saving to filesystem
82
-- | Replace slashes with underscore for saving to filesystem.
83 83
fixSlash :: String -> String
84 84
fixSlash = map (\x -> if x == '/' then '_' else x)
85 85

  
......
91 91
  let (_, fix_nl) = checkData nl il
92 92
  return cdata { cdNodes = fix_nl }
93 93

  
94
-- | Writes cluster data out
94
-- | Writes cluster data out.
95 95
writeData :: Int
96 96
          -> String
97 97
          -> Options
......
108 108
               name err >> return False
109 109
    Ok processed -> writeDataInner nlen name opts cdata processed
110 110

  
111
-- | Inner function for writing cluster data to disk.
111 112
writeDataInner :: Int
112 113
               -> String
113 114
               -> Options
b/htools/Ganeti/HTools/Program/Hspace.hs
48 48
import Ganeti.HTools.ExtLoader
49 49
import Ganeti.HTools.Loader
50 50

  
51
-- | Options list and functions
51
-- | Options list and functions.
52 52
options :: [OptType]
53 53
options =
54 54
    [ oPrintNodes
......
110 110
cpuEff :: Cluster.CStats -> Double
111 111
cpuEff = effFn Cluster.csIcpu (fromIntegral . Cluster.csVcpu)
112 112

  
113
-- | Holds data for converting a 'Cluster.CStats' structure into
114
-- detailed statictics.
113 115
statsData :: [(String, Cluster.CStats -> String)]
114 116
statsData = [ ("SCORE", printf "%.8f" . Cluster.csScore)
115 117
            , ("INST_CNT", printf "%d" . Cluster.csNinst)
......
133 135
            , ("MNODE_DSK_AVAIL", printf "%d" . Cluster.csMdsk)
134 136
            ]
135 137

  
138
-- | List holding 'RSpec' formatting information.
136 139
specData :: [(String, RSpec -> String)]
137 140
specData = [ ("MEM", printf "%d" . rspecMem)
138 141
           , ("DSK", printf "%d" . rspecDsk)
139 142
           , ("CPU", printf "%d" . rspecCpu)
140 143
           ]
141 144

  
145
-- | List holding 'Cluster.CStats' formatting information.
142 146
clusterData :: [(String, Cluster.CStats -> String)]
143 147
clusterData = [ ("MEM", printf "%.0f" . Cluster.csTmem)
144 148
              , ("DSK", printf "%.0f" . Cluster.csTdsk)
......
146 150
              , ("VCPU", printf "%d" . Cluster.csVcpu)
147 151
              ]
148 152

  
149
-- | Function to print stats for a given phase
153
-- | Function to print stats for a given phase.
150 154
printStats :: Phase -> Cluster.CStats -> [(String, String)]
151 155
printStats ph cs =
152 156
  map (\(s, fn) -> (printf "%s_%s" kind s, fn cs)) statsData
......
211 215
    map (\(spec, cnt) -> printf "%d,%d,%d=%d" (rspecMem spec)
212 216
                         (rspecDsk spec) (rspecCpu spec) cnt)
213 217

  
218
-- | Formats \"key-metrics\" values.
214 219
formatRSpec :: Double -> String -> RSpec -> [(String, String)]
215 220
formatRSpec m_cpu s r =
216 221
    [ ("KM_" ++ s ++ "_CPU", show $ rspecCpu r)
......
219 224
    , ("KM_" ++ s ++ "_DSK", show $ rspecDsk r)
220 225
    ]
221 226

  
227
-- | Shows allocations stats.
222 228
printAllocationStats :: Double -> Node.List -> Node.List -> IO ()
223 229
printAllocationStats m_cpu ini_nl fin_nl = do
224 230
  let ini_stats = Cluster.totalResources ini_nl
......
228 234
  printKeys $ formatRSpec m_cpu "POOL"ralo
229 235
  printKeys $ formatRSpec m_cpu "UNAV" runa
230 236

  
231
-- | Ensure a value is quoted if needed
237
-- | Ensure a value is quoted if needed.
232 238
ensureQuoted :: String -> String
233 239
ensureQuoted v = if not (all (\c -> isAlphaNum c || c == '.') v)
234 240
                 then '\'':v ++ "'"
235 241
                 else v
236 242

  
237
-- | Format a list of key\/values as a shell fragment
243
-- | Format a list of key\/values as a shell fragment.
238 244
printKeys :: [(String, String)] -> IO ()
239 245
printKeys = mapM_ (\(k, v) ->
240 246
                   printf "HTS_%s=%s\n" (map toUpper k) (ensureQuoted v))
241 247

  
248
-- | Converts instance data to a list of strings.
242 249
printInstance :: Node.List -> Instance.Instance -> [String]
243 250
printInstance nl i = [ Instance.name i
244 251
                     , Container.nameOf nl $ Instance.pNode i
......
250 257
                     , show (Instance.vcpus i)
251 258
                     ]
252 259

  
253
-- | Optionally print the allocation map
260
-- | Optionally print the allocation map.
254 261
printAllocationMap :: Int -> String
255 262
                   -> Node.List -> [Instance.Instance] -> IO ()
256 263
printAllocationMap verbose msg nl ixes =
......
314 321
  printClusterScores ini_nl fin_nl
315 322
  printClusterEff (Cluster.totalResources fin_nl)
316 323

  
324
-- | Displays the initial/final cluster scores.
317 325
printClusterScores :: Node.List -> Node.List -> IO ()
318 326
printClusterScores ini_nl fin_nl = do
319 327
  printf "  - initial cluster score: %.8f\n" $ Cluster.compCV ini_nl::IO ()
320 328
  printf "  -   final cluster score: %.8f\n" $ Cluster.compCV fin_nl
321 329

  
330
-- | Displays the cluster efficiency.
322 331
printClusterEff :: Cluster.CStats -> IO ()
323 332
printClusterEff cs =
324 333
    mapM_ (\(s, fn) ->
b/htools/Ganeti/HTools/Types.hs
180 180
           | FailoverAndReplace Ndx  -- ^ Failover, replace secondary (f, r:ns)
181 181
             deriving (Show, Read)
182 182

  
183
-- | Instance disk template type
183
-- | Instance disk template type.
184 184
data DiskTemplate = DTDiskless
185 185
                  | DTFile
186 186
                  | DTSharedFile
......
189 189
                  | DTDrbd8
190 190
                    deriving (Show, Read, Eq, Enum, Bounded)
191 191

  
192
-- | Converts a DiskTemplate to String
192
-- | Converts a DiskTemplate to String.
193 193
dtToString :: DiskTemplate -> String
194 194
dtToString DTDiskless   = C.dtDiskless
195 195
dtToString DTFile       = C.dtFile
......
198 198
dtToString DTBlock      = C.dtBlock
199 199
dtToString DTDrbd8      = C.dtDrbd8
200 200

  
201
-- | Converts a DiskTemplate from String
201
-- | Converts a DiskTemplate from String.
202 202
dtFromString :: (Monad m) => String -> m DiskTemplate
203 203
dtFromString s =
204 204
    case () of
......
281 281
isBad :: Result a  -> Bool
282 282
isBad = not . isOk
283 283

  
284
-- | Converter from Either String to 'Result'
284
-- | Converter from Either String to 'Result'.
285 285
eitherToResult :: Either String a -> Result a
286 286
eitherToResult (Left s) = Bad s
287 287
eitherToResult (Right v) = Ok v
b/htools/Ganeti/HTools/Version.hs.in
1 1
-- Hey Emacs, this is a -*- haskell -*- file
2
{- | Auto-generated module holding version information.
3
-}
2 4

  
3 5
module Ganeti.HTools.Version
4 6
    (
b/htools/test.hs
37 37
import Ganeti.HTools.CLI
38 38
import Ganeti.HTools.Utils (sepSplit)
39 39

  
40
-- | Options list and functions
40
-- | Options list and functions.
41 41
options :: [OptType]
42 42
options =
43 43
    [ oReplay
......
61 61
incIORef :: IORef Int -> IO ()
62 62
incIORef ir = atomicModifyIORef ir (\x -> (x + 1, ()))
63 63

  
64
-- | Wrapper over a test runner with error counting
64
-- | Wrapper over a test runner with error counting.
65 65
wrapTest :: IORef Int
66 66
         -> (Args -> IO Result)
67 67
         -> Args

Also available in: Unified diff