implement c->reboot(c) in the api.  Remove lxc-shutdown.in, the
bash script.  Replace it with lxc_shutdown.c which uses the
API.

Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
---
 configure.ac            |   1 -
 src/lxc/Makefile.am     |   3 +-
 src/lxc/arguments.h     |   4 +-
 src/lxc/lxc-shutdown.in | 165 ------------------------------------------------
 src/lxc/lxc_shutdown.c  | 117 ++++++++++++++++++++++++++++++++++
 src/lxc/lxccontainer.c  |  18 ++++++
 src/lxc/lxccontainer.h  |   2 +
 7 files changed, 142 insertions(+), 168 deletions(-)
 delete mode 100644 src/lxc/lxc-shutdown.in
 create mode 100644 src/lxc/lxc_shutdown.c

diff --git a/configure.ac b/configure.ac
index 414d71b..83d997b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -383,7 +383,6 @@ AC_CONFIG_FILES([
        src/lxc/lxc-checkconfig
        src/lxc/lxc-version
        src/lxc/lxc-create
-       src/lxc/lxc-shutdown
        src/lxc/lxc-start-ephemeral
        src/lxc/lxc-destroy
        src/lxc/legacy/lxc-ls
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 4a19061..ce79904 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -124,7 +124,6 @@ bin_SCRIPTS = \
        lxc-checkconfig \
        lxc-version \
        lxc-create \
-       lxc-shutdown \
        lxc-destroy
 
 EXTRA_DIST = \
@@ -147,6 +146,7 @@ endif
 bin_PROGRAMS = \
        lxc-attach \
        lxc-unshare \
+       lxc-shutdown \
        lxc-stop \
        lxc-start \
        lxc-clone \
@@ -191,6 +191,7 @@ lxc_restart_SOURCES = lxc_restart.c
 lxc_clone_SOURCES = lxc_clone.c
 lxc_start_SOURCES = lxc_start.c
 lxc_stop_SOURCES = lxc_stop.c
+lxc_shutdown_SOURCES = lxc_shutdown.c
 lxc_unfreeze_SOURCES = lxc_unfreeze.c
 lxc_unshare_SOURCES = lxc_unshare.c
 lxc_wait_SOURCES = lxc_wait.c
diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
index 002a919..a0f0fc9 100644
--- a/src/lxc/arguments.h
+++ b/src/lxc/arguments.h
@@ -61,9 +61,11 @@ struct lxc_arguments {
        int ttynum;
        char escape;
 
-       /* for lxc-wait */
+       /* for lxc-wait and lxc-shutdown */
        char *states;
        long timeout;
+       int wait;
+       int reboot;
 
        /* close fds from parent? */
        int close_all_fds;
diff --git a/src/lxc/lxc-shutdown.in b/src/lxc/lxc-shutdown.in
deleted file mode 100644
index c81e736..0000000
--- a/src/lxc/lxc-shutdown.in
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/bin/sh
-
-# (C) Copyright Canonical 2011,2012
-
-# 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
-
-set -e
-
-. @DATADIR@/lxc/lxc.functions
-
-usage() {
-    echo "usage: lxc-shutdown -n name [-w] [-r] [-P lxcpath]"
-    echo "  Cleanly shut down a container."
-    echo "  -w: wait for shutdown to complete."
-    echo "  -r: reboot (ignore -w)."
-    echo "  -t timeout: wait at most timeout seconds (implies -w), then kill"
-    echo "              the container."
-    echo "  -P lxcpath: path to the lxc container directories."
-}
-
-alarm() {
-    trap 'exit 0' TERM
-    pid=$1
-    timeout=$2
-    sleep $timeout
-    kill $pid
-}
-
-dolxcstop()
-{
-    echo "Calling lxc-stop on $lxc_name"
-    lxc-stop -n $lxc_name -P "$lxc_path"
-    exit 0
-}
-
-usage_err() {
-    [ -n "$1" ] && echo "$1" >&2
-    usage
-    exit 1
-}
-
-optarg_check() {
-    [ -n "$2" ] || usage_err "option '$1' requires an argument"
-}
-
-timeout="-1"
-
-reboot=0
-dowait=0
-
-while [ $# -gt 0 ]; do
-    opt="$1"
-    shift
-    case "$opt" in
-    -h|--help)
-        usage
-        exit 0
-        ;;
-    -n|--name)
-        optarg_check $opt "$1"
-        lxc_name=$1
-        shift
-        ;;
-    -w|--wait)
-        dowait=1
-        ;;
-    -r|--reboot)
-        reboot=1
-        ;;
-    -t|--timeout)
-        optarg_check $opt "$1"
-        timeout=$1
-        dowait=1
-        shift
-        ;;
-    -P|--lxcpath)
-        optarg_check $opt "$1"
-        lxc_path=$1
-        dowait=1
-        shift
-        ;;
-    --)
-        break;;
-    -?)
-        usage_err "unknown option '$opt'"
-        ;;
-    -*)
-        # split opts -abc into -a -b -c
-        set -- $(echo "${opt#-}" | sed 's/\(.\)/ -\1/g') "$@"
-        ;;
-    *)
-        usage_err "unknown option '$opt'"
-        exit 1
-        ;;
-    esac
-done
-
-if [ -z "$lxc_name" ]; then
-    echo "no container name specified"
-    usage
-    exit 1
-fi
-
-if [ ! -d "$lxc_path" ]; then
-    echo "$lxc_path: no such directory"
-    exit 1
-fi
-
-if [ "$(id -u)" != "0" ]; then
-   echo "This command has to be run as root"
-   exit 1
-fi
-
-which lxc-info > /dev/null 2>&1 || { echo "lxc-info not found."; exit 1; }
-which lxc-wait > /dev/null 2>&1 || { echo "lxc-wait not found."; exit 1; }
-
-pid=`lxc-info -n $lxc_name -P "$lxc_path" -p 2>/dev/null | awk '{ print $2 }'`
-if [ "$pid" = "-1" ]; then
-    echo "$lxc_name is not running"
-    exit 1
-fi
-
-if [ $reboot -eq 1 ]; then
-    kill -s INT $pid
-    exit 0
-else
-    kill -s PWR $pid
-fi
-
-if [ $dowait -eq 0 ]; then
-    exit 0
-fi
-
-if [ $timeout != "-1" ]; then
-    trap dolxcstop EXIT
-    alarm $$ $timeout 2>/dev/null &
-    alarmpid=$!
-fi
-
-while ! lxc-info -n $lxc_name -P "$lxc_path" --state-is STOPPED; do
-    sleep 1
-done
-
-if [ $timeout != "-1" ]; then
-    trap - EXIT
-    # include subprocesses; otherwise, we may have to wait until sleep 
completes
-    # if called from a non-interactive context
-    kill $alarmpid $(ps --no-headers --ppid $alarmpid -o pid) 2>/dev/null || :
-fi
-
-echo "Container $lxc_name has shut down"
-
-exit 0
diff --git a/src/lxc/lxc_shutdown.c b/src/lxc/lxc_shutdown.c
new file mode 100644
index 0000000..c9b5083
--- /dev/null
+++ b/src/lxc/lxc_shutdown.c
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright © 2013 Serge Hallyn <serge.hal...@ubuntu.com>.
+ * Copyright © 2013 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "../lxc/lxccontainer.h"
+
+/*
+ * usage: 
+ lxc-shutdown -h
+ usage: lxc-shutdown -n name [-w] [-r] [-P lxcpath]
+       Cleanly shut down a container.
+       -w: wait for shutdown to complete.
+       -r: reboot (ignore -w).
+       -t timeout: wait at most timeout seconds (implies -w), then kill
+          the container.
+       -P lxcpath: path to the lxc container directories.
+*/
+
+#include <stdio.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <lxc/lxc.h>
+#include <lxc/log.h>
+
+#include "arguments.h"
+#include "utils.h"
+
+lxc_log_define(lxc_shutdown, lxc);
+
+static int my_parser(struct lxc_arguments* args, int c, char* arg)
+{
+       switch (c) {
+       case 'r': args->reboot = 1; break;
+       case 'w': args->wait = 1; break;
+       case 't': args->timeout = atoi(arg); break;
+       }
+       return 0;
+}
+
+static const struct option my_longopts[] = {
+       {"reboot", no_argument, 0, 'r'},
+       {"wait", no_argument, 0, 'w'},
+       {"timeout", required_argument, 0, 't'},
+       LXC_COMMON_OPTIONS
+};
+
+static struct lxc_arguments my_args = {
+       .progname = "lxc-shutdown",
+       .help     = "\
+--name=NAME [-w] [-r] [-t timeout] [-P lxcpath]\n\
+\n\
+lxc-stop stops a container with the identifier NAME\n\
+\n\
+Options :\n\
+  -n, --name=NAME   NAME for name of the container\n\
+  -t, --timeout=T   wait T seconds before hardkilling\n\
+  -w, --wait        wait for the container to shut down\n\
+  -r, --reboot      reboot the container (ignore wait)\n",
+       .options  = my_longopts,
+       .parser   = my_parser,
+       .checker  = NULL,
+};
+
+int main(int argc, char *argv[])
+{
+       struct lxc_container *c;
+
+       /* this is a short term test.  We'll probably want to check for
+        * write access to lxcpath instead */
+       if (geteuid()) {
+               fprintf(stderr, "%s must be run as root\n", argv[0]);
+               exit(1);
+       }
+
+       if (lxc_arguments_parse(&my_args, argc, argv))
+               exit(1);
+
+       if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
+                        my_args.progname, my_args.quiet, my_args.lxcpath[0]))
+               exit(1);
+
+       c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
+       if (!c) {
+               fprintf(stderr, "System error loading container\n");
+               exit(1);
+       }
+
+       if (!c->is_running(c)) {
+               fprintf(stderr, "%s is not running\n", my_args.name);
+               exit(1);
+       }
+
+       if (my_args.reboot)
+               exit(c->reboot(c) ? 0 : 1);
+
+       if (!c->shutdown(c, my_args.timeout))
+               exit(c->wait(c, "STOPPED", -1) ? 0 : 1);
+
+       exit(0);
+}
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 23db6f2..2126c89 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -689,6 +689,23 @@ out:
        return bret;
 }
 
