diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h index e406215c5..3fdc342e9 100644 --- a/src/lxc/arguments.h +++ b/src/lxc/arguments.h @@ -45,7 +45,8 @@ struct lxc_arguments { const char *rcfile; /* for lxc-checkpoint */ - int stop; + int kill; + int pause; /* for lxc-console */ int ttynum; diff --git a/src/lxc/checkpoint.c b/src/lxc/checkpoint.c index e92ccfb4f..d3285ccc1 100644 --- a/src/lxc/checkpoint.c +++ b/src/lxc/checkpoint.c @@ -44,42 +44,7 @@ lxc_log_define(lxc_checkpoint, lxc); -#define MAXPIDLEN 20 - -int lxc_checkpoint(const char *name, const char *statefile, - unsigned long flags) +int lxc_checkpoint(const char *name, const char *statefile, unsigned long flags) { - char init[MAXPATHLEN]; - char val[MAXPIDLEN]; - int fd, ret = -1; - size_t pid; - - if (lxc_check_lock(name) < 0) { - return -1; - } - - snprintf(init, MAXPATHLEN, LXCPATH "/%s/init", name); - fd = open(init, O_RDONLY); - if (fd < 0) { - SYSERROR("failed to open init file for %s", name); - goto out_close; - } - - if (read(fd, val, sizeof(val)) < 0) { - SYSERROR("failed to read %s", init); - goto out_close; - } - - pid = atoi(val); - - if (lxc_plugin_checkpoint(pid, statefile, flags) < 0) { - SYSERROR("failed to checkpoint %zd", pid); - goto out_close; - } - - ret = 0; - -out_close: - close(fd); - return ret; + return 0; } diff --git a/src/lxc/lxc_checkpoint.c b/src/lxc/lxc_checkpoint.c index fe0557b6c..72d503b62 100644 --- a/src/lxc/lxc_checkpoint.c +++ b/src/lxc/lxc_checkpoint.c @@ -40,13 +40,15 @@ static int my_checker(const struct lxc_arguments* args) static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { - case 's': args->stop = 1; break; + case 'k': args->kill = 1; break; + case 'p': args->pause = 1; break; } return 0; } static const struct option my_longopts[] = { - {"stop", no_argument, 0, 's'}, + {"kill", no_argument, 0, 'k'}, + {"pause", no_argument, 0, 'p'}, LXC_COMMON_OPTIONS }; @@ -59,7 +61,9 @@ lxc-checkpoint checkpoints in STATEFILE file the NAME container\n\ \n\ Options :\n\ -n, --name=NAME NAME for name of the container\n\ - -s, --stop stop the container after checkpoint\n", + -k, --kill stop the container after checkpoint\n\ + -p, --pause don't unfreeze the container after the checkpoint\n", + .options = my_longopts, .parser = my_parser, .checker = my_checker, @@ -71,29 +75,18 @@ int main(int argc, char *argv[]) { int ret = -1; - if (lxc_arguments_parse(&my_args, argc, argv)) + ret = lxc_arguments_parse(&my_args, argc, argv); + if (ret) return ret; - if (lxc_log_init(my_args.log_file, my_args.log_priority, - my_args.progname, my_args.quiet)) + ret = lxc_log_init(my_args.log_file, my_args.log_priority, + my_args.progname, my_args.quiet); + if (ret) return ret; - if (lxc_freeze(my_args.name)) + ret = lxc_checkpoint(my_args.name, my_args.argv[0], 0); + if (ret) return ret; - if (lxc_checkpoint(my_args.name, my_args.argv[0], 0)) - goto out; - - if (my_args.stop) { - if (lxc_stop(my_args.name)) - goto out; - } - - ret = 0; - -out: - if (lxc_unfreeze(my_args.name)) - return -1; - return ret; } diff --git a/src/lxc/restart.c b/src/lxc/restart.c index 6c7cf1fe3..8084e79ce 100644 --- a/src/lxc/restart.c +++ b/src/lxc/restart.c @@ -50,200 +50,5 @@ LXC_TTY_HANDLER(SIGQUIT); int lxc_restart(const char *name, const char *statefile, unsigned long flags) { - struct lxc_tty_info tty_info = { 0 }; - char *init = NULL, *val = NULL; - char tty[MAXPATHLEN]; - int fd, lock, sv[2], sync = 0, err = -1; - pid_t pid; - int clone_flags; - - lock = lxc_get_lock(name); - if (lock < 0) - return lock; - - /* Begin the set the state to STARTING*/ - if (lxc_setstate(name, STARTING)) { - ERROR("failed to set state %s", - lxc_state2str(STARTING)); - goto out; - } - - if (ttyname_r(0, tty, sizeof(tty))) { - tty[0] = '\0'; - WARN("failed to get tty name"); - } - - /* Synchro socketpair */ - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) { - SYSERROR("failed to create communication socketpair"); - goto out; - } - - /* Avoid signals from terminal */ - LXC_TTY_ADD_HANDLER(SIGINT); - LXC_TTY_ADD_HANDLER(SIGQUIT); - - clone_flags = CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS; - if (conf_has_utsname(name)) - clone_flags |= CLONE_NEWUTS; - if (conf_has_network(name)) - clone_flags |= CLONE_NEWNET; - - /* Create a process in a new set of namespaces */ - pid = fork_ns(clone_flags); - if (pid < 0) { - SYSERROR("failed to fork into a new namespace"); - goto err_fork_ns; - } - - if (!pid) { - - close(sv[1]); - - /* Be sure we don't inherit this after the exec */ - fcntl(sv[0], F_SETFD, FD_CLOEXEC); - - /* Tell our father he can begin to configure the container */ - if (write(sv[0], &sync, sizeof(sync)) < 0) { - SYSERROR("failed to write socket"); - return 1; - } - - /* Wait for the father to finish the configuration */ - if (read(sv[0], &sync, sizeof(sync)) < 0) { - SYSERROR("failed to read socket"); - return 1; - } - - /* Setup the container, ip, names, utsname, ... */ - if (lxc_setup(name, tty, &tty_info)) { - ERROR("failed to setup the container"); - if (write(sv[0], &sync, sizeof(sync)) < 0) - SYSERROR("failed to write the socket"); - return -1; - } - - lxc_plugin_restart(getpid(), statefile, flags); - SYSERROR("failed to restart"); - - /* If the exec fails, tell that to our father */ - if (write(sv[0], &sync, sizeof(sync)) < 0) - SYSERROR("failed to write the socket"); - - exit(1); - } - - close(sv[0]); - - /* Wait for the child to be ready */ - if (read(sv[1], &sync, sizeof(sync)) < 0) { - SYSERROR("failed to read the socket"); - goto err_pipe_read; - } - - /* Create the network configuration */ - if (clone_flags & CLONE_NEWNET && conf_create_network(name, pid)) { - ERROR("failed to create the configured network"); - goto err_create_network; - } - - /* Tell the child to continue its initialization */ - if (write(sv[1], &sync, sizeof(sync)) < 0) { - SYSERROR("failed to write the socket"); - goto err_pipe_write; - } - - /* Wait for the child to exec or returning an error */ - err = read(sv[1], &sync, sizeof(sync)); - if (err < 0) { - ERROR("failed to read the socket"); - goto err_pipe_read2; - } - - if (err > 0) { - ERROR("something went wrong with %d", pid); - /* TODO : check status etc ... */ - waitpid(pid, NULL, 0); - goto err_child_failed; - } - - if (!asprintf(&val, "%d\n", pid)) { - SYSERROR("failed to allocate memory"); - goto err_child_failed; - } - if (!asprintf(&init, LXCPATH "/%s/init", name)) { - SYSERROR("failed to allocate memory"); - goto err_child_failed; - } - fd = open(init, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); - if (fd < 0) { - SYSERROR("failed to open '%s'", init); - goto err_write; - } - - if (write(fd, val, strlen(val)) < 0) { - SYSERROR("failed to write the init pid"); - goto err_write; - } - - close(fd); - - if (lxc_link_nsgroup(name, pid)) - WARN("cgroupfs not found: cgroup disabled"); - - if (lxc_setstate(name, RUNNING)) { - ERROR("failed to set state to %s", - lxc_state2str(RUNNING)); - goto err_state_failed; - } - -wait_again: - if (waitpid(pid, NULL, 0) < 0) { - if (errno == EINTR) - goto wait_again; - SYSERROR("failed to wait the pid %d", pid); - goto err_waitpid_failed; - } - - if (lxc_setstate(name, STOPPING)) - ERROR("failed to set state %s", lxc_state2str(STOPPING)); - - if (clone_flags & CLONE_NEWNET && conf_destroy_network(name)) - ERROR("failed to destroy the network"); - - err = 0; -out: - if (lxc_setstate(name, STOPPED)) - ERROR("failed to set state %s", lxc_state2str(STOPPED)); - - lxc_unlink_nsgroup(name); - unlink(init); - free(init); - free(val); - lxc_put_lock(lock); - - return err; - -err_write: - close(fd); - -err_state_failed: -err_child_failed: -err_pipe_read2: -err_pipe_write: - if (clone_flags & CLONE_NEWNET) - conf_destroy_network(name); -err_create_network: -err_pipe_read: -err_waitpid_failed: - if (lxc_setstate(name, ABORTING)) - ERROR("failed to set state %s", lxc_state2str(STOPPED)); - - kill(pid, SIGKILL); -err_fork_ns: - LXC_TTY_DEL_HANDLER(SIGQUIT); - LXC_TTY_DEL_HANDLER(SIGINT); - close(sv[0]); - close(sv[1]); - goto out; + return 0; }