diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-07-22 14:37:30 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-07-22 14:37:30 +0100 |
commit | 9fe075decce7db2045261794f9ab897a82cba408 (patch) | |
tree | 3200a9352121ff405b109fed0f01188c6d302f14 | |
parent | 5e3d36c2c840c5da77065b0676c0f2a64fee638a (diff) | |
download | xen-9fe075decce7db2045261794f9ab897a82cba408.tar.gz xen-9fe075decce7db2045261794f9ab897a82cba408.tar.bz2 xen-9fe075decce7db2045261794f9ab897a82cba408.zip |
tools: xenbackendd for NetBSD
Attached patch introduces xenbackendd. It is used on NetBSD
to launch the hotplug scripts. Later xenbackendd can be improved to
also launch qemu-dm as child process and will notice when qemu-dm
crashes.
The changes the patch makes:
- rename hotplug scripts as xenbackendd expects them
(current names were taken from pkgsrc)
- install hotplug scripts as executable scripts
- introduce xenbackendd
- build/install/launch on NetBSD only
Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
-rw-r--r-- | tools/Makefile | 1 | ||||
-rw-r--r-- | tools/hotplug/NetBSD/Makefile | 8 | ||||
-rw-r--r-- | tools/hotplug/NetBSD/block (renamed from tools/hotplug/NetBSD/block-nbsd) | 0 | ||||
-rw-r--r-- | tools/hotplug/NetBSD/vif-bridge (renamed from tools/hotplug/NetBSD/vif-bridge-nbsd) | 0 | ||||
-rw-r--r-- | tools/hotplug/NetBSD/vif-ip (renamed from tools/hotplug/NetBSD/vif-ip-nbsd) | 0 | ||||
-rw-r--r-- | tools/misc/xend | 11 | ||||
-rw-r--r-- | tools/xenbackendd/Makefile | 41 | ||||
-rw-r--r-- | tools/xenbackendd/xenbackendd.c | 319 |
8 files changed, 376 insertions, 4 deletions
diff --git a/tools/Makefile b/tools/Makefile index 89ee9710de..78b3990604 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -25,6 +25,7 @@ SUBDIRS-$(CONFIG_Linux) += blktap SUBDIRS-$(CONFIG_Linux) += blktap2 SUBDIRS-$(CONFIG_NetBSD) += libaio SUBDIRS-$(CONFIG_NetBSD) += blktap2 +SUBDIRS-$(CONFIG_NetBSD) += xenbackendd SUBDIRS-y += libfsimage SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen SUBDIRS-$(CONFIG_Linux) += fs-back diff --git a/tools/hotplug/NetBSD/Makefile b/tools/hotplug/NetBSD/Makefile index 18be7df8d8..06eee0556c 100644 --- a/tools/hotplug/NetBSD/Makefile +++ b/tools/hotplug/NetBSD/Makefile @@ -3,9 +3,9 @@ include $(XEN_ROOT)/tools/Rules.mk # Xen script dir and scripts to go there. XEN_SCRIPTS = -XEN_SCRIPTS += block-nbsd -XEN_SCRIPTS += vif-bridge-nbsd -XEN_SCRIPTS += vif-ip-nbsd +XEN_SCRIPTS += block +XEN_SCRIPTS += vif-bridge +XEN_SCRIPTS += vif-ip XEN_SCRIPT_DATA = @@ -23,7 +23,7 @@ install-scripts: $(INSTALL_DIR) $(DESTDIR)$(XEN_SCRIPT_DIR) set -e; for i in $(XEN_SCRIPTS); \ do \ - $(INSTALL_DATA) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \ + $(INSTALL_PROG) $$i $(DESTDIR)$(XEN_SCRIPT_DIR); \ done set -e; for i in $(XEN_SCRIPT_DATA); \ do \ diff --git a/tools/hotplug/NetBSD/block-nbsd b/tools/hotplug/NetBSD/block index d853e11584..d853e11584 100644 --- a/tools/hotplug/NetBSD/block-nbsd +++ b/tools/hotplug/NetBSD/block diff --git a/tools/hotplug/NetBSD/vif-bridge-nbsd b/tools/hotplug/NetBSD/vif-bridge index ecfef15012..ecfef15012 100644 --- a/tools/hotplug/NetBSD/vif-bridge-nbsd +++ b/tools/hotplug/NetBSD/vif-bridge diff --git a/tools/hotplug/NetBSD/vif-ip-nbsd b/tools/hotplug/NetBSD/vif-ip index ca4fd60580..ca4fd60580 100644 --- a/tools/hotplug/NetBSD/vif-ip-nbsd +++ b/tools/hotplug/NetBSD/vif-ip diff --git a/tools/misc/xend b/tools/misc/xend index 4dd550bbed..f33e35bf24 100644 --- a/tools/misc/xend +++ b/tools/misc/xend @@ -107,6 +107,14 @@ def start_consoled(): def start_blktapctrl(): start_daemon("blktapctrl", "") +def start_xenbackendd(): + XENBACKENDD_DEBUG = os.getenv("XENBACKENDD_DEBUG") + args = "" + if XENBACKENDD_DEBUG: + args += "-d" + if os.uname()[0] == 'NetBSD': + start_daemon("xenbackendd", args) + def main(): try: check_logging() @@ -121,11 +129,13 @@ def main(): if os.uname()[0] != "SunOS": start_xenstored() start_consoled() + start_xenbackendd() start_blktapctrl() return daemon.start() elif sys.argv[1] == 'trace_start': start_xenstored() start_consoled() + start_xenbackendd() start_blktapctrl() return daemon.start(trace=1) elif sys.argv[1] == 'stop': @@ -135,6 +145,7 @@ def main(): elif sys.argv[1] == 'restart': start_xenstored() start_consoled() + start_xenbackendd() start_blktapctrl() return daemon.stop() or daemon.start() elif sys.argv[1] == 'status': diff --git a/tools/xenbackendd/Makefile b/tools/xenbackendd/Makefile new file mode 100644 index 0000000000..4421f7d27e --- /dev/null +++ b/tools/xenbackendd/Makefile @@ -0,0 +1,41 @@ +# Copyright (c) 2009 Advanced Micro Devices, 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; under version 2 of the License. +# +# 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. + +XEN_ROOT=../.. +include $(XEN_ROOT)/tools/Rules.mk + +CFLAGS += -Werror +CFLAGS += $(CFLAGS_libxenstore) +CPPFLAGS += -DXEN_SCRIPT_DIR="\"$(XEN_SCRIPT_DIR)\"" +LDFLAGS += $(LDFLAGS_libxenstore) + +SBIN = xenbackendd + +.PHONY: all +all: build + +.PHONY: build +build: $(SBIN) + +.PHONY: install +install: build + $(INSTALL_DIR) $(DESTDIR)$(SBINDIR) + $(INSTALL_PROG) xenbackendd $(DESTDIR)$(SBINDIR) + +.PHONY: clean +clean: + rm -f $(SBIN) $(DEPS) + + +%: %.c Makefile + $(CC) $(CFLAGS) $(CPPFLAGS) $< $(LDFLAGS) -o $@ + +-include $(DEPS) diff --git a/tools/xenbackendd/xenbackendd.c b/tools/xenbackendd/xenbackendd.c new file mode 100644 index 0000000000..852a11536f --- /dev/null +++ b/tools/xenbackendd/xenbackendd.c @@ -0,0 +1,319 @@ +/* $NetBSD: xenbackendd.c,v 1.1.1.1 2008/08/07 20:26:57 cegger Exp $ */ +/* + * Copyright (C) 2006 Manuel Bouyer <bouyer@netbsd.org> + * Copyright (C) 2009 Christoph Egger <Christoph.Egger@amd.com> + * + * 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; under version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <syslog.h> + +#include <xs.h> + +#define DEVTYPE_UNKNOWN 0 +#define DEVTYPE_VIF 1 +#define DEVTYPE_VBD 2 + +#define DOMAIN_PATH "/local/domain/0" + +#ifndef XEN_SCRIPT_DIR +#error XEN_SCRIPT_DIR not defined +#endif + +#ifndef VBD_SCRIPT +#define VBD_SCRIPT XEN_SCRIPT_DIR"/block" +#endif +#ifndef LOG_FILE +#define LOG_FILE "/var/log/xen/xenbackendd.log" +#endif +#ifndef PID_FILE +#define PID_FILE "/var/run/xenbackendd.pid" +#endif + + +struct xs_handle *xs; + +int fflag = 0; +int dflag = 0; + +const char *vbd_script = NULL; +const char *log_file = NULL; +const char *pidfile = NULL; + +static void +dolog(int pri, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + fflush(stderr); + va_start(ap, fmt); + vsyslog(pri, fmt, ap); + va_end(ap); +} + +static void +dodebug(const char *fmt, ...) +{ + va_list ap; + + if (dflag == 0) + return; + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); + printf("\n"); + fflush(stdout); +} + +static void +doexec(const char *cmd, const char *arg1, const char *arg2) +{ + dodebug("exec %s %s %s", cmd, arg1, arg2); + switch(vfork()) { + case -1: + dolog(LOG_ERR, "can't vfork: %s", strerror(errno)); + break; + case 0: + execl(cmd, cmd, arg1, arg2, NULL); + dolog(LOG_ERR, "can't exec %s: %s", cmd, strerror(errno)); + exit(EXIT_FAILURE); + /* NOTREACHED */ + break; + default: + wait(NULL); + break; + } +} + +static void +usage(void) +{ + fprintf(stderr, + "usage: %s [-d] [-f] [-l log_file] [-p pif_file] [-s vbd_script]\n", + getprogname()); + exit(EXIT_FAILURE); +} + +static int +xen_setup(void) +{ + xs = xs_daemon_open(); + if (xs == NULL) { + dolog(LOG_ERR, + "Failed to contact xenstore (%s). Is it running?", + strerror(errno)); + goto out; + } + + if (!xs_watch(xs, DOMAIN_PATH, "backend")) { + dolog(LOG_ERR, "xenstore watch on backend fails."); + goto out; + } + return 0; + + out: + if (xs) { + xs_daemon_close(xs); + xs = NULL; + } + return -1; +} + +int +main(int argc, char * const argv[]) +{ + char **vec; + unsigned int num; + char *s; + int state; + char *sstate; + char *p; + char buf[80]; + int type = DEVTYPE_UNKNOWN; + int ch; + int debug_fd; + FILE *pidfile_f; + + while ((ch = getopt(argc, argv, "dfl:p:s:")) != -1) { + switch (ch) { + case 'd': + dflag = 1; + break; + case 'f': + fflag = 1; + break; + case 'l': + log_file = optarg; + break; + case 'p': + pidfile = pidfile; + case 's': + vbd_script = optarg; + break; + default: + usage(); + } + } + + if (vbd_script == NULL) + vbd_script = VBD_SCRIPT; + if (pidfile == NULL) + pidfile = PID_FILE; + if (log_file == NULL) + log_file = LOG_FILE; + + openlog("xenbackendd", LOG_PID | LOG_NDELAY, LOG_DAEMON); + + if (fflag == 0) { + /* open log file */ + debug_fd = open(log_file, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (debug_fd == -1) { + dolog(LOG_ERR, "can't open %s: %s", + log_file, strerror(errno)); + exit(EXIT_FAILURE); + } + } + + if (fflag == 0) { + /* daemonize */ + pidfile_f = fopen(pidfile, "w"); + if (pidfile_f == NULL) { + dolog(LOG_ERR, "can't open %s: %s", + pidfile, strerror(errno)); + exit(EXIT_FAILURE); + } + if (daemon(0, 0) < 0) { + dolog(LOG_ERR, "can't daemonize: %s", + strerror(errno)); + exit(EXIT_FAILURE); + } + fprintf(pidfile_f, "%d\n", (int)getpid()); + fclose(pidfile_f); + + /* redirect stderr to log file */ + if (dup2(debug_fd, STDERR_FILENO) < 0) { + dolog(LOG_ERR, "can't redirect stderr to %s: %s\n", + log_file, strerror(errno)); + exit(EXIT_FAILURE); + } + + /* also redirect stdout if we're in debug mode */ + if (dflag) { + if (dup2(debug_fd, STDOUT_FILENO) < 0) { + dolog(LOG_ERR, + "can't redirect stdout to %s: %s\n", + log_file, strerror(errno)); + exit(EXIT_FAILURE); + } + } + + close(debug_fd); + debug_fd = -1; + } + + if (xen_setup() < 0) + exit(EXIT_FAILURE); + + for (;;) { + vec = xs_read_watch(xs, &num); + if (!vec) { + dolog(LOG_ERR, "xs_read_watch: NULL\n"); + continue; + } + + if (strlen(vec[XS_WATCH_PATH]) < sizeof("state")) + goto next1; + + /* find last component of path, check if it's "state" */ + p = &vec[XS_WATCH_PATH][ + strlen(vec[XS_WATCH_PATH]) - sizeof("state")]; + if (p[0] != '/') + goto next1; + p[0] = '\0'; + p++; + if (strcmp(p, "state") != 0) + goto next1; + + snprintf(buf, sizeof(buf), "%s/state", vec[XS_WATCH_PATH]); + sstate = xs_read(xs, XBT_NULL, buf, 0); + if (sstate == NULL) { + dolog(LOG_ERR, + "Failed to read %s (%s)", buf, strerror(errno)); + goto next1; + } + + state = atoi(sstate); + snprintf(buf, sizeof(buf), "%s/hotplug-status", + vec[XS_WATCH_PATH]); + s = xs_read(xs, XBT_NULL, buf, 0); + if (s != NULL && state != 6 /* XenbusStateClosed */) + goto next2; + + if (strncmp(vec[XS_WATCH_PATH], + DOMAIN_PATH "/backend/vif", + strlen(DOMAIN_PATH "/backend/vif")) == 0) + type = DEVTYPE_VIF; + + if (strncmp(vec[XS_WATCH_PATH], + DOMAIN_PATH "/backend/vbd", + strlen(DOMAIN_PATH "/backend/vbd")) == 0) + type = DEVTYPE_VBD; + + switch(type) { + case DEVTYPE_VIF: + if (s) + free(s); + snprintf(buf, sizeof(buf), "%s/script", + vec[XS_WATCH_PATH]); + s = xs_read(xs, XBT_NULL, buf, 0); + if (s == NULL) { + dolog(LOG_ERR, + "Failed to read %s (%s)", buf, + strerror(errno)); + goto next2; + } + doexec(s, vec[XS_WATCH_PATH], sstate); + break; + + case DEVTYPE_VBD: + doexec(vbd_script, vec[XS_WATCH_PATH], sstate); + break; + + default: + break; + } + +next2: + if (s) + free(s); + free(sstate); + +next1: + free(vec); + } + + return 0; +} |