From: Ben Pfaff Date: Thu, 14 May 2009 20:39:12 +0000 (-0700) Subject: Move watchdog timer utility from vswitchext to openvswitch. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=925829dfc34b0cf5c72c0722a9c7bf3cd4de3865;p=openvswitch Move watchdog timer utility from vswitchext to openvswitch. --- diff --git a/debian/.gitignore b/debian/.gitignore index 6eae253c..2053c5c1 100644 --- a/debian/.gitignore +++ b/debian/.gitignore @@ -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 diff --git a/debian/control.in b/debian/control.in index 81a68308..e344b9fe 100644 --- a/debian/control.in +++ b/debian/control.in @@ -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 index 00000000..56b7e418 --- /dev/null +++ b/debian/openvswitch-wdt.default @@ -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 index 00000000..ca882bbb --- /dev/null +++ b/debian/openvswitch-wdt.dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/openvswitch-wdt.init b/debian/openvswitch-wdt.init new file mode 100755 index 00000000..33cd19c0 --- /dev/null +++ b/debian/openvswitch-wdt.init @@ -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 +# +# 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 index 00000000..80a04e13 --- /dev/null +++ b/debian/openvswitch-wdt.install @@ -0,0 +1 @@ +_debian/utilities/ovs-wdt usr/sbin diff --git a/utilities/.gitignore b/utilities/.gitignore index 7d824f90..eed86ca2 100644 --- a/utilities/.gitignore +++ b/utilities/.gitignore @@ -15,3 +15,4 @@ /ovs-pki.8 /vlogconf /vlogconf.8 +/ovs-wdt diff --git a/utilities/automake.mk b/utilities/automake.mk index b91a604e..5c7030fb 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -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 index 00000000..3c5d797c --- /dev/null +++ b/utilities/ovs-wdt.c @@ -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 . + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* 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); +} diff --git a/xenserver/vswitch-xen.spec b/xenserver/vswitch-xen.spec index 12e04459..4a68e2f7 100644 --- a/xenserver/vswitch-xen.spec +++ b/xenserver/vswitch-xen.spec @@ -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 \