Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / CLI.hs @ a69ff623

History | View | Annotate | Download (16.1 kB)

1 209b3711 Iustin Pop
{-| Implementation of command-line functions.
2 209b3711 Iustin Pop
3 209b3711 Iustin Pop
This module holds the common cli-related functions for the binaries,
4 209b3711 Iustin Pop
separated into this module since Utils.hs is used in many other places
5 6ef35e3c Iustin Pop
and this is more IO oriented.
6 209b3711 Iustin Pop
7 209b3711 Iustin Pop
-}
8 209b3711 Iustin Pop
9 e2fa2baf Iustin Pop
{-
10 e2fa2baf Iustin Pop
11 a69ff623 Iustin Pop
Copyright (C) 2009, 2010, 2011 Google Inc.
12 e2fa2baf Iustin Pop
13 e2fa2baf Iustin Pop
This program is free software; you can redistribute it and/or modify
14 e2fa2baf Iustin Pop
it under the terms of the GNU General Public License as published by
15 e2fa2baf Iustin Pop
the Free Software Foundation; either version 2 of the License, or
16 e2fa2baf Iustin Pop
(at your option) any later version.
17 e2fa2baf Iustin Pop
18 e2fa2baf Iustin Pop
This program is distributed in the hope that it will be useful, but
19 e2fa2baf Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
20 e2fa2baf Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 e2fa2baf Iustin Pop
General Public License for more details.
22 e2fa2baf Iustin Pop
23 e2fa2baf Iustin Pop
You should have received a copy of the GNU General Public License
24 e2fa2baf Iustin Pop
along with this program; if not, write to the Free Software
25 e2fa2baf Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 e2fa2baf Iustin Pop
02110-1301, USA.
27 e2fa2baf Iustin Pop
28 e2fa2baf Iustin Pop
-}
29 e2fa2baf Iustin Pop
30 209b3711 Iustin Pop
module Ganeti.HTools.CLI
31 0427285d Iustin Pop
    ( Options(..)
32 0427285d Iustin Pop
    , OptType
33 75d1edf8 Iustin Pop
    , parseOpts
34 e0eb63f0 Iustin Pop
    , shTemplate
35 ba9349b8 Iustin Pop
    , defaultLuxiSocket
36 417f6b50 Iustin Pop
    , maybePrintNodes
37 33e44f0c Iustin Pop
    , maybePrintInsts
38 0427285d Iustin Pop
    -- * The options
39 16c2369c Iustin Pop
    , oDataFile
40 df18fdfe Iustin Pop
    , oDiskMoves
41 df18fdfe Iustin Pop
    , oDynuFile
42 f0f21ec4 Iustin Pop
    , oEvacMode
43 10f396e1 Iustin Pop
    , oExInst
44 df18fdfe Iustin Pop
    , oExTags
45 0df5a1b4 Iustin Pop
    , oExecJobs
46 a423b510 Iustin Pop
    , oGroup
47 0427285d Iustin Pop
    , oIDisk
48 df18fdfe Iustin Pop
    , oIMem
49 0427285d Iustin Pop
    , oINodes
50 df18fdfe Iustin Pop
    , oIVcpus
51 df18fdfe Iustin Pop
    , oLuxiSocket
52 0427285d Iustin Pop
    , oMaxCpu
53 df18fdfe Iustin Pop
    , oMaxSolLength
54 0427285d Iustin Pop
    , oMinDisk
55 4f807a57 Iustin Pop
    , oMinGain
56 4f807a57 Iustin Pop
    , oMinGainLim
57 df18fdfe Iustin Pop
    , oMinScore
58 df18fdfe Iustin Pop
    , oNoHeaders
59 df18fdfe Iustin Pop
    , oNodeSim
60 df18fdfe Iustin Pop
    , oOfflineNode
61 df18fdfe Iustin Pop
    , oOneline
62 df18fdfe Iustin Pop
    , oOutputDir
63 df18fdfe Iustin Pop
    , oPrintCommands
64 df18fdfe Iustin Pop
    , oPrintInsts
65 df18fdfe Iustin Pop
    , oPrintNodes
66 df18fdfe Iustin Pop
    , oQuiet
67 df18fdfe Iustin Pop
    , oRapiMaster
68 02da9d07 Iustin Pop
    , oSaveCluster
69 0427285d Iustin Pop
    , oShowHelp
70 df18fdfe Iustin Pop
    , oShowVer
71 df18fdfe Iustin Pop
    , oTieredSpec
72 df18fdfe Iustin Pop
    , oVerbose
73 209b3711 Iustin Pop
    ) where
