Revision ce207617 htools/Ganeti/HTools/CLI.hs

b/htools/Ganeti/HTools/CLI.hs
211 211
    [dsk, ram, cpu] -> return $ RSpec cpu ram dsk
212 212
    _ -> err
213 213

  
214
-- | Disk template choices.
215
optComplDiskTemplate :: OptCompletion
216
optComplDiskTemplate = OptComplChoices $
217
                       map diskTemplateToRaw [minBound..maxBound]
218

  
214 219
-- * Command line options
215 220

  
216 221
oDataFile :: OptType
217
oDataFile = Option "t" ["text-data"]
218
            (ReqArg (\ f o -> Ok o { optDataFile = Just f }) "FILE")
219
            "the cluster data FILE"
222
oDataFile =
223
  (Option "t" ["text-data"]
224
   (ReqArg (\ f o -> Ok o { optDataFile = Just f }) "FILE")
225
   "the cluster data FILE",
226
   OptComplFile)
220 227

  
221 228
oDiskMoves :: OptType
222
oDiskMoves = Option "" ["no-disk-moves"]
223
             (NoArg (\ opts -> Ok opts { optDiskMoves = False}))
224
             "disallow disk moves from the list of allowed instance changes,\
225
             \ thus allowing only the 'cheap' failover/migrate operations"
229
oDiskMoves =
230
  (Option "" ["no-disk-moves"]
231
   (NoArg (\ opts -> Ok opts { optDiskMoves = False}))
232
   "disallow disk moves from the list of allowed instance changes,\
233
   \ thus allowing only the 'cheap' failover/migrate operations",
234
   OptComplNone)
226 235

  
227 236
oDiskTemplate :: OptType
228
oDiskTemplate = Option "" ["disk-template"]
229
                (reqWithConversion diskTemplateFromRaw
230
                 (\dt opts -> Ok opts { optDiskTemplate = Just dt })
231
                 "TEMPLATE") "select the desired disk template"
237
oDiskTemplate =
238
  (Option "" ["disk-template"]
239
   (reqWithConversion diskTemplateFromRaw
240
    (\dt opts -> Ok opts { optDiskTemplate = Just dt })
241
    "TEMPLATE") "select the desired disk template",
242
   optComplDiskTemplate)
232 243

  
233 244
oSpindleUse :: OptType
234
oSpindleUse = Option "" ["spindle-use"]
235
              (reqWithConversion (tryRead "parsing spindle-use")
236
               (\su opts -> do
237
                  when (su < 0) $
238
                       fail "Invalid value of the spindle-use\
239
                            \ (expected >= 0)"
240
                  return $ opts { optSpindleUse = Just su })
241
               "SPINDLES") "select how many virtual spindle instances use\
242
                           \ [default read from cluster]"
245
oSpindleUse =
246
  (Option "" ["spindle-use"]
247
   (reqWithConversion (tryRead "parsing spindle-use")
248
    (\su opts -> do
249
       when (su < 0) $
250
            fail "Invalid value of the spindle-use (expected >= 0)"
251
       return $ opts { optSpindleUse = Just su })
252
    "SPINDLES") "select how many virtual spindle instances use\
253
                \ [default read from cluster]",
254
   OptComplNumeric)
243 255

  
244 256
oSelInst :: OptType
245
oSelInst = Option "" ["select-instances"]
246
          (ReqArg (\ f opts -> Ok opts { optSelInst = sepSplit ',' f }) "INSTS")
247
          "only select given instances for any moves"
257
oSelInst =
258
  (Option "" ["select-instances"]
259
   (ReqArg (\ f opts -> Ok opts { optSelInst = sepSplit ',' f }) "INSTS")
260
   "only select given instances for any moves",
261
   OptComplManyInstances)
248 262

  
249 263
oInstMoves :: OptType
250
oInstMoves = Option "" ["no-instance-moves"]
251
             (NoArg (\ opts -> Ok opts { optInstMoves = False}))
252
             "disallow instance (primary node) moves from the list of allowed,\
253
             \ instance changes, thus allowing only slower, but sometimes\
254
             \ safer, drbd secondary changes"
264
oInstMoves =
265
  (Option "" ["no-instance-moves"]
266
   (NoArg (\ opts -> Ok opts { optInstMoves = False}))
267
   "disallow instance (primary node) moves from the list of allowed,\
268
   \ instance changes, thus allowing only slower, but sometimes\
269
   \ safer, drbd secondary changes",
270
   OptComplNone)
