Move watchdog timer utility from vswitchext to openvswitch.
authorBen Pfaff <blp@nicira.com>
Thu, 14 May 2009 20:39:12 +0000 (13:39 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 14 May 2009 20:39:12 +0000 (13:39 -0700)
debian/.gitignore
debian/control.in
debian/openvswitch-wdt.default [new file with mode: 0644]
debian/openvswitch-wdt.dirs [new file with mode: 0644]
debian/openvswitch-wdt.init [new file with mode: 0755]
debian/openvswitch-wdt.install [new file with mode: 0644]
utilities/.gitignore
utilities/automake.mk
utilities/ovs-wdt.c [new file with mode: 0644]
xenserver/vswitch-xen.spec

index 6eae253c650a4a01b254df83443adfe67006a84a..2053c5c100aa4f00d463362964fe986df6327d66 100644 (file)
@@ -17,9 +17,3 @@
 /openvswitch-switch
 /openvswitch-switch-config
 /openvswitch-switch.copyright
-/openvswitch-wdt
-/openvswitch-wdt.copyright
-/openvswitch-wdt.default
-/openvswitch-wdt.dirs
-/openvswitch-wdt.init
-/openvswitch-wdt.install
index 81a6830897378df9c2efedb188648505cd0bbcf5..e344b9fec59df2a4cbabc4f196147393d45d3f32 100644 (file)
@@ -121,3 +121,11 @@ Description: Monitor utility for OpenVSwitch switches
  channel and datapath.  If either become unresponsive, the switch is
  rebooted.
 
+Package: openvswitch-wdt
+Architecture: any
+Recommends: openvswitch-switch
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Watchdog utility for OpenVSwitch switches
+ The ovs-wdt program included in this package manages the hardware
+ watchdog timer in switches based on the Portwell NAR-5520 hardware.
+
diff --git a/debian/openvswitch-wdt.default b/debian/openvswitch-wdt.default
new file mode 100644 (file)
index 0000000..56b7e41
--- /dev/null
@@ -0,0 +1,24 @@
+# This is a POSIX shell fragment                -*- sh -*-
+
+# To configure the OpenVSwitch reliability packages, modify the following.
+# Afterward, the watchdog timer and oops handling will be configured 
+# automatically at boot time.  It can be started immediately with
+#       /etc/init.d/openvswitch-wdt start
+
+# Defaults for initscript
+# sourced by /etc/init.d/openvswitch-wdt
+# installed at /etc/default/openvswitch-wdt by the maintainer scripts
+
+# OOPS_REBOOT_TIME: The number of seconds the system should wait until it
+# reboots when the kernel oops.  A value of zero causes the system to 
+# wait forever.
+OOPS_REBOOT_TIME=1
+
+# WDT_TIMEOUT: The number of seconds the watchdog timer should wait until
+# it reboots the system when it hasn't received a keep-alive.  A value
+# of zero disables the watchdog timer.
+WDT_TIMEOUT=30
+
+# WDT_INTERVAL: The number of seconds to wait between sending keep-alive
+# messages to the watchdog timer.
+WDT_INTERVAL=1
diff --git a/debian/openvswitch-wdt.dirs b/debian/openvswitch-wdt.dirs
new file mode 100644 (file)
index 0000000..ca882bb
--- /dev/null
@@ -0,0 +1,2 @@
+usr/bin
+usr/sbin
diff --git a/debian/openvswitch-wdt.init b/debian/openvswitch-wdt.init
new file mode 100755 (executable)
index 0000000..33cd19c
--- /dev/null
@@ -0,0 +1,176 @@
+#!/bin/sh 
+#
+# Example init.d script with LSB support.
+#
+# Please read this init.d carefully and modify the sections to
+# adjust it to the program you want to run.
+#
+# Copyright (c) 2007, 2009 Javier Fernandez-Sanguino <jfs@debian.org>
+#
+# This is free software; you may 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,
+# or (at your option) any later version.
+#
+# This 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 with
+# the Debian operating system, in /usr/share/common-licenses/GPL;  if
+# not, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA 02111-1307 USA
+#
+### BEGIN INIT INFO
+# Provides:          openvswitch-wdt
+# Required-Start:    $network $local_fs
+# Required-Stop:     
+# Should-Start:      $named $syslog openvswitch-switch
+# Should-Stop:       
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: OpenVSwitch switch watchdog
+### END INIT INFO
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+
+DAEMON=/usr/sbin/ovs-wdt
+NAME=openvswitch-wdt
+DESC="OpenVSwitch switch watchdog"
+
+PIDFILE=/var/run/$NAME.pid 
+
+test -x $DAEMON || exit 0
+
+. /lib/lsb/init-functions
+
+# Default options, these can be overriden by the information
+# at /etc/default/$NAME
+DAEMON_OPTS=""          # Additional options given to the daemon 
+
+DODTIME=10              # Time to wait for the daemon to die, in seconds
+                        # If this value is set too low you might not
+                        # let some daemons to die gracefully and
+                        # 'restart' will not work
+                        
+# Include defaults if available
+if [ -f /etc/default/$NAME ] ; then
+       . /etc/default/$NAME
+fi
+
+set -e
+
+running_pid() {
+# Check if a given process pid's cmdline matches a given name
+    pid=$1
+    name=$2
+    [ -z "$pid" ] && return 1 
+    [ ! -d /proc/$pid ] &&  return 1
+    return 0
+}
+
+running() {
+# Check if the process is running looking at /proc
+# (works for all users)
+
+    # No pidfile, probably no daemon present
+    [ ! -f "$PIDFILE" ] && return 1
+    pid=`cat $PIDFILE`
+    running_pid $pid $DAEMON || return 1
+    return 0
+}
+
+start_daemon() {
+# Start the process using the wrapper
+    if test $WDT_TIMEOUT != 0; then
+        start-stop-daemon --start --quiet -m --background --pidfile $PIDFILE \
+            --exec $DAEMON -- --timeout=$WDT_TIMEOUT --interval=$WDT_INTERVAL $DAEMON_OPTS 
+    fi
+
+    # Wait up to 3 seconds for the daemon to start.
+    for i in 1 2 3; do
+        if running; then
+            break
+        fi
+        sleep 1
+    done
+
+    echo $OOPS_REBOOT_TIME > /proc/sys/kernel/panic
+    echo 1 > /proc/sys/kernel/panic_on_oops
+}
+
+stop_daemon() {
+    start-stop-daemon -o --stop --pidfile $PIDFILE
+    rm $PIDFILE
+}
+
+case "$1" in
+  start)
+       log_daemon_msg "Starting $DESC " "$NAME"
+        # Check if it's running first
+        if running ;  then
+            log_progress_msg "apparently already running"
+            log_end_msg 0
+            exit 0
+        fi
+        if start_daemon && running ;  then
+            # It's ok, the daemon started and is running
+            log_end_msg 0
+        else
+            # Either we could not start it or it is not running
+            # after we did
+            # NOTE: Some daemons might die some time after they start,
+            # this code does not try to detect this and might give
+            # a false positive (use 'status' for that)
+            log_end_msg 1
+        fi
+       ;;
+  stop)
+        log_daemon_msg "Stopping $DESC" "$NAME"
+        if running ; then
+            # Only stop the daemon if we see it running
+            stop_daemon
+            log_end_msg $?
+        else
+            # If it's not running don't do anything
+            log_progress_msg "apparently not running"
+            log_end_msg 0
+            exit 0
+        fi
+        ;;
+  restart|force-reload)
+        log_daemon_msg "Restarting $DESC" "$NAME"
+        if running ;  then
+            stop_daemon
+            # Wait some sensible amount, some daemons need this
+            [ -n "$DIETIME" ] && sleep $DIETIME
+        fi
+        start_daemon
+        running
+        log_end_msg $?
+       ;;
+  status)
+        log_daemon_msg "Checking status of $DESC" "$NAME"
+        if running ;  then
+            log_progress_msg "running"
+            log_end_msg 0
+        else
+            log_progress_msg "apparently not running"
+            log_end_msg 1
+            exit 1
+        fi
+        ;;
+  # Use this if the daemon cannot reload
+  reload)
+        log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon"
+        log_warning_msg "cannot re-read the config file (use restart)."
+        ;;
+  *)
+       N=/etc/init.d/$NAME
+       echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
+       exit 1
+       ;;
+esac
+
+exit 0
diff --git a/debian/openvswitch-wdt.install b/debian/openvswitch-wdt.install
new file mode 100644 (file)
index 0000000..80a04e1
--- /dev/null
@@ -0,0 +1 @@
+_debian/utilities/ovs-wdt usr/sbin
index 7d824f905cc44776779123aa2814abd69193d9ef..eed86ca267c717c784f82e365d0279573498e8e4 100644 (file)
@@ -15,3 +15,4 @@
 /ovs-pki.8
 /vlogconf
 /vlogconf.8
