pacemaker/crm_history_6_441f4448eba6.patch
Tim Serong 0440703030 - Upgrade to 1.1.6.
- PE: Demote from Master does not clear previous errors
- crmd: Prevent secondary DC fencing resulting from CIB updates
  that are lost due to elections
- crmd: Log duplicate DC detection as a WARNING not ERROR
- crmd: Bug lf#2632 - Correctly handle nodes that return faster
  than stonith
- Core: Treat GNUTLS_E_UNEXPECTED_PACKET_LENGTH as normal
  termination of a TLS session
- cib: Call gnutls_bye() and shutdown() when disconnecting from
  remote TLS connections
- cib: Remove disconnected remote connections from mainloop
- cib: Attempt a graceful sign-off for remote TLS connections
- Core: Ensure there is sufficient space for EOS when building
  short-form option strings (prevents segfault)
- Core: Fix variable expansion in pkg-config files
- PE: Resolve memory leak reported by valgrind
- PE: Fix memory leak for re-allocated resources reported by
  valgrind
- PE: Improve the merging with template's operations
- crmd: Allow nodes to fence themselves if they're the last one
  standing (lf#2584)
- stonith: Add an API call for listing installed agents
- stonith: Allow the fencing history to be queried
- stonith: Ensure completed operations are recorded as such in
  the history
- stonith: Support --quiet to display just the seconds since
  epoch at which a node was last shot
- stonith: Serialize actions for a given device
- stonith: Add missing entries to stonith_error2string() (missing

OBS-URL: https://build.opensuse.org/package/show/network:ha-clustering:Factory/pacemaker?expand=0&rev=18
2011-09-20 14:36:23 +00:00

246 lines
8.6 KiB
Diff

# HG changeset patch
# User Dejan Muhamedagic <dejan@hello-penguin.com>
# Date 1313081065 -7200
# Node ID 441f4448eba6eda1a2cf44d3d63a0db9f8d56a20
# Parent c3068d22de72d1ba616d43c808091bef830eb9f6
Medium: Shell: reimplement the history latest command (bnc#710958)
This command is going to show logs for the latest transition.
Basically, it's the same as "history transition", but it will
wait for the current (if any) transition to finish.
(Also, the horrible transition command arg parsing has been
improved.)
diff --git a/shell/modules/report.py b/shell/modules/report.py
--- a/shell/modules/report.py
+++ b/shell/modules/report.py
@@ -467,8 +467,7 @@ class Report(Singleton):
def is_last_live_recent(self):
'''
Look at the last live hb_report. If it's recent enough,
- return True. Return True also if self.to_dt is not empty
- (not an open end report).
+ return True.
'''
try:
last_ts = os.stat(self.desc).st_mtime
@@ -800,6 +799,7 @@ class Report(Singleton):
if self.source != "live":
self.error("refresh not supported")
return False
+ self.last_live_update = 0
self.loc = self.manage_live_report(force)
self.report_setup()
self.ready = self.check_report()
@@ -884,18 +884,10 @@ class Report(Singleton):
print "Nodes:",' '.join(self.cibnode_l)
print "Groups:",' '.join(self.cibgrp_d.keys())
print "Resources:",' '.join(self.cibrsc_l)
- def latest(self):
- '''
- Get the very latest cluster events, basically from the
- latest transition.
- Some transitions may be empty though.
- '''
def events(self):
'''
Show all events.
'''
- if not self.prepare_source():
- return False
all_re_l = self.build_re("resource",self.cibrsc_l) + \
self.build_re("node",self.cibnode_l)
if not all_re_l:
@@ -906,6 +898,8 @@ class Report(Singleton):
'''
Search for events within the given transition.
'''
+ if not self.prepare_source():
+ return False
pe_base = os.path.basename(pe_file)
r = re.search("pe-[^-]+-([0-9]+)[.]", pe_base)
pe_num = r.group(1)
@@ -926,6 +920,9 @@ class Report(Singleton):
self.warn("strange, no timestamps found")
return False
# limit the log scope temporarily
+ common_info("logs for transition %s (%s-%s)" %
+ (pe_file.replace(self.loc+"/",""), \
+ shorttime(start_ts), shorttime(end_ts)))
self.logobj.set_log_timeframe(start_ts, end_ts)
self.events()
self.logobj.set_log_timeframe(self.from_dt, self.to_dt)
@@ -994,6 +991,11 @@ class Report(Singleton):
'Find a PE or dot file matching part of the path.'
pe_l = path.endswith(".dot") and self.dotlist() or self.pelist()
return [x for x in pe_l if x.endswith(path)]
+ def pe2dot(self, f):
+ f = f.replace("bz2","dot")
+ if os.path.isfile(f):
+ return f
+ return None
def find_file(self, f):
return file_find_by_name(self.loc, f)
diff --git a/shell/modules/ui.py.in b/shell/modules/ui.py.in
--- a/shell/modules/ui.py.in
+++ b/shell/modules/ui.py.in
@@ -1796,22 +1796,15 @@ Examine Pacemaker's history: node and re
return crm_report.info()
def latest(self,cmd):
"usage: latest"
- try:
- prev_level = levels.previous().myname()
- except:
- prev_level = ''
- if prev_level != "cibconfig":
- common_err("%s is available only when invoked from configure" % cmd)
- return False
- ts = cib_factory.last_commit_at()
- if not ts:
- common_err("no last commit time found")
- return False
if not wait4dc("transition", not options.batch):
return False
- self._set_source("live", ts)
+ self._set_source("live")
crm_report.refresh_source()
- return crm_report.events()
+ f = self._get_pe_byidx(-1)
+ if not f:
+ common_err("no transitions found")
+ return False
+ crm_report.show_transition_log(f)
def resource(self,cmd,*args):
"usage: resource <rsc> [<rsc> ...]"
return crm_report.resource(*args)
@@ -1853,6 +1846,30 @@ Examine Pacemaker's history: node and re
else:
s = '\n'.join(l)
page_string(s)
+ def _get_pe_byname(self, s):
+ l = crm_report.find_pe_files(s)
+ if len(l) == 0:
+ common_err("%s: path not found" % s)
+ return None
+ elif len(l) > 1:
+ common_err("%s: path ambiguous" % s)
+ return None
+ return l[0]
+ def _get_pe_byidx(self, idx):
+ l = crm_report.pelist()
+ if len(l) < abs(idx):
+ common_err("pe input file not found")
+ return None
+ return l[idx]
+ def _get_pe_bynum(self, n):
+ l = crm_report.pelist([n])
+ if len(l) == 0:
+ common_err("%s: PE file %d not found" % n)
+ return None
+ elif len(l) > 1:
+ common_err("%s: PE file %d ambiguous" % n)
+ return None
+ return l[0]
def transition(self,cmd,*args):
"""usage: transition [<number>|<file>] [nograph] [v...] [scores] [actions] [utilization]
transition showdot [<number>|<file>]"""
@@ -1864,48 +1881,35 @@ Examine Pacemaker's history: node and re
return False
subcmd = "showdot"
argl.remove(subcmd)
- f = None
- startarg = 1
- if argl and re.search('pe-', argl[0]):
- l = crm_report.find_pe_files(argl[0])
- if len(l) == 0:
- common_err("%s: path not found" % argl[0])
- return False
- elif len(l) > 1:
- common_err("%s: path ambiguous" % argl[0])
- return False
- f = l[0]
+ if argl:
+ if re.search('pe-', argl[0]):
+ f = self._get_pe_byname(argl[0])
+ argl.pop(0)
+ elif is_int(argl[0]):
+ n = int(argl[0])
+ if n <= 0:
+ f = self._get_pe_byidx(n-1)
+ else:
+ f = self._get_pe_bynum(n)
+ argl.pop(0)
+ else:
+ f = self._get_pe_byidx(-1)
else:
- try: n = convert2ints(argl[0])
- except: n = None
- if n is None:
- idx = -1
- startarg = 0 # peinput number missing
- elif n <= 0:
- idx = n - 1
- n = [] # to get all peinputs
- else:
- idx = 0
- if subcmd == "showdot":
- l = crm_report.dotlist(n)
- else:
- l = crm_report.pelist(n)
- if len(l) < abs(idx):
- if subcmd == "show":
- common_err("pe input file not found")
- else:
- common_err("dot file not found")
- return False
- f = l[idx]
+ f = self._get_pe_byidx(-1)
if not f:
return False
rc = True
if subcmd == "show":
self.pe_file = f # self.pe_file needed by self.ptest
+ common_info("running ptest with %s" % f)
rc = ptestlike(self.ptest,'vv',"%s %s" % \
- (cmd, subcmd), *argl[startarg:])
+ (cmd, subcmd), *argl)
else:
- show_dot_graph(f.replace("bz2","dot"))
+ f = crm_report.pe2dot(f)
+ if not f:
+ common_err("dot file not found in the report")
+ return False
+ show_dot_graph(f)
if rc:
crm_report.show_transition_log(f)
return rc
diff --git a/shell/modules/utils.py b/shell/modules/utils.py
--- a/shell/modules/utils.py
+++ b/shell/modules/utils.py
@@ -449,6 +449,9 @@ def check_range(a):
return False
return (int(a[0]) <= int(a[1]))
+def shorttime(ts):
+ return time.strftime("%X",time.localtime(ts))
+
def sort_by_mtime(l):
'Sort a (small) list of files by time mod.'
l2 = [(os.stat(x).st_mtime, x) for x in l]
@@ -489,6 +492,13 @@ def convert2ints(l):
else: # it's a string then
return int(l)
except: return None
+def is_int(s):
+ 'Check if the string can be converted to an integer.'
+ try:
+ i = int(s)
+ return True
+ except:
+ return False
def is_process(s):
proc = subprocess.Popen("ps -e -o pid,command | grep -qs '%s'" % s, \