Statistics
| Branch: | Tag: | Revision:

root / Ganeti / HTools / CLI.hs @ 2f567ac0

History | View | Annotate | Download (12 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 e2fa2baf Iustin Pop
Copyright (C) 2009 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 0427285d Iustin Pop
    -- * The options
36 0427285d Iustin Pop
    , oPrintNodes
37 507fda3f Iustin Pop
    , oPrintInsts
38 0427285d Iustin Pop
    , oPrintCommands
39 0427285d Iustin Pop
    , oOneline
40 0427285d Iustin Pop
    , oNoHeaders
41 0427285d Iustin Pop
    , oOutputDir
42 0427285d Iustin Pop
    , oNodeFile
43 0427285d Iustin Pop
    , oInstFile
44 b2278348 Iustin Pop
    , oNodeSim
45 0427285d Iustin Pop
    , oRapiMaster
46 0427285d Iustin Pop
    , oLuxiSocket
47 0df5a1b4 Iustin Pop
    , oExecJobs
48 0427285d Iustin Pop
    , oMaxSolLength
49 0427285d Iustin Pop
    , oVerbose
50 0427285d Iustin Pop
    , oQuiet
51 0427285d Iustin Pop
    , oOfflineNode
52 0427285d Iustin Pop
    , oMinScore
53 0427285d Iustin Pop
    , oIMem
54 0427285d Iustin Pop
    , oIDisk
55 0427285d Iustin Pop
    , oIVcpus
56 0427285d Iustin Pop
    , oINodes
57 0427285d Iustin Pop
    , oMaxCpu
58 0427285d Iustin Pop
    , oMinDisk
59 c0501c69 Iustin Pop
    , oDiskMoves
60 4f83a560 Iustin Pop
    , oDynuFile
61 0427285d Iustin Pop
    , oShowVer
62 0427285d Iustin Pop
    , oShowHelp
63 209b3711 Iustin Pop
    ) where
