From: "Daniel P. Berrange" <berrange(a)redhat.com>
To be able todo controlled shutdown/reboot of containers an
API to talk to init via /dev/initctl is required. Fortunately
this is quite straightforward to implement, and is supported
by both sysvinit and systemd. Upstart support for /dev/initctl
is unclear.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
include/libvirt/virterror.h | 1 +
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/libvirt_private.syms | 4 ++
src/util/virinitctl.c | 161 ++++++++++++++++++++++++++++++++++++++++++++
src/util/virinitctl.h | 41 +++++++++++
src/util/virterror.c | 1 +
7 files changed, 210 insertions(+)
create mode 100644 src/util/virinitctl.c
create mode 100644 src/util/virinitctl.h
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index a877683..4d79620 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -114,6 +114,7 @@ typedef enum {
VIR_FROM_SSH = 50, /* Error from libssh2 connection transport */
VIR_FROM_LOCKSPACE = 51, /* Error from lockspace */
+ VIR_FROM_INITCTL = 52, /* Error from initctl device communication */
# ifdef VIR_ENUM_SENTINELS
VIR_ERR_DOMAIN_LAST
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ec59efb..77bc04b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -153,6 +153,7 @@ src/util/virauthconfig.c
src/util/virdbus.c
src/util/virfile.c
src/util/virhash.c
+src/util/virinitctl.c
src/util/virkeyfile.c
src/util/virlockspace.c
src/util/virnetdev.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 627dbb5..6401dec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -94,6 +94,7 @@ UTIL_SOURCES = \
util/virdbus.c util/virdbus.h \
util/virhash.c util/virhash.h \
util/virhashcode.c util/virhashcode.h \
+ util/virinitctl.c util/virinitctl.h \
util/virkeycode.c util/virkeycode.h \
util/virkeyfile.c util/virkeyfile.h \
util/virkeymaps.h \
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2573b8a..f308b55 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1356,6 +1356,10 @@ virFileTouch;
virFileUpdatePerm;
+# virinitctl.h
+virInitctlSetRunLevel;
+
+
# virkeycode.h
virKeycodeSetTypeFromString;
virKeycodeSetTypeToString;
diff --git a/src/util/virinitctl.c b/src/util/virinitctl.c
new file mode 100644
index 0000000..c70ea3a
--- /dev/null
+++ b/src/util/virinitctl.c
@@ -0,0 +1,161 @@
+/*
+ * virinitctl.c: API for talking to init systems via initctl
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include <sys/param.h>
+#include <fcntl.h>
+
+#include "internal.h"
+#include "virinitctl.h"
+#include "virterror_internal.h"
+#include "util.h"
+#include "memory.h"
+#include "virfile.h"
+
+#define VIR_FROM_THIS VIR_FROM_INITCTL
+
+/* These constants & struct definitions are taken from
+ * systemd, under terms of LGPLv2+
+ *
+ * initreq.h Interface to talk to init through /dev/initctl.
+ *
+ * Copyright (C) 1995-2004 Miquel van Smoorenburg
+ */
+
+#if defined(__FreeBSD_kernel__)
+# define VIR_INITCTL_FIFO "/etc/.initctl"
+#else
+# define VIR_INITCTL_FIFO "/dev/initctl"
+#endif
+
+#define VIR_INITCTL_MAGIC 0x03091969
+#define VIR_INITCTL_CMD_START 0
+#define VIR_INITCTL_CMD_RUNLVL 1
+#define VIR_INITCTL_CMD_POWERFAIL 2
+#define VIR_INITCTL_CMD_POWERFAILNOW 3
+#define VIR_INITCTL_CMD_POWEROK 4
+#define VIR_INITCTL_CMD_BSD 5
+#define VIR_INITCTL_CMD_SETENV 6
+#define VIR_INITCTL_CMD_UNSETENV 7
+
+#define VIR_INITCTL_CMD_CHANGECONS 12345
+
+#ifdef MAXHOSTNAMELEN
+# define VIR_INITCTL_RQ_HLEN MAXHOSTNAMELEN
+#else
+# define VIR_INITCTL_RQ_HLEN 64
+#endif
+
+/*
+* This is what BSD 4.4 uses when talking to init.
+* Linux doesn't use this right now.
+*/
+struct virInitctlRequestBSD {
+ char gen_id[8]; /* Beats me.. telnetd uses "fe" */
+ char tty_id[16]; /* Tty name minus /dev/tty */
+ char host[VIR_INITCTL_RQ_HLEN]; /* Hostname */
+ char term_type[16]; /* Terminal type */
+ int signal; /* Signal to send */
+ int pid_value; /* Process to send to */
+ char exec_name[128]; /* Program to execute */
+ char reserved[128]; /* For future expansion. */
+};
+
+
+/*
+ * Because of legacy interfaces, "runlevel" and "sleeptime"
+ * aren't in a separate struct in the union.
+ *
+ * The weird sizes are because init expects the whole
+ * struct to be 384 bytes.
+ */
+struct virInitctlRequest {
+ int magic; /* Magic number */
+ int cmd; /* What kind of request */
+ int runlevel; /* Runlevel to change to */
+ int sleeptime; /* Time between TERM and KILL */
+ union {
+ struct virInitctlRequestBSD bsd;
+ char data[368];
+ } i;
+};
+
+
+/*
+ * Send a message to init to change the runlevel
+ *
+ * Returns 1 on success, 0 if initctl does not exist, -1 on error
+ */
+int virInitctlSetRunLevel(virInitctlRunLevel level,
+ const char *vroot)
+{
+ struct virInitctlRequest req;
+ int fd = -1;
+ char *path = NULL;
+ int ret = -1;
+
+ memset(&req, 0, sizeof(req));
+
+ req.magic = VIR_INITCTL_MAGIC;
+ req.sleeptime = 0;
+ req.cmd = VIR_INITCTL_CMD_RUNLVL;
+ req.runlevel = level;
+
+ if (vroot) {
+ if (virAsprintf(&path, "%s/%s", vroot, VIR_INITCTL_FIFO) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ } else {
+ if (!(path = strdup(VIR_INITCTL_FIFO))) {
+ virReportOOMError();
+ return -1;
+ }
+ }
+
+ if ((fd = open(path, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
+ if (errno == ENOENT) {
+ ret = 0;
+ goto cleanup;
+ }
+ virReportSystemError(errno,
+ _("Cannot open init control %s"),
+ path);
+ goto cleanup;
+ }
+
+ if (safewrite(fd, &req, sizeof(req)) != sizeof(req)) {
+ virReportSystemError(errno,
+ _("Failed to send request to init control %s"),
+ path);
+ goto cleanup;
+ }
+
+ ret = 1;
+
+cleanup:
+ VIR_FREE(path);
+ VIR_FORCE_CLOSE(fd);
+ return ret;
+}
diff --git a/src/util/virinitctl.h b/src/util/virinitctl.h
new file mode 100644
index 0000000..09c078f
--- /dev/null
+++ b/src/util/virinitctl.h
@@ -0,0 +1,41 @@
+/*
+ * virinitctl.h: API for talking to init systems via initctl
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __VIR_INITCTL_H__
+# define __VIR_INITCTL_H__
+
+typedef enum virInitctlRunLevel virInitctlRunLevel;
+enum virInitctlRunLevel {
+ VIR_INITCTL_RUNLEVEL_POWEROFF = 0,
+ VIR_INITCTL_RUNLEVEL_1 = 1,
+ VIR_INITCTL_RUNLEVEL_2 = 2,
+ VIR_INITCTL_RUNLEVEL_3 = 3,
+ VIR_INITCTL_RUNLEVEL_4 = 4,
+ VIR_INITCTL_RUNLEVEL_5 = 5,
+ VIR_INITCTL_RUNLEVEL_REBOOT = 6,
+};
+
+int virInitctlSetRunLevel(virInitctlRunLevel level,
+ const char *vroot);
+
+#endif
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 213188e..1142c40 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -117,6 +117,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
"SSH transport layer", /* 50 */
"Lock Space",
+ "Init control",
)
--
1.7.11.7