74 209b3711 Iustin Pop
75 e8f89bb6 Iustin Pop
import Data.Maybe (fromMaybe)
76 8e445e6d Iustin Pop
import qualified Data.Version
77 8e445e6d Iustin Pop
import Monad
78 209b3711 Iustin Pop
import System.Console.GetOpt
79 209b3711 Iustin Pop
import System.IO
80 209b3711 Iustin Pop
import System.Info
81 209b3711 Iustin Pop
import System
82 e8f89bb6 Iustin Pop
import Text.Printf (printf)
83 209b3711 Iustin Pop
84 209b3711 Iustin Pop
import qualified Ganeti.HTools.Version as Version(version)
85 a69ff623 Iustin Pop
import qualified Ganeti.Constants as C
86 92e32d76 Iustin Pop
import Ganeti.HTools.Types
87 1f9066c0 Iustin Pop
import Ganeti.HTools.Utils
88 fae371cc Iustin Pop
89 8e445e6d Iustin Pop
-- | The default value for the luxi socket
90 8e445e6d Iustin Pop
defaultLuxiSocket :: FilePath
91 a69ff623 Iustin Pop
defaultLuxiSocket = C.masterSocket
92 8e445e6d Iustin Pop
93 0427285d Iustin Pop
-- | Command line options structure.
94 0427285d Iustin Pop
data Options = Options
95 df18fdfe Iustin Pop
    { optDataFile    :: Maybe FilePath -- ^ Path to the cluster data file
96 df18fdfe Iustin Pop
    , optDiskMoves   :: Bool           -- ^ Allow disk moves
97 df18fdfe Iustin Pop
    , optDynuFile    :: Maybe FilePath -- ^ Optional file with dynamic use data
98 f0f21ec4 Iustin Pop
    , optEvacMode    :: Bool           -- ^ Enable evacuation mode
99 10f396e1 Iustin Pop
    , optExInst      :: [String]       -- ^ Instances to be excluded
100 df18fdfe Iustin Pop
    , optExTags      :: Maybe [String] -- ^ Tags to use for exclusion
101 1f9066c0 Iustin Pop
    , optExecJobs    :: Bool           -- ^ Execute the commands via Luxi
102 a423b510 Iustin Pop
    , optGroup       :: Maybe GroupID  -- ^ The UUID of the group to process
103 1f9066c0 Iustin Pop
    , optINodes      :: Int            -- ^ Nodes required for an instance
104 1f9066c0 Iustin Pop
    , optISpec       :: RSpec          -- ^ Requested instance specs
105 df18fdfe Iustin Pop
    , optLuxi        :: Maybe FilePath -- ^ Collect data from Luxi
106 df18fdfe Iustin Pop
    , optMaster      :: String         -- ^ Collect data from RAPI
107 df18fdfe Iustin Pop
    , optMaxLength   :: Int            -- ^ Stop after this many steps
108 1f9066c0 Iustin Pop
    , optMcpu        :: Double         -- ^ Max cpu ratio for nodes
109 1f9066c0 Iustin Pop
    , optMdsk        :: Double         -- ^ Max disk usage ratio for nodes
110 4f807a57 Iustin Pop
    , optMinGain     :: Score          -- ^ Min gain we aim for in a step
111 4f807a57 Iustin Pop
    , optMinGainLim  :: Score          -- ^ Limit below which we apply mingain
112 df18fdfe Iustin Pop
    , optMinScore    :: Score          -- ^ The minimum score we aim for
113 df18fdfe Iustin Pop
    , optNoHeaders   :: Bool           -- ^ Do not show a header line
114 9983063b Iustin Pop
    , optNodeSim     :: [String]       -- ^ Cluster simulation mode
115 df18fdfe Iustin Pop
    , optOffline     :: [String]       -- ^ Names of offline nodes
116 df18fdfe Iustin Pop
    , optOneline     :: Bool           -- ^ Switch output to a single line
117 df18fdfe Iustin Pop
    , optOutPath     :: FilePath       -- ^ Path to the output directory
118 02da9d07 Iustin Pop
    , optSaveCluster :: Maybe FilePath -- ^ Save cluster state to this file
119 df18fdfe Iustin Pop
    , optShowCmds    :: Maybe FilePath -- ^ Whether to show the command list
120 1f9066c0 Iustin Pop
    , optShowHelp    :: Bool           -- ^ Just show the help
121 df18fdfe Iustin Pop
    , optShowInsts   :: Bool           -- ^ Whether to show the instance map
122 df18fdfe Iustin Pop
    , optShowNodes   :: Maybe [String] -- ^ Whether to show node status
123 df18fdfe Iustin Pop
    , optShowVer     :: Bool           -- ^ Just show the program version
124 df18fdfe Iustin Pop
    , optTieredSpec  :: Maybe RSpec    -- ^ Requested specs for tiered mode
125 df18fdfe Iustin Pop
    , optVerbose     :: Int            -- ^ Verbosity level
126 0427285d Iustin Pop
    } deriving Show