255 271

  
256 272
oDynuFile :: OptType
257
oDynuFile = Option "U" ["dynu-file"]
258
            (ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
259
            "Import dynamic utilisation data from the given FILE"
273
oDynuFile =
274
  (Option "U" ["dynu-file"]
275
   (ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
276
   "Import dynamic utilisation data from the given FILE",
277
   OptComplFile)
260 278

  
261 279
oEvacMode :: OptType
262
oEvacMode = Option "E" ["evac-mode"]
263
            (NoArg (\opts -> Ok opts { optEvacMode = True }))
264
            "enable evacuation mode, where the algorithm only moves \
265
            \ instances away from offline and drained nodes"
280
oEvacMode =
281
  (Option "E" ["evac-mode"]
282
   (NoArg (\opts -> Ok opts { optEvacMode = True }))
283
   "enable evacuation mode, where the algorithm only moves \
284
   \ instances away from offline and drained nodes",
285
   OptComplNone)
266 286

  
267 287
oExInst :: OptType
268
oExInst = Option "" ["exclude-instances"]
269
          (ReqArg (\ f opts -> Ok opts { optExInst = sepSplit ',' f }) "INSTS")
270
          "exclude given instances from any moves"
288
oExInst =
289
  (Option "" ["exclude-instances"]
290
   (ReqArg (\ f opts -> Ok opts { optExInst = sepSplit ',' f }) "INSTS")
291
   "exclude given instances from any moves",
292
   OptComplManyInstances)
271 293

  
272 294
oExTags :: OptType
273
oExTags = Option "" ["exclusion-tags"]
274
            (ReqArg (\ f opts -> Ok opts { optExTags = Just $ sepSplit ',' f })
275
             "TAG,...") "Enable instance exclusion based on given tag prefix"
295
oExTags =
296
  (Option "" ["exclusion-tags"]
297
   (ReqArg (\ f opts -> Ok opts { optExTags = Just $ sepSplit ',' f })
298
    "TAG,...") "Enable instance exclusion based on given tag prefix",
299
   OptComplString)
276 300

  
277 301
oExecJobs :: OptType
278
oExecJobs = Option "X" ["exec"]
279
             (NoArg (\ opts -> Ok opts { optExecJobs = True}))
280
             "execute the suggested moves via Luxi (only available when using\
281
             \ it for data gathering)"
302
oExecJobs =
303
  (Option "X" ["exec"]
304
   (NoArg (\ opts -> Ok opts { optExecJobs = True}))
305
   "execute the suggested moves via Luxi (only available when using\
306
   \ it for data gathering)",
307
   OptComplNone)
282 308

  
283 309
oGroup :: OptType
284
oGroup = Option "G" ["group"]
285
            (ReqArg (\ f o -> Ok o { optGroup = Just f }) "ID")
286
            "the ID of the group to balance"
310
oGroup =
311
  (Option "G" ["group"]
312
   (ReqArg (\ f o -> Ok o { optGroup = Just f }) "ID")
313
   "the ID of the group to balance",
314
   OptComplOneGroup)
287 315

  
288 316
oIAllocSrc :: OptType
289
oIAllocSrc = Option "I" ["ialloc-src"]
290
             (ReqArg (\ f opts -> Ok opts { optIAllocSrc = Just f }) "FILE")
291
             "Specify an iallocator spec as the cluster data source"
317
oIAllocSrc =
318
  (Option "I" ["ialloc-src"]
319
   (ReqArg (\ f opts -> Ok opts { optIAllocSrc = Just f }) "FILE")
320
   "Specify an iallocator spec as the cluster data source",
321
   OptComplFile)
292 322

  
293 323
oLuxiSocket :: OptType
294
oLuxiSocket = Option "L" ["luxi"]
295
              (OptArg ((\ f opts -> Ok opts { optLuxi = Just f }) .
296
                       fromMaybe Path.defaultLuxiSocket) "SOCKET")
297
              "collect data via Luxi, optionally using the given SOCKET path"
324
oLuxiSocket =
325
  (Option "L" ["luxi"]
326
   (OptArg ((\ f opts -> Ok opts { optLuxi = Just f }) .
327
            fromMaybe Path.defaultLuxiSocket) "SOCKET")
328
   "collect data via Luxi, optionally using the given SOCKET path",
329
   OptComplFile)
298 330

  
299 331
oMachineReadable :: OptType
300
oMachineReadable = Option "" ["machine-readable"]
301
                   (OptArg (\ f opts -> do
302
                     flag <- parseYesNo True f
303
                     return $ opts { optMachineReadable = flag }) "CHOICE")
304
          "enable machine readable output (pass either 'yes' or 'no' to\
305
          \ explicitly control the flag, or without an argument defaults to\
306
          \ yes"
332
oMachineReadable =
333
  (Option "" ["machine-readable"]
334
   (OptArg (\ f opts -> do
335
              flag <- parseYesNo True f
336
              return $ opts { optMachineReadable = flag }) "CHOICE")
337
   "enable machine readable output (pass either 'yes' or 'no' to\
338
   \ explicitly control the flag, or without an argument defaults to\
339
   \ yes",
340
   optComplYesNo)
307 341

  
308 342
oMaxCpu :: OptType
309
oMaxCpu = Option "" ["max-cpu"]
310
          (reqWithConversion (tryRead "parsing max-cpu")
311
           (\mcpu opts -> do
312
              when (mcpu <= 0) $
313
                   fail "Invalid value of the max-cpu ratio,\
314
                        \ expected >0"
315
              return $ opts { optMcpu = Just mcpu }) "RATIO")
316
          "maximum virtual-to-physical cpu ratio for nodes (from 0\
317
          \ upwards) [default read from cluster]"
343
oMaxCpu =
344
  (Option "" ["max-cpu"]
345
   (reqWithConversion (tryRead "parsing max-cpu")
346
    (\mcpu opts -> do
347
       when (mcpu <= 0) $
348
            fail "Invalid value of the max-cpu ratio, expected >0"
349
       return $ opts { optMcpu = Just mcpu }) "RATIO")
350
   "maximum virtual-to-physical cpu ratio for nodes (from 0\
351
   \ upwards) [default read from cluster]",
352
   OptComplNumeric)
318 353

  
319 354
oMaxSolLength :: OptType
320
oMaxSolLength = Option "l" ["max-length"]
321
                (reqWithConversion (tryRead "max solution length")
322
                 (\i opts -> Ok opts { optMaxLength = i }) "N")
323
                "cap the solution at this many balancing or allocation \
324
                \ rounds (useful for very unbalanced clusters or empty \
325
                \ clusters)"
355
oMaxSolLength =
356
  (Option "l" ["max-length"]
357
   (reqWithConversion (tryRead "max solution length")
358
    (\i opts -> Ok opts { optMaxLength = i }) "N")
359
   "cap the solution at this many balancing or allocation \
360
   \ rounds (useful for very unbalanced clusters or empty \
361
   \ clusters)",
362
   OptComplNumeric)
326 363

  
327 364
oMinDisk :: OptType
328
oMinDisk = Option "" ["min-disk"]
329
           (reqWithConversion (tryRead "min free disk space")
330
            (\n opts -> Ok opts { optMdsk = n }) "RATIO")
331
           "minimum free disk space for nodes (between 0 and 1) [0]"
365
oMinDisk =
366
  (Option "" ["min-disk"]
367
   (reqWithConversion (tryRead "min free disk space")
368
    (\n opts -> Ok opts { optMdsk = n }) "RATIO")
369
   "minimum free disk space for nodes (between 0 and 1) [0]",
370
   OptComplNumeric)
332 371

  
333 372
oMinGain :: OptType
334
oMinGain = Option "g" ["min-gain"]
335
           (reqWithConversion (tryRead "min gain")
336
            (\g opts -> Ok opts { optMinGain = g }) "DELTA")
337
            "minimum gain to aim for in a balancing step before giving up"
373
oMinGain =
374
  (Option "g" ["min-gain"]
375
   (reqWithConversion (tryRead "min gain")
376
    (\g opts -> Ok opts { optMinGain = g }) "DELTA")
377
   "minimum gain to aim for in a balancing step before giving up",
378
   OptComplNumeric)
338 379

  
339 380
oMinGainLim :: OptType
340
oMinGainLim = Option "" ["min-gain-limit"]
341
            (reqWithConversion (tryRead "min gain limit")
342
             (\g opts -> Ok opts { optMinGainLim = g }) "SCORE")
343
            "minimum cluster score for which we start checking the min-gain"
