import logging
import errno
import itertools
+import optparse
from cStringIO import StringIO
from ganeti import utils
from ganeti import netutils
from ganeti import qlang
-from optparse import (OptionParser, TitledHelpFormatter,
+from optparse import (TitledHelpFormatter,
Option, OptionValueError)
QR_UNKNOWN,
QR_INCOMPLETE) = range(3)
+#: Maximum batch size for ChooseJob
+_CHOOSE_BATCH = 25
+
class _Argument:
- def __init__(self, min=0, max=None): # pylint: disable-msg=W0622
+ def __init__(self, min=0, max=None): # pylint: disable=W0622
self.min = min
self.max = max
Value can be any of the ones passed to the constructor.
"""
- # pylint: disable-msg=W0622
+ # pylint: disable=W0622
def __init__(self, min=0, max=None, choices=None):
_Argument.__init__(self, min=min, max=max)
self.choices = choices
SubmitOpCode(op, opts=opts)
-def check_unit(option, opt, value): # pylint: disable-msg=W0613
+def check_unit(option, opt, value): # pylint: disable=W0613
"""OptParsers custom converter for units.
"""
return kv_dict
-def check_ident_key_val(option, opt, value): # pylint: disable-msg=W0613
+def check_ident_key_val(option, opt, value): # pylint: disable=W0613
"""Custom parser for ident:key=val,key=val options.
This will store the parsed values as a tuple (ident, {key: val}). As such,
"""
if ":" not in value:
- ident, rest = value, ''
+ ident, rest = value, ""
else:
ident, rest = value.split(":", 1)
return retval
-def check_key_val(option, opt, value): # pylint: disable-msg=W0613
+def check_key_val(option, opt, value): # pylint: disable=W0613
"""Custom parser class for key=val,key=val options.
This will store the parsed values as a dict {key: val}.
return _SplitKeyVal(opt, value)
-def check_bool(option, opt, value): # pylint: disable-msg=W0613
+def check_bool(option, opt, value): # pylint: disable=W0613
"""Custom parser for yes/no options.
This will store the parsed value as either True or False.
" (defaults to one space)"))
USEUNITS_OPT = cli_option("--units", default=None,
- dest="units", choices=('h', 'm', 'g', 't'),
+ dest="units", choices=("h", "m", "g", "t"),
help="Specify units for output (one of h/m/g/t)")
FIELDS_OPT = cli_option("-o", "--output", dest="output", action="store",
type="keyval", default={},
help="Backend parameters")
-HVOPTS_OPT = cli_option("-H", "--hypervisor-parameters", type="keyval",
- default={}, dest="hvparams",
- help="Hypervisor parameters")
+HVOPTS_OPT = cli_option("-H", "--hypervisor-parameters", type="keyval",
+ default={}, dest="hvparams",
+ help="Hypervisor parameters")
HYPERVISOR_OPT = cli_option("-H", "--hypervisor-parameters", dest="hypervisor",
help="Hypervisor and hypervisor options, in the"
" times, if not given defaults to all nodes)",
completion_suggest=OPT_COMPL_ONE_NODE)
-NODEGROUP_OPT = cli_option("-g", "--node-group",
+NODEGROUP_OPT_NAME = "--node-group"
+NODEGROUP_OPT = cli_option("-g", NODEGROUP_OPT_NAME,
dest="nodegroup",
help="Node group (name or uuid)",
metavar="<nodegroup>",
" [%s]" % constants.DEFAULT_VG),
metavar="VG", default=None)
-YES_DOIT_OPT = cli_option("--yes-do-it", dest="yes_do_it",
+YES_DOIT_OPT = cli_option("--yes-do-it", "--ya-rly", dest="yes_do_it",
help="Destroy cluster", action="store_true")
NOVOTING_OPT = cli_option("--no-voting", dest="no_voting",
cmd = aliases[cmd]
func, args_def, parser_opts, usage, description = commands[cmd]
- parser = OptionParser(option_list=parser_opts + COMMON_OPTS,
- description=description,
- formatter=TitledHelpFormatter(),
- usage="%%prog %s %s" % (cmd, usage))
+ parser = CustomOptionParser(option_list=parser_opts + COMMON_OPTS,
+ description=description,
+ formatter=TitledHelpFormatter(),
+ usage="%%prog %s %s" % (cmd, usage))
parser.disable_interspersed_args()
options, args = parser.parse_args()
return func, options, args
+class CustomOptionParser(optparse.OptionParser):
+ def _match_long_opt(self, opt):
+ """Override C{OptionParser}'s function for matching long options.
+
+ The default implementation does prefix-based abbreviation matching. We
+ disable such behaviour as it can can lead to confusing conflicts (e.g.
+ C{--force} and C{--force-multi}).
+
+ """
+ if opt in self._long_opt:
+ return opt
+ else:
+ raise optparse.BadOptionError(opt)
+
+
def _CheckArguments(cmd, args_def, args):
"""Verifies the arguments using the argument definition.
"""Splits the value of a --node option.
"""
- if value and ':' in value:
- return value.split(':', 1)
+ if value and ":" in value:
+ return value.split(":", 1)
else:
return (value, None)
"""
if os_variants:
- return ['%s+%s' % (os_name, v) for v in os_variants]
+ return ["%s+%s" % (os_name, v) for v in os_variants]
else:
return [os_name]
"""
if choices is None:
- choices = [('y', True, 'Perform the operation'),
- ('n', False, 'Do not perform the operation')]
+ choices = [("y", True, "Perform the operation"),
+ ("n", False, "Do not perform the operation")]
if not choices or not isinstance(choices, list):
raise errors.ProgrammerError("Invalid choices argument to AskUser")
for entry in choices:
- if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == '?':
+ if not isinstance(entry, tuple) or len(entry) < 3 or entry[0] == "?":
raise errors.ProgrammerError("Invalid choices element to AskUser")
answer = choices[-1][1]
try:
chars = [entry[0] for entry in choices]
chars[-1] = "[%s]" % chars[-1]
- chars.append('?')
+ chars.append("?")
maps = dict([(entry[0], entry[1]) for entry in choices])
while True:
f.write(text)
- f.write('\n')
+ f.write("\n")
f.write("/".join(chars))
f.write(": ")
line = f.readline(2).strip().lower()
if line in maps:
answer = maps[line]
break
- elif line == '?':
+ elif line == "?":
for entry in choices:
f.write(" %s - %s\n" % (entry[0], entry[2]))
f.write("\n")
retcode = 0
else:
obuf.write("Unhandled exception: %s" % msg)
- return retcode, obuf.getvalue().rstrip('\n')
+ return retcode, obuf.getvalue().rstrip("\n")
def GenericMain(commands, override=None, aliases=None):
"""
# Pause watcher by acquiring an exclusive lock on watcher state file
self.feedback_fn("Blocking watcher")
- watcher_block = utils.FileLock.Open(constants.WATCHER_STATEFILE)
+ watcher_block = utils.FileLock.Open(constants.WATCHER_LOCK_FILE)
try:
# TODO: Currently, this just blocks. There's no timeout.
# TODO: Should it be a shared lock?
if unitfields is None:
unitfields = []
- numfields = utils.FieldSet(*numfields) # pylint: disable-msg=W0142
- unitfields = utils.FieldSet(*unitfields) # pylint: disable-msg=W0142
+ numfields = utils.FieldSet(*numfields) # pylint: disable=W0142
+ unitfields = utils.FieldSet(*unitfields) # pylint: disable=W0142
format_fields = []
for field in fields:
if separator is None:
mlens = [0 for name in fields]
- format_str = ' '.join(format_fields)
+ format_str = " ".join(format_fields)
else:
format_str = separator.replace("%", "%%").join(format_fields)
for line in data:
args = []
if line is None:
- line = ['-' for _ in fields]
+ line = ["-" for _ in fields]
for idx in range(len(fields)):
if separator is None:
args.append(mlens[idx])
if not names:
names = None
- if (force_filter or
- (names and len(names) == 1 and qlang.MaybeFilter(names[0]))):
- try:
- (filter_text, ) = names
- except ValueError:
- raise errors.OpPrereqError("Exactly one argument must be given as a"
- " filter")
-
- logging.debug("Parsing '%s' as filter", filter_text)
- filter_ = qlang.ParseFilter(filter_text)
- else:
- filter_ = qlang.MakeSimpleFilter("name", names)
+ filter_ = qlang.MakeFilter(names, force_filter)
response = cl.Query(resource, fields, filter_)
@return: a string with the formatted timestamp
"""
- if not isinstance (ts, (tuple, list)) or len(ts) != 2:
- return '?'
+ if not isinstance(ts, (tuple, list)) or len(ts) != 2:
+ return "?"
sec, usec = ts
return time.strftime("%F %T", time.localtime(sec)) + ".%06d" % usec
if not value:
raise errors.OpPrereqError("Empty time specification passed")
suffix_map = {
- 's': 1,
- 'm': 60,
- 'h': 3600,
- 'd': 86400,
- 'w': 604800,
+ "s": 1,
+ "m": 60,
+ "h": 3600,
+ "d": 86400,
+ "w": 604800,
}
if value[-1] not in suffix_map:
try:
stream.write(txt % args)
else:
stream.write(txt)
- stream.write('\n')
+ stream.write("\n")
stream.flush()
except IOError, err:
if err.errno == errno.EPIPE:
"""
assert self.jobs, "_ChooseJob called with empty job list"
- result = self.cl.QueryJobs([i[2] for i in self.jobs], ["status"])
+ result = self.cl.QueryJobs([i[2] for i in self.jobs[:_CHOOSE_BATCH]],
+ ["status"])
assert result
for job_data, status in zip(self.jobs, result):