Quoting Stéphane Graber (stgra...@ubuntu.com): > On 05/17/2013 03:15 PM, Serge Hallyn wrote: > > implement c->reboot(c) in the api. Remove lxc-shutdown.in, the > > bash script. Replace it with lxc_shutdown.c which uses the > > API. > > > Thanks for those changes. As we briefly discussed on IRC, I think we > should rework a bit the set of binaries we have to stop containers, move > to a single one that tries to "do the right thing" by default. > > So my suggestion is basically to: > - Kill lxc-shutdown > - Change lxc-stop so that: > * Default behaviour is to call shutdown(), wait 15s for STOPPED, if > not STOPPED, print a message to the user and call stop()
If noone objects to this change in behavior (as opposed to deprecation) I'll go ahead and merge the two patches and implement this. > * We have a -r option to reboot the container (with proper check that > the container indeed rebooted within the next 15s) > * We have a -s option to shutdown the container without the automatic > fallback to stop() > * Add a -k option allowing a user to just kill a container > (equivalent to old lxc-stop, no shutdown() call and no delay). > > We'd therefore end up with a single binary which does shutdown, stop and > reboot, properly checks that the actions are carried out and supports > timing out and fallback to kill. > > The 15s timeout would be over-ridable through -t, 15s is a guess as to > how long users would be ready to wait for a container to die assuming > some complex processes (database and similar) need enough time to sync > their data and exit. > > Does that sound reasonable to everyone? > > > > 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 > > */ > > > > > -- > Stéphane Graber > Ubuntu developer > http://www.ubuntu.com > ------------------------------------------------------------------------------ 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