64 209b3711 Iustin Pop
65 e8f89bb6 Iustin Pop
import Data.Maybe (fromMaybe)
66 8e445e6d Iustin Pop
import qualified Data.Version
67 8e445e6d Iustin Pop
import Monad
68 209b3711 Iustin Pop
import System.Console.GetOpt
69 209b3711 Iustin Pop
import System.IO
70 209b3711 Iustin Pop
import System.Info
71 209b3711 Iustin Pop
import System
72 e8f89bb6 Iustin Pop
import Text.Printf (printf)
73 209b3711 Iustin Pop
74 209b3711 Iustin Pop
import qualified Ganeti.HTools.Version as Version(version)
75 92e32d76 Iustin Pop
import Ganeti.HTools.Types
76 fae371cc Iustin Pop
77 8e445e6d Iustin Pop
-- | The default value for the luxi socket
78 8e445e6d Iustin Pop
defaultLuxiSocket :: FilePath
79 8e445e6d Iustin Pop
defaultLuxiSocket = "/var/run/ganeti/socket/ganeti-master"
80 8e445e6d Iustin Pop
81 0427285d Iustin Pop
-- | Command line options structure.
82 0427285d Iustin Pop
data Options = Options
83 0427285d Iustin Pop
    { optShowNodes :: Bool           -- ^ Whether to show node status
84 507fda3f Iustin Pop
    , optShowInsts :: Bool           -- ^ Whether to show the instance map
85 0427285d Iustin Pop
    , optShowCmds  :: Maybe FilePath -- ^ Whether to show the command list
86 0427285d Iustin Pop
    , optOneline   :: Bool           -- ^ Switch output to a single line
87 0427285d Iustin Pop
    , optOutPath   :: FilePath       -- ^ Path to the output directory
88 0427285d Iustin Pop
    , optNoHeaders :: Bool           -- ^ Do not show a header line
89 0427285d Iustin Pop
    , optNodeFile  :: FilePath       -- ^ Path to the nodes file
90 0427285d Iustin Pop
    , optNodeSet   :: Bool           -- ^ The nodes have been set by options
91 0427285d Iustin Pop
    , optInstFile  :: FilePath       -- ^ Path to the instances file
92 0427285d Iustin Pop
    , optInstSet   :: Bool           -- ^ The insts have been set by options
93 b2278348 Iustin Pop
    , optNodeSim   :: Maybe String   -- ^ Cluster simulation mode
94 0427285d Iustin Pop
    , optMaxLength :: Int            -- ^ Stop after this many steps
95 0427285d Iustin Pop
    , optMaster    :: String         -- ^ Collect data from RAPI
96 0427285d Iustin Pop
    , optLuxi      :: Maybe FilePath -- ^ Collect data from Luxi
97 0df5a1b4 Iustin Pop
    , optExecJobs  :: Bool           -- ^ Execute the commands via Luxi
98 0427285d Iustin Pop
    , optOffline   :: [String]       -- ^ Names of offline nodes
99 0427285d Iustin Pop
    , optIMem      :: Int            -- ^ Instance memory
100 0427285d Iustin Pop
    , optIDsk      :: Int            -- ^ Instance disk
101 0427285d Iustin Pop
    , optIVCPUs    :: Int            -- ^ Instance VCPUs
102 0427285d Iustin Pop
    , optINodes    :: Int            -- ^ Nodes required for an instance
103 92e32d76 Iustin Pop
    , optMinScore  :: Score          -- ^ The minimum score we aim for
104 0427285d Iustin Pop
    , optMcpu      :: Double         -- ^ Max cpu ratio for nodes
105 0427285d Iustin Pop
    , optMdsk      :: Double         -- ^ Max disk usage ratio for nodes
106 c0501c69 Iustin Pop
    , optDiskMoves :: Bool           -- ^ Allow disk moves
107 4f83a560 Iustin Pop
    , optDynuFile  :: Maybe FilePath -- ^ Optional file with dynamic use data
108 0427285d Iustin Pop
    , optVerbose   :: Int            -- ^ Verbosity level
109 0427285d Iustin Pop
    , optShowVer   :: Bool           -- ^ Just show the program version
110 0427285d Iustin Pop
    , optShowHelp  :: Bool           -- ^ Just show the help
111 0427285d Iustin Pop
    } deriving Show
112 0427285d Iustin Pop
113 0427285d Iustin Pop
-- | Default values for the command line options.
114 0427285d Iustin Pop
defaultOptions :: Options
115 0427285d Iustin Pop
defaultOptions  = Options
116 0427285d Iustin Pop
 { optShowNodes = False
117 507fda3f Iustin Pop
 , optShowInsts = False
118 0427285d Iustin Pop
 , optShowCmds  = Nothing
119 0427285d Iustin Pop
 , optOneline   = False
120 0427285d Iustin Pop
 , optNoHeaders = False
121 0427285d Iustin Pop
 , optOutPath   = "."
122 0427285d Iustin Pop
 , optNodeFile  = "nodes"
123 0427285d Iustin Pop
 , optNodeSet   = False
124 0427285d Iustin Pop
 , optInstFile  = "instances"
125 0427285d Iustin Pop
 , optInstSet   = False
126 b2278348 Iustin Pop
 , optNodeSim   = Nothing
127 0427285d Iustin Pop
 , optMaxLength = -1
128 0427285d Iustin Pop
 , optMaster    = ""
129 0427285d Iustin Pop
 , optLuxi      = Nothing
130 0df5a1b4 Iustin Pop
 , optExecJobs  = False
131 0427285d Iustin Pop
 , optOffline   = []
132 0427285d Iustin Pop
 , optIMem      = 4096
133 0427285d Iustin Pop
 , optIDsk      = 102400
134 0427285d Iustin Pop
 , optIVCPUs    = 1
135 0427285d Iustin Pop
 , optINodes    = 2
136 0427285d Iustin Pop
 , optMinScore  = 1e-9
137 0427285d Iustin Pop
 , optMcpu      = -1
138 0427285d Iustin Pop
 , optMdsk      = -1
139 c0501c69 Iustin Pop
 , optDiskMoves = True
140 4f83a560 Iustin Pop
 , optDynuFile  = Nothing
141 0427285d Iustin Pop
 , optVerbose   = 1
142 0427285d Iustin Pop
 , optShowVer   = False
143 0427285d Iustin Pop
 , optShowHelp  = False
144 0427285d Iustin Pop
 }
