Hello community,
here is the log from the commit of package booth for openSUSE:Factory checked in at 2016-04-01 13:02:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/booth (Old)
and /work/SRC/openSUSE:Factory/.booth.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "booth"
Changes:
--------
--- /work/SRC/openSUSE:Factory/booth/booth.changes 2016-01-22 01:09:43.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.booth.new/booth.changes 2016-04-01 13:02:49.000000000 +0200
@@ -1,0 +2,14 @@
+Wed Mar 23 16:35:54 UTC 2016 - opensuse-packaging@opensuse.org
+
+- Update to version v1.0_6_g106efdf:
+ + Feature: extprog: add capability to run a set of programs
+ + Medium: extprog: external tests timeout after renewal interval
+
+-------------------------------------------------------------------
+Wed Mar 16 15:53:29 UTC 2016 - dmuhamedagic@suse.com
+
+- Update to release v1.0
+ + systemd: add booth-arbitrator.service (bsc#967036)
+ + main: improve address matching procedure
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ booth.spec ++++++
--- /var/tmp/diff_new_pack.Mqf5sy/_old 2016-04-01 13:02:50.000000000 +0200
+++ /var/tmp/diff_new_pack.Mqf5sy/_new 2016-04-01 13:02:50.000000000 +0200
@@ -46,7 +46,7 @@
License: GPL-2.0+
Group: %{pkg_group}
Version: 1.0
-Release: 0rc1
+Release: 0
Source: booth.tar.bz2
Source1: %name-rpmlintrc
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -103,6 +103,7 @@
# systemd
mkdir -p %{buildroot}/%{_unitdir}
cp -a conf/booth@.service %{buildroot}/%{_unitdir}/booth@.service
+cp -a conf/booth-arbitrator.service %{buildroot}/%{_unitdir}/booth-arbitrator.service
ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcbooth-arbitrator
%else
# sysV init
@@ -156,6 +157,7 @@
%if %{defined _unitdir}
%{_unitdir}/booth@.service
+%{_unitdir}/booth-arbitrator.service
%exclude %{_initddir}/booth-arbitrator
%else
%{_initddir}/booth-arbitrator
@@ -167,22 +169,6 @@
%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}
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.Mqf5sy/_old 2016-04-01 13:02:50.000000000 +0200
+++ /var/tmp/diff_new_pack.Mqf5sy/_new 2016-04-01 13:02:50.000000000 +0200
@@ -1,4 +1,4 @@
<servicedata>
<service name="tar_scm">
<param name="url">git://github.com/ClusterLabs/booth.git</param>
- <param name="changesrevision">9c5c19f2c9217db9bf6265e8e753ac15ba631ae0</param></service></servicedata>
\ No newline at end of file
+ <param name="changesrevision">106efdf386c23aa7c740f1d238ecd04fd63f5ebc</param></service></servicedata>
\ No newline at end of file
++++++ booth.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/.git_info new/booth/.git_info
--- old/booth/.git_info 2016-01-12 15:03:32.000000000 +0100
+++ new/booth/.git_info 2016-03-23 17:32:51.000000000 +0100
@@ -1 +1 @@
-v1.0rc1
+v1.0-6-g106efdf
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/ChangeLog new/booth/ChangeLog
--- old/booth/ChangeLog 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/ChangeLog 2016-03-23 17:31:14.000000000 +0100
@@ -1,3 +1,8 @@
+* Mar Jan 16 2016 Dejan Muhamedagic and others
+- stable release 1.0
+- systemd: add booth-arbitrator.service (bsc#967036)
+- main: improve address matching procedure
+
* Mon Jan 11 2016 Dejan Muhamedagic and others
- release candidate 1.0 rc1
- main: prevent segfault on no arguments
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/README new/booth/README
--- old/booth/README 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/README 2016-03-23 17:31:14.000000000 +0100
@@ -118,14 +118,18 @@
renewals are configurable and by default set to half ticket
expire time.
-Before ticket renewal, the leader runs an external program if
-such program is set in 'before-acquire-handler'. The external
-program should ensure that the cluster managed service which is
-protected by this ticket can run at this site. If that program
-fails, the leader relinquishes the ticket. It announces its
-intention to step down by broadcasting an unsolicited VOTE_FOR
-with an empty vote. On receiving such RPC other servers start new
-elections to elect a new leader.
+Before ticket renewal, the leader runs one or more external
+programs if such are set in 'before-acquire-handler'. This can
+point either to a file or a directory. In the former case, that
+file is the program, but in the latter there could be a number of
+programs in the specified directory. All files which have the
+executable bit set and whose names don't start with a '.' are
+run sequentially. This program or programs should ensure that the
+cluster managed service which is protected by this ticket can run
+at this site. If any of them fails, the leader relinquishes the
+ticket. It announces its intention to step down by broadcasting
+an unsolicited VOTE_FOR with an empty vote. On receiving such RPC
+other servers start new elections to elect a new leader.
Split brain
------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/booth.spec new/booth/booth.spec
--- old/booth/booth.spec 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/booth.spec 2016-03-23 17:31:14.000000000 +0100
@@ -29,7 +29,7 @@
License: GPL-2.0+
Group: %{pkg_group}
Version: 1.0
-Release: rc1
+Release: 0
Source: booth.tar.bz2
Source1: %name-rpmlintrc
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -86,6 +86,7 @@
# systemd
mkdir -p %{buildroot}/%{_unitdir}
cp -a conf/booth@.service %{buildroot}/%{_unitdir}/booth@.service
+cp -a conf/booth-arbitrator.service %{buildroot}/%{_unitdir}/booth-arbitrator.service
ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcbooth-arbitrator
%else
# sysV init
@@ -148,6 +149,7 @@
%if %{defined _unitdir}
%{_unitdir}/booth@.service
+%{_unitdir}/booth-arbitrator.service
%exclude %{_initddir}/booth-arbitrator
%else
%{_initddir}/booth-arbitrator
@@ -159,23 +161,6 @@
%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}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/conf/booth-arbitrator.service new/booth/conf/booth-arbitrator.service
--- old/booth/conf/booth-arbitrator.service 1970-01-01 01:00:00.000000000 +0100
+++ new/booth/conf/booth-arbitrator.service 2016-03-23 17:31:14.000000000 +0100
@@ -0,0 +1,16 @@
+# This file is part of Booth.
+
+[Unit]
+Description=Booth - Ticket Manager for Pacemaker Clusters
+Documentation=man:boothd(8)
+After=network-online.target
+ConditionFileNotEmpty=/etc/booth/booth.conf
+Conflicts=pacemaker.service
+
+[Install]
+WantedBy=multi-user.target
+
+[Service]
+Type=simple
+ExecStart=/usr/sbin/boothd daemon -S -c /etc/booth/booth.conf
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/conf/booth@.service new/booth/conf/booth@.service
--- old/booth/conf/booth@.service 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/conf/booth@.service 2016-03-23 17:31:14.000000000 +0100
@@ -4,7 +4,8 @@
Description=Booth - Ticket Manager for Pacemaker Clusters
Documentation=man:boothd(8)
After=network-online.target
-ConditionFileExists=/etc/booth/%i.conf
+ConditionFileNotEmpty=/etc/booth/%i.conf
+Conflicts=pacemaker.service
[Install]
Alias=boothd
@@ -12,6 +13,5 @@
[Service]
Type=simple
-Conflicts=pacemaker.service
ExecStart=/usr/sbin/boothd daemon -S -c %i
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/configure.ac new/booth/configure.ac
--- old/booth/configure.ac 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/configure.ac 2016-03-23 17:31:14.000000000 +0100
@@ -4,7 +4,7 @@
# bootstrap / init
AC_PREREQ([2.61])
-AC_INIT([booth], [1.0-0-rc1], [users@clusterlabs.org])
+AC_INIT([booth], [1.0], [users@clusterlabs.org])
AM_INIT_AUTOMAKE([-Wno-portability])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/docs/boothd.8.txt new/booth/docs/boothd.8.txt
--- old/booth/docs/boothd.8.txt 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/docs/boothd.8.txt 2016-03-23 17:31:14.000000000 +0100
@@ -282,10 +282,10 @@
If the network reliability is often reduced over prolonged
periods, it is advisable to try to renew more often.
+
-Before every renewal, if defined, the command specified in
-'before-acquire-handler' is run. In that case the 'renewal-freq'
-parameter is effectively also the local cluster monitoring
-interval.
+Before every renewal, if defined, the command or commands
+specified in 'before-acquire-handler' is run. In that case the
+'renewal-freq' parameter is effectively also the local cluster
+monitoring interval.
*'timeout'*::
After that time 'booth' will re-send packets if there was an
@@ -314,9 +314,11 @@
file defines priority for conflicting requests.
*'before-acquire-handler'*::
- If set, this command will be called before 'boothd' tries to
- acquire or renew a ticket. On exit code other than 0,
- 'boothd' relinquishes the ticket.
+ If set, this parameter specifies either a file containing a
+ program to be run or a directory where a number of programs
+ can reside. They are invoked before 'boothd' tries to acquire
+ or renew a ticket. If any of them exits with a code other
+ than 0, 'boothd' relinquishes the ticket.
+
Thus it is possible to ensure whether the services and its
dependencies protected by the ticket are in good shape at this
@@ -325,6 +327,10 @@
be unable to run. In that case, it is of no use to claim the
ticket.
+
+One or more arguments may follow the program or directory
+location. Typically, there is at least the name of one of
+the resources which depend on this ticket.
++
See below for details about booth specific environment variables.
The distributed 'service-runnable' script is an example which may
be used to test whether a pacemaker resource can be started.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/script/lsb/booth-arbitrator new/booth/script/lsb/booth-arbitrator
--- old/booth/script/lsb/booth-arbitrator 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/script/lsb/booth-arbitrator 2016-03-23 17:31:14.000000000 +0100
@@ -126,15 +126,9 @@
local rc=0
for cnf in ${BOOTH_CONF_FILE:-$CONF_DIR/*.conf} ; do
- if [ $# != 1 ] ; then
- echo "== For configuration file $cnf:"
- fi
cnf_base=`basename $cnf`
"$@"
rc=$((rc|$?))
- if [ $# != 1 ] ; then
- echo "== configuration file $cnf done"
- fi
done
return $rc
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/script/unit-test.py new/booth/script/unit-test.py
--- old/booth/script/unit-test.py 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/script/unit-test.py 2016-03-23 17:31:14.000000000 +0100
@@ -220,7 +220,7 @@
]);
logging.info("started booth with PID %d, lockfile %s" % (self.booth.pid, self.lockfile))
- self.booth.expect("BOOTH site daemon is starting", timeout=2)
+ self.booth.expect("BOOTH site \S+ \(build \S+\) daemon is starting", timeout=2)
#print self.booth.before; exit
self.gdb = self.start_a_process("gdb",
@@ -471,14 +471,14 @@
comment = tkt.aux.get("comment", "")
logging.info("ticket change %s (%s:%d) %s" % (ktkt, fn, self.current_nr, comment))
self.set_state(tkt)
+ if gdb:
+ for (k, v) in gdb.iteritems():
+ self.send_cmd(k + " " + v.replace("§", "\n"))
if msg:
self.current_nr = msg.aux.get("line")
comment = msg.aux.get("comment", "")
logging.info("sending %s (%s:%d) %s" % (kmsg, fn, self.current_nr, comment))
self.send_message(self.merge_dicts(data["message"], msg))
- if gdb:
- for (k, v) in gdb.iteritems():
- self.send_cmd(k + " " + v.replace("§", "\n"))
if data.has_key(kgdb) and len(gdb) == 0:
self.user_debug("manual override")
if out:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/src/config.c new/booth/src/config.c
--- old/booth/src/config.c 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/src/config.c 2016-03-23 17:31:14.000000000 +0100
@@ -330,7 +330,7 @@
}
/* make arguments for execv(2)
- * tk_test.prog points to the path
+ * tk_test.path points to the path
* tk_test.argv is argument vector (starts with the prog)
* (strtok pokes holes in the configuration parameter value, i.e.
* we don't need to allocate memory for arguments)
@@ -340,21 +340,21 @@
char *p;
int i = 0;
- if (tk_test.prog) {
- free(tk_test.prog);
+ if (tk_test.path) {
+ free(tk_test.path);
}
- if (!(tk_test.prog = strdup(val))) {
+ if (!(tk_test.path = strdup(val))) {
log_error("out of memory");
return -1;
}
- p = strtok(tk_test.prog, " \t");
+ p = strtok(tk_test.path, " \t");
tk_test.argv[i++] = p;
do {
p = strtok(NULL, " \t");
if (i >= MAX_ARGS) {
log_error("too many arguments for the acquire-handler");
- free(tk_test.prog);
+ free(tk_test.path);
return -1;
}
tk_test.argv[i++] = p;
@@ -509,7 +509,7 @@
strcpy(booth_conf->arb_group, "nobody");
parse_weights("", defaults.weight);
- defaults.clu_test.prog = NULL;
+ defaults.clu_test.path = NULL;
defaults.clu_test.pid = 0;
defaults.clu_test.status = 0;
defaults.clu_test.progstate = EXTPROG_IDLE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/src/config.h new/booth/src/config.h
--- old/booth/src/config.h 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/src/config.h 2016-03-23 17:31:14.000000000 +0100
@@ -97,7 +97,8 @@
/* Program to ask whether it makes sense to
* acquire the ticket */
struct clu_test {
- char *prog;
+ char *path;
+ int is_dir;
char *argv[MAX_ARGS];
pid_t pid;
int status; /* child exit status */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/src/handler.c new/booth/src/handler.c
--- old/booth/src/handler.c 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/src/handler.c 2016-03-23 17:31:14.000000000 +0100
@@ -20,6 +20,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -61,6 +63,173 @@
}
}
+static void
+run_ext_prog(struct ticket_config *tk, char *prog)
+{
+ if (set_booth_env(tk)) {
+ _exit(1);
+ }
+ closefiles(); /* don't leak open files */
+ tk_log_debug("running handler %s", prog);
+ execv(prog, tk_test.argv);
+ tk_log_error("%s: execv failed (%s)", prog, strerror(errno));
+ _exit(1);
+}
+
+static int
+prog_filter(const struct dirent *dp)
+{
+ return (*dp->d_name != '.');
+}
+
+static pid_t curr_pid;
+static int ignore_status;
+
+static int
+test_exit_status(struct ticket_config *tk, char *prog, int status, int log_msg)
+{
+ int rv = -1;
+
+ if (WIFEXITED(status)) {
+ rv = WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ rv = 128 + WTERMSIG(status);
+ }
+ if (rv) {
+ if (log_msg) {
+ tk_log_warn("handler \"%s\" failed: %s",
+ prog, interpret_rv(status));
+ tk_log_warn("we are not allowed to acquire ticket");
+ }
+ } else {
+ tk_log_debug("handler \"%s\" exited with success",
+ prog);
+ }
+ return rv;
+}
+
+static void
+reset_test_state(struct ticket_config *tk)
+{
+ tk_test.pid = 0;
+ tk_test.progstate = EXTPROG_IDLE;
+}
+
+int tk_test_exit_status(struct ticket_config *tk)
+{
+ int rv;
+
+ rv = test_exit_status(tk, tk_test.path, tk_test.status, !tk_test.is_dir);
+ reset_test_state(tk);
+ return rv;
+}
+
+void wait_child(int sig)
+{
+ int i, status;
+ struct ticket_config *tk;
+
+ /* use waitpid(2) and not wait(2) in order not to interfear
+ * with popen(2)/pclose(2) and system(2) used in pacemaker.c
+ */
+ foreach_ticket(i, tk) {
+ if (tk_test.path && tk_test.pid >= 0 &&
+ (tk_test.progstate == EXTPROG_RUNNING ||
+ tk_test.progstate == EXTPROG_IGNORE) &&
+ waitpid(tk_test.pid, &status, WNOHANG) == tk_test.pid) {
+ if (tk_test.progstate == EXTPROG_IGNORE) {
+ /* not interested in the outcome */
+ reset_test_state(tk);
+ } else {
+ tk_test.status = status;
+ tk_test.progstate = EXTPROG_EXITED;
+ }
+ }
+ }
+}
+
+/* the parent may want to have us stop processing scripts, say
+ * when the ticket gets revoked
+ */
+static void ignore_rest(int sig)
+{
+ signal(SIGTERM, SIG_IGN);
+ log_info("external programs handler caught TERM, ignoring status of external test programs");
+ ignore_status = 1;
+ if (curr_pid > 0) {
+ (void)kill(curr_pid, SIGTERM);
+ }
+}
+
+void ext_prog_timeout(struct ticket_config *tk)
+{
+ tk_log_warn("handler timed out");
+}
+
+int is_ext_prog_running(struct ticket_config *tk)
+{
+ if (!tk_test.path)
+ return 0;
+ return (tk_test.pid > 0 && tk_test.progstate == EXTPROG_RUNNING);
+}
+
+void ignore_ext_test(struct ticket_config *tk)
+{
+ if (is_ext_prog_running(tk)) {
+ (void)kill(tk_test.pid, SIGTERM);
+ tk_test.progstate = EXTPROG_IGNORE;
+ }
+}
+
+static void
+process_ext_dir(struct ticket_config *tk)
+{
+ char prog[FILENAME_MAX+1];
+ int rv, n_progs, i, status;
+ struct dirent **proglist, *dp;
+
+ signal(SIGTERM, (__sighandler_t)ignore_rest);
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGUSR1, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ tk_log_debug("running programs in directory %s", tk_test.path);
+ n_progs = scandir(tk_test.path, &proglist, prog_filter, alphasort);
+ if (n_progs == -1) {
+ tk_log_error("%s: scandir failed (%s)", tk_test.path, strerror(errno));
+ _exit(1);
+ }
+ for (i = 0; i < n_progs; i++) {
+ if (ignore_status)
+ break;
+ dp = proglist[i];
+ if (strlen(dp->d_name) + strlen(tk_test.path) + 1 > FILENAME_MAX) {
+ tk_log_error("%s: name exceeds max length (%s)",
+ tk_test.path, dp->d_name);
+ _exit(1);
+ }
+ strcpy(prog, tk_test.path);
+ strcat(prog, "/");
+ strcat(prog, dp->d_name);
+ switch(curr_pid=fork()) {
+ case -1:
+ log_error("fork: %s", strerror(errno));
+ _exit(1);
+ case 0: /* child */
+ run_ext_prog(tk, prog);
+ default: /* parent */
+ while (waitpid(curr_pid, &status, 0) != curr_pid)
+ ;
+ curr_pid = 0;
+ if (!ignore_status) {
+ rv = test_exit_status(tk, prog, status, 1);
+ if (rv)
+ _exit(rv);
+ }
+ }
+ }
+ _exit(0);
+}
+
/* run some external program
* return codes:
* RUNCMD_ERR: executing program failed (or some other failure)
@@ -70,22 +239,27 @@
{
int rv = 0;
pid_t pid;
+ struct stat stbuf;
- if (!tk_test.prog)
+ if (!tk_test.path)
return 0;
+ if (stat(tk_test.path, &stbuf)) {
+ tk_log_error("%s: stat failed (%s)", tk_test.path, strerror(errno));
+ return RUNCMD_ERR;
+ }
+ tk_test.is_dir = (stbuf.st_mode & S_IFDIR);
+
switch(pid=fork()) {
case -1:
log_error("fork: %s", strerror(errno));
return RUNCMD_ERR;
case 0: /* child */
- if (set_booth_env(tk)) {
- exit(1);
+ if (tk_test.is_dir) {
+ process_ext_dir(tk);
+ } else {
+ run_ext_prog(tk, tk_test.path);
}
- closefiles(); /* don't leak open files */
- execv(tk_test.prog, tk_test.argv);
- tk_log_error("%s: execv failed (%s)", tk_test.prog, strerror(errno));
- exit(1);
default: /* parent */
tk_test.pid = pid;
tk_test.progstate = EXTPROG_RUNNING;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/src/handler.h new/booth/src/handler.h
--- old/booth/src/handler.h 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/src/handler.h 2016-03-23 17:31:14.000000000 +0100
@@ -25,6 +25,11 @@
};
int run_handler(struct ticket_config *tk);
+int tk_test_exit_status(struct ticket_config *tk);
+void ignore_ext_test(struct ticket_config *tk);
+int is_ext_prog_running(struct ticket_config *tk);
+void ext_prog_timeout(struct ticket_config *tk);
+void wait_child(int sig);
#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/src/main.c new/booth/src/main.c
--- old/booth/src/main.c 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/src/main.c 2016-03-23 17:31:14.000000000 +0100
@@ -58,8 +58,9 @@
#include "ticket.h"
#include "request.h"
#include "attr.h"
+#include "handler.h"
-#define RELEASE_VERSION "0.2.0"
+#define RELEASE_VERSION "1.0"
#define RELEASE_STR RELEASE_VERSION " (build " BOOTH_BUILD_VERSION ")"
#define CLIENT_NALLOC 32
@@ -1396,31 +1397,6 @@
exit(0);
}
-static void wait_child(int sig)
-{
- int i, status;
- struct ticket_config *tk;
-
- /* use waitpid(2) and not wait(2) in order not to interfear
- * with popen(2)/pclose(2) and system(2) used in pacemaker.c
- */
- foreach_ticket(i, tk) {
- if (tk_test.prog && tk_test.pid >= 0 &&
- (tk_test.progstate == EXTPROG_RUNNING ||
- tk_test.progstate == EXTPROG_IGNORE) &&
- waitpid(tk_test.pid, &status, WNOHANG) == tk_test.pid) {
- if (tk_test.progstate == EXTPROG_IGNORE) {
- /* not interested in the outcome */
- tk_test.pid = 0;
- tk_test.progstate = EXTPROG_IDLE;
- } else {
- tk_test.status = status;
- tk_test.progstate = EXTPROG_EXITED;
- }
- }
- }
-}
-
static int do_server(int type)
{
int rv = -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/src/ticket.c new/booth/src/ticket.c
--- old/booth/src/ticket.c 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/src/ticket.c 2016-03-23 17:31:14.000000000 +0100
@@ -190,59 +190,6 @@
}
}
-/* Ask an external program whether getting the ticket
- * makes sense.
-* Eg. if the services have a failcount of INFINITY,
-* we can't serve here anyway. */
-static int run_external_prog(struct ticket_config *tk,
- int start_election)
-{
- int rv;
-
- rv = run_handler(tk);
- switch (rv) {
- case RUNCMD_ERR:
- tk_log_warn("couldn't run external test, not allowed to acquire ticket");
- ext_prog_failed(tk, start_election);
- break;
- case 0:
- /* immediately returned with success */
- break;
- case RUNCMD_MORE:
- tk_log_debug("forked %s", tk_test.prog);
- break;
- default:
- break;
- }
-
- return rv;
-}
-
-static int test_exit_status(struct ticket_config *tk,
- int start_election)
-{
- int rv = -1, status;
-
- status = tk_test.status;
- if (WIFEXITED(status)) {
- rv = WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- rv = 128 + WTERMSIG(status);
- }
- if (rv) {
- tk_log_warn("handler \"%s\" failed: %s",
- tk_test.prog, interpret_rv(status));
- tk_log_warn("we are not allowed to acquire ticket");
- ext_prog_failed(tk, start_election);
- } else {
- tk_log_debug("handler \"%s\" exited with success",
- tk_test.prog);
- }
- tk_test.pid = 0;
- tk_test.progstate = EXTPROG_IDLE;
- return rv;
-}
-
#define attr_found(geo_ap, ap) \
((geo_ap) && !strcmp((geo_ap)->val, (ap)->attr_val))
@@ -292,19 +239,26 @@
{
int rv = 0;
- if (!tk_test.prog)
+ if (!tk_test.path)
return 0;
switch(tk_test.progstate) {
case EXTPROG_IDLE:
- rv = run_external_prog(tk, start_election);
+ rv = run_handler(tk);
+ if (rv == RUNCMD_ERR) {
+ tk_log_warn("couldn't run external test, not allowed to acquire ticket");
+ ext_prog_failed(tk, start_election);
+ }
break;
case EXTPROG_RUNNING:
/* should never get here, but just in case */
rv = RUNCMD_MORE;
break;
case EXTPROG_EXITED:
- rv = test_exit_status(tk, start_election);
+ rv = tk_test_exit_status(tk);
+ if (rv) {
+ ext_prog_failed(tk, start_election);
+ }
break;
case EXTPROG_IGNORE:
/* nothing to do here */
@@ -376,15 +330,6 @@
}
}
-static void ignore_extprog(struct ticket_config *tk)
-{
- if (tk_test.prog && tk_test.pid >= 0 &&
- tk_test.progstate == EXTPROG_RUNNING) {
- tk_test.progstate = EXTPROG_IGNORE;
- (void)kill(tk_test.pid, SIGTERM);
- }
-}
-
static void start_revoke_ticket(struct ticket_config *tk)
{
tk_log_info("revoking ticket");
@@ -392,7 +337,6 @@
save_committed_tkt(tk);
reset_ticket(tk);
set_leader(tk, no_leader);
- ignore_extprog(tk);
ticket_write(tk);
ticket_broadcast(tk, OP_REVOKE, OP_ACK, RLT_SUCCESS, OR_ADMIN);
}
@@ -497,6 +441,7 @@
void reset_ticket(struct ticket_config *tk)
{
+ ignore_ext_test(tk);
disown_ticket(tk);
no_resends(tk);
set_state(tk, ST_INIT);
@@ -943,8 +888,13 @@
if (tk->leader != local) {
tk_log_warn("lost at %s", site_string(tk->leader));
} else {
- tk_log_warn("lost majority (revoking locally)");
- reason = tk->election_reason ? tk->election_reason : OR_REACQUIRE;
+ if (is_ext_prog_running(tk)) {
+ ext_prog_timeout(tk);
+ reason = OR_LOCAL_FAIL;
+ } else {
+ tk_log_warn("lost majority (revoking locally)");
+ reason = tk->election_reason ? tk->election_reason : OR_REACQUIRE;
+ }
}
tk->lost_leader = tk->leader;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/src/transport.c new/booth/src/transport.c
--- old/booth/src/transport.c 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/src/transport.c 2016-03-23 17:31:14.000000000 +0100
@@ -102,12 +102,12 @@
if (matched == node->addrlen) {
- /* Full match. */
+ /* Exact match. */
+exact_match:
*address_bits_matched = matched * 8;
-found:
*me = node;
did_match = EXACT_MATCH;
- continue;
+ break;
}
if (!fuzzy_allowed)
@@ -120,14 +120,14 @@
if (matched * 8 < *address_bits_matched)
continue;
if (!bits_left)
- goto found;
+ goto exact_match;
node_bits = n_a[bytes];
ip_bits = ipaddr[bytes];
if (((node_bits ^ ip_bits) & mask) == 0) {
/* _At_least_ prefixlen bits matched. */
- *address_bits_matched = prefixlen;
if (did_match < EXACT_MATCH) {
+ *address_bits_matched = prefixlen;
*me = node;
did_match = FUZZY_MATCH;
}
@@ -769,7 +769,7 @@
* packet */
char buffer[MAX_MSG_LEN];
/* Used for unit tests */
- void *msg;
+ struct boothc_ticket_msg *msg;
sa_len = sizeof(sa);
@@ -781,7 +781,7 @@
if (rv == -1)
return;
- deliver_fn(msg, rv);
+ deliver_fn((void*)msg, rv);
}
static int booth_udp_init(void *f)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/unit-tests/020_ext-verifier.txt new/booth/unit-tests/020_ext-verifier.txt
--- old/booth/unit-tests/020_ext-verifier.txt 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/unit-tests/020_ext-verifier.txt 2016-03-23 17:31:14.000000000 +0100
@@ -13,10 +13,11 @@
term_duration 3000
# but shall start renewal now
term_expires time(0) + 1000
- ext_verifier "test `set|grep ^BOOTH|wc -l` -ge 5"
- hb_sent_at time(0) - 10
+ req_sent_at time(0) - 10
+gdb0:
+ call parse_extprog("test `set|grep ^BOOTH|wc -l` -ge 5", booth_conf->ticket+0)
outgoing0:
header.cmd OP_HEARTBEAT
@@ -25,7 +26,7 @@
ticket1:
ext_verifier 'test "$BOOTH_TICKET" == "tick1"'
# cause re-query of the verifier
- hb_sent_at time(0) - 10
+ req_sent_at time(0) - 10
#
#gdb1:
@@ -40,7 +41,7 @@
ticket2:
ext_verifier 'test "$BOOTH_TICKET" == "tick2FOO"'
# cause re-query of the verifier
- hb_sent_at time(0) - 10
+ req_sent_at time(0) - 10
# We just tell the others we don't have it anymore.
outgoing2:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/booth/unit-tests/_defaults.txt new/booth/unit-tests/_defaults.txt
--- old/booth/unit-tests/_defaults.txt 2016-01-12 11:50:01.000000000 +0100
+++ new/booth/unit-tests/_defaults.txt 2016-03-23 17:31:14.000000000 +0100
@@ -15,14 +15,15 @@
# defaults for all tests
state ST_INIT
- next_cron 0
+ next_cron.tv_sec 0
+
# time(0)+1
# local is site[0] per convention
leader booth_conf->site+1
#owner booth_conf->site+1
#expires time(0)+1
- term_expires time(0)+1
+ term_expires.tv_sec time(0)+1
#last_ack_ballot 242
leader 0
@@ -51,5 +52,4 @@
ticket.leader -1
ticket.term 0
ticket.term_valid_for 0
- ticket.leader_commit -1