127 0427285d Iustin Pop
128 0427285d Iustin Pop
-- | Default values for the command line options.
129 0427285d Iustin Pop
defaultOptions :: Options
130 0427285d Iustin Pop
defaultOptions  = Options
131 df18fdfe Iustin Pop
 { optDataFile    = Nothing
132 df18fdfe Iustin Pop
 , optDiskMoves   = True
133 df18fdfe Iustin Pop
 , optDynuFile    = Nothing
134 f0f21ec4 Iustin Pop
 , optEvacMode    = False
135 10f396e1 Iustin Pop
 , optExInst      = []
136 df18fdfe Iustin Pop
 , optExTags      = Nothing
137 1f9066c0 Iustin Pop
 , optExecJobs    = False
138 a423b510 Iustin Pop
 , optGroup       = Nothing
139 1f9066c0 Iustin Pop
 , optINodes      = 2
140 1f9066c0 Iustin Pop
 , optISpec       = RSpec 1 4096 102400
141 df18fdfe Iustin Pop
 , optLuxi        = Nothing
142 df18fdfe Iustin Pop
 , optMaster      = ""
143 df18fdfe Iustin Pop
 , optMaxLength   = -1
144 f4c0b8c5 Iustin Pop
 , optMcpu        = defVcpuRatio
145 f4c0b8c5 Iustin Pop
 , optMdsk        = defReservedDiskRatio
146 4f807a57 Iustin Pop
 , optMinGain     = 1e-2
147 4f807a57 Iustin Pop
 , optMinGainLim  = 1e-1
148 df18fdfe Iustin Pop
 , optMinScore    = 1e-9
149 df18fdfe Iustin Pop
 , optNoHeaders   = False
150 9983063b Iustin Pop
 , optNodeSim     = []
151 df18fdfe Iustin Pop
 , optOffline     = []
152 df18fdfe Iustin Pop
 , optOneline     = False
153 df18fdfe Iustin Pop
 , optOutPath     = "."
154 02da9d07 Iustin Pop
 , optSaveCluster = Nothing
155 df18fdfe Iustin Pop
 , optShowCmds    = Nothing
156 1f9066c0 Iustin Pop
 , optShowHelp    = False
157 df18fdfe Iustin Pop
 , optShowInsts   = False
158 df18fdfe Iustin Pop
 , optShowNodes   = Nothing
159 df18fdfe Iustin Pop
 , optShowVer     = False
160 df18fdfe Iustin Pop
 , optTieredSpec  = Nothing
161 df18fdfe Iustin Pop
 , optVerbose     = 1
162 0427285d Iustin Pop
 }
163 0427285d Iustin Pop
164 0427285d Iustin Pop
-- | Abrreviation for the option type
165 2f567ac0 Iustin Pop
type OptType = OptDescr (Options -> Result Options)
166 0427285d Iustin Pop
167 16c2369c Iustin Pop
oDataFile :: OptType
168 16c2369c Iustin Pop
oDataFile = Option "t" ["text-data"]
169 16c2369c Iustin Pop
            (ReqArg (\ f o -> Ok o { optDataFile = Just f }) "FILE")
170 16c2369c Iustin Pop
            "the cluster data FILE"
171 0427285d Iustin Pop
172 df18fdfe Iustin Pop
oDiskMoves :: OptType
173 df18fdfe Iustin Pop
oDiskMoves = Option "" ["no-disk-moves"]
174 df18fdfe Iustin Pop
             (NoArg (\ opts -> Ok opts { optDiskMoves = False}))