145 0427285d Iustin Pop
146 0427285d Iustin Pop
-- | Abrreviation for the option type
147 2f567ac0 Iustin Pop
type OptType = OptDescr (Options -> Result Options)
148 0427285d Iustin Pop
149 0427285d Iustin Pop
oPrintNodes :: OptType
150 0427285d Iustin Pop
oPrintNodes = Option "p" ["print-nodes"]
151 2f567ac0 Iustin Pop
              (NoArg (\ opts -> Ok opts { optShowNodes = True }))
152 0427285d Iustin Pop
              "print the final node list"
153 0427285d Iustin Pop
154 507fda3f Iustin Pop
oPrintInsts :: OptType
155 507fda3f Iustin Pop
oPrintInsts = Option "" ["print-instances"]
156 2f567ac0 Iustin Pop
              (NoArg (\ opts -> Ok opts { optShowInsts = True }))
157 507fda3f Iustin Pop
              "print the final instance map"
158 507fda3f Iustin Pop
159 0427285d Iustin Pop
oPrintCommands :: OptType
160 0427285d Iustin Pop
oPrintCommands = Option "C" ["print-commands"]
161 2f567ac0 Iustin Pop
                 (OptArg ((\ f opts -> Ok opts { optShowCmds = Just f }) .
162 0427285d Iustin Pop
                          fromMaybe "-")
163 0427285d Iustin Pop
                  "FILE")
164 0427285d Iustin Pop
                 "print the ganeti command list for reaching the solution,\
165 0427285d Iustin Pop
                 \ if an argument is passed then write the commands to a\
166 0427285d Iustin Pop
                 \ file named as such"
167 0427285d Iustin Pop
168 0427285d Iustin Pop
oOneline :: OptType
169 0427285d Iustin Pop
oOneline = Option "o" ["oneline"]
170 2f567ac0 Iustin Pop
           (NoArg (\ opts -> Ok opts { optOneline = True }))
171 0427285d Iustin Pop
           "print the ganeti command list for reaching the solution"
172 0427285d Iustin Pop
173 0427285d Iustin Pop
oNoHeaders :: OptType
174 0427285d Iustin Pop
oNoHeaders = Option "" ["no-headers"]
175 2f567ac0 Iustin Pop
             (NoArg (\ opts -> Ok opts { optNoHeaders = True }))
176 0427285d Iustin Pop
             "do not show a header line"
