Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2014-10-11 19:26:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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-28 19:54:13.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.crmsh.new/crmsh.changes 2014-10-11 19:28:33.000000000 +0200 @@ -1,0 +2,19 @@ +Fri Oct 10 17:30:14 UTC 2014 - kgronl...@suse.com + +- high: report: Find nodes for any log type (boo#900654) +- high: hb_report: Collect logs from journald (boo#900654) +- upstream cs: 2.1.0-98-g2405e74 + +------------------------------------------------------------------- +Fri Oct 10 08:50:08 UTC 2014 - kgronl...@suse.com + +- high: ui_maintenance: Add maintenance sublevel (bnc#899234) +- medium: rsctest: Add basic support for systemd services +- medium: ui_maintenance: Combine action and actionssh into a single command +- low: rsctest: Better error message for unsupported action +- low: cibconfig: Improve wording of commit prompt +- high: cibconfig: Delay reinitialization after commit (bnc#900271) +- medium: main: Disable interspersed args +- upstream cs: 2.1.0-95-g744ad66 + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.5NmvSC/_old 2014-10-11 19:28:34.000000000 +0200 +++ /var/tmp/diff_new_pack.5NmvSC/_new 2014-10-11 19:28:34.000000000 +0200 @@ -41,7 +41,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0+ Group: %{pkg_group} -Version: 2.1+git82 +Version: 2.1+git98 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/doc/crm.8.adoc new/crmsh/doc/crm.8.adoc --- old/crmsh/doc/crm.8.adoc 2014-09-26 12:07:07.000000000 +0200 +++ new/crmsh/doc/crm.8.adoc 2014-10-10 19:26:22.000000000 +0200 @@ -3808,6 +3808,76 @@ weak-bond resource-1 resource-2 ........ +[[cmdhelp_maintenance,Maintenance mode commands]] +=== `maintenance` - Maintenance mode commands + +Maintenance mode commands are commands that manipulate resources +directly without going through the cluster infrastructure. Therefore, +it is essential to ensure that the cluster does not attempt to monitor +or manipulate the resources while these commands are being executed. + +To ensure this, these commands require that maintenance mode is set +either for the particular resource, or for the whole cluster. + +[[cmdhelp_maintenance_on,Enable maintenance mode]] +==== `on` + +Enables maintenances mode, either for the whole cluster +or for the given resource. + +Usage: +............... +on +on <rsc> +............... +Example: +............... +on rsc1 +............... + +[[cmdhelp_maintenance_off,Disable maintenance mode]] +==== `off` + +Disables maintenances mode, either for the whole cluster +or for the given resource. + +Usage: +............... +off +off <rsc> +............... +Example: +............... +off rsc1 +............... + +[[cmdhelp_maintenance_action,Invoke a resource action]] +==== `action` + +Invokes the given action for the resource. This is +done directly via the resource agent, so the command must +be issued while the cluster or the resource is in +maintenance mode. + +Unless the action is `start` or `monitor`, the action must be invoked +on the same node as where the resource is running. If the resource is +running on multiple nodes, the command will fail. + +To use pssh for executing resource actions on multiple nodes, append +`ssh` after the action name. This requires SSH access to be configured +between the nodes and the pssh package to be installed. + +Usage: +............... +action <rsc> <action> +action <rsc> <action> ssh +............... +Example: +............... +action webserver reload +action webserver monitor ssh +............... + [[cmdhelp_history,Cluster history]] === `history` - Cluster history diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/doc/website-v1/Makefile new/crmsh/doc/website-v1/Makefile --- old/crmsh/doc/website-v1/Makefile 2014-09-26 12:07:07.000000000 +0200 +++ new/crmsh/doc/website-v1/Makefile 2014-10-10 19:26:22.000000000 +0200 @@ -1,4 +1,5 @@ ASCIIDOC := asciidoc +CRMCONF := crm.conf SRC := faq.adoc documentation.adoc development.adoc installation.adoc \ configuration.adoc about.adoc rsctest-guide.adoc \ history-guide.adoc start-guide.adoc man-1.2.adoc scripts.adoc man-2.0.adoc @@ -20,33 +21,33 @@ all: site -gen/index.html: index.adoc crm.conf +gen/index.html: index.adoc $(CRMCONF) @mkdir -p $(dir $@) - @$(ASCIIDOC) --unsafe -b html5 -f crm.conf -o $@ $< + @$(ASCIIDOC) --unsafe -b html5 -f $(CRMCONF) -o $@ $< @python ./postprocess.py -o $@ $< -gen/%/index.html: %.adoc crm.conf +gen/%/index.html: %.adoc $(CRMCONF) @mkdir -p $(dir $@) - @$(ASCIIDOC) --unsafe -b html5 -f crm.conf -o $@ $< + @$(ASCIIDOC) --unsafe -b html5 -f $(CRMCONF) -o $@ $< @python ./postprocess.py -o $@ $< -gen/man/index.html: ../crm.8.adoc crm.conf +gen/man/index.html: ../crm.8.adoc $(CRMCONF) @mkdir -p $(dir $@) - @$(ASCIIDOC) --unsafe -b html5 -f crm.conf -o $@ $< + @$(ASCIIDOC) --unsafe -b html5 -f $(CRMCONF) -o $@ $< @python ./postprocess.py -o $@ $< -gen/404.html: 404.adoc crm.conf +gen/404.html: 404.adoc $(CRMCONF) @mkdir -p $(dir $@) - @$(ASCIIDOC) --unsafe -b html5 -f crm.conf -o $@ $< + @$(ASCIIDOC) --unsafe -b html5 -f $(CRMCONF) -o $@ $< @python ./postprocess.py -o $@ $< -news.adoc: $(NEWS) crm.conf +news.adoc: $(NEWS) $(CRMCONF) @echo "news:" $(NEWS) python ./make-news.py $@ $(NEWS) gen/news/index.html: news.adoc @mkdir -p $(dir $@) - $(ASCIIDOC) --unsafe -b html5 -f crm.conf -o $@ $< + $(ASCIIDOC) --unsafe -b html5 -f $(CRMCONF) -o $@ $< @python ./postprocess.py -o $@ $< gen/css/%.css: css/%.css diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/doc/website-v1/crmold.conf new/crmsh/doc/website-v1/crmold.conf --- old/crmsh/doc/website-v1/crmold.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/crmsh/doc/website-v1/crmold.conf 2014-10-10 19:26:22.000000000 +0200 @@ -0,0 +1,602 @@ +# +# html5.conf +# +# Asciidoc configuration file. +# html5 backend. +# + +[miscellaneous] +outfilesuffix=.html + +[attributes] +basebackend=html +basebackend-html= +basebackend-html5= +b +[replacements2] +# Line break. +(?m)^(.*)\s\+$=\1<br> + +[replacements] +ifdef::asciidoc7compatible[] +# Superscripts. +\^(.+?)\^=<sup>\1</sup> +# Subscripts. +~(.+?)~=<sub>\1</sub> +endif::asciidoc7compatible[] + +[ruler-blockmacro] +<hr> + +[pagebreak-blockmacro] +<div style="page-break-after:always"></div> + +[blockdef-pass] +asciimath-style=template="asciimathblock",subs=() +latexmath-style=template="latexmathblock",subs=() + +[macros] +(?u)^(?P<name>audio|video)::(?P<target>\S*?)(\[(?P<attrlist>.*?)\])$=# +# math macros. +# Special characters are escaped in HTML math markup. +(?su)[\\]?(?P<name>asciimath|latexmath):(?P<subslist>\S*?)\[(?P<passtext>.*?)(?<!\\)\]=[specialcharacters] +(?u)^(?P<name>asciimath|latexmath)::(?P<subslist>\S*?)(\[(?P<passtext>.*?)\])$=#[specialcharacters] + +[asciimath-inlinemacro] +`{passtext}` + +[asciimath-blockmacro] +<div class="mathblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="content"> +<div class="title">{title}</div> +`{passtext}` +</div></div> + +[asciimathblock] +<div class="mathblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="content"> +<div class="title">{title}</div> +`|` +</div></div> + +[latexmath-inlinemacro] +{passtext} + +[latexmath-blockmacro] +<div class="mathblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="content"> +<div class="title">{title}</div> +{passtext} +</div></div> + +[latexmathblock] +<div class="mathblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="content"> +<div class="title">{title}</div> +| +</div></div> + +[image-inlinemacro] +<span class="image{role? {role}}"> +<a class="image" href="{link}"> +{data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"}> +{data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"} +{data-uri#}{sys:"{python}" -u -c "import mimetypes,base64,sys; print 'src=\"data:'+mimetypes.guess_type(r'{target}')[0]+';base64,'; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}"> +{link#}</a> +</span> + +[image-blockmacro] +<div class="imageblock{style? {style}}{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}{align? style="text-align:{align};"}{float? style="float:{float};"}> +<div class="content"> +<a class="image" href="{link}"> +{data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}> +{data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} +{data-uri#}{sys:"{python}" -u -c "import mimetypes,base64,sys; print 'src=\"data:'+mimetypes.guess_type(r'{target}')[0]+';base64,'; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}"> +{link#}</a> +</div> +<div class="title">{caption={figure-caption} {counter:figure-number}. }{title}</div> +</div> + +[audio-blockmacro] +<div class="audioblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{caption=}{title}</div> +<div class="content"> +<audio src="{imagesdir=}{imagesdir?/}{target}"{autoplay-option? autoplay}{nocontrols-option! controls}{loop-option? loop}> +Your browser does not support the audio tag. +</audio> +</div></div> + +[video-blockmacro] +<div class="videoblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{caption=}{title}</div> +<div class="content"> +<video src="{imagesdir=}{imagesdir?/}{target}"{width? width="{width}"}{height? height="{height}"}{poster? poster="{poster}"}{autoplay-option? autoplay}{nocontrols-option! controls}{loop-option? loop}> +Your browser does not support the video tag. +</video> +</div></div> + +[unfloat-blockmacro] +<div style="clear:both;"></div> + +[toc-blockmacro] +template::[toc] + +[indexterm-inlinemacro] +# Index term. +{empty} + +[indexterm2-inlinemacro] +# Index term. +# Single entry index term that is visible in the primary text flow. +{1} + +[footnote-inlinemacro] +# footnote:[<text>]. +<span class="footnote"><br>[{0}]<br></span> + +[footnoteref-inlinemacro] +# footnoteref:[<id>], create reference to footnote. +{2%}<span class="footnoteref"><br><a href="#_footnote_{1}">[{1}]</a><br></span> +# footnoteref:[<id>,<text>], create footnote with ID. +{2#}<span class="footnote" id="_footnote_{1}"><br>[{2}]<br></span> + +[callout-inlinemacro] +ifndef::icons[] +<b><{index}></b> +endif::icons[] +ifdef::icons[] +ifndef::data-uri[] +<img src="{icon={iconsdir}/callouts/{index}.png}" alt="{index}"> +endif::data-uri[] +ifdef::data-uri[] +<img alt="{index}" src="data:image/png;base64, +{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{index}.png}")}"}"> +endif::data-uri[] +endif::icons[] + +# Comment line macros. +[comment-inlinemacro] +{showcomments#}<br><span class="comment">{passtext}</span><br> + +[comment-blockmacro] +{showcomments#}<p><span class="comment">{passtext}</span></p> + +[literal-inlinemacro] +# Inline literal. +<span class="monospaced">{passtext}</span> + +# List tags. +[listtags-bulleted] +list=<div class="ulist{style? {style}}{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ul>|</ul></div> +item=<li>|</li> +text=<p>|</p> + +[listtags-numbered] +# The start attribute is not valid XHTML 1.1 but all browsers support it. +list=<div class="olist{style? {style}}{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ol class="{style}"{start? start="{start}"}>|</ol></div> +item=<li>|</li> +text=<p>|</p> + +[listtags-labeled] +list=<div class="dlist{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<dl>|</dl></div> +entry= +label= +term=<dt class="hdlist1{strong-option? strong}">|</dt> +item=<dd>|</dd> +text=<p>|</p> + +[listtags-horizontal] +list=<div class="hdlist{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<table>{labelwidth?<col width="{labelwidth}%">}{itemwidth?<col width="{itemwidth}%">}|</table></div> +label=<td class="hdlist1{strong-option? strong}">|</td> +term=|<br> +entry=<tr>|</tr> +item=<td class="hdlist2">|</td> +text=<p style="margin-top: 0;">|</p> + +[listtags-qanda] +list=<div class="qlist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ol>|</ol></div> +entry=<li>|</li> +label= +term=<p><em>|</em></p> +item= +text=<p>|</p> + +[listtags-callout] +ifndef::icons[] +list=<div class="colist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ol>|</ol></div> +item=<li>|</li> +text=<p>|</p> +endif::icons[] +ifdef::icons[] +list=<div class="colist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<table>|</table></div> +ifndef::data-uri[] +item=<tr><td><img src="{iconsdir}/callouts/{listindex}.png" alt="{listindex}"></td><td>|</td></tr> +endif::data-uri[] +ifdef::data-uri[] +item=<tr><td><img alt="{listindex}" src="data:image/png;base64, {sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{listindex}.png}")}"}"></td><td>|</td></tr> +endif::data-uri[] +text=| +endif::icons[] + +[listtags-glossary] +list=<div class="dlist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<dl>|</dl></div> +label= +entry= +term=<dt>|</dt> +item=<dd>|</dd> +text=<p>|</p> + +[listtags-bibliography] +list=<div class="ulist{style? {style}}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ul>|</ul></div> +item=<li>|</li> +text=<p>|</p> + +[tags] +# Quoted text. +emphasis=<em>{1?<span class="{1}">}|{1?</span>}</em> +strong=<strong>{1?<span class="{1}">}|{1?</span>}</strong> +monospaced=<span class="monospaced{1? {1}}">|</span> +singlequoted={lsquo}{1?<span class="{1}">}|{1?</span>}{rsquo} +doublequoted={ldquo}{1?<span class="{1}">}|{1?</span>}{rdquo} +unquoted={1?<span class="{1}">}|{1?</span>} +superscript=<sup>{1?<span class="{1}">}|{1?</span>}</sup> +subscript=<sub>{1?<span class="{1}">}|{1?</span>}</sub> + +ifdef::deprecated-quotes[] +# Override with deprecated quote attributes. +emphasis={role?<span class="{role}">}<em{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</em>{role?</span>} +strong={role?<span class="{role}">}<strong{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</strong>{role?</span>} +monospaced=<span class="monospaced{role? {role}}"{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</span> +singlequoted={role?<span class="{role}">}{1,2,3?<span style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?">}{amp}#8216;|{amp}#8217;{1,2,3?</span>}{role?</span>} +doublequoted={role?<span class="{role}">}{1,2,3?<span style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?">}{amp}#8220;|{amp}#8221;{1,2,3?</span>}{role?</span>} +unquoted={role?<span class="{role}">}{1,2,3?<span style="{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}">}|{1,2,3?</span>}{role?</span>} +superscript={role?<span class="{role}">}<sup{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</sup>{role?</span>} +subscript={role?<span class="{role}">}<sub{1,2,3? style="}{1?color:{1};}{2?background-color:{2};}{3?font-size:{3}em;}{1,2,3?"}>|</sub>{role?</span>} +endif::deprecated-quotes[] + +# Inline macros +[http-inlinemacro] +<a href="{name}:{target}">{0={name}:{target}}</a> +[https-inlinemacro] +<a href="{name}:{target}">{0={name}:{target}}</a> +[ftp-inlinemacro] +<a href="{name}:{target}">{0={name}:{target}}</a> +[file-inlinemacro] +<a href="{name}:{target}">{0={name}:{target}}</a> +[irc-inlinemacro] +<a href="{name}:{target}">{0={name}:{target}}</a> +[mailto-inlinemacro] +<a href="mailto:{target}">{0={target}}</a> +[link-inlinemacro] +<a href="{target}">{0={target}}</a> +[callto-inlinemacro] +<a href="{name}:{target}">{0={target}}</a> +# anchor:id[text] +[anchor-inlinemacro] +<a id="{target}"></a> +# [[id,text]] +[anchor2-inlinemacro] +<a id="{1}"></a> +# [[[id]]] +[anchor3-inlinemacro] +<a id="{1}"></a>[{1}] +# xref:id[text] +[xref-inlinemacro] +<a href="#{target}">{0=[{target}]}</a> +# <<id,text>> +[xref2-inlinemacro] +<a href="#{1}">{2=[{1}]}</a> + +# Special word substitution. +[emphasizedwords] +<em>{words}</em> +[monospacedwords] +<span class="monospaced">{words}</span> +[strongwords] +<strong>{words}</strong> + +# Paragraph substitution. +[paragraph] +<div class="paragraph{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<p> +| +</p></div> + +[admonitionparagraph] +template::[admonitionblock] + +# Delimited blocks. +[listingblock] +<div class="listingblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{caption=}{title}</div> +<div class="content monospaced"> +<pre> +| +</pre> +</div></div> + +[literalblock] +<div class="literalblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{title}</div> +<div class="content monospaced"> +<pre> +| +</pre> +</div></div> + +[sidebarblock] +<div class="sidebarblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="content"> +<div class="title">{title}</div> +| +</div></div> + +[openblock] +<div class="openblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{title}</div> +<div class="content"> +| +</div></div> + +[partintroblock] +template::[openblock] + +[abstractblock] +template::[quoteblock] + +[quoteblock] +<div class="quoteblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{title}</div> +<div class="content"> +| +</div> +<div class="attribution"> +<em>{citetitle}</em>{attribution?<br>} +— {attribution} +</div></div> + +[verseblock] +<div class="verseblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{title}</div> +<pre class="content"> +| +</pre> +<div class="attribution"> +<em>{citetitle}</em>{attribution?<br>} +— {attribution} +</div></div> + +[exampleblock] +<div class="exampleblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<div class="title">{caption={example-caption} {counter:example-number}. }{title}</div> +<div class="content"> +| +</div></div> + +[admonitionblock] +<div class="admonitionblock{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}> +<table><tr> +<td class="icon"> +{data-uri%}{icons#}<img src="{icon={iconsdir}/{name}.png}" alt="{caption}"> +{data-uri#}{icons#}<img alt="{caption}" src="data:image/png;base64, +{data-uri#}{icons#}{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/{name}.png}")}"}"> +{icons%}<div class="title">{caption}</div> +</td> +<td class="content"> +<div class="title">{title}</div> +| +</td> +</tr></table> +</div> + +# Tables. +[tabletags-default] +colspec=<col{autowidth-option! style="width:{colpcwidth}%;"}> +bodyrow=<tr>|</tr> +headdata=<th class="tableblock halign-{halign=left} valign-{valign=top}" {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }>|</th> +bodydata=<td class="tableblock halign-{halign=left} valign-{valign=top}" {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }>|</td> +paragraph=<p class="tableblock">|</p> + +[tabletags-header] +paragraph=<p class="tableblock header">|</p> + +[tabletags-emphasis] +paragraph=<p class="tableblock"><em>|</em></p> + +[tabletags-strong] +paragraph=<p class="tableblock"><strong>|</strong></p> + +[tabletags-monospaced] +paragraph=<p class="tableblock monospaced">|</p> + +[tabletags-verse] +bodydata=<td class="tableblock halign-{halign=left} valign-{valign=top}" {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }><div class="verse">|</div></td> +paragraph= + +[tabletags-literal] +bodydata=<td class="tableblock halign-{halign=left} valign-{valign=top}" {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }><div class="literal monospaced"><pre>|</pre></div></td> +paragraph= + +[tabletags-asciidoc] +bodydata=<td class="tableblock halign-{halign=left} valign-{valign=top}" {colspan@1::colspan="{colspan}" }{rowspan@1::rowspan="{rowspan}" }><div>|</div></td> +paragraph= + +[table] +<table class="tableblock frame-{frame=all} grid-{grid=all}{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"} +style=" +margin-left:{align@left:0}{align@center|right:auto}; margin-right:{align@left|center:auto}{align@right:0}; +float:{float}; +{autowidth-option%}width:{tablepcwidth}%; +{autowidth-option#}{width#style=width:{tablepcwidth}%;} +"> +<caption class="title">{caption={table-caption} {counter:table-number}. }{title}</caption> +{colspecs} +{headrows#}<thead> +{headrows} +{headrows#}</thead> +{footrows#}<tfoot> +{footrows} +{footrows#}</tfoot> +<tbody> +{bodyrows} +</tbody> +</table> + +#-------------------------------------------------------------------- +# Deprecated old table definitions. +# + +[miscellaneous] +# Screen width in pixels. +pagewidth=800 +pageunits=px + +[old_tabledef-default] +template=old_table +colspec=<col style="width:{colwidth}{pageunits};" /> +bodyrow=<tr>|</tr> +headdata=<th class="tableblock halign-{colalign=left}">|</th> +footdata=<td class="tableblock halign-{colalign=left}">|</td> +bodydata=<td class="tableblock halign-{colalign=left}">|</td> + +[old_table] +<table class="tableblock frame-{frame=all} grid-{grid=all}"{id? id="{id}"}> +<caption class="title">{caption={table-caption}}{title}</caption> +{colspecs} +{headrows#}<thead> +{headrows} +{headrows#}</thead> +{footrows#}<tfoot> +{footrows} +{footrows#}</tfoot> +<tbody style="vertical-align:top;"> +{bodyrows} +</tbody> +</table> + +# End of deprecated old table definitions. +#-------------------------------------------------------------------- + +[floatingtitle] +<h{level@0:1}{level@1:2}{level@2:3}{level@3:4}{level@4:5}{id? id="{id}"} class="float">{title}</h{level@0:1}{level@1:2}{level@2:3}{level@3:4}{level@4:5}> + +[preamble] +# Untitled elements between header and first section title. +<div id="preamble"> +<div class="sectionbody"> +| +</div> +</div> + +# Document sections. +[sect0] +<h1{id? id="{id}"}>{title}</h1> +| + +[sect1] +<div class="sect1{style? {style}}{role? {role}}"> +<h2{id? id="{id}"}>{numbered?{sectnum} }{title}</h2> +<div class="sectionbody"> +| +</div> +</div> + +[sect2] +<div class="sect2{style? {style}}{role? {role}}"> +<h3{id? id="{id}"}>{numbered?{sectnum} }{title}</h3> +| +</div> + +[sect3] +<div class="sect3{style? {style}}{role? {role}}"> +<h4{id? id="{id}"}>{numbered?{sectnum} }{title}</h4> +| +</div> + +[sect4] +<div class="sect4{style? {style}}{role? {role}}"> +<h5{id? id="{id}"}>{title}</h5> +| +</div> + +[appendix] +<div class="sect1{style? {style}}{role? {role}}"> +<h2{id? id="{id}"}>{numbered?{sectnum} }{appendix-caption} {counter:appendix-number:A}: {title}</h2> +<div class="sectionbody"> +| +</div> +</div> + +[toc] +<div id="toc"> + <div id="toctitle">{toc-title}</div> + <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript> +</div> + +[header] +<!DOCTYPE html> +<html lang="{lang=en}"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset={encoding}"> +<meta name="generator" content="AsciiDoc {asciidoc-version}"> +<meta name="description" content="{description}"> +<meta name="keywords" content="{keywords}"> +<title>crmsh - {title}</title> +{title%}<title>crmsh - {doctitle=}</title> +<link rel="stylesheet" href="http://crmsh.nongnu.org/css/font-awesome.min.css"> +<link rel="stylesheet" href="http://crmsh.nongnu.org/css/crm.css" type="text/css"> +<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700|Ubuntu+Mono' rel='stylesheet' type='text/css'> +<link href="http://crmsh.github.io/atom.xml" type="application/atom+xml" rel="alternate" title="crmsh atom feed"> +<style> +\#movenotice { + width: 600px; + margin-top: 1em; + margin-bottom: 1em; + margin-left: auto; + margin-right: auto; + font-size: 100%; + padding: 4px; + border: 2px dashed red; +} +</style> +</head> +<body> +<div id="header"> +<h1><a href="http://crmsh.github.io/index.html"><span class="fa-stack"> + <i class="fa fa-square fa-stack-2x"></i> + <i class="fa fa-terminal fa-stack-1x fa-inverse"></i> +</span>crmsh</a></h1> +<div id="topbar"> +<ul> +<li><a href="http://crmsh.github.io/news">News</a></li> +<li><a href="http://crmsh.github.io/documentation">Documentation</a></li> +<li><a href="http://crmsh.github.io/development">Development</a></li> +<li><a href="http://crmsh.github.io/about">About</a></li> +</ul> +</div> +</div> +<!--TOC--> +<div id="container"> +<div id="content"> + +<div id="movenotice">We have moved! The website for crmsh is now <a href="http://crmsh.github.io">http://crmsh.github.io</a>.</div> + +<h1>{doctitle}</h1> + +[footer] +</div> +</div> +<div id="footer"> +<div id="footer-text"> +</div> +</div> + +<a href="https://github.com/crmsh/crmsh"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a> + +</body> +</html> + +ifdef::doctype-manpage[] +[synopsis] +template::[sect1] +endif::doctype-manpage[] + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/hb_report/hb_report.in new/crmsh/hb_report/hb_report.in --- old/crmsh/hb_report/hb_report.in 2014-09-26 12:07:07.000000000 +0200 +++ new/crmsh/hb_report/hb_report.in 2014-10-10 19:26:22.000000000 +0200 @@ -305,11 +305,14 @@ # findlog() { local logf="" + collect_journal $FROM_TIME $TO_TIME $WORKDIR/$JOURNAL_F if [ "$HA_LOGFACILITY" ]; then logf=`findmsg $UNIQUE_MSG | awk '{print $1}'` fi if [ -f "$logf" ]; then echo $logf + elif [ -f "$WORKDIR/$JOURNAL_F" ]; then + echo $WORKDIR/$JOURNAL_F else echo ${HA_DEBUGFILE:-$HA_LOGFILE} [ "${HA_DEBUGFILE:-$HA_LOGFILE}" ] && @@ -1094,6 +1097,29 @@ fi fi } +collect_journal() { + local from_time to_time outf + from_time="$1" + to_time="$2" + outf="$3" + if which journalctl > /dev/null 2>&1; then + if isnumber "$from_time" && [ $from_time -eq 0 ]; then + from_time=$(date "+%Y-%m-%d %H:%M") + elif isnumber "$from_time"; then + from_time=$(echo "$from_time" | awk '{ print strftime("%Y-%m-%d %H:%M", $1); }') + fi + if isnumber "$to_time" && [ $to_time -eq 0 ]; then + to_time=$(date "+%Y-%m-%d %H:%M") + elif isnumber "$to_time"; then + to_time=$(echo "$to_time" | awk '{ print strftime("%Y-%m-%d %H:%M", $1); }') + fi + if [ -f $outf ]; then + warning "$outf already exists" + fi + debug "journalctl from: '$1' until: '$2' from_time '$from_time' to_time: '$to_time' > $outf" + journalctl --since "$from_time" --until "$to_time" --no-pager | tail -n +2 > $outf + fi +} # # get all other info (config, stats, etc) # @@ -1314,12 +1340,13 @@ ANALYSIS_F=analysis.txt DESCRIPTION_F=description.txt HALOG_F=ha-log.txt +JOURNAL_F=journal.log BT_F=backtraces.txt SYSINFO_F=sysinfo.txt SYSSTATS_F=sysstats.txt DLM_DUMP_F=dlm_dump.txt TIME_F=time.txt -export ANALYSIS_F DESCRIPTION_F HALOG_F BT_F SYSINFO_F SYSSTATS_F DLM_DUMP_F TIME_F +export ANALYSIS_F DESCRIPTION_F HALOG_F JOURNAL_F BT_F SYSINFO_F SYSSTATS_F DLM_DUMP_F TIME_F CRM_MON_F=crm_mon.txt MEMBERSHIP_F=members.txt HB_UUID_F=hb_uuid.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/Makefile.am new/crmsh/modules/Makefile.am --- old/crmsh/modules/Makefile.am 2014-09-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/Makefile.am 2014-10-10 19:26:22.000000000 +0200 @@ -59,6 +59,7 @@ ui_context.py \ ui_corosync.py \ ui_history.py \ + ui_maintenance.py \ ui_node.py \ ui_options.py \ ui_ra.py \ 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-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/cibconfig.py 2014-10-10 19:26:22.000000000 +0200 @@ -304,9 +304,10 @@ if edit_file(tmp) != 0: break s = open(tmp).read() - if hash(s) != filehash and (not self.save(self._post_edit(s)) - and ask("Do you want to edit again?")): - continue + if hash(s) != filehash: + ok = self.save(self._post_edit(s)) + if not ok and ask("Edit or discard changes (yes to edit, no to discard)?"): + continue rc = True os.unlink(tmp) except OSError, e: @@ -530,7 +531,7 @@ ''' Edit or display a set of cib objects (using cli notation). ''' - vim_stx_str = "#vim:set syntax=pcmk\n" + vim_stx_str = "# vim: set filetype=pcmk:\n" def __init__(self, *args): CibObjectSet.__init__(self, *args) @@ -1201,6 +1202,11 @@ else: return self + def meta_attributes(self, name): + "Returns all meta attribute values with the given name" + v = self.node.xpath('./meta_attributes/nvpair[@name="%s"]/@value' % (name)) + return v + def find_child_in_node(self, child): for c in self.node.iterchildren(): if c.tag == child.obj_type and \ @@ -2313,7 +2319,6 @@ if is_live_cib(): self.last_commit_time = t self.reset() - self.initialize() return rc def _update_schema(self): 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-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/main.py 2014-10-10 19:26:22.000000000 +0200 @@ -105,6 +105,7 @@ See the crm(8) man page or call %prog help for more details.""", version="%prog " + config.CRM_VERSION) + parser.disable_interspersed_args() 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 " + 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-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/report.py 2014-10-10 19:26:22.000000000 +0200 @@ -727,8 +727,7 @@ def get_nodes(self): 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"))]) + if self.find_node_log(p) is not None]) 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/rsctest.py new/crmsh/modules/rsctest.py --- old/crmsh/modules/rsctest.py 2014-09-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/rsctest.py 2014-10-10 19:26:22.000000000 +0200 @@ -18,7 +18,7 @@ import os import sys from msg import common_err, common_debug, common_warn, common_info -from utils import rmdir_r, quote +from utils import rmdir_r, quote, this_node, ext_cmd from xmlutil import get_topmost_rsc, get_op_timeout, get_child_nvset_node, is_ms, is_cloned @@ -166,11 +166,10 @@ '''defined in subclasses''' pass - def runop(self, op, nodes=None): + def runop(self, op, nodes=None, local_only=False): ''' Execute an operation. ''' - from crm_pssh import do_pssh_cmd if not nodes or self.run_on_all(op): nodes = self.nodes self.last_op = op @@ -182,12 +181,16 @@ # shell doesn't allow "-" in var names envvar = attr.replace("-", "_") cmd = "%s=%s %s" % (envvar, quote(self.rscenv[attr]), cmd) - statuses = do_pssh_cmd(cmd, nodes, self.outdir, self.errdir, self.timeout) - for i in range(len(nodes)): - try: - self.ec_l[nodes[i]] = statuses[i] - except: - self.ec_l[nodes[i]] = self.undef + if local_only: + self.ec_l[this_node()] = ext_cmd(cmd) + else: + from crm_pssh import do_pssh_cmd + statuses = do_pssh_cmd(cmd, nodes, self.outdir, self.errdir, self.timeout) + for i in range(len(nodes)): + try: + self.ec_l[nodes[i]] = statuses[i] + except: + self.ec_l[nodes[i]] = self.undef return def stop(self, node): @@ -305,6 +308,31 @@ return cmd +class RASystemd(RADriver): + ''' + Execute operations on systemd resources. + ''' + + # Error codes are meaningless for systemd... + SYSD_OK = 0 + SYSD_ERR_GENERIC = 1 + SYSD_NOT_RUNNING = 3 + + def __init__(self, *args): + RADriver.__init__(self, *args) + self.ec_ok = self.SYSD_OK + self.ec_stopped = self.SYSD_NOT_RUNNING + self.ec_master = self.unused + + def set_rscenv(self, op): + RADriver.set_rscenv(self, op) + + def exec_cmd(self, op): + op = "status" if op == "monitor" else op + cmd = "systemctl %s %s.service" % (op, self.ra_type) + return cmd + + class RAStonith(RADriver): ''' Execute operations on Stonith resources. @@ -355,7 +383,8 @@ ra_driver = { "ocf": RAOCF, "lsb": RALSB, - "stonith": RAStonith + "stonith": RAStonith, + "systemd": RASystemd } @@ -430,4 +459,31 @@ rc |= test_node(node) return rc + +def call_resource(rsc, cmd, nodes, local_only): + """ + Calls the given operation on the resource. + local_only: Only performs the call locally (don't use pssh). + """ + ra_class = rsc.get("class") + if ra_class not in ra_driver: + common_err("Calling '%s' for resource not supported" % (cmd)) + return False + d = ra_driver[ra_class](rsc, []) + + import ra + agent = ra.get_ra(rsc) + actions = agent.actions().keys() + ['meta-data', 'validate-all'] + + if cmd not in actions: + common_err("action '%s' not supported by %s" % (cmd, ra.name)) + return False + d.runop(cmd, nodes, local_only=local_only) + for node in nodes: + ok = d.is_ok(node) + if not ok: + common_err("%s failed with rc=%d on %s" % + (cmd, d.op_status(node), node)) + return all(d.is_ok(node) for node in nodes) + # vim:ts=4:sw=4:et: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_maintenance.py new/crmsh/modules/ui_maintenance.py --- old/crmsh/modules/ui_maintenance.py 1970-01-01 01:00:00.000000000 +0100 +++ new/crmsh/modules/ui_maintenance.py 2014-10-10 19:26:22.000000000 +0200 @@ -0,0 +1,108 @@ +# Copyright (C) 2014 Kristoffer Gronlund <kgronl...@suse.com> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import command +import completers as compl +from cibconfig import cib_factory +import utils +import xmlutil + +_compl_actions = compl.choice(['start', 'stop', 'monitor', 'meta-data', 'validate-all', + 'promote', 'demote', 'notify', 'reload', 'migrate_from', + 'migrate_to', 'recover']) + + +class Maintenance(command.UI): + ''' + Commands that should only be run while in + maintenance mode. + ''' + name = "maintenance" + + rsc_maintenance = "crm_resource -r '%s' --meta -p maintenance -v '%s'" + + def __init__(self): + command.UI.__init__(self) + + def requires(self): + return cib_factory.initialize() + + def _onoff(self, resource, onoff): + if resource is not None: + return utils.ext_cmd(self.rsc_maintenance % (resource, onoff)) == 0 + else: + return cib_factory.create_object('property', 'maintenance-mode=%s' % (onoff)) + + @command.skill_level('administrator') + @command.completers_repeating(compl.call(cib_factory.rsc_id_list)) + def do_on(self, context, resource=None): + ''' + Enable maintenance mode (for the optional resource or for everything) + ''' + return self._onoff(resource, 'true') + + @command.skill_level('administrator') + @command.completers_repeating(compl.call(cib_factory.rsc_id_list)) + def do_off(self, context, resource=None): + ''' + Disable maintenance mode (for the optional resource or for everything) + ''' + return self._onoff(resource, 'false') + + def _in_maintenance_mode(self, obj): + if cib_factory.get_property("maintenance-mode") == "true": + return True + v = obj.meta_attributes("maintenance") + return v and all(x == 'true' for x in v) + + def _runs_on_this_node(self, resource): + nodes = utils.running_on(resource) + return set(nodes) == set([utils.this_node()]) + + @command.skill_level('administrator') + @command.completers(compl.call(cib_factory.rsc_id_list), _compl_actions, compl.choice(["ssh"])) + def do_action(self, context, resource, action, ssh=None): + ''' + Issue action out-of-band to the given resource, making + sure that the resource is in maintenance mode first + ''' + obj = cib_factory.find_object(resource) + if not obj: + context.fatal_error("Resource not found: %s" % (resource)) + if not xmlutil.is_resource(obj.node): + context.fatal_error("Not a resource: %s" % (resource)) + if not self._in_maintenance_mode(obj): + context.fatal_error("Not in maintenance mode.") + + if ssh is None: + if action not in ('start', 'monitor'): + if not self._runs_on_this_node(resource): + context.fatal_error("Resource %s must be running on this node (%s)" % + (resource, utils.this_node())) + + import rsctest + return rsctest.call_resource(obj.node, action, [utils.this_node()], local_only=True) + elif ssh == "ssh": + import rsctest + if action in ('start', 'promote', 'demote', 'recover', 'meta-data'): + return rsctest.call_resource(obj.node, action, + [utils.this_node()], local_only=True) + else: + all_nodes = cib_factory.node_id_list() + return rsctest.call_resource(obj.node, action, all_nodes, local_only=False) + else: + context.fatal_error("Unknown argument: %s" % (ssh)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_ra.py new/crmsh/modules/ui_ra.py --- old/crmsh/modules/ui_ra.py 2014-09-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/ui_ra.py 2014-10-10 19:26:22.000000000 +0200 @@ -57,7 +57,7 @@ if c in self.provider_classes: providers = ra.ra_providers_all(c) if providers: - print "%s / " % (c, ' '.join(providers)) + print "%s / %s" % (c, ' '.join(providers)) else: print "%s" % c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh/modules/ui_root.py new/crmsh/modules/ui_root.py --- old/crmsh/modules/ui_root.py 2014-09-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/ui_root.py 2014-10-10 19:26:22.000000000 +0200 @@ -35,16 +35,17 @@ import cmd_status import ui_cib import ui_cluster -import ui_corosync -import ui_resource import ui_configure +import ui_corosync import ui_history -import ui_ra -import ui_site +import ui_maintenance import ui_node -import ui_report import ui_options +import ui_ra +import ui_report +import ui_resource import ui_script +import ui_site class Root(command.UI): @@ -55,32 +56,6 @@ # name is the user-visible name of this CLI level. name = 'root' - @command.level(ui_cluster.Cluster) - @command.help('''Cluster setup and management -Commands at this level enable low-level cluster configuration -management with HA awareness. -''') - def do_cluster(self): - pass - - @command.level(ui_corosync.Corosync) - @command.help('''Corosync configuration management -Corosync is the underlying messaging layer for most HA clusters. -This level provides commands for editing and managing the corosync -configuration. -''') - def do_corosync(self): - pass - - @command.level(ui_script.Script) - @command.help('''Cluster scripts -Cluster scripts can perform cluster-wide configuration, -validation and management. See the `list` command for -an overview of available scripts. -''') - def do_script(self): - pass - @command.level(ui_cib.CibShadow) @command.help('''manage shadow CIBs A shadow CIB is a regular cluster configuration which is kept in @@ -91,13 +66,12 @@ def do_cib(self): pass - @command.level(ui_resource.RscMgmt) - @command.help('''resources management -Everything related to resources management is available at this -level. Most commands are implemented using the crm_resource(8) -program. + @command.level(ui_cluster.Cluster) + @command.help('''Cluster setup and management +Commands at this level enable low-level cluster configuration +management with HA awareness. ''') - def do_resource(self): + def do_cluster(self): pass @command.level(ui_configure.CibConfig) @@ -111,20 +85,13 @@ def do_configure(self): pass - @command.level(ui_node.NodeMgmt) - @command.help('''nodes management -A few node related tasks such as node standby are implemented -here. -''') - def do_node(self): - pass - - @command.level(ui_options.CliOptions) - @command.help('''user preferences -Several user preferences are available. Note that it is possible -to save the preferences to a startup file. + @command.level(ui_corosync.Corosync) + @command.help('''Corosync configuration management +Corosync is the underlying messaging layer for most HA clusters. +This level provides commands for editing and managing the corosync +configuration. ''') - def do_options(self): + def do_corosync(self): pass @command.level(ui_history.History) @@ -136,13 +103,28 @@ def do_history(self): pass - @command.level(ui_site.Site) - @command.help('''Geo-cluster support -The site level. + @command.level(ui_maintenance.Maintenance) + @command.help('''maintenance +Commands that should only be executed while in +maintenance mode. +''') + def do_maintenance(self): + pass -Geo-cluster related management. + @command.level(ui_node.NodeMgmt) + @command.help('''nodes management +A few node related tasks such as node standby are implemented +here. ''') - def do_site(self): + def do_node(self): + pass + + @command.level(ui_options.CliOptions) + @command.help('''user preferences +Several user preferences are available. Note that it is possible +to save the preferences to a startup file. +''') + def do_options(self): pass @command.level(ui_ra.RA) @@ -162,6 +144,33 @@ def do_report(self, context, *args): return ui_report.create_report(context, args) + @command.level(ui_resource.RscMgmt) + @command.help('''resources management +Everything related to resources management is available at this +level. Most commands are implemented using the crm_resource(8) +program. +''') + def do_resource(self): + pass + + @command.level(ui_script.Script) + @command.help('''Cluster scripts +Cluster scripts can perform cluster-wide configuration, +validation and management. See the `list` command for +an overview of available scripts. +''') + def do_script(self): + pass + + @command.level(ui_site.Site) + @command.help('''Geo-cluster support +The site level. + +Geo-cluster related management. +''') + def do_site(self): + pass + @command.help('''show cluster status Show cluster status. The status is displayed by `crm_mon`. Supply additional arguments for more information or different format. 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-09-26 12:07:07.000000000 +0200 +++ new/crmsh/modules/utils.py 2014-10-10 19:26:22.000000000 +0200 @@ -1329,6 +1329,23 @@ return None +def running_on(resource): + "returns list of node names where the given resource is running" + rsc_locate = "crm_resource --resource '%s' --locate" + rc, out, err = get_stdout_stderr(rsc_locate % (resource)) + if rc != 0: + return [] + nodes = [] + head = "resource %s is running on: " % (resource) + for line in out.split('\n'): + if line.strip().startswith(head): + w = line[len(head):].split() + if w: + nodes.append(w[0]) + common_debug("%s running on: %s" % (resource, nodes)) + return nodes + + # This RE matches nvpair values that can # be left unquoted _NOQUOTES_RE = re.compile(r'^[\w\.-]+$') -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org