175 df18fdfe Iustin Pop
             "disallow disk moves from the list of allowed instance changes,\
176 df18fdfe Iustin Pop
             \ thus allowing only the 'cheap' failover/migrate operations"
177 b2278348 Iustin Pop
178 df18fdfe Iustin Pop
oDynuFile :: OptType
179 df18fdfe Iustin Pop
oDynuFile = Option "U" ["dynu-file"]
180 df18fdfe Iustin Pop
            (ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
181 df18fdfe Iustin Pop
            "Import dynamic utilisation data from the given FILE"
182 0427285d Iustin Pop
183 f0f21ec4 Iustin Pop
oEvacMode :: OptType
184 f0f21ec4 Iustin Pop
oEvacMode = Option "E" ["evac-mode"]
185 f0f21ec4 Iustin Pop
            (NoArg (\opts -> Ok opts { optEvacMode = True }))
186 f0f21ec4 Iustin Pop
            "enable evacuation mode, where the algorithm only moves \
187 f0f21ec4 Iustin Pop
            \ instances away from offline and drained nodes"
188 f0f21ec4 Iustin Pop
189 10f396e1 Iustin Pop
oExInst :: OptType
190 10f396e1 Iustin Pop
oExInst = Option "" ["exclude-instances"]
191 10f396e1 Iustin Pop
          (ReqArg (\ f opts -> Ok opts { optExInst = sepSplit ',' f }) "INSTS")
192 10f396e1 Iustin Pop
          "exclude given instances  from any moves"
193 10f396e1 Iustin Pop
194 df18fdfe Iustin Pop
oExTags :: OptType
195 df18fdfe Iustin Pop
oExTags = Option "" ["exclusion-tags"]
196 df18fdfe Iustin Pop
            (ReqArg (\ f opts -> Ok opts { optExTags = Just $ sepSplit ',' f })
197 df18fdfe Iustin Pop
             "TAG,...") "Enable instance exclusion based on given tag prefix"
198 0427285d Iustin Pop
199 0df5a1b4 Iustin Pop
oExecJobs :: OptType
200 0df5a1b4 Iustin Pop
oExecJobs = Option "X" ["exec"]
201 2f567ac0 Iustin Pop
             (NoArg (\ opts -> Ok opts { optExecJobs = True}))
202 0df5a1b4 Iustin Pop
             "execute the suggested moves via Luxi (only available when using\
203 71e635f3 René Nussbaumer
             \ it for data gathering)"
204 0df5a1b4 Iustin Pop
205 a423b510 Iustin Pop
oGroup :: OptType
206 a423b510 Iustin Pop
oGroup = Option "G" ["group"]
207 a423b510 Iustin Pop
            (ReqArg (\ f o -> Ok o { optGroup = Just f }) "ID")
208 a423b510 Iustin Pop
            "the ID of the group to balance"
209 a423b510 Iustin Pop
210 df18fdfe Iustin Pop
oIDisk :: OptType
211 df18fdfe Iustin Pop
oIDisk = Option "" ["disk"]
212 df18fdfe Iustin Pop
         (ReqArg (\ d opts ->
213 df18fdfe Iustin Pop
                     let ospec = optISpec opts
214 df18fdfe Iustin Pop
                         nspec = ospec { rspecDsk = read d }
215 df18fdfe Iustin Pop
                     in Ok opts { optISpec = nspec }) "DISK")
216 df18fdfe Iustin Pop
         "disk size for instances"
217 0427285d Iustin Pop
218 0427285d Iustin Pop
oIMem :: OptType
219 0427285d Iustin Pop
oIMem = Option "" ["memory"]
220 1f9066c0 Iustin Pop
        (ReqArg (\ m opts ->
221 1f9066c0 Iustin Pop
                     let ospec = optISpec opts
222 1f9066c0 Iustin Pop
                         nspec = ospec { rspecMem = read m }
223 1f9066c0 Iustin Pop
                     in Ok opts { optISpec = nspec }) "MEMORY")
224 0427285d Iustin Pop
        "memory size for instances"
225 0427285d Iustin Pop
226 df18fdfe Iustin Pop
oINodes :: OptType
227 df18fdfe Iustin Pop
oINodes = Option "" ["req-nodes"]
228 df18fdfe Iustin Pop
          (ReqArg (\ n opts -> Ok opts { optINodes = read n }) "NODES")
