Package ClusterShell :: Package CLI :: Module OptionParser
[hide private]
[frames] | no frames]

Source Code for Module ClusterShell.CLI.OptionParser

  1  #!/usr/bin/env python 
  2  # 
  3  # Copyright (C) 2010-2015 CEA/DAM 
  4  # 
  5  # This file is part of ClusterShell. 
  6  # 
  7  # ClusterShell is free software; you can redistribute it and/or 
  8  # modify it under the terms of the GNU Lesser General Public 
  9  # License as published by the Free Software Foundation; either 
 10  # version 2.1 of the License, or (at your option) any later version. 
 11  # 
 12  # ClusterShell is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 15  # Lesser General Public License for more details. 
 16  # 
 17  # You should have received a copy of the GNU Lesser General Public 
 18  # License along with ClusterShell; if not, write to the Free Software 
 19  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 
 20   
 21  """ 
 22  Common ClusterShell CLI OptionParser 
 23   
 24  With few exceptions, ClusterShell command-lines share most option 
 25  arguments. This module provides a common OptionParser class. 
 26  """ 
 27   
 28  from copy import copy 
 29  import optparse 
 30   
 31  from ClusterShell import __version__ 
 32  from ClusterShell.Engine.Factory import PreferredEngine 
 33  from ClusterShell.CLI.Display import THREE_CHOICES 
 34   
 35   
