Unverified Commit 826a94a5 by Christian Brauner Committed by GitHub

Merge pull request #2544 from 2xsec/bugfix

tools: add default log priority & cleanups
parents 5493a1bf 34a10bfa
......@@ -45,6 +45,21 @@
lxc_log_define(lxc_attach, lxc);
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static int add_to_simple_array(char ***array, ssize_t *capacity, char *value);
static bool stdfd_is_pty(void);
static int lxc_attach_create_log_file(const char *log_file);
static int elevated_privileges;
static signed long new_personality = -1;
static int namespace_flags = -1;
static int remount_sys_proc;
static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV;
static char **extra_env;
static ssize_t extra_env_size;
static char **extra_keep;
static ssize_t extra_keep_size;
static const struct option my_longopts[] = {
{"elevated-privileges", optional_argument, 0, 'e'},
{"arch", required_argument, 0, 'a'},
......@@ -60,43 +75,60 @@ static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS
};
static int elevated_privileges = 0;
static signed long new_personality = -1;
static int namespace_flags = -1;
static int remount_sys_proc = 0;
static lxc_attach_env_policy_t env_policy = LXC_ATTACH_KEEP_ENV;
static char **extra_env = NULL;
static ssize_t extra_env_size = 0;
static char **extra_keep = NULL;
static ssize_t extra_keep_size = 0;
static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
{
ssize_t count = 0;
if (!array)
return -1;
if (*array)
for (; (*array)[count]; count++);
/* we have to reallocate */
if (count >= *capacity - 1) {
ssize_t new_capacity = ((count + 1) / 32 + 1) * 32;
char **new_array = realloc((void*)*array, sizeof(char *) * new_capacity);
if (!new_array)
return -1;
memset(&new_array[count], 0, sizeof(char*)*(new_capacity - count));
*array = new_array;
*capacity = new_capacity;
}
if (!(*array))
return -1;
(*array)[count] = value;
return 0;
}
static struct lxc_arguments my_args = {
.progname = "lxc-attach",
.help = "\
--name=NAME [-- COMMAND]\n\
\n\
Execute the specified COMMAND - enter the container NAME\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-e, --elevated-privileges=PRIVILEGES\n\
Use elevated privileges instead of those of the\n\
container. If you don't specify privileges to be\n\
elevated as OR'd list: CAP, CGROUP and LSM (capabilities,\n\
cgroup and restrictions, respectively) then all of them\n\
will be elevated.\n\
WARNING: This may leak privileges into the container.\n\
Use with care.\n\
-a, --arch=ARCH Use ARCH for program instead of container's own\n\
architecture.\n\
-s, --namespaces=FLAGS\n\
Don't attach to all the namespaces of the container\n\
but just to the following OR'd list of flags:\n\
MOUNT, PID, UTSNAME, IPC, USER or NETWORK.\n\
WARNING: Using -s implies -e with all privileges\n\
elevated, it may therefore leak privileges into the\n\
container. Use with care.\n\
-R, --remount-sys-proc\n\
Remount /sys and /proc if not attaching to the\n\
mount namespace when using -s in order to properly\n\
reflect the correct namespace context. See the\n\
lxc-attach(1) manual page for details.\n\
--clear-env Clear all environment variables before attaching.\n\
The attached shell/program will start with only\n\
container=lxc set.\n\
--keep-env Keep all current environment variables. This\n\
is the current default behaviour, but is likely to\n\
change in the future.\n\
-L, --pty-log=FILE\n\
Log pty output to FILE\n\
-v, --set-var Set an additional variable that is seen by the\n\
attached program in the container. May be specified\n\
multiple times.\n\
--keep-var Keep an additional environment variable. Only\n\
applicable if --clear-env is specified. May be used\n\
multiple times.\n\
-f, --rcfile=FILE\n\
Load configuration file FILE\n\
",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
};
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
......@@ -160,65 +192,45 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
return 0;
}
static struct lxc_arguments my_args = {
.progname = "lxc-attach",
.help = "\
--name=NAME [-- COMMAND]\n\
\n\
Execute the specified COMMAND - enter the container NAME\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-e, --elevated-privileges=PRIVILEGES\n\
Use elevated privileges instead of those of the\n\
container. If you don't specify privileges to be\n\
elevated as OR'd list: CAP, CGROUP and LSM (capabilities,\n\
cgroup and restrictions, respectively) then all of them\n\
will be elevated.\n\
WARNING: This may leak privileges into the container.\n\
Use with care.\n\
-a, --arch=ARCH Use ARCH for program instead of container's own\n\
architecture.\n\
-s, --namespaces=FLAGS\n\
Don't attach to all the namespaces of the container\n\
but just to the following OR'd list of flags:\n\
MOUNT, PID, UTSNAME, IPC, USER or NETWORK.\n\
WARNING: Using -s implies -e with all privileges\n\
elevated, it may therefore leak privileges into the\n\
container. Use with care.\n\
-R, --remount-sys-proc\n\
Remount /sys and /proc if not attaching to the\n\
mount namespace when using -s in order to properly\n\
reflect the correct namespace context. See the\n\
lxc-attach(1) manual page for details.\n\
--clear-env Clear all environment variables before attaching.\n\
The attached shell/program will start with only\n\
container=lxc set.\n\
--keep-env Keep all current environment variables. This\n\
is the current default behaviour, but is likely to\n\
change in the future.\n\
-L, --pty-log=FILE\n\
Log pty output to FILE\n\
-v, --set-var Set an additional variable that is seen by the\n\
attached program in the container. May be specified\n\
multiple times.\n\
--keep-var Keep an additional environment variable. Only\n\
applicable if --clear-env is specified. May be used\n\
multiple times.\n\
-f, --rcfile=FILE\n\
Load configuration file FILE\n\
",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
};
static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
{
ssize_t count = 0;
if (!array)
return -1;
if (*array)
for (; (*array)[count]; count++);
/* we have to reallocate */
if (count >= *capacity - 1) {
ssize_t new_capacity = ((count + 1) / 32 + 1) * 32;
char **new_array = realloc((void*)*array, sizeof(char *) * new_capacity);
if (!new_array)
return -1;
memset(&new_array[count], 0, sizeof(char*)*(new_capacity - count));
*array = new_array;
*capacity = new_capacity;
}
if (!(*array))
return -1;
(*array)[count] = value;
return 0;
}
static bool stdfd_is_pty(void)
{
if (isatty(STDIN_FILENO))
return true;
if (isatty(STDOUT_FILENO))
return true;
if (isatty(STDERR_FILENO))
return true;
......@@ -240,40 +252,34 @@ static int lxc_attach_create_log_file(const char *log_file)
int main(int argc, char *argv[])
{
int ret = -1, r;
int ret = -1;
int wexit = 0;
struct lxc_log log;
pid_t pid;
lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL};
r = lxc_caps_init();
if (r)
if (lxc_caps_init())
exit(EXIT_FAILURE);
r = lxc_arguments_parse(&my_args, argc, argv);
if (r)
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
if (geteuid()) {
if (geteuid())
if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
ERROR("You lack access to %s", my_args.lxcpath[0]);
exit(EXIT_FAILURE);
}
}
struct lxc_container *c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c)
......
......@@ -36,23 +36,15 @@
lxc_log_define(lxc_cgroup, lxc);
static int my_checker(const struct lxc_arguments* args)
{
if (!args->argc) {
ERROR("Missing state object");
return -1;
}
return 0;
}
static int my_checker(const struct lxc_arguments *args);
static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS
};
static struct lxc_arguments my_args = {
.progname = "lxc-cgroup",
.help = "\
.progname = "lxc-cgroup",
.help = "\
--name=NAME state-object [value]\n\
\n\
Get or set the value of a state object (for example, 'cpuset.cpus')\n\
......@@ -61,11 +53,23 @@ in the container's cgroup for the corresponding subsystem.\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
--rcfile=FILE Load configuration file FILE\n",
.options = my_longopts,
.parser = NULL,
.checker = my_checker,
.options = my_longopts,
.parser = NULL,
.checker = my_checker,
.log_priority = "ERROR",
.log_file = "none",
};
static int my_checker(const struct lxc_arguments *args)
{
if (!args->argc) {
ERROR("Missing state object");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
char *state_object = NULL, *value = NULL;
......@@ -75,18 +79,15 @@ int main(int argc, char *argv[])
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
state_object = my_args.argv[0];
......@@ -143,6 +144,7 @@ int main(int argc, char *argv[])
lxc_container_put(c);
exit(EXIT_FAILURE);
}
INFO("%*s", ret, buffer);
}
......
......@@ -30,16 +30,24 @@
#include "log.h"
#include "utils.h"
static char *checkpoint_dir = NULL;
static bool stop = false;
static bool verbose = false;
static bool do_restore = false;
static bool daemonize_set = false;
static bool pre_dump = false;
static char *predump_dir = NULL;
static char *actionscript_path = NULL;
#define OPT_PREDUMP_DIR (OPT_USAGE + 1)
#define OPT_PREDUMP_DIR OPT_USAGE + 1
lxc_log_define(lxc_checkpoint, lxc);
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static int my_checker(const struct lxc_arguments *args);
static bool checkpoint(struct lxc_container *c);
static bool restore_finalize(struct lxc_container *c);
static bool restore(struct lxc_container *c);
static char *checkpoint_dir;
static bool stop;
static bool verbose;
static bool do_restore;
static bool daemonize_set;
static bool pre_dump;
static char *predump_dir;
static char *actionscript_path;
static const struct option my_longopts[] = {
{"checkpoint-dir", required_argument, 0, 'D'},
......@@ -54,31 +62,39 @@ static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS
};
lxc_log_define(lxc_checkpoint, lxc);
static int my_checker(const struct lxc_arguments *args)
{
if (do_restore && stop) {
ERROR("-s not compatible with -r");
return -1;
} else if (!do_restore && daemonize_set) {
ERROR("-d/-F not compatible with -r");
return -1;
}
if (!checkpoint_dir) {
ERROR("-D is required");
return -1;
}
if (pre_dump && do_restore) {
ERROR("-p not compatible with -r");
return -1;
}
return 0;
}
static struct lxc_arguments my_args = {
.progname = "lxc-checkpoint",
.help = "\
--name=NAME\n\
\n\
lxc-checkpoint checkpoints and restores a container\n\
Serializes a container's running state to disk to allow restoring it in\n\
its running state at a later time.\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-r, --restore Restore container\n\
-D, --checkpoint-dir=DIR directory to save the checkpoint in\n\
-v, --verbose Enable verbose criu logs\n\
-A, --action-script=PATH Path to criu action script\n\
Checkpoint options:\n\
-s, --stop Stop the container after checkpointing.\n\
-p, --pre-dump Only pre-dump the memory of the container.\n\
Container keeps on running and following\n\
checkpoints will only dump the changes.\n\
--predump-dir=DIR path to images from previous dump (relative to -D)\n\
Restore options:\n\
-d, --daemon Daemonize the container (default)\n\
-F, --foreground Start with the current tty attached to /dev/console\n\
--rcfile=FILE Load configuration file FILE\n\
",
.options = my_longopts,
.parser = my_parser,
.daemonize = 1,
.checker = my_checker,
.log_priority = "ERROR",
.log_file = "none",
};
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
......@@ -88,7 +104,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
if (!checkpoint_dir)
return -1;
break;
case 'A':
case 'A':
actionscript_path = strdup(arg);
if (!actionscript_path)
return -1;
......@@ -123,37 +139,29 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
return 0;
}
static struct lxc_arguments my_args = {
.progname = "lxc-checkpoint",
.help = "\
--name=NAME\n\
\n\
lxc-checkpoint checkpoints and restores a container\n\
Serializes a container's running state to disk to allow restoring it in\n\
its running state at a later time.\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-r, --restore Restore container\n\
-D, --checkpoint-dir=DIR directory to save the checkpoint in\n\
-v, --verbose Enable verbose criu logs\n\
-A, --action-script=PATH Path to criu action script\n\
Checkpoint options:\n\
-s, --stop Stop the container after checkpointing.\n\
-p, --pre-dump Only pre-dump the memory of the container.\n\
Container keeps on running and following\n\
checkpoints will only dump the changes.\n\
--predump-dir=DIR path to images from previous dump (relative to -D)\n\
Restore options:\n\
-d, --daemon Daemonize the container (default)\n\
-F, --foreground Start with the current tty attached to /dev/console\n\
--rcfile=FILE Load configuration file FILE\n\
",
.options = my_longopts,
.parser = my_parser,
.daemonize = 1,
.checker = my_checker,
};
static int my_checker(const struct lxc_arguments *args)
{
if (do_restore && stop) {
ERROR("-s not compatible with -r");
return -1;
} else if (!do_restore && daemonize_set) {
ERROR("-d/-F not compatible with -r");
return -1;
}
if (!checkpoint_dir) {
ERROR("-D is required");
return -1;
}
if (pre_dump && do_restore) {
ERROR("-p not compatible with -r");
return -1;
}
return 0;
}
static bool checkpoint(struct lxc_container *c)
{
......@@ -262,18 +270,15 @@ int main(int argc, char *argv[])
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
......
......@@ -44,28 +44,8 @@
lxc_log_define(lxc_console, lxc);
static char etoc(const char *expr)
{
/* returns "control code" of given expression */
char c = expr[0] == '^' ? expr[1] : expr[0];
return 1 + ((c > 'Z') ? (c - 'a') : (c - 'Z'));
}
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
case 't':
if (lxc_safe_uint(arg, &args->ttynum) < 0)
return -1;
break;
case 'e':
args->escape = etoc(arg);
break;
}
return 0;
}
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static char etoc(const char *expr);
static const struct option my_longopts[] = {
{"tty", required_argument, 0, 't'},
......@@ -74,8 +54,8 @@ static const struct option my_longopts[] = {
};
static struct lxc_arguments my_args = {
.progname = "lxc-console",
.help = "\
.progname = "lxc-console",
.help = "\
--name=NAME [--tty NUMBER]\n\
\n\
lxc-console logs on the container with the identifier NAME\n\
......@@ -85,35 +65,56 @@ Options :\n\
-t, --tty=NUMBER console tty number\n\
-e, --escape=PREFIX prefix for escape command\n\
--rcfile=FILE Load configuration file FILE\n",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.ttynum = -1,
.escape = 1,
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
.ttynum = -1,
.escape = 1,
};
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
case 't':
if (lxc_safe_uint(arg, &args->ttynum) < 0)
return -1;
break;
case 'e':
args->escape = etoc(arg);
break;
}
return 0;
}
static char etoc(const char *expr)
{
/* returns "control code" of given expression */
char c = expr[0] == '^' ? expr[1] : expr[0];
return 1 + ((c > 'Z') ? (c - 'a') : (c - 'Z'));
}
int main(int argc, char *argv[])
{
int ret;
struct lxc_container *c;
struct lxc_log log;
ret = lxc_arguments_parse(&my_args, argc, argv);
if (ret)
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
......
......@@ -31,64 +31,15 @@
#include "arguments.h"
#include "log.h"
#include "storage_utils.h"
#include "utils.h"
lxc_log_define(lxc_create, lxc);
static uint64_t get_fssize(char *s)
{
uint64_t ret;
char *end;
ret = strtoull(s, &end, 0);
if (end == s)
{
ERROR("Invalid blockdev size '%s', using default size", s);
return 0;
}
while (isblank(*end))
end++;
if (*end == '\0')
ret *= 1024ULL * 1024ULL; /* MB by default */
else if (*end == 'b' || *end == 'B')
ret *= 1ULL;
else if (*end == 'k' || *end == 'K')
ret *= 1024ULL;
else if (*end == 'm' || *end == 'M')
ret *= 1024ULL * 1024ULL;
else if (*end == 'g' || *end == 'G')
ret *= 1024ULL * 1024ULL * 1024ULL;
else if (*end == 't' || *end == 'T')
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
else
{
ERROR("Invalid blockdev unit size '%c' in '%s', using default size", *end, s);
return 0;
}
return ret;
}
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
case 'B': args->bdevtype = arg; break;
case 'f': args->configfile = arg; break;
case 't': args->template = arg; break;
case '0': args->lvname = arg; break;
case '1': args->vgname = arg; break;
case '2': args->thinpool = arg; break;
case '3': args->fstype = arg; break;
case '4': args->fssize = get_fssize(arg); break;
case '5': args->zfsroot = arg; break;
case '6': args->dir = arg; break;
case '7': args->rbdname = arg; break;
case '8': args->rbdpool = arg; break;
}
return 0;
}
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static uint64_t get_fssize(char *s);
static void create_helpfn(const struct lxc_arguments *args);
static bool validate_bdev_args(struct lxc_arguments *args);
static const struct option my_longopts[] = {
{"bdev", required_argument, 0, 'B'},
......@@ -106,35 +57,10 @@ static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS
};
static void create_helpfn(const struct lxc_arguments *args)
{
char *argv[3], *path;
pid_t pid;
if (!args->template)
return;
pid = fork();
if (pid) {
(void)wait_for_pid(pid);
return;
}
path = get_template_path(args->template);
argv[0] = path;
argv[1] = "-h";
argv[2] = NULL;
execv(path, argv);
ERROR("Error executing %s -h", path);
_exit(EXIT_FAILURE);
}
static struct lxc_arguments my_args = {
.progname = "lxc-create",
.helpfn = create_helpfn,
.help = "\
.progname = "lxc-create",
.helpfn = create_helpfn,
.help = "\
--name=NAME --template=TEMPLATE [OPTION...]\n\
\n\
lxc-create creates a container\n\
......@@ -170,64 +96,148 @@ Options :\n\
--fssize=SIZE[U] Create filesystem of\n\
size SIZE * unit U (bBkKmMgGtT)\n\
(Default: 1G, default unit: M)\n",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
};
static bool validate_bdev_args(struct lxc_arguments *a)
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
case 'B':
args->bdevtype = arg;
break;
case 'f':
args->configfile = arg;
break;
case 't':
args->template = arg;
break;
case '0':
args->lvname = arg;
break;
case '1':
args->vgname = arg;
break;
case '2':
args->thinpool = arg;
break;
case '3':
args->fstype = arg;
break;
case '4':
args->fssize = get_fssize(arg);
break;
case '5':
args->zfsroot = arg;
break;
case '6':
args->dir = arg;
break;
case '7':
args->rbdname = arg;
break;
case '8':
args->rbdpool = arg;
break;
}
return 0;
}
static uint64_t get_fssize(char *s)
{
uint64_t ret;
char *end;
ret = strtoull(s, &end, 0);
if (end == s) {
ERROR("Invalid blockdev size '%s', using default size", s);
return 0;
}
while (isblank(*end))
end++;
if (*end == '\0') {
ret *= 1024ULL * 1024ULL; /* MB by default */
} else if (*end == 'b' || *end == 'B') {
ret *= 1ULL;
} else if (*end == 'k' || *end == 'K') {
ret *= 1024ULL;
} else if (*end == 'm' || *end == 'M') {
ret *= 1024ULL * 1024ULL;
} else if (*end == 'g' || *end == 'G') {
ret *= 1024ULL * 1024ULL * 1024ULL;
} else if (*end == 't' || *end == 'T') {
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
} else {
ERROR("Invalid blockdev unit size '%c' in '%s', using default size", *end, s);
return 0;
}
return ret;
}
static void create_helpfn(const struct lxc_arguments *args)
{
char *argv[3], *path;
pid_t pid;
if (!args->template)
return;
pid = fork();
if (pid) {
(void)wait_for_pid(pid);
return;
}
path = get_template_path(args->template);
argv[0] = path;
argv[1] = "-h";
argv[2] = NULL;
execv(path, argv);
ERROR("Error executing %s -h", path);
_exit(EXIT_FAILURE);
}
static bool validate_bdev_args(struct lxc_arguments *args)
{
if (strncmp(a->bdevtype, "best", strlen(a->bdevtype)) != 0) {
if (a->fstype || a->fssize) {
if (strncmp(a->bdevtype, "lvm", strlen(a->bdevtype)) != 0 &&
strncmp(a->bdevtype, "loop", strlen(a->bdevtype)) != 0 &&
strncmp(a->bdevtype, "rbd", strlen(a->bdevtype)) != 0) {
if (strncmp(args->bdevtype, "best", strlen(args->bdevtype)) != 0) {
if (args->fstype || args->fssize)
if (strncmp(args->bdevtype, "lvm", strlen(args->bdevtype)) != 0 &&
strncmp(args->bdevtype, "loop", strlen(args->bdevtype)) != 0 &&
strncmp(args->bdevtype, "rbd", strlen(args->bdevtype)) != 0) {
ERROR("Filesystem type and size are only valid with block devices");
return false;
}
}
if (strncmp(a->bdevtype, "lvm", strlen(a->bdevtype)) != 0) {
if (a->lvname || a->vgname || a->thinpool) {
if (strncmp(args->bdevtype, "lvm", strlen(args->bdevtype)) != 0)
if (args->lvname || args->vgname || args->thinpool) {
ERROR("--lvname, --vgname and --thinpool are only valid with -B lvm");
return false;
}
}
if (strncmp(a->bdevtype, "rbd", strlen(a->bdevtype)) != 0) {
if (a->rbdname || a->rbdpool) {
if (strncmp(args->bdevtype, "rbd", strlen(args->bdevtype)) != 0)
if (args->rbdname || args->rbdpool) {
ERROR("--rbdname and --rbdpool are only valid with -B rbd");
return false;
}
}
if (strncmp(a->bdevtype, "zfs", strlen(a->bdevtype)) != 0) {
if (a->zfsroot) {
if (strncmp(args->bdevtype, "zfs", strlen(args->bdevtype)) != 0)
if (args->zfsroot) {
ERROR("zfsroot is only valid with -B zfs");
return false;
}
}
}
return true;
}
static bool is_valid_storage_type(const char *type)
{
if (strcmp(type, "dir") == 0 ||
strcmp(type, "btrfs") == 0 ||
strcmp(type, "loop") == 0 ||
strcmp(type, "lvm") == 0 ||
strcmp(type, "nbd") == 0 ||
strcmp(type, "overlay") == 0 ||
strcmp(type, "overlayfs") == 0 ||
strcmp(type, "rbd") == 0 ||
strcmp(type, "zfs") == 0)
return true;
return false;
}
int main(int argc, char *argv[])
{
struct lxc_container *c;
......@@ -238,21 +248,15 @@ int main(int argc, char *argv[])
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
if (!my_args.log_file)
log.file = "none";
else
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
if (!my_args.template) {
ERROR("A template must be specified");
......@@ -318,13 +322,12 @@ int main(int argc, char *argv[])
spec.fssize = my_args.fssize;
if ((strncmp(my_args.bdevtype, "zfs", strlen(my_args.bdevtype)) == 0) ||
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0))
if (my_args.zfsroot)
spec.zfs.zfsroot = my_args.zfsroot;
}
if ((strncmp(my_args.bdevtype, "lvm", strlen(my_args.bdevtype)) == 0) ||
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
if (my_args.lvname)
spec.lvm.lv = my_args.lvname;
......@@ -336,7 +339,7 @@ int main(int argc, char *argv[])
}
if ((strncmp(my_args.bdevtype, "rbd", strlen(my_args.bdevtype)) == 0) ||
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
(strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
if (my_args.rbdname)
spec.rbd.rbdname = my_args.rbdname;
......@@ -354,7 +357,7 @@ int main(int argc, char *argv[])
flags = LXC_CREATE_QUIET;
if (!c->create(c, my_args.template, my_args.bdevtype, &spec, flags, &argv[optind])) {
fprintf(stderr, "Error creating container %s\n", c->name);
ERROR("Failed to create container %s", c->name);
lxc_container_put(c);
exit(EXIT_FAILURE);
}
......
......@@ -35,6 +35,8 @@
lxc_log_define(lxc_destroy, lxc);
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static bool do_destroy(struct lxc_container *c);
static bool do_destroy_with_snapshots(struct lxc_container *c);
static const struct option my_longopts[] = {
{"force", no_argument, 0, 'f'},
......@@ -43,8 +45,8 @@ static const struct option my_longopts[] = {
};
static struct lxc_arguments my_args = {
.progname = "lxc-destroy",
.help = "\
.progname = "lxc-destroy",
.help = "\
--name=NAME [-f] [-P lxcpath]\n\
\n\
lxc-destroy destroys a container with the identifier NAME\n\
......@@ -54,106 +56,35 @@ Options :\n\
-s, --snapshots destroy including all snapshots\n\
-f, --force wait for the container to shut down\n\
--rcfile=FILE Load configuration file FILE\n",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.task = DESTROY,
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
.task = DESTROY,
};
static bool do_destroy(struct lxc_container *c);
static bool do_destroy_with_snapshots(struct lxc_container *c);
int main(int argc, char *argv[])
{
struct lxc_container *c;
struct lxc_log log;
bool bret;
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
ERROR("System error loading container");
exit(EXIT_FAILURE);
}
if (my_args.rcfile) {
c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) {
ERROR("Failed to load rcfile");
lxc_container_put(c);
exit(EXIT_FAILURE);
}
c->configfile = strdup(my_args.rcfile);
if (!c->configfile) {
ERROR("Out of memory setting new config filename");
lxc_container_put(c);
exit(EXIT_FAILURE);
}
}
if (!c->may_control(c)) {
ERROR("Insufficent privileges to control %s", my_args.name);
lxc_container_put(c);
exit(EXIT_FAILURE);
}
if (!c->is_defined(c)) {
ERROR("Container is not defined");
lxc_container_put(c);
exit(EXIT_FAILURE);
}
if (my_args.task == SNAP) {
bret = do_destroy_with_snapshots(c);
if (bret)
ERROR("Destroyed container %s including snapshots", my_args.name);
} else {
bret = do_destroy(c);
if (bret)
ERROR("Destroyed container %s", my_args.name);
}
lxc_container_put(c);
if (bret)
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
case 'f': args->force = 1; break;
case 's': args->task = SNAP; break;
case 'f':
args->force = 1;
break;
case 's':
args->task = SNAP;
break;
}
return 0;
}
static bool do_destroy(struct lxc_container *c)
{
int ret;
bool bret = true;
char path[MAXPATHLEN];
/* First check whether the container has dependent clones or snapshots. */
int ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
if (ret < 0 || ret >= MAXPATHLEN)
return false;
......@@ -187,9 +118,8 @@ static bool do_destroy(struct lxc_container *c)
char buf[256];
ret = c->get_config_item(c, "lxc.ephemeral", buf, 256);
if (ret > 0 && strcmp(buf, "0") == 0) {
if (ret > 0 && strcmp(buf, "0") == 0)
bret = c->destroy(c);
}
}
if (!bret) {
......@@ -273,3 +203,75 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
return bret;
}
int main(int argc, char *argv[])
{
struct lxc_container *c;
struct lxc_log log;
bool bret;
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
ERROR("System error loading container");
exit(EXIT_FAILURE);
}
if (my_args.rcfile) {
c->clear_config(c);
if (!c->load_config(c, my_args.rcfile)) {
ERROR("Failed to load rcfile");
lxc_container_put(c);
exit(EXIT_FAILURE);
}
c->configfile = strdup(my_args.rcfile);
if (!c->configfile) {
ERROR("Out of memory setting new config filename");
lxc_container_put(c);
exit(EXIT_FAILURE);
}
}
if (!c->may_control(c)) {
ERROR("Insufficent privileges to control %s", my_args.name);
lxc_container_put(c);
exit(EXIT_FAILURE);
}
if (!c->is_defined(c)) {
ERROR("Container is not defined");
lxc_container_put(c);
exit(EXIT_FAILURE);
}
if (my_args.task == SNAP) {
bret = do_destroy_with_snapshots(c);
if (bret)
ERROR("Destroyed container %s including snapshots", my_args.name);
} else {
bret = do_destroy(c);
if (bret)
ERROR("Destroyed container %s", my_args.name);
}
lxc_container_put(c);
if (bret)
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
......@@ -33,21 +33,23 @@
#include "log.h"
#include "utils.h"
lxc_log_define(lxc_device, lxc);
#if HAVE_IFADDRS_H
#include <ifaddrs.h>
#else
#include "include/ifaddrs.h"
#endif
lxc_log_define(lxc_device, lxc);
static bool is_interface(const char *dev_name, pid_t pid);
static const struct option my_longopts[] = {
LXC_COMMON_OPTIONS
};
static struct lxc_arguments my_args = {
.progname = "lxc-device",
.help = "\
.progname = "lxc-device",
.help = "\
--name=NAME -- add|del DEV\n\
\n\
lxc-device attach or detach DEV to or from container.\n\
......@@ -55,9 +57,11 @@ lxc-device attach or detach DEV to or from container.\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
--rcfile=FILE Load configuration file FILE\n",
.options = my_longopts,
.parser = NULL,
.checker = NULL,
.options = my_longopts,
.parser = NULL,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
};
static bool is_interface(const char *dev_name, pid_t pid)
......@@ -110,25 +114,22 @@ int main(int argc, char *argv[])
}
if (lxc_arguments_parse(&my_args, argc, argv))
goto err;
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
ERROR("%s doesn't exist", my_args.name);
goto err;
exit(EXIT_FAILURE);
}
if (my_args.rcfile) {
......@@ -136,65 +137,60 @@ int main(int argc, char *argv[])
if (!c->load_config(c, my_args.rcfile)) {
ERROR("Failed to load rcfile");
goto err1;
goto err;
}
c->configfile = strdup(my_args.rcfile);
if (!c->configfile) {
ERROR("Out of memory setting new config filename");
goto err1;
goto err;
}
}
if (!c->is_running(c)) {
ERROR("Container %s is not running", c->name);
goto err1;
goto err;
}
if (my_args.argc < 2) {
ERROR("Error: no command given (Please see --help output)");
goto err1;
goto err;
}
cmd = my_args.argv[0];
dev_name = my_args.argv[1];
if (my_args.argc < 3)
dst_name = dev_name;
else
dst_name = my_args.argv[2];
if (strncmp(cmd, "add", strlen(cmd)) == 0) {
if (is_interface(dev_name, 1)) {
if (is_interface(dev_name, 1))
ret = c->attach_interface(c, dev_name, dst_name);
} else {
else
ret = c->add_device_node(c, dev_name, dst_name);
}
if (ret != true) {
ERROR("Failed to add %s to %s", dev_name, c->name);
goto err1;
goto err;
}
} else if (strncmp(cmd, "del", strlen(cmd)) == 0) {
if (is_interface(dev_name, c->init_pid(c))) {
if (is_interface(dev_name, c->init_pid(c)))
ret = c->detach_interface(c, dev_name, dst_name);
} else {
else
ret = c->remove_device_node(c, dev_name, dst_name);
}
if (ret != true) {
ERROR("Failed to del %s from %s", dev_name, c->name);
goto err1;
goto err;
}
} else {
ERROR("Error: Please use add or del (Please see --help output)");
goto err1;
goto err;
}
exit(EXIT_SUCCESS);
err1:
lxc_container_put(c);
err:
lxc_container_put(c);
exit(EXIT_FAILURE);
}
......@@ -43,8 +43,46 @@
lxc_log_define(lxc_execute, lxc);
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static bool set_argv(struct lxc_container *c, struct lxc_arguments *args);
static struct lxc_list defines;
static const struct option my_longopts[] = {
{"daemon", no_argument, 0, 'd'},
{"rcfile", required_argument, 0, 'f'},
{"define", required_argument, 0, 's'},
{"uid", required_argument, 0, 'u'},
{"gid", required_argument, 0, 'g'},
{"share-net", required_argument, 0, OPT_SHARE_NET},
{"share-ipc", required_argument, 0, OPT_SHARE_IPC},
{"share-uts", required_argument, 0, OPT_SHARE_UTS},
{"share-pid", required_argument, 0, OPT_SHARE_PID},
LXC_COMMON_OPTIONS
};
static struct lxc_arguments my_args = {
.progname = "lxc-execute",
.help = "\
--name=NAME -- COMMAND\n\
\n\
lxc-execute creates a container with the identifier NAME\n\
and execs COMMAND into this container.\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-d, --daemon Daemonize the container\n\
-f, --rcfile=FILE Load configuration file FILE\n\
-s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
-u, --uid=UID Execute COMMAND with UID inside the container\n\
-g, --gid=GID Execute COMMAND with GID inside the container\n",
.options = my_longopts,
.parser = my_parser,
.log_priority = "ERROR",
.log_file = "none",
.daemonize = 0,
};
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
int ret;
......@@ -82,43 +120,9 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
args->share_ns[LXC_NS_PID] = arg;
break;
}
return 0;
}
static const struct option my_longopts[] = {
{"daemon", no_argument, 0, 'd'},
{"rcfile", required_argument, 0, 'f'},
{"define", required_argument, 0, 's'},
{"uid", required_argument, 0, 'u'},
{"gid", required_argument, 0, 'g'},
{"share-net", required_argument, 0, OPT_SHARE_NET},
{"share-ipc", required_argument, 0, OPT_SHARE_IPC},
{"share-uts", required_argument, 0, OPT_SHARE_UTS},
{"share-pid", required_argument, 0, OPT_SHARE_PID},
LXC_COMMON_OPTIONS
};
static struct lxc_arguments my_args = {
.progname = "lxc-execute",
.help = "\
--name=NAME -- COMMAND\n\
\n\
lxc-execute creates a container with the identifier NAME\n\
and execs COMMAND into this container.\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-d, --daemon Daemonize the container\n\
-f, --rcfile=FILE Load configuration file FILE\n\
-s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
-u, --uid=UID Execute COMMAND with UID inside the container\n\
-g, --gid=GID Execute COMMAND with GID inside the container\n",
.options = my_longopts,
.parser = my_parser,
.daemonize = 0,
};
static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
{
int ret;
......@@ -134,6 +138,7 @@ static bool set_argv(struct lxc_container *c, struct lxc_arguments *args)
return false;
args->argv = components;
for (p = components; *p; p++)
args->argc++;
......@@ -156,18 +161,15 @@ int main(int argc, char *argv[])
if (lxc_arguments_parse(&my_args, argc, argv))
exit(err);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(err);
}
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(err);
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
......@@ -195,12 +197,11 @@ int main(int argc, char *argv[])
goto out;
}
if (my_args.argc == 0) {
if (my_args.argc == 0)
if (!set_argv(c, &my_args)) {
ERROR("Missing command to execute!");
goto out;
}
}
bret = lxc_config_define_load(&defines, c);
if (!bret)
......@@ -244,12 +245,11 @@ int main(int argc, char *argv[])
if (c->daemonize) {
err = EXIT_SUCCESS;
} else {
if (WIFEXITED(c->error_num)) {
if (WIFEXITED(c->error_num))
err = WEXITSTATUS(c->error_num);
} else {
else
/* Try to die with the same signal the task did. */
kill(0, WTERMSIG(c->error_num));
}
}
out:
......
......@@ -41,8 +41,8 @@ static const struct option my_longopts[] = {
};
static struct lxc_arguments my_args = {
.progname = "lxc-freeze",
.help = "\
.progname = "lxc-freeze",
.help = "\
--name=NAME\n\
\n\
lxc-freeze freezes a container with the identifier NAME\n\
......@@ -50,9 +50,11 @@ lxc-freeze freezes a container with the identifier NAME\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
--rcfile=FILE Load configuration file FILE\n",
.options = my_longopts,
.parser = NULL,
.checker = NULL,
.options = my_longopts,
.parser = NULL,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
};
int main(int argc, char *argv[])
......@@ -63,18 +65,15 @@ int main(int argc, char *argv[])
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
......
......@@ -46,41 +46,58 @@
#include "confile.h"
#include "log.h"
static struct lxc_list defines;
lxc_log_define(lxc_start, lxc);
static int ensure_path(struct lxc_arguments *args, char **confpath, const char *path)
{
int err = -1, fd;
char *fullpath = NULL;
if (path) {
if (access(path, W_OK)) {
fd = creat(path, 0600);
if (fd < 0 && errno != EEXIST) {
ERROR("Failed to create '%s'", path);
goto err;
}
if (fd >= 0)
close(fd);
}
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static int ensure_path(struct lxc_arguments *args, char **confpath, const char *path);
fullpath = realpath(path, NULL);
if (!fullpath) {
ERROR("Failed to get the real path of '%s'", path);
goto err;
}
*confpath = fullpath;
}
static struct lxc_list defines;
err = EXIT_SUCCESS;
static const struct option my_longopts[] = {
{"daemon", no_argument, 0, 'd'},
{"foreground", no_argument, 0, 'F'},
{"rcfile", required_argument, 0, 'f'},
{"define", required_argument, 0, 's'},
{"console", required_argument, 0, 'c'},
{"console-log", required_argument, 0, 'L'},
{"close-all-fds", no_argument, 0, 'C'},
{"pidfile", required_argument, 0, 'p'},
{"share-net", required_argument, 0, OPT_SHARE_NET},
{"share-ipc", required_argument, 0, OPT_SHARE_IPC},
{"share-uts", required_argument, 0, OPT_SHARE_UTS},
{"share-pid", required_argument, 0, OPT_SHARE_PID},
LXC_COMMON_OPTIONS
};
err:
return err;
}
static struct lxc_arguments my_args = {
.progname = "lxc-start",
.help = "\
--name=NAME -- COMMAND\n\
\n\
lxc-start start COMMAND in specified container NAME\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-d, --daemon Daemonize the container (default)\n\
-F, --foreground Start with the current tty attached to /dev/console\n\
-p, --pidfile=FILE Create a file with the process id\n\
-f, --rcfile=FILE Load configuration file FILE\n\
-c, --console=FILE Use specified FILE for the container console\n\
-L, --console-log=FILE Log container console output to FILE\n\
-C, --close-all-fds If any fds are inherited, close them\n\
If not specified, exit with failure instead\n\
Note: --daemon implies --close-all-fds\n\
-s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
--share-[net|ipc|uts|pid]=NAME Share a namespace with another container or pid\n\
",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
.daemonize = 1,
.pidfile = NULL,
};
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
......@@ -124,49 +141,34 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
return 0;
}
static const struct option my_longopts[] = {
{"daemon", no_argument, 0, 'd'},
{"foreground", no_argument, 0, 'F'},
{"rcfile", required_argument, 0, 'f'},
{"define", required_argument, 0, 's'},
{"console", required_argument, 0, 'c'},
{"console-log", required_argument, 0, 'L'},
{"close-all-fds", no_argument, 0, 'C'},
{"pidfile", required_argument, 0, 'p'},
{"share-net", required_argument, 0, OPT_SHARE_NET},
{"share-ipc", required_argument, 0, OPT_SHARE_IPC},
{"share-uts", required_argument, 0, OPT_SHARE_UTS},
{"share-pid", required_argument, 0, OPT_SHARE_PID},
LXC_COMMON_OPTIONS
};
static int ensure_path(struct lxc_arguments *args, char **confpath, const char *path)
{
int fd;
char *fullpath = NULL;
static struct lxc_arguments my_args = {
.progname = "lxc-start",
.help = "\
--name=NAME -- COMMAND\n\
\n\
lxc-start start COMMAND in specified container NAME\n\
\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
-d, --daemon Daemonize the container (default)\n\
-F, --foreground Start with the current tty attached to /dev/console\n\
-p, --pidfile=FILE Create a file with the process id\n\
-f, --rcfile=FILE Load configuration file FILE\n\
-c, --console=FILE Use specified FILE for the container console\n\
-L, --console-log=FILE Log container console output to FILE\n\
-C, --close-all-fds If any fds are inherited, close them\n\
If not specified, exit with failure instead\n\
Note: --daemon implies --close-all-fds\n\
-s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
--share-[net|ipc|uts|pid]=NAME Share a namespace with another container or pid\n\
",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.daemonize = 1,
.pidfile = NULL,
};
if (path) {
if (access(path, W_OK)) {
fd = creat(path, 0600);
if (fd < 0 && errno != EEXIST) {
ERROR("Failed to create '%s'", path);
return -1;
}
if (fd >= 0)
close(fd);
}
fullpath = realpath(path, NULL);
if (!fullpath) {
ERROR("Failed to get the real path of '%s'", path);
return -1;
}
*confpath = fullpath;
}
return 0;
}
int main(int argc, char *argv[])
{
......@@ -194,18 +196,15 @@ int main(int argc, char *argv[])
else
args = my_args.argv;
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(err);
}
if (lxc_log_init(&log))
exit(err);
lxcpath = my_args.lxcpath[0];
if (access(lxcpath, O_RDONLY) < 0) {
......@@ -297,12 +296,11 @@ int main(int argc, char *argv[])
goto out;
}
if (my_args.pidfile != NULL) {
if (my_args.pidfile)
if (ensure_path(&my_args, &c->pidfile, my_args.pidfile) < 0) {
ERROR("Failed to ensure pidfile '%s'", my_args.pidfile);
goto out;
}
}
if (my_args.console)
if (!c->set_config_item(c, "lxc.console.path", my_args.console))
......@@ -315,9 +313,8 @@ int main(int argc, char *argv[])
if (!lxc_setup_shared_ns(&my_args, c))
goto out;
if (!my_args.daemonize) {
if (!my_args.daemonize)
c->want_daemonize(c, false);
}
if (my_args.close_all_fds)
c->want_close_all_fds(c, true);
......
......@@ -34,36 +34,12 @@
#include "log.h"
#include "utils.h"
#define OPT_NO_LOCK OPT_USAGE + 1
#define OPT_NO_KILL OPT_USAGE + 2
#define OPT_NO_LOCK (OPT_USAGE + 1)
#define OPT_NO_KILL (OPT_USAGE + 2)
lxc_log_define(lxc_stop, lxc);
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
case 'r':
args->reboot = 1;
break;
case 'W':
args->nowait = 1;
break;
case 't':
if (lxc_safe_long(arg, &args->timeout) < 0)
return -1;
break;
case 'k':
args->hardstop = 1;
break;
case OPT_NO_LOCK:
args->nolock = 1;
break;
case OPT_NO_KILL:
args->nokill = 1;
break;
}
return 0;
}
static int my_parser(struct lxc_arguments *args, int c, char *arg);
static const struct option my_longopts[] = {
{"reboot", no_argument, 0, 'r'},
......@@ -76,8 +52,8 @@ static const struct option my_longopts[] = {
};
static struct lxc_arguments my_args = {
.progname = "lxc-stop",
.help = "\
.progname = "lxc-stop",
.help = "\
--name=NAME\n\
\n\
lxc-stop stops a container with the identifier NAME\n\
......@@ -91,12 +67,40 @@ Options :\n\
--nolock Avoid using API locks\n\
--nokill Only request clean shutdown, don't force kill after timeout\n\
--rcfile=FILE Load configuration file FILE\n",
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.timeout = -2,
.options = my_longopts,
.parser = my_parser,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
.timeout = -2,
};
static int my_parser(struct lxc_arguments *args, int c, char *arg)
{
switch (c) {
case 'r':
args->reboot = 1;
break;
case 'W':
args->nowait = 1;
break;
case 't':
if (lxc_safe_long(arg, &args->timeout) < 0)
return -1;
break;
case 'k':
args->hardstop = 1;
break;
case OPT_NO_LOCK:
args->nolock = 1;
break;
case OPT_NO_KILL:
args->nokill = 1;
break;
}
return 0;
}
int main(int argc, char *argv[])
{
struct lxc_container *c;
......@@ -107,18 +111,15 @@ int main(int argc, char *argv[])
if (lxc_arguments_parse(&my_args, argc, argv))
exit(ret);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(ret);
}
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(ret);
/* Set default timeout */
if (my_args.timeout == -2) {
......
......@@ -40,8 +40,8 @@ static const struct option my_longopts[] = {
};
static struct lxc_arguments my_args = {
.progname = "lxc-unfreeze",
.help = "\
.progname = "lxc-unfreeze",
.help = "\
--name=NAME\n\
\n\
lxc-unfreeze unfreezes a container with the identifier NAME\n\
......@@ -49,9 +49,11 @@ lxc-unfreeze unfreezes a container with the identifier NAME\n\
Options :\n\
-n, --name=NAME NAME of the container\n\
--rcfile=FILE Load configuration file FILE\n",
.options = my_longopts,
.parser = NULL,
.checker = NULL,
.options = my_longopts,
.parser = NULL,
.checker = NULL,
.log_priority = "ERROR",
.log_file = "none",
};
int main(int argc, char *argv[])
......@@ -62,18 +64,15 @@ int main(int argc, char *argv[])
if (lxc_arguments_parse(&my_args, argc, argv))
exit(EXIT_FAILURE);
/* Only create log if explicitly instructed */
if (my_args.log_file || my_args.log_priority) {
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
log.name = my_args.name;
log.file = my_args.log_file;
log.level = my_args.log_priority;
log.prefix = my_args.progname;
log.quiet = my_args.quiet;
log.lxcpath = my_args.lxcpath[0];
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
}
if (lxc_log_init(&log))
exit(EXIT_FAILURE);
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
if (!c) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment