Introduce a class for CLI options
[ganeti-local] / Ganeti / HTools / CLI.hs
1 {-| Implementation of command-line functions.
2
3 This module holds the common cli-related functions for the binaries,
4 separated into this module since Utils.hs is used in many other places
5 and this is more IO oriented.
6
7 -}
8
9 module Ganeti.HTools.CLI
10     ( CLIOptions(..)
11     , parseOpts
12     , parseEnv
13     , shTemplate
14     ) where
15
16 import System.Console.GetOpt
17 import System.Posix.Env
18 import System.IO
19 import System.Info
20 import System
21 import Monad
22 import Text.Printf (printf)
23 import qualified Data.Version
24
25 import qualified Ganeti.HTools.Version as Version(version)
26
27 -- | Class for types which support show help and show version
28 class CLIOptions a where
29     showHelp    :: a -> Bool
30     showVersion :: a -> Bool
31
32 -- | Command line parser, using the 'options' structure.
33 parseOpts :: (CLIOptions b) =>
34              [String]            -- ^ The command line arguments
35           -> String              -- ^ The program name
36           -> [OptDescr (b -> b)] -- ^ The supported command line options
37           -> b                   -- ^ The default options record
38           -> IO (b, [String])    -- ^ The resulting options a leftover
39                                  -- arguments
40 parseOpts argv progname options defaultOptions =
41     case getOpt Permute options argv of
42       (o, n, []) ->
43           do
44             let resu@(po, _) = (foldl (flip id) defaultOptions o, n)
45             when (showHelp po) $ do
46               putStr $ usageInfo header options
47               exitWith ExitSuccess
48             when (showVersion po) $ do
49               printf "%s %s\ncompiled with %s %s\nrunning on %s %s\n"
50                      progname Version.version
51                      compilerName (Data.Version.showVersion compilerVersion)
52                      os arch
53               exitWith ExitSuccess
54             return resu
55       (_, _, errs) ->
56           ioError (userError (concat errs ++ usageInfo header options))
57       where header = printf "%s %s\nUsage: %s [OPTION...]"
58                      progname Version.version progname
59
60 -- | Parse the environment and return the node/instance names.
61 -- This also hardcodes here the default node/instance file names.
62 parseEnv :: () -> IO (String, String)
63 parseEnv () = do
64   a <- getEnvDefault "HTOOLS_NODES" "nodes"
65   b <- getEnvDefault "HTOOLS_INSTANCES" "instances"
66   return (a, b)
67
68 -- | A shell script template for autogenerated scripts
69 shTemplate :: String
70 shTemplate =
71     printf "#!/bin/sh\n\n\
72            \# Auto-generated script for executing cluster rebalancing\n\n\
73            \# To stop, touch the file /tmp/stop-htools\n\n\
74            \set -e\n\n\
75            \check() {\n\
76            \  if [ -f /tmp/stop-htools ]; then\n\
77            \    echo 'Stop requested, exiting'\n\
78            \    exit 0\n\
79            \  fi\n\
80            \}\n\n"