229 df18fdfe Iustin Pop
          "number of nodes for the new instances (1=plain, 2=mirrored)"
230 0427285d Iustin Pop
231 0427285d Iustin Pop
oIVcpus :: OptType
232 0427285d Iustin Pop
oIVcpus = Option "" ["vcpus"]
233 1f9066c0 Iustin Pop
          (ReqArg (\ p opts ->
234 1f9066c0 Iustin Pop
                       let ospec = optISpec opts
235 1f9066c0 Iustin Pop
                           nspec = ospec { rspecCpu = read p }
236 1f9066c0 Iustin Pop
                       in Ok opts { optISpec = nspec }) "NUM")
237 0427285d Iustin Pop
          "number of virtual cpus for instances"
238 0427285d Iustin Pop
239 df18fdfe Iustin Pop
oLuxiSocket :: OptType
240 df18fdfe Iustin Pop
oLuxiSocket = Option "L" ["luxi"]
241 df18fdfe Iustin Pop
              (OptArg ((\ f opts -> Ok opts { optLuxi = Just f }) .
242 df18fdfe Iustin Pop
                       fromMaybe defaultLuxiSocket) "SOCKET")
243 df18fdfe Iustin Pop
              "collect data via Luxi, optionally using the given SOCKET path"
244 0427285d Iustin Pop
245 0427285d Iustin Pop
oMaxCpu :: OptType
246 0427285d Iustin Pop
oMaxCpu = Option "" ["max-cpu"]
247 2f567ac0 Iustin Pop
          (ReqArg (\ n opts -> Ok opts { optMcpu = read n }) "RATIO")
248 f4c0b8c5 Iustin Pop
          "maximum virtual-to-physical cpu ratio for nodes (from 1\
249 f4c0b8c5 Iustin Pop
          \ upwards) [64]"
250 0427285d Iustin Pop
251 df18fdfe Iustin Pop
oMaxSolLength :: OptType
252 df18fdfe Iustin Pop
oMaxSolLength = Option "l" ["max-length"]
253 df18fdfe Iustin Pop
                (ReqArg (\ i opts -> Ok opts { optMaxLength = read i }) "N")
254 df18fdfe Iustin Pop
                "cap the solution at this many moves (useful for very\
255 df18fdfe Iustin Pop
                \ unbalanced clusters)"
256 df18fdfe Iustin Pop
257 0427285d Iustin Pop
oMinDisk :: OptType
258 0427285d Iustin Pop
oMinDisk = Option "" ["min-disk"]
259 2f567ac0 Iustin Pop
           (ReqArg (\ n opts -> Ok opts { optMdsk = read n }) "RATIO")
260 f4c0b8c5 Iustin Pop
           "minimum free disk space for nodes (between 0 and 1) [0]"
261 0427285d Iustin Pop
262 4f807a57 Iustin Pop
oMinGain :: OptType
263 4f807a57 Iustin Pop
oMinGain = Option "g" ["min-gain"]
264 4f807a57 Iustin Pop
            (ReqArg (\ g opts -> Ok opts { optMinGain = read g }) "DELTA")
265 4f807a57 Iustin Pop
            "minimum gain to aim for in a balancing step before giving up"
266 4f807a57 Iustin Pop
267 4f807a57 Iustin Pop
oMinGainLim :: OptType
268 4f807a57 Iustin Pop
oMinGainLim = Option "" ["min-gain-limit"]
269 4f807a57 Iustin Pop
            (ReqArg (\ g opts -> Ok opts { optMinGainLim = read g }) "SCORE")
270 4f807a57 Iustin Pop
            "minimum cluster score for which we start checking the min-gain"
271 4f807a57 Iustin Pop
272 df18fdfe Iustin Pop
oMinScore :: OptType
273 df18fdfe Iustin Pop
oMinScore = Option "e" ["min-score"]
274 df18fdfe Iustin Pop
            (ReqArg (\ e opts -> Ok opts { optMinScore = read e }) "EPSILON")
275 4f807a57 Iustin Pop
            "mininum score to aim for"
276 c0501c69 Iustin Pop
277 df18fdfe Iustin Pop
oNoHeaders :: OptType
278 df18fdfe Iustin Pop
oNoHeaders = Option "" ["no-headers"]
279 df18fdfe Iustin Pop
             (NoArg (\ opts -> Ok opts { optNoHeaders = True }))