177 0427285d Iustin Pop
178 0427285d Iustin Pop
oOutputDir :: OptType
179 0427285d Iustin Pop
oOutputDir = Option "d" ["output-dir"]
180 2f567ac0 Iustin Pop
             (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
181 0427285d Iustin Pop
             "directory in which to write output files"
182 0427285d Iustin Pop
183 0427285d Iustin Pop
oNodeFile :: OptType
184 0427285d Iustin Pop
oNodeFile = Option "n" ["nodes"]
185 2f567ac0 Iustin Pop
            (ReqArg (\ f o -> Ok o { optNodeFile = f,
186 2f567ac0 Iustin Pop
                                     optNodeSet = True }) "FILE")
187 0427285d Iustin Pop
            "the node list FILE"
188 0427285d Iustin Pop
189 0427285d Iustin Pop
oInstFile :: OptType
190 0427285d Iustin Pop
oInstFile = Option "i" ["instances"]
191 2f567ac0 Iustin Pop
            (ReqArg (\ f o -> Ok o { optInstFile = f,
192 2f567ac0 Iustin Pop
                                     optInstSet = True }) "FILE")
193 0427285d Iustin Pop
            "the instance list FILE"
194 0427285d Iustin Pop
195 b2278348 Iustin Pop
oNodeSim :: OptType
196 b2278348 Iustin Pop
oNodeSim = Option "" ["simulate"]
197 2f567ac0 Iustin Pop
            (ReqArg (\ f o -> Ok o { optNodeSim = Just f }) "SPEC")
198 b2278348 Iustin Pop
            "simulate an empty cluster, given as 'num_nodes,disk,memory,cpus'"
199 b2278348 Iustin Pop
200 0427285d Iustin Pop
oRapiMaster :: OptType
201 0427285d Iustin Pop
oRapiMaster = Option "m" ["master"]
202 2f567ac0 Iustin Pop
              (ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
203 0427285d Iustin Pop
              "collect data via RAPI at the given ADDRESS"
204 0427285d Iustin Pop
205 0427285d Iustin Pop
oLuxiSocket :: OptType
206 0427285d Iustin Pop
oLuxiSocket = Option "L" ["luxi"]
207 2f567ac0 Iustin Pop
              (OptArg ((\ f opts -> Ok opts { optLuxi = Just f }) .
208 0427285d Iustin Pop
                       fromMaybe defaultLuxiSocket) "SOCKET")
209 0427285d Iustin Pop
              "collect data via Luxi, optionally using the given SOCKET path"
210 0427285d Iustin Pop
211 0df5a1b4 Iustin Pop
oExecJobs :: OptType
212 0df5a1b4 Iustin Pop
oExecJobs = Option "X" ["exec"]
213 2f567ac0 Iustin Pop
             (NoArg (\ opts -> Ok opts { optExecJobs = True}))
214 0df5a1b4 Iustin Pop
             "execute the suggested moves via Luxi (only available when using\
215 0df5a1b4 Iustin Pop
             \ it for data gathering"
216 0df5a1b4 Iustin Pop
217 0427285d Iustin Pop
oVerbose :: OptType
218 0427285d Iustin Pop
oVerbose = Option "v" ["verbose"]
219 2f567ac0 Iustin Pop
           (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts + 1 }))
220 0427285d Iustin Pop
           "increase the verbosity level"
221 0427285d Iustin Pop
222 0427285d Iustin Pop
oQuiet :: OptType
223 0427285d Iustin Pop
oQuiet = Option "q" ["quiet"]
224 2f567ac0 Iustin Pop
         (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts - 1 }))
225 0427285d Iustin Pop
         "decrease the verbosity level"
226 0427285d Iustin Pop
227 0427285d Iustin Pop
oOfflineNode :: OptType
228 0427285d Iustin Pop
oOfflineNode = Option "O" ["offline"]
229 2f567ac0 Iustin Pop
               (ReqArg (\ n o -> Ok o { optOffline = n:optOffline o }) "NODE")
230 0427285d Iustin Pop
               "set node as offline"
231 0427285d Iustin Pop
232 0427285d Iustin Pop
oMaxSolLength :: OptType
233 0427285d Iustin Pop
oMaxSolLength = Option "l" ["max-length"]
234 2f567ac0 Iustin Pop
                (ReqArg (\ i opts -> Ok opts { optMaxLength = read i }) "N")
235 0427285d Iustin Pop
                "cap the solution at this many moves (useful for very\
236 0427285d Iustin Pop
                \ unbalanced clusters)"
237 0427285d Iustin Pop
238 0427285d Iustin Pop
oMinScore :: OptType
239 0427285d Iustin Pop
oMinScore = Option "e" ["min-score"]
240 2f567ac0 Iustin Pop
            (ReqArg (\ e opts -> Ok opts { optMinScore = read e }) "EPSILON")
241 0427285d Iustin Pop
            " mininum score to aim for"
242 0427285d Iustin Pop
243 0427285d Iustin Pop
oIMem :: OptType
244 0427285d Iustin Pop
oIMem = Option "" ["memory"]
245 2f567ac0 Iustin Pop
        (ReqArg (\ m opts -> Ok opts { optIMem = read m }) "MEMORY")