+/ovs-wdt
index b91a604efdf0c28c2e5c726a71a0407c554bd59c..5c7030fbb0e7a0900eb548ffe1bc8bbcc97c0a4c 100644 (file)
@@ -3,7 +3,8 @@ bin_PROGRAMS += \
        utilities/cfg-mod \
        utilities/dpctl \
        utilities/ovs-discover \
-       utilities/ovs-kill
+       utilities/ovs-kill \
+       utilities/ovs-wdt
 noinst_PROGRAMS += utilities/nlmon
 bin_SCRIPTS += utilities/ovs-pki
 noinst_SCRIPTS += utilities/ovs-pki-cgi utilities/ovs-parse-leaks
@@ -53,5 +54,7 @@ utilities_ovs_discover_LDADD = lib/libopenvswitch.a
 utilities_ovs_kill_SOURCES = utilities/ovs-kill.c
 utilities_ovs_kill_LDADD = lib/libopenvswitch.a
 
+utilities_ovs_wdt_SOURCES = utilities/ovs-wdt.c
+
 utilities_nlmon_SOURCES = utilities/nlmon.c
 utilities_nlmon_LDADD = lib/libopenvswitch.a
diff --git a/utilities/ovs-wdt.c b/utilities/ovs-wdt.c
new file mode 100644 (file)
index 0000000..3c5d797
--- /dev/null
@@ -0,0 +1,263 @@
+/* Copyright (c) 2008, 2009 Nicira Networks, Inc.
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, Nicira Networks gives permission
+ * to link the code of its release of vswitchd with the OpenSSL project's
+ * "OpenSSL" library (or with modified versions of it that use the same
+ * license as the "OpenSSL" library), and distribute the linked
+ * executables.  You must obey the GNU General Public License in all
+ * respects for all of the code used other than "OpenSSL".  If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so.  If you do not wish to do so,
+ * delete this exception statement from your version.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+
+/* Default values for the interval and timer.  In seconds. */
+#define DEFAULT_INTERVAL  1
+#define DEFAULT_TIMEOUT   30
+
+int fd = -1;
+
+/* The WDT is automatically enabled when /dev/watchdog is opened.  If we
+ * do not send the magic value to the device first before exiting, the 
+ * system will reboot.  This function allows the program to exit without 
+ * causing a reboot.
+ */
+static void
+cleanup(void)
+{
+    if (fd == -1) {
+        return;
+    }
+
+    /* Writing the magic value "V" to the device is an indication that
+     * the device is about to be closed.  This causes the watchdog to be
+     * disabled after the call to close.
+     */
+    if (write(fd, "V", 1) != 1) {
+        fprintf(stderr, "Couldn't write magic val: %d\n", errno);
+        return;
+    }
+    close(fd); 
+    fd = -1;
+}
+
+
+/* If we receive a SIGINT, cleanup first, which will disable the
+ * watchdog timer.
+ */
+static void
+sighandler(int signum)
+{
+    cleanup();
+    signal(signum, SIG_DFL);
+    raise(signum);
+}
+
+static void
+setup_signal(void)
+{
+    struct sigaction action;
+
+    action.sa_handler = sighandler;
+    sigemptyset(&action.sa_mask);
+    action.sa_flags = 0;
+
+    if (sigaction(SIGINT, &action, NULL) != 0) {
+        fprintf(stderr, "Problem setting up SIGINT handler...\n");
+    }
+    if (sigaction(SIGTERM, &action, NULL) != 0) {
+        fprintf(stderr, "Problem setting up SIGTERM handler...\n");
+    }
+}
+
+
+/* Print information on the WDT hardware */
+static void
+print_wdt_info(void)
+{
+    struct watchdog_info ident;
+
+    if (ioctl(fd, WDIOC_GETSUPPORT, &ident) == -1) {
+        fprintf(stderr, "Couldn't get version: %d\n", errno);
+        cleanup();
+        exit(-1);
+    }
+    printf("identity: %s, ver: %d, opt: %#x\n", ident.identity, 
+            ident.firmware_version, ident.options);
+}
+
+
+static void
+print_help(char *progname)
+{
+    printf("%s: Watchdog timer utility\n", progname);
+    printf("usage: %s [OPTIONS]\n\n", progname);
+    printf("Options:\n");
+    printf("  -t, --timeout=SECS     expiration time of WDT (default: %d)\n",
+            DEFAULT_TIMEOUT);
+    printf("  -i, --interval=SECS    interval to send keep-alives (default: %d)\n",
+            DEFAULT_INTERVAL);
+    printf("  -d, --disable          disable the WDT and exit\n");
+    printf("  -h, --help             display this help message\n");
+    printf("  -v, --verbose          enable verbose printing\n");
+    printf("  -V, --version          display version information of WDT and exit\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+    int arg;
+    int optc;
+    int verbose = 0;
+    int interval = DEFAULT_INTERVAL;
+    int timeout = DEFAULT_TIMEOUT;
+    static struct option const longopts[] =
+    { 
+        {"timeout", required_argument, NULL, 't'},
+        {"interval", required_argument, NULL, 'i'},
+        {"disable", no_argument, NULL, 'd'},
+        {"help", no_argument, NULL, 'h'},
+        {"verbose", no_argument, NULL, 'v'},
+        {"version", no_argument, NULL, 'V'},
+        {0, 0, 0, 0}
+    };
+
+    setup_signal();
+
+    fd = open("/dev/watchdog", O_RDWR);
+    if (fd == -1) {
+        fprintf(stderr, "Couldn't open watchdog device: %s\n", strerror(errno));
+        exit(-1);
+    }
+
+    while ((optc = getopt_long(argc, argv, "t:i:dh?vV", longopts, NULL)) != -1) {
+        switch (optc) {
+        case 't':
+            timeout = strtol(optarg, NULL, 10);
+            if (!timeout) {
+                fprintf(stderr, "Invalid timeout: %s\n", optarg);
+                goto error;
+            }
+            break;
+
+       case 'i':
+            interval = strtol(optarg, NULL, 10);
+            if (!interval) {
+                fprintf(stderr, "Invalid interval: %s\n", optarg);
+                goto error;
+            }
+            break;
+
+        case 'd':
+            arg = WDIOS_DISABLECARD;
+            if (ioctl(fd, WDIOC_SETOPTIONS, &arg) == -1) {
+                fprintf(stderr, "Couldn't disable: %d\n", errno);
+                goto error;
+            }
+            cleanup();
+            exit(0);
+            break;
+
+        case 'h':
+            print_help(argv[0]);
+            cleanup();
+            exit(0);
+            break;
+
+        case 'v':
+            verbose = 1;
+            break;
+
+        case 'V':
+            print_wdt_info();
+            cleanup();
+            exit(0);
+            break;
+
+        default:
+            print_help(argv[0]);
+            goto error;
+            break;
+        }
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    /* Sanity-check the arguments */
+    if (argc != 0) {
+        fprintf(stderr, "Illegal argument: %s\n", argv[0]);
+        goto error;
+    }
+
+    if (verbose) {
+        print_wdt_info();
+        printf("timeout: %d, interval: %d\n", timeout, interval);
+    }
+
+    /* Prevent the interval being greater than the timeout, since it
+     * will always cause a reboot.
+     */
+    if (interval > timeout) {
+        fprintf(stderr, "Interval greater than timeout: %d > %d\n", 
+                interval, timeout);
+        goto error;
+    }
+
+    /* Always set the timeout */
+    if (ioctl(fd, WDIOC_SETTIMEOUT, &timeout) == -1) {
+        fprintf(stderr, "Couldn't set timeout: %d\n", errno);
+        goto error;
+    }
+
+    /* Loop and send a keep-alive every "interval" seconds */
+    while (1) {
+        if (verbose) {
+            if (ioctl(fd, WDIOC_GETTIMELEFT, &arg) == -1) {
+                fprintf(stderr, "Couldn't get time left: %d\n", errno);
+                goto error;
+            }
+            printf("Sending keep alive, time remaining: %d\n", arg);
+        }
+
+        /* Send a keep-alive.  The argument is ignored */
+        if (ioctl(fd, WDIOC_KEEPALIVE, &arg) == -1) {
+            fprintf(stderr, "Couldn't keepalive: %d\n", errno);
+            goto error;
+        }
+
+        sleep(interval);
+    }
+
+    /* Never directly reached... */
+error:
+    cleanup();
+    exit(-1);
+}
index 12e044593605fd2630f065bbcedbd9c4e7c32bf1..4a68e2f77af5b86d6e95bed1618b91bf90c826a9 100644 (file)
@@ -75,7 +75,7 @@ find datapath/linux-2.6 -name *.ko -exec install -m 755  \{\} $RPM_BUILD_ROOT%{_
 rm -rf $RPM_BUILD_ROOT/root/vswitch/bin/controller \
     $RPM_BUILD_ROOT/root/vswitch/bin/ovs-* \
     $RPM_BUILD_ROOT/root/vswitch/bin/secchan \
-    $RPM_BUILD_ROOT/root/vswitch/bin/wdt \
+    $RPM_BUILD_ROOT/root/vswitch/bin/ovs-wdt \
     $RPM_BUILD_ROOT/root/vswitch/sbin/ovs-monitor \
     $RPM_BUILD_ROOT/root/vswitch/share/man/man8/controller.8 \
     $RPM_BUILD_ROOT/root/vswitch/share/man/man8/ovs-*.8 \