Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2014-09-28 19:53:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crmsh (Old) and /work/SRC/openSUSE:Factory/.crmsh.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh" Changes: -------- --- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2014-09-19 22:27:44.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2014-09-28 19:54:13.000000000 +0200 @@ -1,0 +2,9 @@ +Fri Sep 26 10:18:39 UTC 2014 - kgronl...@suse.com + +- low: report: Sort list of nodes +- low: ui_cluster: More informative error message +- low: main: Replace getopt with optparse +- high: parse: Allow empty attribute values in nvpairs (bnc#898625) +- upstream cs: 2.1.0-82-ge8abd85 + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.npnU5D/_old 2014-09-28 19:54:15.000000000 +0200 +++ /var/tmp/diff_new_pack.npnU5D/_new 2014-09-28 19:54:15.000000000 +0200 @@ -41,7 +41,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0+ Group: %{pkg_group} -Version: 2.1+git71 +Version: 2.1+git82 Release: %{?crmsh_release}%{?dist} Url: http://crmsh.github.io Source0: crmsh.tar.bz2 ++++++ crmsh.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/cibconfig.py new/crmsh/modules/cibconfig.py --- old/crmsh/modules/cibconfig.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/cibconfig.py 2014-09-26 12:07:07.000000000 +0200 @@ -499,7 +499,7 @@ Test objects for sanity. This is about semantics. ''' rc = self.__check_unique_clash(set_obj_all) - for obj in self.obj_set: + for obj in sorted(self.obj_set, key=lambda x: x.obj_id): rc |= obj.check_sanity() return rc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/cibverify.py new/crmsh/modules/cibverify.py --- old/crmsh/modules/cibverify.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/cibverify.py 2014-09-26 12:07:07.000000000 +0200 @@ -35,9 +35,8 @@ def verify(cib): rc, _, stderr = utils.get_stdout_stderr(cib_verify, cib) for i, line in enumerate(line for line in stderr.split('\n') if line): - line = _prettify(line, 0 if i == 0 else 7) if i == 0: - err_buf.error(line) + err_buf.error(_prettify(line, 0)) else: - err_buf.writemsg(line) + err_buf.writemsg(_prettify(line, 7)) return rc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/constants.py new/crmsh/modules/constants.py --- old/crmsh/modules/constants.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/constants.py 2014-09-26 12:07:07.000000000 +0200 @@ -254,12 +254,6 @@ "simulate": "crm_simulate", } -ra_if = None # class interface to RA -stonithd_metadata = None # stonithd meta data -pe_metadata = None # PE meta data -crmd_metadata = None # crmd meta data -cib_metadata = None # cib meta data -crm_properties_metadata = None # PE + crmd + cib meta data meta_progs = ("crmd", "pengine", "stonithd", "cib") # elide these properties from tab completion crmd_metadata_do_not_complete = ("dc-version", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/main.py new/crmsh/modules/main.py --- old/crmsh/modules/main.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/main.py 2014-09-26 12:07:07.000000000 +0200 @@ -17,7 +17,6 @@ import sys import os -import getopt import atexit import random @@ -92,76 +91,62 @@ return shadow -def usage(rc): - f = sys.stderr - if rc == 0: - f = sys.stdout - print >> f, """Usage: crm [OPTIONS] [SUBCOMMAND ARGS...] - - -f, --file='FILE':: - Load commands from the given file. If a dash `-` is used in place - of a file name, `crm` will read commands from the shell standard - input (`stdin`). - - -c, --cib='CIB':: - Start the session using the given shadow CIB file. - Equivalent to `cib use <CIB>`. - - -D, --display='OUTPUT_TYPE':: - Choose one of the output options: plain, color, or - uppercase. The default is color if the terminal emulation - supports colors. Otherwise, plain is used. - - -F, --force:: - Make `crm` proceed with applying changes where it would normally - ask the user to confirm before proceeding. This option is mainly - useful in scripts, and should be used with care. - - -w, --wait:: - Make crm wait for the cluster transition to finish (for the - changes to take effect) after each processed line. - - -H, --history='DIR|FILE':: - The `history` commands can either work directly on the live - cluster (default), or on a report generated by the `report` - command. Use this option to specify a directory or file containing - the previously generated report. - - -h, --help:: - Print help page. - - --version:: - Print crmsh version and build information (Mercurial Hg changeset - hash). - - -d, --debug:: - Print verbose debugging information. - - -R, --regression-tests:: - Enables extra verbose trace logging used by the regression - tests. Logs all external calls made by crmsh. - - --scriptdir='DIR':: - Extra directory where crm looks for cluster scripts. Can be - a semicolon-separated list of directories. - - Use crm without arguments for an interactive session. - Supply one or more arguments for a "single-shot" use. - Supply level name to start working at that level. - Specify with -f a file which contains a script. Use '-' for - standard input or use pipe/redirection. - - Examples: - - # crm -f stopapp2.txt - # crm -w resource stop global_www - # echo stop global_www | crm resource - # crm configure property no-quorum-policy=ignore - # crm ra info pengine - # crm status +def make_option_parser(): + from optparse import OptionParser + parser = OptionParser(usage="""%prog [-h|--help] [OPTIONS] [SUBCOMMAND ARGS...] +or %prog help SUBCOMMAND + +For a list of available subcommands, use %prog help. + +Use %prog without arguments for an interactive session. +Call a subcommand directly for a "single-shot" use. +Call %prog with a level name as argument to start an interactive +session from that level. + +See the crm(8) man page or call %prog help for more details.""", + version="%prog " + config.CRM_VERSION) + parser.add_option("-f", "--file", dest="filename", metavar="FILE", + help="Load commands from the given file. If a dash (-) " + + "is used in place of a file name, crm will read commands " + + "from the shell standard input (stdin).") + parser.add_option("-c", "--cib", dest="cib", metavar="CIB", + help="Start the session using the given shadow CIB file. " + + "Equivalent to `cib use <CIB>`.") + parser.add_option("-D", "--display", dest="display", metavar="OUTPUT_TYPE", + help="Choose one of the output options: plain, color, or uppercase. " + + "The default is color if the terminal emulation supports colors, " + + "else plain.") + parser.add_option("-F", "--force", action="store_true", default=False, dest="force", + help="Make crm proceed with applying changes where it would normally " + + "ask the user to confirm before proceeding. This option is mainly useful " + + "in scripts, and should be used with care.") + parser.add_option("-w", "--wait", action="store_true", default=False, dest="wait", + help="Make crm wait for the cluster transition to finish " + + "(for the changes to take effect) after each processed line.") + parser.add_option("-H", "--history", dest="history", metavar="DIR|FILE", + help="The `history` commands can either work directly on the live " + + "cluster (default), or on a report generated by the `report` " + + "command. Use this option to specify a directory or file containing " + + "the previously generated report.") + parser.add_option("-d", "--debug", action="store_true", default=False, dest="debug", + help="Print verbose debugging information.") + parser.add_option("-R", "--regression-tests", action="store_true", default=False, + dest="regression_tests", + help="Enables extra verbose trace logging used by the regression " + + "tests. Logs all external calls made by crmsh.") + parser.add_option("--scriptdir", dest="scriptdir", metavar="DIR", + help="Extra directory where crm looks for cluster scripts. Can be " + + "a semicolon-separated list of directories.") + parser.add_option("-X", dest="profile", metavar="PROFILE", + help="Collect profiling data and save in PROFILE.") + return parser + + +option_parser = make_option_parser() - See the crm(8) man page or the crm help system for more details. - """ + +def usage(rc): + option_parser.print_usage(file=(sys.stderr if rc != 0 else sys.stdout)) sys.exit(rc) @@ -200,9 +185,7 @@ return l -def do_work(context, user_args): - compatibility_setup() - +def handle_noninteractive_use(context, user_args): if options.shadow: if not context.run("cib use " + options.shadow): return 1 @@ -228,7 +211,24 @@ err_buf.reset_lineno(-1) else: return 1 + return None + +def render_prompt(context): + rendered_prompt = constants.prompt + if options.interactive and not options.batch: + # TODO: fix how color interacts with readline, + # seems the color prompt messes it up + promptstr = "crm(%s)%s# " % (cib_prompt(), context.prompt()) + constants.prompt = promptstr + if clidisplay.colors_enabled(): + rendered_prompt = term.render(clidisplay.prompt(promptstr)) + else: + rendered_prompt = promptstr + return rendered_prompt + + +def setup_context(context): if options.input_file and options.input_file != "-": try: sys.stdin = open(options.input_file) @@ -239,20 +239,19 @@ if options.interactive and not options.batch: context.setup_readline() + +def do_work(context, user_args): + compatibility_setup() + rc = handle_noninteractive_use(context, user_args) + if rc is not None: + return rc + + setup_context(context) + rc = 0 while True: try: - rendered_prompt = constants.prompt - if options.interactive and not options.batch: - # TODO: fix how color interacts with readline, - # seems the color prompt messes it up - promptstr = "crm(%s)%s# " % (cib_prompt(), context.prompt()) - constants.prompt = promptstr - if clidisplay.colors_enabled(): - rendered_prompt = term.render(clidisplay.prompt(promptstr)) - else: - rendered_prompt = promptstr - inp = utils.multi_input(rendered_prompt) + inp = utils.multi_input(render_prompt(context)) if inp is None: if options.interactive: rc = 0 @@ -300,47 +299,20 @@ def parse_options(): - try: - opts, user_args = getopt.getopt( - sys.argv[1:], - 'whdc:f:FX:RD:H:', - ("wait", "version", "help", "debug", - "cib=", "file=", "force", "profile=", - "regression-tests", "display=", "history=", - "scriptdir=")) - for o, p in opts: - if o in ("-h", "--help"): - usage(0) - elif o == "--version": - print >> sys.stdout, ("%s" % config.CRM_VERSION) - sys.exit(0) - elif o == "-d": - config.core.debug = "yes" - elif o == "-X": - options.profile = p - elif o == "-R": - options.regression_tests = True - elif o in ("-D", "--display"): - config.color.style = p - elif o in ("-F", "--force"): - config.core.force = "yes" - elif o in ("-f", "--file"): - options.batch = True - options.interactive = False - err_buf.reset_lineno() - options.input_file = p - elif o in ("-H", "--history"): - options.history = p - elif o in ("-w", "--wait"): - config.core.wait = "yes" - elif o in ("-c", "--cib"): - options.shadow = p - elif o == "--scriptdir": - options.scriptdir = p - return user_args - except getopt.GetoptError, msg: - print msg - usage(1) + opts, args = option_parser.parse_args() + config.core.debug = "yes" if opts.debug else config.core.debug + options.profile = opts.profile or options.profile + options.regression_tests = opts.regression_tests or options.regression_tests + config.color.style = opts.display or config.color.style + config.core.force = opts.force or config.core.force + if opts.filename: + err_buf.reset_lineno() + options.input_file, options.batch, options.interactive = opts.filename, True, False + options.history = opts.history or options.history + config.core.wait = opts.wait or config.core.wait + options.shadow = opts.cib or options.shadow + options.scriptdir = opts.scriptdir or options.scriptdir + return args def profile_run(context, user_args): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/parse.py new/crmsh/modules/parse.py --- old/crmsh/modules/parse.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/parse.py 2014-09-26 12:07:07.000000000 +0200 @@ -37,15 +37,15 @@ class BaseParser(object): - _NVPAIR_RE = re.compile(r'([^=@$][^=]*)=(.+)$') - _NVPAIR_ID_RE = re.compile(r'\$([^:=]+)(?::(.+))?=(.+)$') + _NVPAIR_RE = re.compile(r'([^=@$][^=]*)=(.*)$') + _NVPAIR_ID_RE = re.compile(r'\$([^:=]+)(?::(.+))?=(.*)$') _NVPAIR_REF_RE = re.compile(r'@([^:]+)(?::(.+))?$') _IDENT_RE = re.compile(r'([a-z0-9_#$-][^=]*)$', re.IGNORECASE) _DISPATCH_RE = re.compile(r'[a-z0-9_]+$', re.IGNORECASE) _DESC_RE = re.compile(r'description=(.+)$', re.IGNORECASE) _RESOURCE_RE = re.compile(r'([a-z_#$][^=]*)$', re.IGNORECASE) _IDSPEC_RE = re.compile(r'(\$id-ref|\$id)=(.*)$', re.IGNORECASE) - _ID_RE = re.compile(r'\$id=(.+)$', re.IGNORECASE) + _ID_RE = re.compile(r'\$id=(.*)$', re.IGNORECASE) _ID_NEW_RE = re.compile(r'([\w-]+):$', re.IGNORECASE) def can_parse(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ra.py new/crmsh/modules/ra.py --- old/crmsh/modules/ra.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/ra.py 2014-09-26 12:07:07.000000000 +0200 @@ -42,9 +42,6 @@ ''' Getting information from the resource agents. ''' - def __init__(self): - self.good = self.is_lrmd_accessible() - def lrmadmin(self, opts, xml=False): ''' Get information directly from lrmd using lrmadmin. @@ -84,9 +81,6 @@ ''' Getting information from the resource agents (direct). ''' - def __init__(self): - self.good = True - def meta(self, ra_class, ra_type, ra_provider): l = [] if ra_class == "ocf": @@ -162,9 +156,6 @@ ''' Getting information from the resource agents via new crm_resource. ''' - def __init__(self): - self.good = True - def crm_resource(self, opts): ''' Get information from crm_resource. @@ -210,8 +201,13 @@ return False v_min = version.LooseVersion(minimum_glue) v_this = version.LooseVersion(glue_ver) - return v_this >= v_min or \ - (userdir.getuser() in ("root", config.path.crm_daemon_user)) + if v_this < v_min: + return False + if userdir.getuser() not in ("root", config.path.crm_daemon_user): + return False + if not (is_program(lrmadmin_prog) and is_process("lrmd")): + return False + return utils.ext_cmd(">/dev/null 2>&1 %s -C" % lrmadmin_prog) == 0 def crm_resource_support(): @@ -219,19 +215,16 @@ return s != "" +@utils.memoize def ra_if(): - if constants.ra_if: - return constants.ra_if if crm_resource_support(): common_debug("Using crm_resource for agent discovery") - constants.ra_if = RaCrmResource() - elif can_use_lrmadmin(): + return RaCrmResource() + if can_use_lrmadmin(): common_debug("Using lrmd for agent discovery") - constants.ra_if = RaLrmd() - if not constants.ra_if or not constants.ra_if.good: - common_debug("Using OS for agent discovery") - constants.ra_if = RaOS() - return constants.ra_if + return RaLrmd() + common_debug("Using OS for agent discovery") + return RaOS() def ra_classes(): @@ -288,43 +281,37 @@ return cache.store(id, list) +@utils.memoize def get_pe_meta(): - if not constants.pe_metadata: - constants.pe_metadata = RAInfo("pengine", "metadata") - return constants.pe_metadata + return RAInfo("pengine", "metadata") +@utils.memoize def get_crmd_meta(): - if not constants.crmd_metadata: - constants.crmd_metadata = RAInfo("crmd", "metadata") - constants.crmd_metadata.exclude_from_completion( - constants.crmd_metadata_do_not_complete) - return constants.crmd_metadata + info = RAInfo("crmd", "metadata") + info.exclude_from_completion(constants.crmd_metadata_do_not_complete) + return info +@utils.memoize def get_stonithd_meta(): - if not constants.stonithd_metadata: - constants.stonithd_metadata = RAInfo("stonithd", "metadata") - return constants.stonithd_metadata + return RAInfo("stonithd", "metadata") +@utils.memoize def get_cib_meta(): - if not constants.cib_metadata: - constants.cib_metadata = RAInfo("cib", "metadata") - return constants.cib_metadata + return RAInfo("cib", "metadata") +@utils.memoize def get_properties_meta(): - if not constants.crm_properties_metadata: - get_pe_meta() - get_crmd_meta() - get_cib_meta() - constants.crm_properties_metadata = copy.deepcopy(constants.crmd_metadata) - constants.crm_properties_metadata.add_ra_params(constants.pe_metadata) - constants.crm_properties_metadata.add_ra_params(constants.cib_metadata) - return constants.crm_properties_metadata + meta = copy.deepcopy(get_crmd_meta()) + meta.add_ra_params(get_pe_meta()) + meta.add_ra_params(get_cib_meta()) + return meta +@utils.memoize def get_properties_list(): try: return get_properties_meta().params().keys() @@ -336,13 +323,12 @@ ''' Do external program metadata. ''' - l = [] if is_program(prog): rc, l = stdout2list("%s metadata" % prog) - if rc != 0: - common_debug("%s metadata exited with code %d" % (prog, rc)) - l = [] - return l + if rc == 0: + return l + common_debug("%s metadata exited with code %d" % (prog, rc)) + return [] def get_nodes_text(n, tag): @@ -636,7 +622,7 @@ if self.ra_class == "stonith" and op in ("start", "stop"): continue if op not in self.actions(): - common_warn("%s: action %s not advertised in meta-data, it may not be supported by the RA" % (id, op)) + common_warn("%s: action '%s' not found in Resource Agent meta-data" % (id, op)) rc |= 1 if "interval" in n_ops[op]: v = n_ops[op]["interval"] @@ -737,16 +723,14 @@ return s def format_parameter(self, n): - l = [] head = self.meta_param_head(n) if not head: self.error("no name attribute for parameter") return "" - l.append(head) + l = [head] longdesc = get_nodes_text(n, "longdesc") if longdesc: - longdesc = self.ra_tab + longdesc.replace("\n", "\n" + self.ra_tab) + '\n' - l.append(longdesc) + l.append(self.ra_tab + longdesc.replace("\n", "\n" + self.ra_tab) + '\n') return '\n'.join(l) def meta_parameter(self, param): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/report.py new/crmsh/modules/report.py --- old/crmsh/modules/report.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/report.py 2014-09-26 12:07:07.000000000 +0200 @@ -725,10 +725,10 @@ return pe_file.replace("%s/" % self.loc, "") def get_nodes(self): - return [os.path.basename(p) - for p in os.listdir(self.loc) - if os.path.isdir(os.path.join(self.loc, p)) and - os.path.isfile(os.path.join(self.loc, p, "ha-log.txt"))] + return sorted([os.path.basename(p) + for p in os.listdir(self.loc) + if os.path.isdir(os.path.join(self.loc, p)) and + os.path.isfile(os.path.join(self.loc, p, "ha-log.txt"))]) def check_nodes(self): 'Verify if the nodes in cib match the nodes in the report.' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_cluster.py new/crmsh/modules/ui_cluster.py --- old/crmsh/modules/ui_cluster.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/modules/ui_cluster.py 2014-09-26 12:07:07.000000000 +0200 @@ -157,7 +157,7 @@ ''' stack = utils.cluster_stack() if not stack: - err_buf.error("Cluster stack not detected!") + err_buf.error("No supported cluster stack found (tried heartbeat|openais|corosync)") if utils.cluster_stack() == 'corosync': print "Services:" for svc in ["corosync", "pacemaker"]: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/testcases/confbasic.exp new/crmsh/test/testcases/confbasic.exp --- old/crmsh/test/testcases/confbasic.exp 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/test/testcases/confbasic.exp 2014-09-26 12:07:07.000000000 +0200 @@ -56,8 +56,8 @@ .EXT crm_resource --show-metadata ocf:heartbeat:Delay .EXT crm_resource --show-metadata ocf:pacemaker:Stateful .EXT crm_resource --show-metadata ocf:heartbeat:Dummy -.EXT pengine metadata .EXT crmd metadata +.EXT pengine metadata .EXT cib metadata .INP: show node node1 \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/testcases/newfeatures.exp new/crmsh/test/testcases/newfeatures.exp --- old/crmsh/test/testcases/newfeatures.exp 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/test/testcases/newfeatures.exp 2014-09-26 12:07:07.000000000 +0200 @@ -37,8 +37,8 @@ .EXT crm_resource --show-metadata stonith:heartbeat:ssh .EXT stonithd metadata .EXT crm_resource --show-metadata ocf:heartbeat:Dummy -.EXT pengine metadata .EXT crmd metadata +.EXT pengine metadata .EXT cib metadata .INP: commit nvpair_ref: 'p0-state' None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/unittests/test_parse.py new/crmsh/test/unittests/test_parse.py --- old/crmsh/test/unittests/test_parse.py 2014-09-19 12:38:36.000000000 +0200 +++ new/crmsh/test/unittests/test_parse.py 2014-09-26 12:07:07.000000000 +0200 @@ -148,6 +148,9 @@ out = self.parser.parse('primitive st stonith:ssh params hostlist=node1 meta target-role=Started op start requires=nothing timeout=60s op monitor interval=60m timeout=60s') self.assertEqual(out.get('id'), 'st') + out = self.parser.parse('primitive st stonith:ssh params hostlist= meta') + self.assertEqual(out.get('id'), 'st') + out = self.parser.parse('primitive st stonith:null params hostlist=node1 meta description="some description here" op start requires=nothing op monitor interval=60m') self.assertEqual(out.get('id'), 'st') -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org