246 0427285d Iustin Pop
        "memory size for instances"
247 0427285d Iustin Pop
248 0427285d Iustin Pop
oIDisk :: OptType
249 0427285d Iustin Pop
oIDisk = Option "" ["disk"]
250 2f567ac0 Iustin Pop
         (ReqArg (\ d opts -> Ok opts { optIDsk = read d }) "DISK")
251 0427285d Iustin Pop
         "disk size for instances"
252 0427285d Iustin Pop
253 0427285d Iustin Pop
oIVcpus :: OptType
254 0427285d Iustin Pop
oIVcpus = Option "" ["vcpus"]
255 2f567ac0 Iustin Pop
          (ReqArg (\ p opts -> Ok opts { optIVCPUs = read p }) "NUM")
256 0427285d Iustin Pop
          "number of virtual cpus for instances"
257 0427285d Iustin Pop
258 0427285d Iustin Pop
oINodes :: OptType
259 0427285d Iustin Pop
oINodes = Option "" ["req-nodes"]
260 2f567ac0 Iustin Pop
          (ReqArg (\ n opts -> Ok opts { optINodes = read n }) "NODES")
261 0427285d Iustin Pop
          "number of nodes for the new instances (1=plain, 2=mirrored)"
262 0427285d Iustin Pop
263 0427285d Iustin Pop
oMaxCpu :: OptType
264 0427285d Iustin Pop
oMaxCpu = Option "" ["max-cpu"]
265 2f567ac0 Iustin Pop
          (ReqArg (\ n opts -> Ok opts { optMcpu = read n }) "RATIO")
266 0427285d Iustin Pop
          "maximum virtual-to-physical cpu ratio for nodes"
267 0427285d Iustin Pop
268 0427285d Iustin Pop
oMinDisk :: OptType
269 0427285d Iustin Pop
oMinDisk = Option "" ["min-disk"]
270 2f567ac0 Iustin Pop
           (ReqArg (\ n opts -> Ok opts { optMdsk = read n }) "RATIO")
271 0427285d Iustin Pop
           "minimum free disk space for nodes (between 0 and 1)"
272 0427285d Iustin Pop
273 c0501c69 Iustin Pop
oDiskMoves :: OptType
274 c0501c69 Iustin Pop
oDiskMoves = Option "" ["no-disk-moves"]
275 2f567ac0 Iustin Pop
             (NoArg (\ opts -> Ok opts { optDiskMoves = False}))
276 c0501c69 Iustin Pop
             "disallow disk moves from the list of allowed instance changes,\
277 c0501c69 Iustin Pop
             \ thus allowing only the 'cheap' failover/migrate operations"