280 df18fdfe Iustin Pop
             "do not show a header line"
281 4f83a560 Iustin Pop
282 df18fdfe Iustin Pop
oNodeSim :: OptType
283 df18fdfe Iustin Pop
oNodeSim = Option "" ["simulate"]
284 9983063b Iustin Pop
            (ReqArg (\ f o -> Ok o { optNodeSim = f:optNodeSim o }) "SPEC")
285 df18fdfe Iustin Pop
            "simulate an empty cluster, given as 'num_nodes,disk,ram,cpu'"
286 df18fdfe Iustin Pop
287 df18fdfe Iustin Pop
oOfflineNode :: OptType
288 df18fdfe Iustin Pop
oOfflineNode = Option "O" ["offline"]
289 df18fdfe Iustin Pop
               (ReqArg (\ n o -> Ok o { optOffline = n:optOffline o }) "NODE")
290 df18fdfe Iustin Pop
               "set node as offline"
291 df18fdfe Iustin Pop
292 df18fdfe Iustin Pop
oOneline :: OptType
293 df18fdfe Iustin Pop
oOneline = Option "o" ["oneline"]
294 df18fdfe Iustin Pop
           (NoArg (\ opts -> Ok opts { optOneline = True }))
295 df18fdfe Iustin Pop
           "print the ganeti command list for reaching the solution"
296 df18fdfe Iustin Pop
297 df18fdfe Iustin Pop
oOutputDir :: OptType
298 df18fdfe Iustin Pop
oOutputDir = Option "d" ["output-dir"]
299 df18fdfe Iustin Pop
             (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
300 df18fdfe Iustin Pop
             "directory in which to write output files"
301 df18fdfe Iustin Pop
302 df18fdfe Iustin Pop
oPrintCommands :: OptType
303 df18fdfe Iustin Pop
oPrintCommands = Option "C" ["print-commands"]
304 df18fdfe Iustin Pop
                 (OptArg ((\ f opts -> Ok opts { optShowCmds = Just f }) .
305 df18fdfe Iustin Pop
                          fromMaybe "-")
306 df18fdfe Iustin Pop
                  "FILE")
307 df18fdfe Iustin Pop
                 "print the ganeti command list for reaching the solution,\
308 df18fdfe Iustin Pop
                 \ if an argument is passed then write the commands to a\
309 df18fdfe Iustin Pop
                 \ file named as such"
310 df18fdfe Iustin Pop
311 df18fdfe Iustin Pop
oPrintInsts :: OptType
312 df18fdfe Iustin Pop
oPrintInsts = Option "" ["print-instances"]
313 df18fdfe Iustin Pop
              (NoArg (\ opts -> Ok opts { optShowInsts = True }))
314 df18fdfe Iustin Pop
              "print the final instance map"
315 df18fdfe Iustin Pop
316 df18fdfe Iustin Pop
oPrintNodes :: OptType
317 df18fdfe Iustin Pop
oPrintNodes = Option "p" ["print-nodes"]
318 df18fdfe Iustin Pop
              (OptArg ((\ f opts ->
319 6dfa04fd Iustin Pop
                            let (prefix, realf) = case f of
320 6dfa04fd Iustin Pop
                                  '+':rest -> (["+"], rest)
321 6dfa04fd Iustin Pop
                                  _ -> ([], f)
322 6dfa04fd Iustin Pop
                                splitted = prefix ++ sepSplit ',' realf
323 df18fdfe Iustin Pop
                            in Ok opts { optShowNodes = Just splitted }) .
324 df18fdfe Iustin Pop
                       fromMaybe []) "FIELDS")
325 df18fdfe Iustin Pop
              "print the final node list"
326 df18fdfe Iustin Pop
327 df18fdfe Iustin Pop
oQuiet :: OptType
328 df18fdfe Iustin Pop
oQuiet = Option "q" ["quiet"]
329 df18fdfe Iustin Pop
         (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts - 1 }))
330 df18fdfe Iustin Pop
         "decrease the verbosity level"