36 -def check_autostep(option, opt, value):
37 """type-checker function for autostep""" 38 try: 39 if '%' in value: 40 return float(value[:-1]) / 100.0 41 return int(value) 42 except ValueError: 43 if value == 'auto': 44 return value 45 error_fmt = "option %s: invalid value: %r, should be node count, " \ 46 "node percentage or 'auto'" 47 raise optparse.OptionValueError(error_fmt % (opt, value))
48
49 -def check_safestring(option, opt, value):
50 """type-checker function for safestring""" 51 try: 52 safestr = str(value) 53 # check if the string is not empty and not an option 54 if not safestr or safestr.startswith('-'): 55 raise ValueError() 56 return safestr 57 except ValueError: 58 raise optparse.OptionValueError( 59 "option %s: invalid value: %r" % (opt, value))
60 61
62 -class Option(optparse.Option):
63 """This Option subclass adds a new safestring type.""" 64 TYPES = optparse.Option.TYPES + ("autostep", "safestring",) 65 TYPE_CHECKER = copy(optparse.Option.TYPE_CHECKER) 66 TYPE_CHECKER["autostep"] = check_autostep 67 TYPE_CHECKER["safestring"] = check_safestring
68
69 -class OptionParser(optparse.OptionParser):
70 """Derived OptionParser for all CLIs""" 71
72 - def __init__(self, usage, **kwargs):
73 """Initialize ClusterShell CLI OptionParser""" 74 optparse.OptionParser.__init__(self, usage, 75 version="%%prog %s" % __version__, 76 option_class=Option, 77 **kwargs) 78 79 # Set parsing to stop on the first non-option 80 self.disable_interspersed_args() 81 82 # Always install groupsource support 83 self.add_option("-s", "--groupsource", action="store", 84 type="safestring", dest="groupsource", 85 help="optional groups.conf(5) group source to use")
86
87 - def install_config_options(self, filename=''):
88 """Install config options override""" 89 self.add_option("-O", "--option", action="append", metavar="KEY=VALUE", 90 dest="option", default=[], 91 help="override any key=value %s options" % filename)
92
93 - def install_nodes_options(self):
94 """Install nodes selection options""" 95 optgrp = optparse.OptionGroup(self, "Selecting target nodes") 96 optgrp.add_option("-w", action="append", type="safestring", 97 dest="nodes", help="nodes where to run the command") 98 optgrp.add_option("-x", action="append", type="safestring", 99 dest="exclude", metavar="NODES", 100 help="exclude nodes from the node list") 101 optgrp.add_option("-a", "--all", action="store_true", dest="nodes_all", 102 help="run command on all nodes") 103 optgrp.add_option("-g", "--group", action="append", type="safestring", 104 dest="group", help="run command on a group of nodes") 105 optgrp.add_option("-X", action="append", dest="exgroup", 106 metavar="GROUP", type="safestring", 107 help="exclude nodes from this group") 108 optgrp.add_option("-E", "--engine", action="store", dest="engine", 109 choices=["auto"] + PreferredEngine.engines.keys(), 110 default="auto", help=optparse.SUPPRESS_HELP) 111 optgrp.add_option("--hostfile", "--machinefile", action="append", 112 dest="hostfile", default=[], metavar='FILE', 113 help="path to file containing a list of target hosts") 114 optgrp.add_option("--topology", action="store", dest="topofile", 115 default=None, metavar='FILE', 116 help="topology configuration file to use for tree " 117 "mode") 118 optgrp.add_option("--pick", action="store", dest="pick", 119 metavar="N", type="int", 120 help="pick N node(s) at random in nodeset") 121 self.add_option_group(optgrp)
122
123 - def install_display_options(self, 124 debug_option=True, 125 verbose_options=False, 126 separator_option=False, 127 dshbak_compat=False, 128 msgtree_mode=False):
129 """Install options needed by Display class""" 130 optgrp = optparse.OptionGroup(self, "Output behaviour") 131 if verbose_options: 132 optgrp.add_option("-q", "--quiet", action="store_true", 133 dest="quiet", help="be quiet, print essential output only") 134 optgrp.add_option("-v", "--verbose", action="store_true", 135 dest="verbose", help="be verbose, print informative messages") 136 if debug_option: 137 optgrp.add_option("-d", "--debug", action="store_true", 138 dest="debug", 139 help="output more messages for debugging purpose") 140 optgrp.add_option("-G", "--groupbase", action="store_true", 141 dest="groupbase", default=False, 142 help="do not display group source prefix") 143 optgrp.add_option("-L", action="store_true", dest="line_mode", 144 help="disable header block and order output by nodes") 145 optgrp.add_option("-N", action="store_false", dest="label", 146 default=True, help="disable labeling of command line") 147 if dshbak_compat: 148 optgrp.add_option("-b", "-c", "--dshbak", action="store_true", 149 dest="gather", help="gather nodes with same output") 150 else: 151 optgrp.add_option("-P", "--progress", action="store_true", 152 dest="progress", help="show progress during command execution") 153 optgrp.add_option("-b", "--dshbak", action="store_true", 154 dest="gather", help="gather nodes with same output") 155 optgrp.add_option("-B", action="store_true", dest="gatherall", 156 default=False, help="like -b but including standard error") 157 optgrp.add_option("-r", "--regroup", action="store_true", 158 dest="regroup", default=False, 159 help="fold nodeset using node groups") 160 161 if separator_option: 162 optgrp.add_option("-S", "--separator", action="store", 163 dest="separator", default=':', 164 help="node / line content separator string " 165 "(default: ':')") 166 else: 167 optgrp.add_option("-S", action="store_true", dest="maxrc", 168 help="return the largest of command return codes") 169 170 if msgtree_mode: 171 # clubak specific 172 optgrp.add_option("-F", "--fast", action="store_true", 173 dest="fast_mode", 174 help="faster but memory hungry mode") 175 optgrp.add_option("-T", "--tree", action="store_true", 176 dest="trace_mode", 177 help="message tree trace mode") 178 optgrp.add_option("--interpret-keys", action="store", 179 dest="interpret_keys", choices=THREE_CHOICES, 180 default=THREE_CHOICES[-1], help="whether to " 181 "interpret keys (never, always or auto)") 182 183 optgrp.add_option("--color", action="store", dest="whencolor", 184 choices=THREE_CHOICES, help="whether to use ANSI " 185 "colors (never, always or auto)") 186 optgrp.add_option("--diff", action="store_true", dest="diff", 187 help="show diff between gathered outputs") 188 self.add_option_group(optgrp)
189
190 - def _copy_callback(self, option, opt_str, value, parser):
191 """special callback method for copy and rcopy toggles""" 192 # enable interspersed args again 193 self.enable_interspersed_args() 194 # set True to dest option attribute 195 setattr(parser.values, option.dest, True)
196
197 - def install_filecopy_options(self):
198 """Install file copying specific options""" 199 optgrp = optparse.OptionGroup(self, "File copying") 200 optgrp.add_option("-c", "--copy", action="callback", dest="copy", 201 callback=self._copy_callback, 202 help="copy local file or directory to remote nodes") 203 optgrp.add_option("--rcopy", action="callback", dest="rcopy", 204 callback=self._copy_callback, 205 help="copy file or directory from remote nodes") 206 optgrp.add_option("--dest", action="store", dest="dest_path", 207 help="destination file or directory on the nodes") 208 optgrp.add_option("-p", action="store_true", dest="preserve_flag", 209 help="preserve modification times and modes") 210 self.add_option_group(optgrp)
211 212
214 """Install engine/connector (ssh, ...) options""" 215 optgrp = optparse.OptionGroup(self, "Connection options") 216 optgrp.add_option("-f", "--fanout", action="store", dest="fanout", 217 help="use a specified fanout", type="int") 218 #help="queueing delay for traffic grooming" 219 optgrp.add_option("--grooming", action="store", dest="grooming_delay", 220 help=optparse.SUPPRESS_HELP, type="float") 221 optgrp.add_option("-l", "--user", action="store", type="safestring", 222 dest="user", help="execute remote command as user") 223 optgrp.add_option("-o", "--options", action="store", dest="options", 224 help="can be used to give ssh options") 225 optgrp.add_option("-t", "--connect_timeout", action="store", 226 dest="connect_timeout", 227 help="limit time to connect to a node", type="float") 228 optgrp.add_option("-u", "--command_timeout", action="store", 229 dest="command_timeout", 230 help="limit time for command to run on the node", 231 type="float") 232 optgrp.add_option("-R", "--worker", action="store", dest="worker", 233 help="worker name to use for command execution " 234 "('exec', 'rsh', 'ssh', etc. default is 'ssh')") 235 optgrp.add_option("--remote", action="store", dest="remote", 236 choices=('yes', 'no'), 237 help="whether to enable remote execution: in tree " 238 "mode, 'yes' forces connections to the leaf " 239 "nodes for execution, 'no' establishes " 240 "connections up to the leaf parent nodes for " 241 "execution (default is 'yes')") 242 self.add_option_group(optgrp)
243
244 - def install_nodeset_commands(self):
245 """Install nodeset commands""" 246 optgrp = optparse.OptionGroup(self, "Commands") 247 optgrp.add_option("-c", "--count", action="store_true", dest="count", 248 default=False, 249 help="show number of nodes in nodeset(s)") 250 optgrp.add_option("-e", "--expand", action="store_true", dest="expand", 251 default=False, 252 help="expand nodeset(s) to separate nodes") 253 optgrp.add_option("-f", "--fold", action="store_true", dest="fold", 254 default=False, help="fold nodeset(s) (or separate " 255 "nodes) into one nodeset") 256 optgrp.add_option("-l", "--list", action="count", dest="list", 257 default=False, help="list node groups from one " 258 "source (see -s GROUPSOURCE)") 259 optgrp.add_option("-L", "--list-all", action="count", dest="listall", 260 default=False, 261 help="list node groups from all group sources") 262 optgrp.add_option("-r", "--regroup", action="store_true", 263 dest="regroup", default=False, 264 help="fold nodes using node groups (see -s " 265 "GROUPSOURCE)") 266 optgrp.add_option("--list-sources", "--groupsources", 267 action="store_true", dest="groupsources", 268 default=False, 269 help="list all active group sources (see " 270 "groups.conf(5))") 271 self.add_option_group(optgrp)
272
274 """Install nodeset operations""" 275 optgrp = optparse.OptionGroup(self, "Operations") 276 optgrp.add_option("-x", "--exclude", action="append", dest="sub_nodes", 277 default=[], type="string", 278 help="exclude specified nodeset") 279 optgrp.add_option("-i", "--intersection", action="append", 280 dest="and_nodes", default=[], type="string", 281 help="calculate nodesets intersection") 282 optgrp.add_option("-X", "--xor", action="append", dest="xor_nodes", 283 default=[], type="string", 284 help="calculate symmetric difference between " 285 "nodesets") 286 self.add_option_group(optgrp)
287
288 - def install_nodeset_options(self):
289 """Install nodeset options""" 290 optgrp = optparse.OptionGroup(self, "Options") 291 optgrp.add_option("-a", "--all", action="store_true", dest="all", 292 help="call external node groups support to " 293 "display all nodes") 294 optgrp.add_option("--autostep", action="store", dest="autostep", 295 help="enable a-b/step style syntax when folding, " 296 "value is min node count threshold (eg. '4', " 297 "'50%' or 'auto')", 298 type="autostep") 299 optgrp.add_option("-d", "--debug", action="store_true", dest="debug", 300 help="output more messages for debugging purpose") 301 optgrp.add_option("-q", "--quiet", action="store_true", dest="quiet", 302 help="be quiet, print essential output only") 303 optgrp.add_option("-R", "--rangeset", action="store_true", 304 dest="rangeset", help="switch to RangeSet instead " 305 "of NodeSet. Useful when working on numerical " 306 "cluster ranges, eg. 1,5,18-31") 307 optgrp.add_option("-G", "--groupbase", action="store_true", 308 dest="groupbase", help="hide group source prefix " 309 "(always \"@groupname\")") 310 optgrp.add_option("-S", "--separator", action="store", dest="separator", 311 default=' ', help="separator string to use when " 312 "expanding nodesets (default: ' ')") 313 optgrp.add_option("-O", "--output-format", action="store", 314 dest="output_format", metavar='FORMAT', default='%s', 315 help="output format (default: '%s')") 316 optgrp.add_option("-I", "--slice", action="store", 317 dest="slice_rangeset", 318 help="return sliced off result", type="string") 319 optgrp.add_option("--split", action="store", dest="maxsplit", 320 help="split result into a number of subsets", 321 type="int") 322 optgrp.add_option("--contiguous", action="store_true", 323 dest="contiguous", help="split result into " 324 "contiguous subsets") 325 optgrp.add_option("--axis", action="store", dest="axis", 326 metavar="RANGESET", help="fold along these axis only " 327 "(axis 1..n for nD nodeset)") 328 optgrp.add_option("--pick", action="store", dest="pick", 329 metavar="N", type="int", 330 help="pick N node(s) at random in nodeset") 331 self.add_option_group(optgrp)
332