Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2014-03-18 14:13:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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-03-10 12:31:24.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2014-03-18 14:13:42.000000000 +0100 @@ -1,0 +2,21 @@ +Mon Mar 17 12:53:00 UTC 2014 - [email protected] + +- medium: command: Propagate error from auto-commit (bnc#868533) +- medium: crm_pkg: Add --no-refresh to zypper commands +- medium: scripts: Improved setup in cluster init/add (bnc#868008) +- upstream cs: 053db64d9cca + +------------------------------------------------------------------- +Thu Mar 13 14:51:40 UTC 2014 - [email protected] + +- medium: scripts: Improved debug output from cluster scripts (bnc#866636) +- medium: scripts: corosync uses mcastport - 1 (bnc#868008) +- medium: xmlutil: fencing-topology used broken comparison (bnc#866639) +- medium: utils: ask() did not respect force flag in all cases (bnc#868007) +- low: utils: Nicer warning when crm_simulate fails +- low: ui: Don't call nonexistent function on unsupported cluster stack +- low: main: Better descriptions for -d and -R flags. +- low: parse: More liberal parsing of role assignment in constraint rules +- upstream cs: dbf8e3b7538 + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/.hg_archival.txt new/crmsh/.hg_archival.txt --- old/crmsh/.hg_archival.txt 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/.hg_archival.txt 2014-03-17 13:09:30.000000000 +0100 @@ -1,5 +1,5 @@ repo: 13c3bd69e935090cd25213c474cafc3f01b5910b -node: 4bb659cf287e386310ecb8894f2c4f5ab95755d4 +node: 053db64d9cca33de61567a117573c69079345628 branch: default latesttag: 1.2.6-rc1 -latesttagdistance: 462 +latesttagdistance: 476 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/command.py new/crmsh/modules/command.py --- old/crmsh/modules/command.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/command.py 2014-03-17 13:09:30.000000000 +0100 @@ -247,8 +247,9 @@ TODO: Implement full cd navigation. cd ../configure, for example Also implement ls to list commands / levels from current location ''' - context.up() + ok = context.up() context.save_stack() + return ok @help('''List levels and commands Lists the available sublevels and commands @@ -289,22 +290,26 @@ ''') @completer(_cd_completer) def do_cd(self, context, optarg='..'): + ok = True path = optarg.split('/', 1) if len(path) == 1: path = path[0] if path == '..': - context.up() + ok = context.up() elif path == '.' or not path: - return + return ok else: info = self.get_child(path) if not info or not info.level: context.fatal_error("No such level: " + path) context.enter_level(info.level) else: - self.do_cd(context, path[0]) - self.do_cd(context, path[1]) + if not self.do_cd(context, path[0]): + ok = False + if not self.do_cd(context, path[1]): + ok = False context.save_stack() + return True @alias('bye', 'exit') @help('''Exit the interactive shell 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-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/main.py 2014-03-17 13:09:30.000000000 +0100 @@ -180,13 +180,12 @@ Print Pacemaker version and build information (Mercurial Hg changeset hash). - -R, --regression-tests:: - Run in the regression test mode. Used mainly by the - regression testing suite. - -d, --debug:: - Print some debug information. Used by developers. [Not yet - refined enough to print useful information for other users.] + 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 @@ -217,7 +216,7 @@ def set_interactive(): '''Set the interactive option only if we're on a tty.''' - if sys.stdin.isatty(): + if utils.can_ask(): options.interactive = True @@ -422,7 +421,7 @@ load_rc(context, userdir.RC_FILE) atexit.register(exit_handler) - options.interactive = sys.stdin.isatty() + options.interactive = utils.can_ask() if not options.interactive: err_buf.reset_lineno() options.batch = True 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-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/parse.py 2014-03-17 13:09:30.000000000 +0100 @@ -459,7 +459,7 @@ class ConstraintParser(BaseParser): _SCORE_RE = re.compile(r"([^:]+):$") - _ROLE_RE = re.compile(r"\$role=(.+)$", re.IGNORECASE) + _ROLE_RE = re.compile(r"\$?role=(.+)$", re.IGNORECASE) _ROLE2_RE = re.compile(r"role=(.+)$", re.IGNORECASE) _BOOLOP_RE = re.compile(r'(%s)$' % ('|'.join(vars.boolean_ops)), re.IGNORECASE) _UNARYOP_RE = re.compile(r'(%s)$' % ('|'.join(vars.unary_ops)), re.IGNORECASE) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/scripts.py new/crmsh/modules/scripts.py --- old/crmsh/modules/scripts.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/scripts.py 2014-03-17 13:09:30.000000000 +0100 @@ -67,6 +67,20 @@ return "Bad configuration option" not in err +def _pssh_call(hosts, cmd, opts): + "pssh.call with debug logging" + if config.core.debug or options.regression_tests: + err_buf.debug("pssh.call(%s, %s)" % (repr(hosts), cmd)) + return pssh.call(hosts, cmd, opts) + + +def _pssh_copy(hosts, src, dst, opts): + "pssh.copy with debug logging" + if config.core.debug or options.regression_tests: + err_buf.debug("pssh.copy(%s, %s, %s)" % (repr(hosts), src, dst)) + return pssh.copy(hosts, src, dst, opts) + + def _generate_workdir_name(): ''' Generate a temporary folder name to use while @@ -250,7 +264,7 @@ 'PasswordAuthentication=no', 'StrictHostKeyChecking=no', 'ControlPersist=no'] - if config.core.debug: + if options.regression_tests: opts.ssh_extra += ['-vvv'] return opts @@ -322,6 +336,9 @@ hosts2.append((h, p, u)) else: local_node = (h, p, u) + err_buf.debug("Local node: %s, Remote hosts: %s" % ( + local_node, + ', '.join(h[0] for h in hosts2))) return local_node, hosts2 @@ -366,22 +383,24 @@ def _create_remote_workdirs(hosts, path, opts): "Create workdirs on remote hosts" ok = True - for host, result in pssh.call(hosts, - "mkdir -p %s" % (os.path.dirname(path)), - opts).iteritems(): + for host, result in _pssh_call(hosts, + "mkdir -p %s" % (os.path.dirname(path)), + opts).iteritems(): if isinstance(result, pssh.Error): - err_buf.error("[%s]: %s" % (host, result)) + err_buf.error("[%s]: Start: %s" % (host, result)) ok = False if not ok: - raise ValueError("Failed to create working folders, aborting.") + msg = "Failed to connect to one or more of these hosts via SSH: %s" % ( + ', '.join(h[0] for h in hosts)) + raise ValueError(msg) def _copy_to_remote_dirs(hosts, path, opts): "Copy a local folder to same location on remote hosts" ok = True - for host, result in pssh.copy(hosts, - path, - path, opts).iteritems(): + for host, result in _pssh_copy(hosts, + path, + path, opts).iteritems(): if isinstance(result, pssh.Error): err_buf.error("[%s]: %s" % (host, result)) ok = False @@ -394,7 +413,7 @@ Copy src to dst both locally and remotely """ ok = True - ret = pssh.copy(hosts, src, dst, opts) + ret = _pssh_copy(hosts, src, dst, opts) for host, result in ret.iteritems(): if isinstance(result, pssh.Error): err_buf.error("[%s]: %s" % (host, result)) @@ -412,7 +431,7 @@ else: shutil.copytree(src, dst) except (IOError, OSError, shutil.Error), e: - err_buf.error("[%s]: %s" % (utils.this_node(), e)) + err_buf.error("[%s]: %s" % (local_node, e)) ok = False return ok @@ -577,9 +596,9 @@ else: self.opts.input_stream = None - for host, result in pssh.call(self.hosts, - cmdline, - self.opts).iteritems(): + for host, result in _pssh_call(self.hosts, + cmdline, + self.opts).iteritems(): if isinstance(result, pssh.Error): self.error("[%s]: %s", host, result) ok = False @@ -617,34 +636,54 @@ return out -def _run_cleanup(hosts, workdir, opts): +def _cleanup_local(workdir): + "clean up the local tmp dir" + if workdir and os.path.isdir(workdir): + cleanscript = os.path.join(workdir, 'crm_clean.py') + if os.path.isfile(cleanscript): + if subprocess.call([cleanscript, workdir], shell=False) != 0: + shutil.rmtree(workdir) + else: + shutil.rmtree(workdir) + + +def _print_output(host, rc, out, err): + "Print the output from a process that ran on host" + if out: + err_buf.ok("[%s]: %s" % (host, out)) + if err: + err_buf.error("[%s]: %s" % (host, err)) + + +def _run_cleanup(local_node, hosts, workdir, opts): "Clean up after the cluster script" if hosts and workdir: - for host, result in pssh.call(hosts, - "%s %s" % (os.path.join(workdir, 'crm_clean.py'), - workdir), - opts).iteritems(): + cleanscript = os.path.join(workdir, 'crm_clean.py') + for host, result in _pssh_call(hosts, + "%s %s" % (cleanscript, + workdir), + opts).iteritems(): if isinstance(result, pssh.Error): - err_buf.warning("[%s]: Failed to clean up %s: %s" % (host, workdir, result)) + err_buf.debug("[%s]: Failed to clean up %s" % (host, workdir)) + err_buf.error("[%s]: Clean: %s" % (host, result)) else: - rc, out, err = result - print out - if workdir and os.path.isdir(workdir): - shutil.rmtree(workdir) + _print_output(host, *result) + _cleanup_local(workdir) -def _print_debug(hosts, workdir, opts): +def _print_debug(local_node, hosts, workdir, opts): "Print debug output (if any)" dbglog = os.path.join(workdir, 'crm_script.debug') - for host, result in pssh.call(hosts, - "[ -f '%s' ] && cat '%s'" % (dbglog, dbglog), - opts).iteritems(): + for host, result in _pssh_call(hosts, + "[ -f '%s' ] && cat '%s'" % (dbglog, dbglog), + opts).iteritems(): if isinstance(result, pssh.Error): err_buf.error("[%s]: %s" % (host, result)) else: - rc, out, err = result - print out - print err + _print_output(host, *result) + if os.path.isfile(dbglog): + f = open(dbglog).read() + err_buf.ok("[%s]: %s" % (local_node, f)) def run(name, args): @@ -689,6 +728,6 @@ raise ValueError("Internal error while running %s: %s" % (name, e)) finally: if not config.core.debug: - _run_cleanup(hosts, workdir, opts) + _run_cleanup(local_node, hosts, workdir, opts) else: - _print_debug(hosts, workdir, opts) + _print_debug(local_node, hosts, workdir, opts) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_assist.py new/crmsh/modules/ui_assist.py --- old/crmsh/modules/ui_assist.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/ui_assist.py 2014-03-17 13:09:30.000000000 +0100 @@ -83,7 +83,7 @@ print "The following elements will be created:" print " * Colocation constraint, ID: %s" % (constraint_name) print " * Dummy resource, ID: %s" % (dummy_name) - if not sys.stdin.isatty() or utils.ask("Create resources?"): + if not utils.can_ask() or utils.ask("Create resources?"): cib_factory.create_object('primitive', dummy_name, 'ocf:heartbeat:Dummy') colo = ['colocation', constraint_name, 'inf:', '('] colo.extend(nodes) 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-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/ui_cluster.py 2014-03-17 13:09:30.000000000 +0100 @@ -45,7 +45,7 @@ def requires(self): stack = utils.cluster_stack() if len(stack) > 0 and stack != 'corosync': - err_buf.warn("Unsupported cluster stack %s detected." % (stack)) + err_buf.warning("Unsupported cluster stack %s detected." % (stack)) return False return True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_configure.py new/crmsh/modules/ui_configure.py --- old/crmsh/modules/ui_configure.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/ui_configure.py 2014-03-17 13:09:30.000000000 +0100 @@ -792,9 +792,11 @@ return cib_factory.has_cib_changed() def end_game(self, no_questions_asked=False): + ok = True if cib_factory.has_cib_changed(): if no_questions_asked or not options.interactive: - self._commit() + ok = self._commit() elif utils.ask("There are changes pending. Do you want to commit them?"): - self._commit() + ok = self._commit() cib_factory.reset() + return ok diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_context.py new/crmsh/modules/ui_context.py --- old/crmsh/modules/ui_context.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/ui_context.py 2014-03-17 13:09:30.000000000 +0100 @@ -92,7 +92,7 @@ common_err("%s: %s" % (self.get_qualified_name(), msg)) rv = False if cmd or (rv is False): - self._back_out() + rv = self._back_out() and rv return rv def complete(self, line): @@ -232,7 +232,7 @@ def _set_interactive(self): '''Set the interactive option only if we're on a tty.''' - if sys.stdin.isatty(): + if utils.can_ask(): options.interactive = True def execute_command(self): @@ -293,17 +293,21 @@ ''' Navigate up in the levels hierarchy ''' + ok = True if len(self.stack) > 1: - self.current_level().end_game(no_questions_asked=self._in_transit) + ok = self.current_level().end_game(no_questions_asked=self._in_transit) is not False self.stack.pop() self.clear_readline_cache() + return ok def _back_out(self): ''' Restore the stack to the marked position ''' + ok = True while self._mark > 0 and len(self.stack) > self._mark: - self.up() + ok = self.up() and ok + return ok def save_stack(self): self._mark = len(self.stack) @@ -312,9 +316,11 @@ ''' Exit from the top level ''' - self.current_level().end_game() + ok = self.current_level().end_game() if options.interactive and not options.batch: print "bye" + if ok is False and rc == 0: + rc = 1 sys.exit(rc) def level_name(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_corosync.py new/crmsh/modules/ui_corosync.py --- old/crmsh/modules/ui_corosync.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/ui_corosync.py 2014-03-17 13:09:30.000000000 +0100 @@ -50,7 +50,7 @@ def requires(self): stack = utils.cluster_stack() if len(stack) > 0 and stack != 'corosync': - err_buf.warn("Unsupported cluster stack %s detected." % (stack)) + err_buf.warning("Unsupported cluster stack %s detected." % (stack)) return False return True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/utils.py new/crmsh/modules/utils.py --- old/crmsh/modules/utils.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/utils.py 2014-03-17 13:09:30.000000000 +0100 @@ -73,22 +73,38 @@ return True +def can_ask(): + """ + Is user-interactivity possible? + Checks if connected to a TTY. + """ + return sys.stdin.isatty() + + def ask(msg): - # if there's no terminal, no use asking and default to "no" - if not sys.stdin.isatty(): + """ + Ask for user confirmation. + If core.force is true, always return true. + If not interactive and core.force is false, always return false. + """ + if config.core.force: + common_info("%s [YES]" % (msg)) + return True + if not can_ask(): return False - print_msg = True + + msg += ' ' + if msg.endswith('? '): + msg = msg[:-2] + ' ([y]/n)? ' + while True: try: - ans = raw_input(msg + ' ') + ans = raw_input(msg) except EOFError: ans = 'n' - if not ans or ans[0].lower() not in ('n', 'y'): - if print_msg: - print "Please answer with y[es] or n[o]" - print_msg = False - else: - return ans[0].lower() == 'y' + ans = ans[0].lower() + if ans in 'yn': + return ans == 'y' # holds part of line before \ split # for a multi-line input @@ -650,7 +666,11 @@ common_debug("invoke: %s" % ptest) rc, s = get_stdout(ptest, input_s=graph_s) if rc != 0: - common_warn("%s exited with %d" % (ptest, rc)) + common_debug("%s exited with %d" % (ptest, rc)) + if actions and rc == 1: + common_warn("No actions found.") + else: + common_warn("Simulation was unsuccessful (RC=%d)." % (rc)) if dotfile: if os.path.getsize(dotfile) > 0: show_dot_graph(dotfile) @@ -872,7 +892,7 @@ w, h = get_winsize() if not need_pager(s, w, h): print term_render(s) - elif not config.core.pager or not sys.stdout.isatty() or options.batch: + elif not config.core.pager or not can_ask() or options.batch: print term_render(s) else: opts = "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/xmlutil.py new/crmsh/modules/xmlutil.py --- old/crmsh/modules/xmlutil.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/modules/xmlutil.py 2014-03-17 13:09:30.000000000 +0100 @@ -1270,15 +1270,7 @@ return l -def xml_noorder_hash(n): - return sorted([hash(etree.tostring(x)) - for x in n.iterchildren()]) - -xml_hash_d = { - "fencing-topology": xml_noorder_hash, -} - -checker = doctestcompare.LXMLOutputChecker() +_checker = doctestcompare.LXMLOutputChecker() def xml_equals_unordered(a, b): @@ -1291,7 +1283,7 @@ return isinstance(x.tag, basestring) and x.tag or x.text def sortby(v): - return tagflat(v) + ''.join(sorted(v.attrib.keys())) + return tagflat(v) + ''.join(sorted(v.attrib.keys() + v.attrib.values())) def safe_strip(text): return text is not None and text.strip() or '' @@ -1313,24 +1305,13 @@ def xml_equals(n, m, show=False): - if n.tag in xml_hash_d: - n_hash_l = xml_hash_d[n.tag](n) - m_hash_l = xml_hash_d[n.tag](m) - rc = len(n_hash_l) == len(m_hash_l) - for i in range(len(n_hash_l)): - if not rc: - break - if n_hash_l[i] != m_hash_l[i]: - rc = False - else: - #rc = checker.compare_docs(n, m) - rc = xml_equals_unordered(n, m) + rc = xml_equals_unordered(n, m) if not rc and show and config.core.debug: # somewhat strange, but that's how this works from doctest import Example example = Example("etree.tostring(n)", etree.tostring(n)) got = etree.tostring(m) - print checker.output_difference(example, got, 0) + print _checker.output_difference(example, got, 0) return rc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/scripts/add/add.py new/crmsh/scripts/add/add.py --- old/crmsh/scripts/add/add.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/scripts/add/add.py 2014-03-17 13:09:30.000000000 +0100 @@ -2,6 +2,7 @@ import sys import os import crm_script +import crm_init COROSYNC_AUTH = '/etc/corosync/authkey' COROSYNC_CONF = '/etc/corosync/corosync.conf' @@ -9,9 +10,6 @@ host = crm_script.host() add_nodes = crm_script.param('node').split(',') -PACKAGES = ['pacemaker', 'corosync', 'crmsh'] - - def run_collect(): if host not in add_nodes: crm_script.exit_ok(host) @@ -19,7 +17,7 @@ rc, out, err = crm_script.service('pacemaker', 'is-active') if rc == 0 and out.strip() == 'active': crm_script.exit_fail("Pacemaker already running on %s" % (host)) - crm_script.exit_ok(host) + crm_script.exit_ok(crm_init.info()) def make_opts(): @@ -49,11 +47,8 @@ def run_install(): if host not in add_nodes: crm_script.exit_ok(host) - for pkg in PACKAGES: - try: - crm_script.package(pkg, 'latest') - except Exception, e: - crm_script.exit_fail("Error installing package '%s': %s" % (pkg, e)) + packages = ['cluster-glue', 'corosync', 'crmsh', 'pacemaker', 'resource-agents'] + crm_init.install_packages(packages) crm_script.exit_ok(host) @@ -98,6 +93,13 @@ crm_script.exit_ok(host) +def run_firewall(): + if host not in add_nodes: + crm_script.exit_ok(host) + crm_init.configure_firewall() + crm_script.exit_ok(host) + + def start_new_node(): if host not in add_nodes: crm_script.exit_ok(host) @@ -118,6 +120,8 @@ run_install() elif sys.argv[1] == 'copy': run_copy() + elif sys.argv[1] == 'firewall': + run_firewall() elif sys.argv[1] == 'start': start_new_node() else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/scripts/add/main.yml new/crmsh/scripts/add/main.yml --- old/crmsh/scripts/add/main.yml 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/scripts/add/main.yml 2014-03-17 13:09:30.000000000 +0100 @@ -26,6 +26,9 @@ - name: Copy configuration files apply_local: add.py copy + - name: Configure firewall + apply: add.py firewall + - name: Start cluster on new node apply: add.py start diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/scripts/init/Makefile.am new/crmsh/scripts/init/Makefile.am --- old/crmsh/scripts/init/Makefile.am 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/scripts/init/Makefile.am 2014-03-17 13:09:30.000000000 +0100 @@ -21,7 +21,7 @@ scriptinitdir = $(datadir)/@PACKAGE@/scripts/init -scriptinit_DATA = main.yml corosync.conf.template init_common.py basic.cib.template +scriptinit_DATA = main.yml corosync.conf.template basic.cib.template scriptinit_SCRIPTS = collect.py verify.py configure.py authkey.py init.py EXTRA_DIST = $(scriptinit_DATA) $(scriptinit_SCRIPTS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/scripts/init/collect.py new/crmsh/scripts/init/collect.py --- old/crmsh/scripts/init/collect.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/scripts/init/collect.py 2014-03-17 13:09:30.000000000 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/env python import crm_script -import init_common as init +import crm_init try: - crm_script.exit_ok(init.info()) + crm_script.exit_ok(crm_init.info()) except Exception, e: crm_script.exit_fail(str(e)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/scripts/init/configure.py new/crmsh/scripts/init/configure.py --- old/crmsh/scripts/init/configure.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/scripts/init/configure.py 2014-03-17 13:09:30.000000000 +0100 @@ -1,77 +1,19 @@ #!/usr/bin/env python import sys -import os import crm_script - -host = crm_script.host() -hostinfo = crm_script.output(1)[host] - - -def service_enabled(name): - for svc in hostinfo['services']: - if svc['name'] == name and svc['enabled'] == 'enabled': - return True - return False - - -def service_active(name): - for svc in hostinfo['services']: - if svc['name'] == name and svc['active'] == 'active': - return True - return False - -SUSE_FW_TEMPLATE = """## Name: HAE cluster ports -## Description: opens ports for HAE cluster services -TCP="%(tcp)s" -UDP="%(udp)s" -""" - - -def configure_firewall(): - corosync_mcastport = crm_script.param('mcastport') - FW_CLUSTER = '/etc/sysconfig/SuSEfirewall2.d/services/cluster' - - tcp_ports = '30865 5560 7630 21064' - udp_ports = corosync_mcastport - - if service_enabled('SuSEfirewall2_init'): - if os.path.isfile(FW_CLUSTER): - import re - tmpl = open(FW_CLUSTER).read() - tmpl = re.sub(r'^TCP="(.*)"', 'TCP="%s"' % (tcp_ports), tmpl, flags=re.M) - tmpl = re.sub(r'^UDP="(.*)"', 'UDP="%s"' % (udp_ports), tmpl, flags=re.M) - with open(FW_CLUSTER, 'w') as f: - f.write(tmpl) - elif os.path.isdir(os.path.dirname(FW_CLUSTER)): - with open(FW_CLUSTER, 'w') as fwc: - fwc.write(SUSE_FW_TEMPLATE % {'tcp': tcp_ports, - 'udp': udp_ports}) - else: - # neither the cluster file nor the services - # directory exists - crm_script.exit_fail("SUSE firewall is configured but %s does not exist" % - os.path.dirname(FW_CLUSTER)) - if service_active('SuSEfirewall2_init'): - crm_script.service('SuSEfirewall2_init', 'restart') - - # TODO: other platforms +import crm_init def run_install(): - # install packages - PACKAGES = ['cluster-glue', 'corosync', 'crmsh', 'pacemaker', 'resource-agents'] - for pkg in PACKAGES: - try: - crm_script.package(pkg, 'latest') - except Exception, e: - crm_script.exit_fail("Failed to install %s: %s" % (pkg, e)) - - configure_firewall() - + packages = ['cluster-glue', 'corosync', 'crmsh', 'pacemaker', 'resource-agents'] + crm_init.install_packages(packages) + crm_init.configure_firewall() crm_script.exit_ok(True) def make_bindnetaddr(): + host = crm_script.host() + hostinfo = crm_script.output(1)[host] ba = crm_script.param('bindnetaddr') if ba: return ba diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/scripts/init/init_common.py new/crmsh/scripts/init/init_common.py --- old/crmsh/scripts/init/init_common.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/scripts/init/init_common.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,132 +0,0 @@ -import os -import platform -import socket -import crm_script - -PACKAGES = ['booth', 'cluster-glue', 'corosync', 'crmsh', 'csync2', 'drbd', - 'fence-agents', 'gfs2', 'gfs2-utils', 'hawk', 'ocfs2', - 'ocfs2-tools', 'pacemaker', 'pacemaker-mgmt', - 'resource-agents', 'sbd'] -SERVICES = ['sshd', 'ntp', 'corosync', 'pacemaker', 'hawk', 'SuSEfirewall2_init'] -SSH_KEY = os.path.expanduser('~/.ssh/id_rsa') -CSYNC2_KEY = '/etc/csync2/key_hagroup' -CSYNC2_CFG = '/etc/csync2/csync2.cfg' -COROSYNC_CONF = '/etc/corosync/corosync.conf' -SYSCONFIG_SBD = '/etc/sysconfig/sbd' -SYSCONFIG_FW = '/etc/sysconfig/SuSEfirewall2' -SYSCONFIG_FW_CLUSTER = '/etc/sysconfig/SuSEfirewall2.d/services/cluster' - - -def rpm_info(): - 'check installed packages' - return crm_script.rpmcheck(PACKAGES) - - -def svc_info(): - 'check enabled/active services' - state = [] - for service in SERVICES: - active, enabled = 'unknown', 'unknown' - rc, out, err = crm_script.call(["systemctl", "is-enabled", "%s.service" % (service)]) - if rc in (0, 1, 3) and out: - enabled = out.strip() - else: - state.append({'name': service, 'error': err.strip()}) - continue - rc, out, err = crm_script.call(["systemctl", "is-active", "%s.service" % (service)]) - if rc in (0, 1, 3) and out: - active = out.strip() - else: - state.append({'name': service, 'error': err.strip()}) - continue - state.append({'name': service, 'active': active, 'enabled': enabled}) - return state - - -def sys_info(): - 'system information' - system, node, release, version, machine, processor = platform.uname() - distname, distver, distid = platform.linux_distribution() - hostname = platform.node().split('.')[0] - return {'system': system, - 'node': node, - 'release': release, - 'version': version, - 'machine': machine, - 'processor': processor, - 'distname': distname, - 'distver': distver, - 'distid': distid, - 'user': os.getlogin(), - 'hostname': hostname, - 'fqdn': socket.getfqdn()} - - -def net_info(): - ret = {} - interfaces = [] - rc, out, err = crm_script.call(['netstat', '-nr']) - if rc == 0: - data = [l.split() for l in out.split('\n')] - if len(data) < 3: - return {'error': "Failed to parse netstat output"} - keys = data[1] - for line in data[2:]: - if len(line) == len(keys): - interfaces.append(dict(zip(keys, line))) - else: - interfaces.append({'error': err.strip()}) - ret['interfaces'] = interfaces - hostname = platform.node().split('.')[0] - try: - ip = socket.gethostbyname(hostname) - ret['hostname'] = {'name': hostname, 'ip': ip} - except Exception, e: - ret['hostname'] = {'error': str(e)} - return ret - - -def files_info(): - def check(fn): - if os.path.isfile(os.path.expanduser(fn)): - return os.path.expanduser(fn) - return '' - return {'ssh_key': check(SSH_KEY), - 'csync2_key': check(CSYNC2_KEY), - 'csync2_cfg': check(CSYNC2_CFG), - 'corosync_conf': check(COROSYNC_CONF), - 'sysconfig_sbd': check(SYSCONFIG_SBD), - 'sysconfig_fw': check(SYSCONFIG_FW), - 'sysconfig_fw_cluster': check(SYSCONFIG_FW_CLUSTER), - } - - -def logrotate_info(): - rc, _, _ = crm_script.call( - 'grep -r corosync.conf /etc/logrotate.d', - shell=True) - return {'corosync.conf': rc == 0} - - -def disk_info(): - rc, out, err = crm_script.call(['df'], shell=False) - if rc == 0: - disk_use = [] - for line in out.split('\n')[1:]: - line = line.strip() - if line: - data = line.split() - if len(data) >= 6: - disk_use.append((data[5], int(data[4][:-1]))) - return disk_use - return [] - - -def info(): - return {'rpm': rpm_info(), - 'services': svc_info(), - 'system': sys_info(), - 'net': net_info(), - 'files': files_info(), - 'logrotate': logrotate_info(), - 'disk': disk_info()} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/scripts/init/verify.py new/crmsh/scripts/init/verify.py --- old/crmsh/scripts/init/verify.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/scripts/init/verify.py 2014-03-17 13:09:30.000000000 +0100 @@ -1,13 +1,6 @@ #!/usr/bin/env python import crm_script - -data = crm_script.output(1) - - -def verify_host(host, info): - if host != info['system']['hostname']: - crm_script.exit_fail("Hostname mismatch: %s is not %s" % - (host, info['system']['hostname'])) +import crm_init def select_interfaces(user_iface, data): @@ -32,39 +25,6 @@ return user_iface -def compare_system(systems): - def check(value, msg): - vals = set([system[value] for host, system in systems]) - if len(vals) > 1: - info = ', '.join('%s: %s' % (h, system[value]) for h, system in systems) - crm_script.exit_fail("%s: %s" % (msg, info)) - - check('machine', 'Architecture differs') - #check('release', 'Kernel release differs') - check('distname', 'Distribution differs') - check('distver', 'Distribution version differs') - #check('version', 'Kernel version differs') - - -def check_diskspace(): - for host, info in data.iteritems(): - for mount, percent in info['disk']: - interesting = (mount == '/' or - mount.startswith('/var/log') or - mount.startswith('/tmp')) - if interesting and percent > 90: - crm_script.exit_fail("Not enough space on %s:%s" % (host, mount)) - - -def check_services(): - for host, info in data.iteritems(): - for svc in info['services']: - if svc['name'] == 'pacemaker' and svc['active'] == 'active': - crm_script.exit_fail("%s already running pacemaker" % (host)) - if svc['name'] == 'corosync' and svc['active'] == 'active': - crm_script.exit_fail("%s already running corosync" % (host)) - - def make_mcastaddr(): import random random.seed() @@ -72,12 +32,9 @@ return "%d.%d.%d.%d" % (239, b, c, d) try: - for host, info in data.iteritems(): - verify_host(host, info) - compare_system((h, info['system']) for h, info in data.iteritems()) + data = crm_script.output(1) - check_diskspace() - check_services() + crm_init.verify(data) ret = {} ret['iface'] = select_interfaces(crm_script.param('iface'), data) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/unittests/test_bugs.py new/crmsh/test/unittests/test_bugs.py --- old/crmsh/test/unittests/test_bugs.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/test/unittests/test_bugs.py 2014-03-17 13:09:30.000000000 +0100 @@ -225,3 +225,32 @@ xmlutil.sanitize_cib(elems) assert etree.tostring(elems).count("COMMENT TEXT") == 3 + +def test_eq1(): + xml1 = """<cluster_property_set id="cib-bootstrap-options"> + <nvpair id="cib-bootstrap-options-stonith-enabled" name="stonith-enabled" value="true"></nvpair> + <nvpair id="cib-bootstrap-options-stonith-timeout" name="stonith-timeout" value="180"></nvpair> + <nvpair id="cib-bootstrap-options-symmetric-cluster" name="symmetric-cluster" value="false"></nvpair> + <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="freeze"></nvpair> + <nvpair id="cib-bootstrap-options-batch-limit" name="batch-limit" value="20"></nvpair> + <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.1.10-c1a326d"></nvpair> + <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"></nvpair> + <nvpair id="cib-bootstrap-options-last-lrm-refresh" name="last-lrm-refresh" value="1391433789"></nvpair> + <nvpair id="cib-bootstrap-options-is-managed-default" name="is-managed-default" value="true"></nvpair> + </cluster_property_set> + """ + xml2 = """<cluster_property_set id="cib-bootstrap-options"> + <nvpair id="cib-bootstrap-options-stonith-enabled" name="stonith-enabled" value="true"></nvpair> + <nvpair id="cib-bootstrap-options-stonith-timeout" name="stonith-timeout" value="180"></nvpair> + <nvpair id="cib-bootstrap-options-symmetric-cluster" name="symmetric-cluster" value="false"></nvpair> + <nvpair id="cib-bootstrap-options-no-quorum-policy" name="no-quorum-policy" value="freeze"></nvpair> + <nvpair id="cib-bootstrap-options-batch-limit" name="batch-limit" value="20"></nvpair> + <nvpair id="cib-bootstrap-options-dc-version" name="dc-version" value="1.1.10-c1a326d"></nvpair> + <nvpair id="cib-bootstrap-options-cluster-infrastructure" name="cluster-infrastructure" value="corosync"></nvpair> + <nvpair id="cib-bootstrap-options-last-lrm-refresh" name="last-lrm-refresh" value="1391433789"></nvpair> + <nvpair id="cib-bootstrap-options-is-managed-default" name="is-managed-default" value="true"></nvpair> + </cluster_property_set> + """ + e1 = etree.fromstring(xml1) + e2 = etree.fromstring(xml2) + assert xmlutil.xml_equals(e1, e2, show=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/test/unittests/test_cliformat.py new/crmsh/test/unittests/test_cliformat.py --- old/crmsh/test/unittests/test_cliformat.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/test/unittests/test_cliformat.py 2014-03-17 13:09:30.000000000 +0100 @@ -19,6 +19,7 @@ import utils import parse import cibconfig +from lxml import etree from test_parse import MockValidation factory = cibconfig.cib_factory @@ -99,7 +100,6 @@ <resource_ref id="apache"/> </resource_set> </rsc_colocation>""" - from lxml import etree data = etree.fromstring(xml) obj = factory.new_object('colocation', 'colo-2') assert obj is not None @@ -127,7 +127,6 @@ value="Stopped"/> \ </meta_attributes> \ </primitive>""" - from lxml import etree data = etree.fromstring(xml) obj = factory.new_object('primitive', 'dummy') assert obj is not None @@ -152,7 +151,6 @@ <op name="monitor" interval="60" timeout="30" id="dummy2-monitor-60"/> \ </operations> \ </primitive>""" - from lxml import etree data = etree.fromstring(xml) obj = factory.new_object('primitive', 'dummy2') assert obj is not None @@ -163,3 +161,24 @@ exp = 'primitive dummy2 ocf:pacemaker:Dummy meta target-role="Stopped" op start timeout="60" interval="0" op stop timeout="60" interval="0" op monitor interval="60" timeout="30"' assert data == exp assert obj.cli_use_validate() + +def test_fencing(): + xml = """<fencing-topology> + <fencing-level devices="st1" id="fencing" index="1" +target="ha-three"></fencing-level> + <fencing-level devices="st1" id="fencing-0" index="1" +target="ha-two"></fencing-level> + <fencing-level devices="st1" id="fencing-1" index="1" +target="ha-one"></fencing-level> + </fencing-topology>""" + data = etree.fromstring(xml) + obj = factory.new_object('fencing_topology', 'st1') + assert obj is not None + obj.node = data + obj.set_id() + data = obj.repr_cli(format=-1) + print data + exp = 'fencing_topology st1' + assert data == exp + assert obj.cli_use_validate() + 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-03-08 14:13:37.000000000 +0100 +++ new/crmsh/test/unittests/test_parse.py 2014-03-17 13:09:30.000000000 +0100 @@ -203,6 +203,11 @@ self.assertEqual(out.node, 'bar') #print out.to_list() + out = self.parser.parse('location loc-1 thing rule role=slave -inf: #uname eq madrid') + self.assertEqual(out.id, 'loc-1') + self.assertEqual(out.resource, 'thing') + self.assertEqual(out.score, None) + def test_colocation(self): out = self.parser.parse('colocation col-1 inf: foo:master ( bar wiz sequential=yes )') self.assertEqual(out.id, 'col-1') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/utils/Makefile.am new/crmsh/utils/Makefile.am --- old/crmsh/utils/Makefile.am 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/utils/Makefile.am 2014-03-17 13:09:30.000000000 +0100 @@ -21,7 +21,7 @@ utilsdir = $(datadir)/@PACKAGE@/utils -utils_DATA = crm_script.py +utils_DATA = crm_script.py crm_init.py utils_SCRIPTS = crm_clean.py crm_rpmcheck.py crm_pkg.py EXTRA_DIST = $(utils_DATA) $(utils_SCRIPTS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/utils/crm_init.py new/crmsh/utils/crm_init.py --- old/crmsh/utils/crm_init.py 1970-01-01 01:00:00.000000000 +0100 +++ new/crmsh/utils/crm_init.py 2014-03-17 13:09:30.000000000 +0100 @@ -0,0 +1,263 @@ +import os +import re +import platform +import socket +import crm_script + +PACKAGES = ['booth', 'cluster-glue', 'corosync', 'crmsh', 'csync2', 'drbd', + 'fence-agents', 'gfs2', 'gfs2-utils', 'hawk', 'ocfs2', + 'ocfs2-tools', 'pacemaker', 'pacemaker-mgmt', + 'resource-agents', 'sbd'] +SERVICES = ['sshd', 'ntp', 'corosync', 'pacemaker', 'hawk', 'SuSEfirewall2_init'] +SSH_KEY = os.path.expanduser('~/.ssh/id_rsa') +CSYNC2_KEY = '/etc/csync2/key_hagroup' +CSYNC2_CFG = '/etc/csync2/csync2.cfg' +COROSYNC_CONF = '/etc/corosync/corosync.conf' +SYSCONFIG_SBD = '/etc/sysconfig/sbd' +SYSCONFIG_FW = '/etc/sysconfig/SuSEfirewall2' +SYSCONFIG_FW_CLUSTER = '/etc/sysconfig/SuSEfirewall2.d/services/cluster' + + +def rpm_info(): + 'check installed packages' + return crm_script.rpmcheck(PACKAGES) + + +def service_info(service): + "Returns information about a given service" + active, enabled = 'unknown', 'unknown' + rc, out, err = crm_script.call(["/usr/bin/systemctl", "is-enabled", "%s.service" % (service)]) + if rc in (0, 1, 3) and out: + enabled = out.strip() + else: + return {'name': service, 'error': err.strip()} + rc, out, err = crm_script.call(["/usr/bin/systemctl", "is-active", "%s.service" % (service)]) + if rc in (0, 1, 3) and out: + active = out.strip() + else: + return {'name': service, 'error': err.strip()} + return {'name': service, 'active': active, 'enabled': enabled} + + +def services_info(): + 'check enabled/active services' + return [service_info(service) for service in SERVICES] + + +def sys_info(): + 'system information' + system, node, release, version, machine, processor = platform.uname() + distname, distver, distid = platform.linux_distribution() + hostname = platform.node().split('.')[0] + return {'system': system, + 'node': node, + 'release': release, + 'version': version, + 'machine': machine, + 'processor': processor, + 'distname': distname, + 'distver': distver, + 'distid': distid, + 'user': os.getlogin(), + 'hostname': hostname, + 'fqdn': socket.getfqdn()} + + +def net_info(): + ret = {} + interfaces = [] + rc, out, err = crm_script.call(['netstat', '-nr']) + if rc == 0: + data = [l.split() for l in out.split('\n')] + if len(data) < 3: + return {'error': "Failed to parse netstat output"} + keys = data[1] + for line in data[2:]: + if len(line) == len(keys): + interfaces.append(dict(zip(keys, line))) + else: + interfaces.append({'error': err.strip()}) + ret['interfaces'] = interfaces + hostname = platform.node().split('.')[0] + try: + ip = socket.gethostbyname(hostname) + ret['hostname'] = {'name': hostname, 'ip': ip} + except Exception, e: + ret['hostname'] = {'error': str(e)} + return ret + + +def files_info(): + def check(fn): + if os.path.isfile(os.path.expanduser(fn)): + return os.path.expanduser(fn) + return '' + return {'ssh_key': check(SSH_KEY), + 'csync2_key': check(CSYNC2_KEY), + 'csync2_cfg': check(CSYNC2_CFG), + 'corosync_conf': check(COROSYNC_CONF), + 'sysconfig_sbd': check(SYSCONFIG_SBD), + 'sysconfig_fw': check(SYSCONFIG_FW), + 'sysconfig_fw_cluster': check(SYSCONFIG_FW_CLUSTER), + } + + +def logrotate_info(): + rc, _, _ = crm_script.call( + 'grep -r corosync.conf /etc/logrotate.d', + shell=True) + return {'corosync.conf': rc == 0} + + +def disk_info(): + rc, out, err = crm_script.call(['df'], shell=False) + if rc == 0: + disk_use = [] + for line in out.split('\n')[1:]: + line = line.strip() + if line: + data = line.split() + if len(data) >= 6: + disk_use.append((data[5], int(data[4][:-1]))) + return disk_use + return [] + + +def info(): + return {'rpm': rpm_info(), + 'services': services_info(), + 'system': sys_info(), + 'net': net_info(), + 'files': files_info(), + 'logrotate': logrotate_info(), + 'disk': disk_info()} + + +def verify(data): + """ + Given output from info(), verifies + as much as possible before init/add. + """ + def check_diskspace(): + for host, info in data.iteritems(): + for mount, percent in info['disk']: + interesting = (mount == '/' or + mount.startswith('/var/log') or + mount.startswith('/tmp')) + if interesting and percent > 90: + crm_script.exit_fail("Not enough space on %s:%s" % (host, mount)) + + def check_services(): + for host, info in data.iteritems(): + for svc in info['services']: + if svc['name'] == 'pacemaker' and svc['active'] == 'active': + crm_script.exit_fail("%s already running pacemaker" % (host)) + if svc['name'] == 'corosync' and svc['active'] == 'active': + crm_script.exit_fail("%s already running corosync" % (host)) + + def verify_host(host, info): + if host != info['system']['hostname']: + crm_script.exit_fail("Hostname mismatch: %s is not %s" % + (host, info['system']['hostname'])) + + def compare_system(systems): + def check(value, msg): + vals = set([system[value] for host, system in systems]) + if len(vals) > 1: + info = ', '.join('%s: %s' % (h, system[value]) for h, system in systems) + crm_script.exit_fail("%s: %s" % (msg, info)) + + check('machine', 'Architecture differs') + #check('release', 'Kernel release differs') + check('distname', 'Distribution differs') + check('distver', 'Distribution version differs') + #check('version', 'Kernel version differs') + + for host, info in data.iteritems(): + verify_host(host, info) + + compare_system((h, info['system']) for h, info in data.iteritems()) + + check_diskspace() + check_services() + + +# common functions to initialize a cluster node + + +def is_service_enabled(name): + info = service_info(name) + if info.get('name') == name and info.get('enabled') == 'enabled': + return True + return False + + +def is_service_active(name): + info = service_info(name) + if info.get('name') == name and info.get('active') == 'active': + return True + return False + + +def install_packages(packages): + for pkg in packages: + try: + crm_script.package(pkg, 'latest') + except Exception, e: + crm_script.exit_fail("Failed to install %s: %s" % (pkg, e)) + + +def configure_firewall(): + _SUSE_FW_TEMPLATE = """## Name: HAE cluster ports +## Description: opens ports for HAE cluster services +TCP="%(tcp)s" +UDP="%(udp)s" +""" + corosync_mcastport = crm_script.param('mcastport') + if not corosync_mcastport: + rc, out, err = crm_script.call(['crm', 'corosync', 'get', 'totem.interface.mcastport']) + if rc == 0: + corosync_mcastport = out.strip() + FW = '/etc/sysconfig/SuSEfirewall2' + FW_CLUSTER = '/etc/sysconfig/SuSEfirewall2.d/services/cluster' + + tcp_ports = '30865 5560 7630 21064' + udp_ports = '%s %s' % (corosync_mcastport, int(corosync_mcastport) - 1) + + if is_service_enabled('SuSEfirewall2'): + if os.path.isfile(FW_CLUSTER): + tmpl = open(FW_CLUSTER).read() + tmpl = re.sub(r'^TCP="(.*)"', 'TCP="%s"' % (tcp_ports), tmpl, flags=re.M) + tmpl = re.sub(r'^UDP="(.*)"', 'UDP="%s"' % (udp_ports), tmpl, flags=re.M) + with open(FW_CLUSTER, 'w') as f: + f.write(tmpl) + elif os.path.isdir(os.path.dirname(FW_CLUSTER)): + with open(FW_CLUSTER, 'w') as fwc: + fwc.write(_SUSE_FW_TEMPLATE % {'tcp': tcp_ports, + 'udp': udp_ports}) + else: + # neither the cluster file nor the services + # directory exists + crm_script.exit_fail("SUSE firewall is configured but %s does not exist" % + os.path.dirname(FW_CLUSTER)) + + # add cluster to FW_CONFIGURATIONS_EXT + if os.path.isfile(FW): + txt = open(FW).read() + m = re.search(r'^FW_CONFIGURATIONS_EXT="(.*)"', txt, re.M) + if m: + services = m.group(1).split() + if 'cluster' not in services: + services.append('cluster') + txt = re.sub(r'^FW_CONFIGURATIONS_EXT="(.*)"', + r'FW_CONFIGURATIONS_EXT="%s"' % (' '.join(services)), + txt, + flags=re.M) + else: + txt += '\nFW_CONFIGURATIONS_EXT="cluster"' + with open(FW, 'w') as fw: + fw.write(txt) + if is_service_active('SuSEfirewall2'): + crm_script.service('SuSEfirewall2', 'restart') + + # TODO: other platforms diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/utils/crm_pkg.py new/crmsh/utils/crm_pkg.py --- old/crmsh/utils/crm_pkg.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/utils/crm_pkg.py 2014-03-17 13:09:30.000000000 +0100 @@ -107,6 +107,7 @@ cmd = [self._zyp, '--non-interactive', + '--no-refresh', 'install', '--auto-agree-with-licenses', name] @@ -124,6 +125,7 @@ pre_version = self.get_version(name) cmd = [self._zyp, '--non-interactive', + '--no-refresh', 'update', '--auto-agree-with-licenses', name] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/utils/crm_script.py new/crmsh/utils/crm_script.py --- old/crmsh/utils/crm_script.py 2014-03-08 14:13:37.000000000 +0100 +++ new/crmsh/utils/crm_script.py 2014-03-17 13:09:30.000000000 +0100 @@ -171,3 +171,4 @@ except Exception, e: raise IOError("Failed to write %s from template %s: %s" % (dest, template, e)) debug("crm_script(save_template): wrote %s" % (dest)) + -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