331 df18fdfe Iustin Pop
332 df18fdfe Iustin Pop
oRapiMaster :: OptType
333 df18fdfe Iustin Pop
oRapiMaster = Option "m" ["master"]
334 df18fdfe Iustin Pop
              (ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
335 df18fdfe Iustin Pop
              "collect data via RAPI at the given ADDRESS"
336 df18fdfe Iustin Pop
337 02da9d07 Iustin Pop
oSaveCluster :: OptType
338 02da9d07 Iustin Pop
oSaveCluster = Option "S" ["save"]
339 02da9d07 Iustin Pop
            (ReqArg (\ f opts -> Ok opts { optSaveCluster = Just f }) "FILE")
340 02da9d07 Iustin Pop
            "Save cluster state at the end of the processing to FILE"
341 02da9d07 Iustin Pop
342 df18fdfe Iustin Pop
oShowHelp :: OptType
343 df18fdfe Iustin Pop
oShowHelp = Option "h" ["help"]
344 df18fdfe Iustin Pop
            (NoArg (\ opts -> Ok opts { optShowHelp = True}))
345 df18fdfe Iustin Pop
            "show help"
346 df18fdfe Iustin Pop
347 df18fdfe Iustin Pop
oShowVer :: OptType
348 df18fdfe Iustin Pop
oShowVer = Option "V" ["version"]
349 df18fdfe Iustin Pop
           (NoArg (\ opts -> Ok opts { optShowVer = True}))
350 df18fdfe Iustin Pop
           "show the version of the program"
351 0f15cc76 Iustin Pop
352 1f9066c0 Iustin Pop
oTieredSpec :: OptType
353 1f9066c0 Iustin Pop
oTieredSpec = Option "" ["tiered-alloc"]
354 1f9066c0 Iustin Pop
             (ReqArg (\ inp opts -> do
355 1f9066c0 Iustin Pop
                          let sp = sepSplit ',' inp
356 1f9066c0 Iustin Pop
                          prs <- mapM (tryRead "tiered specs") sp
357 1f9066c0 Iustin Pop
                          tspec <-
358 1f9066c0 Iustin Pop
                              case prs of
359 7f4e37f0 Iustin Pop
                                [dsk, ram, cpu] -> return $ RSpec cpu ram dsk
360 03c6d8fa Iustin Pop
                                _ -> Bad $ "Invalid specification: " ++ inp ++
361 03c6d8fa Iustin Pop
                                     ", expected disk,ram,cpu"
362 1f9066c0 Iustin Pop
                          return $ opts { optTieredSpec = Just tspec } )
363 1f9066c0 Iustin Pop
              "TSPEC")
364 7f4e37f0 Iustin Pop
             "enable tiered specs allocation, given as 'disk,ram,cpu'"
365 1f9066c0 Iustin Pop
366 df18fdfe Iustin Pop
oVerbose :: OptType
367 df18fdfe Iustin Pop
oVerbose = Option "v" ["verbose"]
368 df18fdfe Iustin Pop
           (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts + 1 }))
369 df18fdfe Iustin Pop
           "increase the verbosity level"
370 fae371cc Iustin Pop
371 78694255 Iustin Pop
-- | Usage info
372 0427285d Iustin Pop
usageHelp :: String -> [OptType] -> String
373 9f6dcdea Iustin Pop
usageHelp progname =
374 78694255 Iustin Pop
    usageInfo (printf "%s %s\nUsage: %s [OPTION...]"
375 9f6dcdea Iustin Pop
               progname Version.version progname)
376 78694255 Iustin Pop
377 209b3711 Iustin Pop
-- | Command line parser, using the 'options' structure.
378 0427285d Iustin Pop
parseOpts :: [String]               -- ^ The command line arguments
379 0427285d Iustin Pop
          -> String                 -- ^ The program name
380 0427285d Iustin Pop
          -> [OptType]              -- ^ The supported command line options
381 0427285d Iustin Pop
          -> IO (Options, [String]) -- ^ The resulting options and leftover
382 0427285d Iustin Pop
                                    -- arguments
383 0427285d Iustin Pop
parseOpts argv progname options =
384 209b3711 Iustin Pop
    case getOpt Permute options argv of
385 209b3711 Iustin Pop
      (o, n, []) ->
386 209b3711 Iustin Pop
          do
387 2f567ac0 Iustin Pop
            let (pr, args) = (foldM (flip id) defaultOptions o, n)
388 2f567ac0 Iustin Pop
            po <- (case pr of
389 2f567ac0 Iustin Pop
                     Bad msg -> do
390 2f567ac0 Iustin Pop
                       hPutStrLn stderr "Error while parsing command\
391 2f567ac0 Iustin Pop
                                        \line arguments:"
392 2f567ac0 Iustin Pop
                       hPutStrLn stderr msg
393 2f567ac0 Iustin Pop
                       exitWith $ ExitFailure 1
394 2f567ac0 Iustin Pop
                     Ok val -> return val)
