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