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 - [email protected]
+
+- 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 - [email protected]
+
+- 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/[email protected] %{buildroot}/%{_unitdir}/[email protected]
+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}/[email protected]
+%{_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 <[email protected]> and others
+- stable release 1.0
+- systemd: add booth-arbitrator.service (bsc#967036)
+- main: improve address matching procedure
+
 * Mon Jan 11 2016 Dejan Muhamedagic <[email protected]> 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/[email protected] %{buildroot}/%{_unitdir}/[email protected]
+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}/[email protected]
+%{_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/[email protected] 
new/booth/conf/[email protected]
--- old/booth/conf/[email protected]       2016-01-12 11:50:01.000000000 +0100
+++ new/booth/conf/[email protected]       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], [[email protected]])
+AC_INIT([booth], [1.0], [[email protected]])
 
 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 <string.h>
 #include <errno.h>
 #include <arpa/inet.h>
+#include <signal.h>
+#include <sys/wait.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <assert.h>
@@ -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
 


Reply via email to