Page MenuHomeClusterLabs Projects

No OneTemporary

This document is not UTF8. It was detected as Shift JIS and converted to UTF8 for display.
diff --git a/Makefile.am b/Makefile.am
index 9ea8a28..d65b162 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,161 +1,164 @@
# Copyright (c) 2009 Red Hat, Inc.
#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
SPEC = $(PACKAGE_NAME).spec
TARFILE = $(PACKAGE_NAME)-$(VERSION).tar.gz
EXTRA_DIST = autogen.sh conf/booth.conf.example \
$(bootharbitrator_SCRIPTS) $(boothsite_SCRIPTS) \
$(boothnoarch_SCRIPTS)
AUTOMAKE_OPTIONS = foreign
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure depcomp \
config.guess config.sub missing install-sh \
autoheader automake autoconf test_lense.sh
dist_doc_DATA = AUTHORS README COPYING README.upgrade-from-v0.1
notrans_dist_man8_MANS = docs/boothd.8
boothconfdir = ${BOOTHSYSCONFDIR}
boothconf_DATA = conf/booth.conf.example
boothsitedir = /usr/lib/ocf/resource.d/pacemaker
-
boothsite_SCRIPTS = script/ocf/booth-site
+boothocfdir = /usr/lib/ocf/resource.d/booth
+boothocf_SCRIPTS = script/ocf/sharedrsc
+
bootharbitratordir = ${INITDDIR}
bootharbitrator_SCRIPTS = script/lsb/booth-arbitrator
boothnoarchdir = $(datadir)/$(PACKAGE_NAME)
boothnoarch_SCRIPTS = script/service-runnable
TESTS = test/runtests.py
SUBDIRS = src docs
coverity:
cov-build --dir=cov make
cov-analyze --dir cov --concurrency --wait-for-license
cov-format-errors --dir cov
install-exec-local:
$(INSTALL) -d $(DESTDIR)/${boothconfdir}
$(INSTALL) -d $(DESTDIR)/${bootharbitratordir}
$(INSTALL) -d $(DESTDIR)/${boothsitedir}
+ $(INSTALL) -d $(DESTDIR)/${boothocfdir}
$(INSTALL) -d $(DESTDIR)/${SOCKETDIR}
install-exec-hook:
ln -sf ${sbindir}/boothd $(DESTDIR)/${sbindir}/booth
uninstall-local:
rmdir $(DESTDIR)/${boothconfdir} || :;
rmdir $(DESTDIR)/${bootharbitratordir} || :;
rmdir $(DESTDIR)/${boothsitedir} || :;
rmdir $(DESTDIR)/${SOCKETDIR} || :;
test: check
lint:
for dir in src; do make -C $$dir lint; done
dist-clean-local:
rm -f autoconf automake autoheader
dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version
## make rpm/srpm section.
$(SPEC): $(SPEC).in
rm -f $@-t $@
date="$(shell LC_ALL=C date "+%a %b %d %Y")" && \
if [ -f .tarball-version ]; then \
gitver="$(shell cat .tarball-version)" && \
rpmver=$$gitver && \
alphatag="" && \
dirty="" && \
numcomm="0"; \
else \
gitver="$(shell git describe --tags --abbrev=4 --match='v*' HEAD 2>/dev/null)" && \
rpmver=`echo $$gitver | sed -e "s/^v//" -e "s/-.*//g"` && \
alphatag=`echo $$gitver | sed -e "s/.*-//" -e "s/^g//"` && \
vtag=`echo $$gitver | sed -e "s/-.*//g"` && \
numcomm=`git rev-list $$vtag..HEAD | wc -l` && \
git update-index --refresh > /dev/null 2>&1 || true && \
dirty=`git diff-index --name-only HEAD 2>/dev/null`; \
fi && \
if [ -n "$$dirty" ]; then dirty="dirty"; else dirty=""; fi && \
if [ "$$numcomm" = "0" ]; then \
sed \
-e "s#@version@#$$rpmver#g" \
-e "s#%glo.*alpha.*##g" \
-e "s#%glo.*numcomm.*##g" \
-e "s#@dirty@#$$dirty#g" \
-e "s#@date@#$$date#g" \
$< > $@-t; \
else \
sed \
-e "s#@version@#$$rpmver#g" \
-e "s#@alphatag@#$$alphatag#g" \
-e "s#@numcomm@#$$numcomm#g" \
-e "s#@dirty@#$$dirty#g" \
-e "s#@date@#$$date#g" \
$< > $@-t; \
fi; \
if [ -z "$$dirty" ]; then sed -i -e "s#%glo.*dirty.*##g" $@-t; fi
chmod a-w $@-t
mv $@-t $@
$(TARFILE):
$(MAKE) dist
RPMBUILDOPTS = --define "_sourcedir $(abs_builddir)" \
--define "_specdir $(abs_builddir)" \
--define "_builddir $(abs_builddir)" \
--define "_srcrpmdir $(abs_builddir)" \
--define "_rpmdir $(abs_builddir)"
srpm: clean
autoreconf -if
$(MAKE) $(SPEC) $(TARFILE)
rpmbuild $(WITH_LIST) $(RPMBUILDOPTS) --nodeps -bs $(SPEC)
rpm: clean
autoreconf -if
$(MAKE) $(SPEC) $(TARFILE)
rpmbuild $(WITH_LIST) $(RPMBUILDOPTS) -ba $(SPEC)
diff --git a/README-testing b/README-testing
index 6d936f0..f934bd9 100644
--- a/README-testing
+++ b/README-testing
@@ -1,210 +1,217 @@
There's a booth-test RPM available that contains two types of tests.
It installs the necessary files into `/usr/share/booth/tests`.
=== Live tests (booth operation)
BEWARE: Run this with _test_ clusters only!
The live testing utility tests booth operation using the given
`booth.conf`:
$ /usr/share/booth/tests/test/live_test.sh booth.conf
It is possible to run only specific tests. Run the script without
arguments to see usage and the list of tests and netem network
emulation functions.
There are some restrictions on how booth.conf is formatted.
There could be several tickets defined, but only the first ticket
is used for testing. This ticket must have expire and timeout
parameters configured.
Example booth.conf:
------------
transport="UDP"
port="9929"
arbitrator="10.2.12.53"
arbitrator="10.2.13.82"
site="10.2.12.101"
site="10.2.13.101"
site="10.121.187.99"
ticket="ticket-A"
expire = 30
timeout = 3
retries = 3
before-acquire-handler = /usr/share/booth/service-runnable d-src1
------------
A split brain condition is also tested. For that to work, all
sites need `iptables` installed. The supplied script `booth_path`
is used to manipulate iptables rules.
==== Pacemaker configuration
This is a sample pacemaker configuration for a single-node
cluster:
primitive booth ocf:pacemaker:booth-site
primitive d-src1 ocf:heartbeat:Dummy
rsc_ticket global-d-src1 ticket-A: d-src1
+Additionally, you may also add an ocf:booth:sharedrsc resource to
+also check that the ticket is granted always to only one site:
+
+primitive shared ocf:booth:sharedrsc \
+ params dir="10.2.13.82:/var/tmp/boothtestdir"
+rsc_ticket global-shared ticket-A: shared
+
Please adjust to your environment.
==== Network environment emulation
To introduce packet loss or network delays, set the NETEM_ENV
environment variable. There are currently three netem network
emulation settings supported:
- loss: all servers emulate packet loss (30% by default)
- single_loss: the first site in the configuration emulates
packet loss (30% by default)
- net_delay: all servers emulate packet delay (100ms by default
with random variation of 10%)
The settings can be supplied by adding ':' to the emulator name.
For instance:
# NETEM_ENV=loss:50 /usr/share/booth/tests/test/live_test.sh booth.conf
It is not necessary to run the test script on one of the sites.
Just copy the script and make the test `booth.conf` available
locally:
$ scp testsite:/usr/share/booth/tests/test/live_test.sh .
$ scp testsite:/etc/booth/booth.conf .
$ sh live_test.sh booth.conf
You need at least two sites and one arbitrator.
The configuration can contain just one ticket.
It is not necessary to configure the `before-acquire-handler`.
Notes:
- (BEWARE!) the supplied configuration files is copied to
/etc/booth/booth.conf to all sites/arbitrators thus overwriting
any existing configuration
- the utility uses ssh to manage booth at all sites/arbitrators
and logs in as user `root`
- it is required that ssh public authentication works without
providing the passphrase (otherwise it is impractical)
- the log file is ./test_booth.log (it is actually a shell trace,
with timestamps if you're running bash)
- in case one of the tests fail, hb_report is created
If you want to open a bug report, please attach all hb_reports
and `test_booth.log`.
=== Simple tests (commandline, config file)
Run (as non-root)
# python test/runtests.py
to run the tests written in python.
=== Unit tests
These use gdb and pexpect to set boothd state to some configured value,
injecting some input and looking at the output.
# python script/unit-test.py src/boothd unit-tests/
Or, if using the 'booth-test' RPM,
# python unit-test.py src/boothd unit-tests/
This must (currently?) be run as a non-root user; another optional argument is
the test to start from, eg. '003'.
Basically, boothd is started with the config file `unit-tests/booth.conf`, and
gdb gets attached to it.
Then, some ticket state is set, incoming messages are delivered, and outgoing
messages and the state is compared to expected values.
`unit-tests/_defaults.txt` has default values for the initial state and
message data.
Each test file consists of headers and key/value pairs:
--------------------
ticket:
state ST_STABLE
message0: # optional comment for the log file
header.cmd OP_ACCEPTING
ticket.id "asdga"
outgoing0:
header.cmd OP_PREPARING
last_ack_ballot 42
finally:
new_ballot 1234
--------------------
A few details to the the above example:
* Ticket states in RAM (`ticket`, `finally`) are written in host-endianness.
* Message data (`messageN`, `outgoingN`) are automatically converted via `htonl` resp. `ntohl`. They are delivered/checked in the order defined by the integer `N` component.
* Strings are done via `strcpy()`
* `ticket` and `messageN` are assignment chunks
* `finally` and `outgoingN` are compare chunks
* In `outgoingN` you can check _both_ message data (keys with a `.` in them) and ticket state
* Symbolic names are useable, GDB translates them for us
* The test scripts in `unit-tests/` need to be named with 3 digits, an underscore, some text, and `.txt`
* The "fake" `crm_ticket` script gets the current test via `UNIT_TEST`; test scripts can pass additional information via `UNIT_TEST_AUX`.
==== Tips and Hints
There's another special header: `gdb__N__`. These lines are sent to GDB after
injecting a message, but before waiting for an outgoing line. Values that
contain `ツァ` are sent as multiple lines to GDB.
This means that a stanza like
--------------------
gdb0:
watch booth_conf->ticket[0].owner ツァ commands ツァ bt ツァ c ツァ end
--------------------
will cause a watchpoint to be set, and when it is triggered a backtrace (`bt`)
is written to the log file.
This makes it easy to ask for additional data or check for a call-chain when
hitting bugs that can be reproduced via such a unit-test.
# vim: set ft=asciidoc :
diff --git a/booth.spec b/booth.spec
index 8c2578b..4ea1fb1 100644
--- a/booth.spec
+++ b/booth.spec
@@ -1,175 +1,176 @@
%if 0%{?suse_version}
%global booth_docdir %{_defaultdocdir}/%{name}
%else
# newer fedora distros have _pkgdocdir, rely on that when
# available
%{!?_pkgdocdir: %global _pkgdocdir %%{_docdir}/%{name}-%{version}}
# Directory where we install documentation
%global booth_docdir %{_pkgdocdir}
%endif
%global test_path %{_datadir}/booth/tests
%if 0%{?suse_version}
%define _libexecdir %{_libdir}
%endif
%define with_extra_warnings 0
%define with_debugging 0
%define without_fatal_warnings 1
%if 0%{?fedora} || 0%{?centos} || 0%{?rhel}
%define pkg_group System Environment/Daemons
%else
%define pkg_group Productivity/Clustering/HA
%endif
Name: booth
Url: https://github.com/ClusterLabs/booth
Summary: Ticket Manager for Multi-site Clusters
License: GPL-2.0+
Group: %{pkg_group}
Version: 0.2.0
Release: 0
Source: booth.tar.bz2
Source1: %name-rpmlintrc
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: asciidoc
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: glib2-devel
%if 0%{?fedora} || 0%{?centos} || 0%{?rhel}
BuildRequires: cluster-glue-libs-devel
BuildRequires: pacemaker-libs-devel
%else
BuildRequires: libglue-devel
BuildRequires: libpacemaker-devel
%endif
BuildRequires: libxml2-devel
BuildRequires: pkgconfig
%if 0%{?fedora} || 0%{?centos} || 0%{?rhel}
Requires: pacemaker >= 1.1.8
Requires: cluster-glue-libs >= 1.0.6
%else
Requires: pacemaker-ticket-support >= 2.0
%endif
%description
Booth manages tickets which authorize cluster sites located in
geographically dispersed locations to run resources. It
facilitates support of geographically distributed clustering in
Pacemaker.
%prep
%setup -q -n %{name}
%build
./autogen.sh
%configure \
--with-initddir=%{_initrddir} \
--docdir=%{booth_docdir}
make
#except check
#%check
#make check
%install
make DESTDIR=$RPM_BUILD_ROOT install docdir=%{booth_docdir}
mkdir -p %{buildroot}/%{_mandir}/man8/
gzip < docs/boothd.8 > %{buildroot}/%{_mandir}/man8/booth.8.gz
ln %{buildroot}/%{_mandir}/man8/booth.8.gz %{buildroot}/%{_mandir}/man8/boothd.8.gz
%if %{defined _unitdir}
# systemd
mkdir -p %{buildroot}/%{_unitdir}
cp -a conf/booth@.service %{buildroot}/%{_unitdir}/booth@.service
ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcbooth-arbitrator
%else
# sysV init
ln -s ../../%{_initddir}/booth-arbitrator %{buildroot}%{_sbindir}/rcbooth-arbitrator
%endif
#install test-parts
mkdir -p %{buildroot}/%{test_path}
cp -a unit-tests/ script/unit-test.py test conf %{buildroot}/%{test_path}/
chmod +x %{buildroot}/%{test_path}/test/booth_path
chmod +x %{buildroot}/%{test_path}/test/live_test.sh
mkdir -p %{buildroot}/%{test_path}/src/
ln -s %{_sbindir}/boothd %{buildroot}/%{test_path}/src/
rm -f %{buildroot}/%{test_path}/test/*.pyc
%check
%if 0%{?run_build_tests}
echo "%%run_build_tests set to %run_build_tests; including tests"
make check
%else
echo "%%run_build_tests set to %run_build_tests; skipping tests"
%endif
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{_sbindir}/booth
%{_sbindir}/boothd
%{_mandir}/man8/booth.8.gz
%{_mandir}/man8/boothd.8.gz
%dir /usr/lib/ocf
%dir /usr/lib/ocf/resource.d
%dir /usr/lib/ocf/resource.d/pacemaker
%dir %{_sysconfdir}/booth
%{_sbindir}/rcbooth-arbitrator
/usr/lib/ocf/resource.d/pacemaker/booth-site
%config %{_sysconfdir}/booth/booth.conf.example
%if %{defined _unitdir}
%{_unitdir}/booth@.service
%exclude %{_initddir}/booth-arbitrator
%else
%{_initddir}/booth-arbitrator
%endif
%dir %{_datadir}/booth
%{_datadir}/booth/service-runnable
%doc AUTHORS README COPYING
%doc README.upgrade-from-v0.1
# this should be preun, but...
%pre
# new installation?
test -x %{_sbindir}/booth || exit 0
# stop the arbitrator if it's the previous paxos version 1.0
if [ "`booth version | awk '{print $2}'`" = "1.0" ]; then
echo "booth v0.1 found"
if grep -qs 'ticket.*;' /etc/booth/booth.conf; then
echo "Convert the booth configuration in /etc/booth/booth.conf!"
fi
if ps -o pid,cmd -e | grep -qs "[b]oothd arbitrator"; then
rcbooth-arbitrator stop
fi
fi
exit 0
%package test
Summary: Test scripts for Booth
Group: %{pkg_group}
Requires: booth
Requires: python
%description test
This package contains automated tests for Booth,
the Cluster Ticket Manager for Pacemaker.
%files test
%defattr(-,root,root)
%doc README-testing
%{test_path}
+/usr/lib/ocf/resource.d/booth/sharedrsc
%changelog
diff --git a/script/ocf/sharedrsc b/script/ocf/sharedrsc
new file mode 100755
index 0000000..a338bff
--- /dev/null
+++ b/script/ocf/sharedrsc
@@ -0,0 +1,187 @@
+#!/bin/sh
+#
+#
+# sharedrsc OCF RA. Just keep some resource while running and
+# release when stopped. The resource is a directory on a
+# shared filesystem or on a filesystem which is remotely
+# accessible over ssh. Used for booth testing, i.e. to make
+# sure that no two sites keep the same ticket.
+#
+# Copyright (c) 2004 SUSE LINUX AG, Lars Marowsky-Br馥
+# All Rights Reserved.
+# Copyright (c) 2015 SUSE Microfocus, Dejan Muhamedagic
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like. Any license provided herein, whether implied or
+# otherwise, applies only to this software file. Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+
+sharedrsc_meta_data() {
+ cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="sharedrsc" version="1.0">
+<version>1.0</version>
+
+<longdesc lang="en">
+This is sharedrsc Resource Agent.
+It just keeps some resource while running and
+releases it when stopped. The resource is a directory on a
+shared filesystem or on a filesystem which is remotely
+accessible over ssh. Used for booth testing, i.e. to make
+sure that no two sites keep the same ticket.
+</longdesc>
+<shortdesc lang="en">shared resource (booth testing)</shortdesc>
+
+<parameters>
+<parameter name="dir" unique="1" required="1">
+<longdesc lang="en">
+Location of the shared directory. If it's of the form "[user@]host:path"
+then it is assumed that the directory is to be accessed over ssh
+on that host. Otherwise, it must be a directory on a shared
+filesystem (such as nfs or ocfs2).
+</longdesc>
+<shortdesc lang="en">shared directory location</shortdesc>
+<content type="string" default="" />
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="20" />
+<action name="stop" timeout="20" />
+<action name="monitor" timeout="20" interval="10" depth="0" />
+<action name="reload" timeout="20" />
+<action name="migrate_to" timeout="20" />
+<action name="migrate_from" timeout="20" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="20" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+
+sharedrsc_usage() {
+ cat <<END
+usage: $0 {start|stop|monitor|migrate_to|migrate_from|validate-all|meta-data}
+
+Expects to have a fully populated OCF RA-compliant environment set.
+END
+}
+
+runcmd() {
+ local func=$1
+ local dir=$2
+ $func $dir |
+ if [ -n "$SSH_HOST" ]; then
+ ssh -T -o Batchmode=yes $SSH_HOST
+ else
+ /bin/sh
+ fi
+}
+
+getowner() {
+ echo "test -d $1 && cat $1/owner"
+}
+testcmd() {
+ echo "test -d $1 && test \"\`cat $1/owner\`\" = `uname -n`"
+}
+makecmd() {
+ echo "mkdir $1 && echo `uname -n` > $1/owner"
+}
+removecmd() {
+ echo "test -d $1 && test \"\`cat $1/owner\`\" = `uname -n` && rm $1/owner && rmdir $1"
+}
+
+testdir() {
+ runcmd testcmd $1
+}
+makedir() {
+ runcmd makecmd $1
+}
+removedir() {
+ runcmd removecmd $1
+}
+
+sharedrsc_monitor() {
+ if testdir $DIR; then
+ return $OCF_SUCCESS
+ else
+ return $OCF_NOT_RUNNING
+ fi
+}
+
+sharedrsc_start() {
+ if sharedrsc_monitor; then
+ return $OCF_SUCCESS
+ fi
+ makedir $DIR &&
+ return $OCF_SUCCESS
+
+ local owner
+ if ! owner=`runcmd getowner $DIR`; then
+ owner="... nobody, it's only half-claimed"
+ fi
+ ocf_log err "eek, $OCF_RESKEY_dir already owned by $owner"
+ return $OCF_ERR_GENERIC
+}
+
+sharedrsc_stop() {
+ sharedrsc_monitor
+ if [ $? -eq $OCF_NOT_RUNNING ]; then
+ return $OCF_SUCCESS
+ fi
+ removedir $DIR
+}
+
+sharedrsc_getconfig() {
+ local colon_pos
+ colon_pos=`expr index "$OCF_RESKEY_dir" ":"`
+ if [ $colon_pos -gt 0 ]; then
+ SSH_HOST=`echo $OCF_RESKEY_dir | cut -d: -f 1`
+ DIR=`echo $OCF_RESKEY_dir | cut -d: -f 2`
+ else
+ SSH_HOST=
+ DIR=$OCF_RESKEY_dir
+ fi
+}
+
+sharedrsc_validate_all() {
+ if [ `expr index $DIR /` -ne 1 ]; then
+ ocf_log err "dir must be an absolute path"
+ return $OCF_ERR_INSTALLED
+ fi
+ return $OCF_SUCCESS
+}
+
+OCF_REQUIRED_PARAMS="dir"
+ocf_rarun $*
+
+#
+# vim:tabstop=4:shiftwidth=4:textwidth=0:wrapmargin=0

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 27, 12:23 AM (17 h, 22 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1462971
Default Alt Text
(21 KB)

Event Timeline