381
oMinGainLim =
382
  (Option "" ["min-gain-limit"]
383
   (reqWithConversion (tryRead "min gain limit")
384
    (\g opts -> Ok opts { optMinGainLim = g }) "SCORE")
385
   "minimum cluster score for which we start checking the min-gain",
386
   OptComplNumeric)
344 387

  
345 388
oMinScore :: OptType
346
oMinScore = Option "e" ["min-score"]
347
            (reqWithConversion (tryRead "min score")
348
             (\e opts -> Ok opts { optMinScore = e }) "EPSILON")
349
            "mininum score to aim for"
389
oMinScore =
390
  (Option "e" ["min-score"]
391
   (reqWithConversion (tryRead "min score")
392
    (\e opts -> Ok opts { optMinScore = e }) "EPSILON")
393
   "mininum score to aim for",
394
   OptComplNumeric)
350 395

  
351 396
oNoHeaders :: OptType
352
oNoHeaders = Option "" ["no-headers"]
353
             (NoArg (\ opts -> Ok opts { optNoHeaders = True }))
354
             "do not show a header line"
397
oNoHeaders =
398
  (Option "" ["no-headers"]
399
   (NoArg (\ opts -> Ok opts { optNoHeaders = True }))
400
   "do not show a header line",
401
   OptComplNone)
355 402

  
356 403
oNoSimulation :: OptType
357
oNoSimulation = Option "" ["no-simulation"]
358
                (NoArg (\opts -> Ok opts {optNoSimulation = True}))
359
                "do not perform rebalancing simulation"
404
oNoSimulation =
405
  (Option "" ["no-simulation"]
406
   (NoArg (\opts -> Ok opts {optNoSimulation = True}))
407
   "do not perform rebalancing simulation",
408
   OptComplNone)
360 409

  
361 410
oNodeSim :: OptType
362
oNodeSim = Option "" ["simulate"]
363
            (ReqArg (\ f o -> Ok o { optNodeSim = f:optNodeSim o }) "SPEC")
364
            "simulate an empty cluster, given as\
365
            \ 'alloc_policy,num_nodes,disk,ram,cpu'"
411
oNodeSim =
412
  (Option "" ["simulate"]
413
   (ReqArg (\ f o -> Ok o { optNodeSim = f:optNodeSim o }) "SPEC")
414
   "simulate an empty cluster, given as\
415
   \ 'alloc_policy,num_nodes,disk,ram,cpu'",
416
   OptComplString)
366 417

  
367 418
oOfflineNode :: OptType
368
oOfflineNode = Option "O" ["offline"]
369
               (ReqArg (\ n o -> Ok o { optOffline = n:optOffline o }) "NODE")
370
               "set node as offline"
419
oOfflineNode =
420
  (Option "O" ["offline"]
421
   (ReqArg (\ n o -> Ok o { optOffline = n:optOffline o }) "NODE")
422
   "set node as offline",
423
   OptComplOneNode)
371 424

  
372 425
oOutputDir :: OptType
373
oOutputDir = Option "d" ["output-dir"]
374
             (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
375
             "directory in which to write output files"
426
oOutputDir =
427
  (Option "d" ["output-dir"]
428
   (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
429
   "directory in which to write output files",
430
   OptComplDir)
376 431

  
377 432
oPrintCommands :: OptType
378
oPrintCommands = Option "C" ["print-commands"]
379
                 (OptArg ((\ f opts -> Ok opts { optShowCmds = Just f }) .
380
                          fromMaybe "-")
381
                  "FILE")
382
                 "print the ganeti command list for reaching the solution,\
383
                 \ if an argument is passed then write the commands to a\
384
                 \ file named as such"
433
oPrintCommands =
434
  (Option "C" ["print-commands"]
435
   (OptArg ((\ f opts -> Ok opts { optShowCmds = Just f }) .
436
            fromMaybe "-")
437
    "FILE")
438
   "print the ganeti command list for reaching the solution,\
439
   \ if an argument is passed then write the commands to a\
440
   \ file named as such",
441
   OptComplNone)
385 442

  
386 443
oPrintInsts :: OptType
387
oPrintInsts = Option "" ["print-instances"]
388
              (NoArg (\ opts -> Ok opts { optShowInsts = True }))
389
              "print the final instance map"
444
oPrintInsts =
445
  (Option "" ["print-instances"]
446
   (NoArg (\ opts -> Ok opts { optShowInsts = True }))
447
   "print the final instance map",
448
   OptComplNone)
390 449

  
391 450
oPrintNodes :: OptType
392
oPrintNodes = Option "p" ["print-nodes"]
393
              (OptArg ((\ f opts ->
394
                          let (prefix, realf) = case f of
395
                                                  '+':rest -> (["+"], rest)
396
                                                  _ -> ([], f)
397
                              splitted = prefix ++ sepSplit ',' realf
398
                          in Ok opts { optShowNodes = Just splitted }) .
399
                       fromMaybe []) "FIELDS")
400
              "print the final node list"
451
oPrintNodes =
452
  (Option "p" ["print-nodes"]
453
   (OptArg ((\ f opts ->
454
               let (prefix, realf) = case f of
455
                                       '+':rest -> (["+"], rest)
456
                                       _ -> ([], f)
457
                   splitted = prefix ++ sepSplit ',' realf
458
               in Ok opts { optShowNodes = Just splitted }) .
459
            fromMaybe []) "FIELDS")
460
   "print the final node list",
461
   OptComplNone)
401 462

  
402 463
oQuiet :: OptType
403
oQuiet = Option "q" ["quiet"]
404
         (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts - 1 }))
