mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-30 23:20:10 +00:00
shutdown: Rework API and lxc-stop
With this change, shutdown() will no longer call stop() after the timeout, instead it'll just return false and it's up to the caller to then call stop() if appropriate. This also updates the bindings, tests and other scripts. lxc-stop is then updated to do proper option checking and use shutdown, stop or reboot as appropriate. Signed-off-by: Stéphane Graber <stgraber@ubuntu.com> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
509c077284
commit
0464b881e6
@ -270,7 +270,8 @@ if not dest.start() or not dest.wait("RUNNING", timeout=5):
|
|||||||
# Deal with the case where we just attach to the container's console
|
# Deal with the case where we just attach to the container's console
|
||||||
if not args.command and not args.daemon:
|
if not args.command and not args.daemon:
|
||||||
dest.console()
|
dest.console()
|
||||||
dest.shutdown(timeout=5)
|
if not dest.shutdown(timeout=5):
|
||||||
|
dest.stop()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# Try to get the IP addresses
|
# Try to get the IP addresses
|
||||||
@ -318,6 +319,7 @@ for ip in ips:
|
|||||||
break
|
break
|
||||||
|
|
||||||
# Shutdown the container
|
# Shutdown the container
|
||||||
dest.shutdown(timeout=5)
|
if not dest.shutdown(timeout=5):
|
||||||
|
dest.stop()
|
||||||
|
|
||||||
sys.exit(retval)
|
sys.exit(retval)
|
||||||
|
@ -77,7 +77,7 @@ Options :\n\
|
|||||||
.options = my_longopts,
|
.options = my_longopts,
|
||||||
.parser = my_parser,
|
.parser = my_parser,
|
||||||
.checker = NULL,
|
.checker = NULL,
|
||||||
.timeout = 60,
|
.timeout = -2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* returns -1 on failure, 0 on success */
|
/* returns -1 on failure, 0 on success */
|
||||||
@ -95,7 +95,7 @@ static int do_reboot_and_check(struct lxc_arguments *a, struct lxc_container *c)
|
|||||||
return -1;
|
return -1;
|
||||||
if (a->nowait)
|
if (a->nowait)
|
||||||
return 0;
|
return 0;
|
||||||
if (timeout <= 0)
|
if (timeout == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -118,7 +118,7 @@ static int do_reboot_and_check(struct lxc_arguments *a, struct lxc_container *c)
|
|||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
elapsed_time = tv.tv_sec - curtime;
|
elapsed_time = tv.tv_sec - curtime;
|
||||||
if (timeout - elapsed_time <= 0)
|
if (timeout != -1 && timeout - elapsed_time <= 0)
|
||||||
break;
|
break;
|
||||||
timeout -= elapsed_time;
|
timeout -= elapsed_time;
|
||||||
}
|
}
|
||||||
@ -145,6 +145,46 @@ int main(int argc, char *argv[])
|
|||||||
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
|
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* Set default timeout */
|
||||||
|
if (my_args.timeout == -2) {
|
||||||
|
if (my_args.hardstop) {
|
||||||
|
my_args.timeout = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my_args.timeout = 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_args.nowait) {
|
||||||
|
my_args.timeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* some checks */
|
||||||
|
if (!my_args.hardstop && my_args.timeout < -1) {
|
||||||
|
fprintf(stderr, "invalid timeout\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_args.hardstop && my_args.nokill) {
|
||||||
|
fprintf(stderr, "-k can't be used with --nokill\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_args.hardstop && my_args.reboot) {
|
||||||
|
fprintf(stderr, "-k can't be used with -r\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_args.hardstop && my_args.timeout) {
|
||||||
|
fprintf(stderr, "-k doesn't allow timeouts\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_args.nolock && !my_args.hardstop) {
|
||||||
|
fprintf(stderr, "--nolock may only be used with -k\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* shortcut - if locking is bogus, we should be able to kill
|
/* shortcut - if locking is bogus, we should be able to kill
|
||||||
* containers at least */
|
* containers at least */
|
||||||
if (my_args.nolock)
|
if (my_args.nolock)
|
||||||
@ -167,24 +207,27 @@ int main(int argc, char *argv[])
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* kill */
|
||||||
if (my_args.hardstop) {
|
if (my_args.hardstop) {
|
||||||
ret = c->stop(c) ? 0 : 1;
|
ret = c->stop(c) ? 0 : 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reboot */
|
||||||
if (my_args.reboot) {
|
if (my_args.reboot) {
|
||||||
ret = do_reboot_and_check(&my_args, c);
|
ret = do_reboot_and_check(&my_args, c);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (my_args.nokill)
|
/* shutdown */
|
||||||
my_args.timeout = 0;
|
|
||||||
|
|
||||||
s = c->shutdown(c, my_args.timeout);
|
s = c->shutdown(c, my_args.timeout);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
if (!my_args.shutdown)
|
if (my_args.timeout == 0)
|
||||||
ret = c->wait(c, "STOPPED", -1) ? 0 : 1;
|
ret = 0;
|
||||||
|
else if (my_args.nokill)
|
||||||
|
ret = 1;
|
||||||
else
|
else
|
||||||
ret = 1; // fail
|
ret = c->stop(c) ? 0 : 1;
|
||||||
} else
|
} else
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
@ -1348,10 +1348,6 @@ static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
|
|||||||
haltsignal = c->lxc_conf->haltsignal;
|
haltsignal = c->lxc_conf->haltsignal;
|
||||||
kill(pid, haltsignal);
|
kill(pid, haltsignal);
|
||||||
retv = c->wait(c, "STOPPED", timeout);
|
retv = c->wait(c, "STOPPED", timeout);
|
||||||
if (!retv && timeout > 0) {
|
|
||||||
c->stop(c);
|
|
||||||
retv = c->wait(c, "STOPPED", 0); // 0 means don't wait
|
|
||||||
}
|
|
||||||
return retv;
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,12 +362,10 @@ struct lxc_container {
|
|||||||
* SIGPWR.
|
* SIGPWR.
|
||||||
*
|
*
|
||||||
* \param c Container.
|
* \param c Container.
|
||||||
* \param timeout Seconds to wait before forcing a hard stop
|
* \param timeout Seconds to wait before returning false.
|
||||||
* (value must be >0).
|
* (-1 to wait forever, 0 to avoid waiting).
|
||||||
*
|
*
|
||||||
* \return \c true if configuration was loaded successfully, else \c false.
|
* \return \c true if the container was shutdown successfully, else \c false.
|
||||||
*
|
|
||||||
* \note A \p timeout of \c 0 means do not wait.
|
|
||||||
*/
|
*/
|
||||||
bool (*shutdown)(struct lxc_container *c, int timeout);
|
bool (*shutdown)(struct lxc_container *c, int timeout);
|
||||||
|
|
||||||
|
@ -144,7 +144,8 @@ if len(sys.argv) > 1 and sys.argv[1] == "--with-console":
|
|||||||
|
|
||||||
## Shutting down the container
|
## Shutting down the container
|
||||||
print("Shutting down the container")
|
print("Shutting down the container")
|
||||||
container.shutdown(3)
|
if not container.shutdown(3):
|
||||||
|
container.stop()
|
||||||
|
|
||||||
if container.running:
|
if container.running:
|
||||||
print("Stopping the container")
|
print("Stopping the container")
|
||||||
|
@ -1591,9 +1591,8 @@ static PyMethodDef Container_methods[] = {
|
|||||||
METH_VARARGS|METH_KEYWORDS,
|
METH_VARARGS|METH_KEYWORDS,
|
||||||
"shutdown(timeout = -1) -> boolean\n"
|
"shutdown(timeout = -1) -> boolean\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Sends SIGPWR to the container and wait for it to shutdown "
|
"Sends SIGPWR to the container and wait for it to shutdown."
|
||||||
"unless timeout is set to a positive value, in which case "
|
"-1 means wait forever, 0 means skip waiting."
|
||||||
"the container will be killed when the timeout is reached."
|
|
||||||
},
|
},
|
||||||
{"snapshot", (PyCFunction)Container_snapshot,
|
{"snapshot", (PyCFunction)Container_snapshot,
|
||||||
METH_VARARGS|METH_KEYWORDS,
|
METH_VARARGS|METH_KEYWORDS,
|
||||||
|
@ -69,6 +69,9 @@ int main(int argc, char *argv[])
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wait for init to be ready for SIGPWR */
|
||||||
|
sleep(10);
|
||||||
|
|
||||||
if (!c->shutdown(c, 60)) {
|
if (!c->shutdown(c, 60)) {
|
||||||
fprintf(stderr, "%d: failed to shut down %s\n", __LINE__, MYNAME);
|
fprintf(stderr, "%d: failed to shut down %s\n", __LINE__, MYNAME);
|
||||||
goto out;
|
goto out;
|
||||||
|
Loading…
Reference in New Issue
Block a user