278 c0501c69 Iustin Pop
279 4f83a560 Iustin Pop
oDynuFile :: OptType
280 4f83a560 Iustin Pop
oDynuFile = Option "U" ["dynu-file"]
281 2f567ac0 Iustin Pop
            (ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
282 4f83a560 Iustin Pop
            "Import dynamic utilisation data from the given FILE"
283 4f83a560 Iustin Pop
284 0427285d Iustin Pop
oShowVer :: OptType
285 0427285d Iustin Pop
oShowVer = Option "V" ["version"]
286 2f567ac0 Iustin Pop
           (NoArg (\ opts -> Ok opts { optShowVer = True}))
287 0427285d Iustin Pop
           "show the version of the program"
288 0427285d Iustin Pop
289 0427285d Iustin Pop
oShowHelp :: OptType
290 0427285d Iustin Pop
oShowHelp = Option "h" ["help"]
291 2f567ac0 Iustin Pop
            (NoArg (\ opts -> Ok opts { optShowHelp = True}))
292 0427285d Iustin Pop
            "show help"
293 fae371cc Iustin Pop
294 78694255 Iustin Pop
-- | Usage info
295 0427285d Iustin Pop
usageHelp :: String -> [OptType] -> String
296 9f6dcdea Iustin Pop
usageHelp progname =
297 78694255 Iustin Pop
    usageInfo (printf "%s %s\nUsage: %s [OPTION...]"
298 9f6dcdea Iustin Pop
               progname Version.version progname)
299 78694255 Iustin Pop
300 209b3711 Iustin Pop
-- | Command line parser, using the 'options' structure.
301 0427285d Iustin Pop
parseOpts :: [String]               -- ^ The command line arguments
302 0427285d Iustin Pop
          -> String                 -- ^ The program name
303 0427285d Iustin Pop
          -> [OptType]              -- ^ The supported command line options
304 0427285d Iustin Pop
          -> IO (Options, [String]) -- ^ The resulting options and leftover
305 0427285d Iustin Pop
                                    -- arguments
306 0427285d Iustin Pop
parseOpts argv progname options =
307 209b3711 Iustin Pop
    case getOpt Permute options argv of
308 209b3711 Iustin Pop
      (o, n, []) ->
309 209b3711 Iustin Pop
          do
310 2f567ac0 Iustin Pop
            let (pr, args) = (foldM (flip id) defaultOptions o, n)
311 2f567ac0 Iustin Pop
            po <- (case pr of
312 2f567ac0 Iustin Pop
                     Bad msg -> do
313 2f567ac0 Iustin Pop
                       hPutStrLn stderr "Error while parsing command\
314 2f567ac0 Iustin Pop
                                        \line arguments:"
315 2f567ac0 Iustin Pop
                       hPutStrLn stderr msg
316 2f567ac0 Iustin Pop
                       exitWith $ ExitFailure 1
317 2f567ac0 Iustin Pop
                     Ok val -> return val)
318 0427285d Iustin Pop
            when (optShowHelp po) $ do
319 78694255 Iustin Pop
              putStr $ usageHelp progname options
320 209b3711 Iustin Pop
              exitWith ExitSuccess
321 0427285d Iustin Pop
            when (optShowVer po) $ do
322 75d1edf8 Iustin Pop
              printf "%s %s\ncompiled with %s %s\nrunning on %s %s\n"
323 75d1edf8 Iustin Pop
                     progname Version.version
324 75d1edf8 Iustin Pop
                     compilerName (Data.Version.showVersion compilerVersion)
325 75d1edf8 Iustin Pop
                     os arch
326 75d1edf8 Iustin Pop
              exitWith ExitSuccess
327 2f567ac0 Iustin Pop
            return (po, args)
328 f723de38 Iustin Pop
      (_, _, errs) -> do
329 f723de38 Iustin Pop
        hPutStrLn stderr $ "Command line error: "  ++ concat errs
330 f723de38 Iustin Pop
        hPutStrLn stderr $ usageHelp progname options
331 f723de38 Iustin Pop
        exitWith $ ExitFailure 2
332 209b3711 Iustin Pop
333 9188aeef Iustin Pop
-- | A shell script template for autogenerated scripts.
334 e0eb63f0 Iustin Pop
shTemplate :: String
335 e0eb63f0 Iustin Pop
shTemplate =
336 e0eb63f0 Iustin Pop
    printf "#!/bin/sh\n\n\
337 e0eb63f0 Iustin Pop
           \# Auto-generated script for executing cluster rebalancing\n\n\
338 e0eb63f0 Iustin Pop
           \# To stop, touch the file /tmp/stop-htools\n\n\
339 e0eb63f0 Iustin Pop
           \set -e\n\n\
340 e0eb63f0 Iustin Pop
           \check() {\n\
341 e0eb63f0 Iustin Pop
           \  if [ -f /tmp/stop-htools ]; then\n\
342 e0eb63f0 Iustin Pop
           \    echo 'Stop requested, exiting'\n\
343 e0eb63f0 Iustin Pop
           \    exit 0\n\
344 e0eb63f0 Iustin Pop
           \  fi\n\
345 e0eb63f0 Iustin Pop
           \}\n\n"