405
         "decrease the verbosity level"
464
oQuiet =
465
  (Option "q" ["quiet"]
466
   (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts - 1 }))
467
   "decrease the verbosity level",
468
   OptComplNone)
406 469

  
407 470
oRapiMaster :: OptType
408
oRapiMaster = Option "m" ["master"]
409
              (ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
410
              "collect data via RAPI at the given ADDRESS"
471
oRapiMaster =
472
  (Option "m" ["master"]
473
   (ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
474
   "collect data via RAPI at the given ADDRESS",
475
   OptComplHost)
411 476

  
412 477
oSaveCluster :: OptType
413
oSaveCluster = Option "S" ["save"]
414
            (ReqArg (\ f opts -> Ok opts { optSaveCluster = Just f }) "FILE")
415
            "Save cluster state at the end of the processing to FILE"
478
oSaveCluster =
479
  (Option "S" ["save"]
480
   (ReqArg (\ f opts -> Ok opts { optSaveCluster = Just f }) "FILE")
481
   "Save cluster state at the end of the processing to FILE",
482
   OptComplNone)
416 483

  
417 484
oStdSpec :: OptType
418
oStdSpec = Option "" ["standard-alloc"]
419
             (ReqArg (\ inp opts -> do
420
                        tspec <- parseISpecString "standard" inp
421
                        return $ opts { optStdSpec = Just tspec } )
422
              "STDSPEC")
423
             "enable standard specs allocation, given as 'disk,ram,cpu'"
485
oStdSpec =
486
  (Option "" ["standard-alloc"]
487
   (ReqArg (\ inp opts -> do
488
              tspec <- parseISpecString "standard" inp
489
              return $ opts { optStdSpec = Just tspec } )
490
    "STDSPEC")
491
   "enable standard specs allocation, given as 'disk,ram,cpu'",
492
   OptComplString)
424 493

  
425 494
oTieredSpec :: OptType
426
oTieredSpec = Option "" ["tiered-alloc"]
427
             (ReqArg (\ inp opts -> do
428
                        tspec <- parseISpecString "tiered" inp
429
                        return $ opts { optTieredSpec = Just tspec } )
430
              "TSPEC")
431
             "enable tiered specs allocation, given as 'disk,ram,cpu'"
495
oTieredSpec =
496
  (Option "" ["tiered-alloc"]
497
   (ReqArg (\ inp opts -> do
498
              tspec <- parseISpecString "tiered" inp
499
              return $ opts { optTieredSpec = Just tspec } )
500
    "TSPEC")
501
   "enable tiered specs allocation, given as 'disk,ram,cpu'",
502
   OptComplString)
432 503

  
433 504
oVerbose :: OptType
434
oVerbose = Option "v" ["verbose"]
435
           (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts + 1 }))
436
           "increase the verbosity level"
505
oVerbose =
506
  (Option "v" ["verbose"]
507
   (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts + 1 }))
508
   "increase the verbosity level",
509
   OptComplNone)
437 510

  
438 511
-- | Generic options.
439 512
genericOpts :: [GenericOptType Options]

Also available in: Unified diff