395 0427285d Iustin Pop
            when (optShowHelp po) $ do
396 78694255 Iustin Pop
              putStr $ usageHelp progname options
397 209b3711 Iustin Pop
              exitWith ExitSuccess
398 0427285d Iustin Pop
            when (optShowVer po) $ do
399 75d1edf8 Iustin Pop
              printf "%s %s\ncompiled with %s %s\nrunning on %s %s\n"
400 75d1edf8 Iustin Pop
                     progname Version.version
401 75d1edf8 Iustin Pop
                     compilerName (Data.Version.showVersion compilerVersion)
402 c939b58e Iustin Pop
                     os arch :: IO ()
403 75d1edf8 Iustin Pop
              exitWith ExitSuccess
404 2f567ac0 Iustin Pop
            return (po, args)
405 f723de38 Iustin Pop
      (_, _, errs) -> do
406 f723de38 Iustin Pop
        hPutStrLn stderr $ "Command line error: "  ++ concat errs
407 f723de38 Iustin Pop
        hPutStrLn stderr $ usageHelp progname options
408 f723de38 Iustin Pop
        exitWith $ ExitFailure 2
409 209b3711 Iustin Pop
410 9188aeef Iustin Pop
-- | A shell script template for autogenerated scripts.
411 e0eb63f0 Iustin Pop
shTemplate :: String
412 e0eb63f0 Iustin Pop
shTemplate =
413 e0eb63f0 Iustin Pop
    printf "#!/bin/sh\n\n\
414 e0eb63f0 Iustin Pop
           \# Auto-generated script for executing cluster rebalancing\n\n\
415 e0eb63f0 Iustin Pop
           \# To stop, touch the file /tmp/stop-htools\n\n\
416 e0eb63f0 Iustin Pop
           \set -e\n\n\
417 e0eb63f0 Iustin Pop
           \check() {\n\
418 e0eb63f0 Iustin Pop
           \  if [ -f /tmp/stop-htools ]; then\n\
419 e0eb63f0 Iustin Pop
           \    echo 'Stop requested, exiting'\n\
420 e0eb63f0 Iustin Pop
           \    exit 0\n\
421 e0eb63f0 Iustin Pop
           \  fi\n\
422 e0eb63f0 Iustin Pop
           \}\n\n"
423 417f6b50 Iustin Pop
424 417f6b50 Iustin Pop
-- | Optionally print the node list.
425 417f6b50 Iustin Pop
maybePrintNodes :: Maybe [String]       -- ^ The field list
426 417f6b50 Iustin Pop
                -> String               -- ^ Informational message
427 417f6b50 Iustin Pop
                -> ([String] -> String) -- ^ Function to generate the listing
428 417f6b50 Iustin Pop
                -> IO ()
429 417f6b50 Iustin Pop
maybePrintNodes Nothing _ _ = return ()
430 417f6b50 Iustin Pop
maybePrintNodes (Just fields) msg fn = do
431 417f6b50 Iustin Pop
  hPutStrLn stderr ""
432 417f6b50 Iustin Pop
  hPutStrLn stderr (msg ++ " status:")
433 417f6b50 Iustin Pop
  hPutStrLn stderr $ fn fields
434 33e44f0c Iustin Pop
435 33e44f0c Iustin Pop
436 33e44f0c Iustin Pop
-- | Optionally print the instance list.
437 33e44f0c Iustin Pop
maybePrintInsts :: Bool   -- ^ Whether to print the instance list
438 33e44f0c Iustin Pop
                -> String -- ^ Type of the instance map (e.g. initial)
439 33e44f0c Iustin Pop
                -> String -- ^ The instance data
440 33e44f0c Iustin Pop
                -> IO ()
441 33e44f0c Iustin Pop
maybePrintInsts do_print msg instdata =
442 33e44f0c Iustin Pop
  when do_print $ do
443 33e44f0c Iustin Pop
    hPutStrLn stderr ""
444 33e44f0c Iustin Pop
    hPutStrLn stderr $ msg ++ " instance map:"
445 33e44f0c Iustin Pop
    hPutStr stderr instdata