]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
shutdown the container when powering off the container
authorDaniel Lezcano <daniel.lezcano@free.fr>
Thu, 8 Apr 2010 07:44:23 +0000 (09:44 +0200)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Thu, 8 Apr 2010 07:44:23 +0000 (09:44 +0200)
This patch allows to shutdown the container when the system
is powered off in the container.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
src/lxc/Makefile.am
src/lxc/start.c
src/lxc/utmp.c [new file with mode: 0644]
src/lxc/utmp.h [new file with mode: 0644]

index 890f706bf05ceb17f9ffb95ea639e386c32f8b25..4c4783df1c607b438f78b87efbfb931635b97ab0 100644 (file)
@@ -19,7 +19,7 @@ so_PROGRAMS = liblxc.so
 liblxc_so_SOURCES = \
        arguments.c arguments.h \
        commands.c commands.h \
-       start.c \
+       start.c start.h \
        stop.c \
        monitor.c monitor.h \
        console.c \
@@ -44,7 +44,9 @@ liblxc_so_SOURCES = \
         genl.c genl.h \
        \
        mainloop.c mainloop.h \
-       af_unix.c af_unix.h
+       af_unix.c af_unix.h \
+       \
+       utmp.c utmp.h
 
 AM_CFLAGS=-I$(top_srcdir)/src
 
index acfb1e214d34045232a69f2a1bff598a7662f113..0ce82371de854323decbcbd520ac8ea120767dd4 100644 (file)
@@ -93,10 +93,12 @@ int signalfd(int fd, const sigset_t *mask, int flags)
 #include "conf.h"
 #include "cgroup.h"
 #include "log.h"
+#include "cgroup.h"
 #include "error.h"
 #include "af_unix.h"
 #include "mainloop.h"
 #include "utils.h"
+#include "utmp.h"
 #include "monitor.h"
 #include "commands.h"
 #include "console.h"
@@ -255,8 +257,15 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
                goto out_mainloop_open;
        }
 
-       if (lxc_command_mainloop_add(name, &descr, handler))
+       if (lxc_command_mainloop_add(name, &descr, handler)) {
+               ERROR("failed to add command handler to mainloop");
                goto out_mainloop_open;
+       }
+
+       if (lxc_utmp_mainloop_add(&descr, handler)) {
+               ERROR("failed to add utmp handler to mainloop");
+               goto out_mainloop_open;
+       }
 
        return lxc_mainloop(&descr);
 
diff --git a/src/lxc/utmp.c b/src/lxc/utmp.c
new file mode 100644 (file)
index 0000000..0c4e6f8
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/inotify.h>
+
+#include "conf.h"
+#include "cgroup.h"
+#include "start.h"
+#include "mainloop.h"
+#include "lxc.h"
+#include "log.h"
+#define __USE_GNU
+#include <utmpx.h>
+#undef __USE_GNU
+
+lxc_log_define(lxc_utmp, lxc);
+
+static int utmp_handler(int fd, void *data, struct lxc_epoll_descr *descr)
+{
+       struct inotify_event ie;
+       struct utmpx *utmpx;
+       struct lxc_handler *handler = (struct lxc_handler *)data;
+       struct lxc_conf *conf = handler->conf;
+       char prevrun_level = 'N', currun_level = 'N';
+       int ntasks, ret;
+       char path[MAXPATHLEN];
+
+       if (read(fd, &ie, sizeof(ie)) < 0) {
+               SYSERROR("failed to read utmp notification");
+               return -1;
+       }
+
+       if (snprintf(path, MAXPATHLEN, "%s/var/run/utmp", conf->rootfs) >
+           MAXPATHLEN) {
+               ERROR("path is too long");
+               return -1;
+       }
+
+       if (utmpxname(path)) {
+               SYSERROR("failed to 'utmpxname'");
+               return -1;
+       }
+
+       setutxent();
+
+       while ((utmpx = getutxent())) {
+
+               if (utmpx->ut_type == RUN_LVL) {
+                       prevrun_level = utmpx->ut_pid / 256;
+                       currun_level = utmpx->ut_pid % 256;
+               }
+       }
+
+       ntasks = lxc_cgroup_nrtasks(handler->name);
+       if (ntasks < 0) {
+               ERROR("failed to get the number of tasks");
+               goto out;
+       }
+
+       if (ntasks == 1 && prevrun_level == '3') {
+
+               DEBUG("run level is %c/%c", prevrun_level, currun_level);
+               DEBUG("there is %d tasks remaining", ntasks);
+
+               if (currun_level == '0') {
+                       INFO("container has shutdown");
+                       kill(handler->pid, SIGKILL);
+               }
+
+               if (currun_level == '6') {
+                       INFO("container has reboot");
+                       kill(handler->pid, SIGKILL);
+               }
+       }
+
+       ret = 0;
+out:
+       endutxent();
+
+       return ret;
+}
+
+int lxc_utmp_mainloop_add(struct lxc_epoll_descr *descr,
+                         struct lxc_handler *handler)
+{
+       struct lxc_conf *conf = handler->conf;
+       char path[MAXPATHLEN];
+       int fd, wd;
+
+       if (!conf->rootfs)
+               return 0;
+
+       if (snprintf(path, MAXPATHLEN, "%s/var/run/utmp", conf->rootfs) >
+           MAXPATHLEN) {
+               ERROR("path is too long");
+               return -1;
+       }
+
+       if (access(path, F_OK)) {
+               WARN("'%s' not found", path);
+               return 0;
+       }
+
+       fd = inotify_init();
+       if (fd < 0) {
+               SYSERROR("failed to inotify_init");
+               return -1;
+       }
+
+       if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
+               SYSERROR("failed to set inotify fd to close-on-exec");
+               close(fd);
+               return -1;
+       }
+
+       wd = inotify_add_watch(fd, path, IN_MODIFY);
+       if (wd < 0) {
+               SYSERROR("failed to add watch for '%s'", path);
+               close(fd);
+               return -1;
+       }
+
+       if (lxc_mainloop_add_handler(descr, fd, utmp_handler, handler)) {
+               SYSERROR("failed to add mainloop");
+               close(fd);
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/src/lxc/utmp.h b/src/lxc/utmp.h
new file mode 100644 (file)
index 0000000..ac3eee4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+struct lxc_handler;
+struct lxc_epoll_descr;
+
+int lxc_utmp_mainloop_add(struct lxc_epoll_descr *descr,
+                         struct lxc_handler *handler);