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
};
\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,
{
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;
}
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;
}