+static bool lxcapi_reboot(struct lxc_container *c)
+{
+       pid_t pid;
+
+       if (!c)
+               return false;
+       if (!c->is_running(c))
+               return false;
+       pid = c->init_pid(c);
+       if (pid <= 0)
+               return false;
+       if (kill(pid, SIGINT) < 0)
+               return false;
+       return true;
+
+}
+
 static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
 {
        bool retv;
@@ -1635,6 +1652,7 @@ struct lxc_container *lxc_container_new(const char *name, 
const char *configpath
        c->create = lxcapi_create;
        c->createl = lxcapi_createl;
        c->shutdown = lxcapi_shutdown;
+       c->reboot = lxcapi_reboot;
        c->clear_config_item = lxcapi_clear_config_item;
        c->get_config_item = lxcapi_get_config_item;
        c->get_cgroup_item = lxcapi_get_cgroup_item;
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 67fbed4..c718d14 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -50,6 +50,8 @@ struct lxc_container {
        bool (*save_config)(struct lxc_container *c, const char *alt_file);
        bool (*create)(struct lxc_container *c, char *t, char *const argv[]);
        bool (*createl)(struct lxc_container *c, char *t, ...);
+       /* send SIGINT to ask container to reboot */
+       bool (*reboot)(struct lxc_container *c);
        /* send SIGPWR.  if timeout is not 0 or -1, do a hard stop after 
timeout seconds */
        bool (*shutdown)(struct lxc_container *c, int timeout);
        /* clear all network or capability items in the in-memory configuration 
*/
-- 
1.8.1.2


------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to