Signed-off-by: Michael Roth <mdr...@linux.vnet.ibm.com> --- virtagent-server.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/virtagent-server.c b/virtagent-server.c index b0fc0c4..3c8c805 100644 --- a/virtagent-server.c +++ b/virtagent-server.c @@ -113,11 +113,69 @@ static QDict *va_ping(const QDict *params) return va_server_format_response(NULL, 0, NULL); } +/* va_shutdown(): initiate guest shutdown + * params/response qdict format: + * params{shutdown_mode}: "reboot"|"powerdown"|"shutdown" + * response{error}: <error code> + * response{errstr}: <error description> + */ +static QDict *va_shutdown(const QDict *params) +{ + int ret; + const char *shutdown_mode, *shutdown_flag; + + shutdown_mode = qdict_get_try_str(params, "shutdown_mode"); + SLOG("va_shutdown(), shutdown_mode:%s", shutdown_mode); + + if (!shutdown_mode) { + ret = -EINVAL; + LOG("missing shutdown argument"); + goto out; + } else if (strcmp(shutdown_mode, "halt") == 0) { + shutdown_flag = "-H"; + } else if (strcmp(shutdown_mode, "powerdown") == 0) { + shutdown_flag = "-P"; + } else if (strcmp(shutdown_mode, "reboot") == 0) { + shutdown_flag = "-r"; + } else { + ret = -EINVAL; + LOG("invalid shutdown argument"); + goto out; + } + + ret = fork(); + if (ret == 0) { + /* child, start the shutdown */ + setsid(); + fclose(stdin); + fclose(stdout); + fclose(stderr); + + sleep(5); + ret = execl("/sbin/shutdown", "shutdown", shutdown_flag, "+0", + "hypervisor initiated shutdown", (char*)NULL); + if (ret < 0) { + LOG("execl() failed: %s", strerror(errno)); + exit(1); + } + exit(0); + } else if (ret < 0) { + LOG("fork() failed: %s", strerror(errno)); + } else { + ret = 0; + } + +out: + return va_server_format_response(NULL, ret, strerror(errno)); +} + static VARPCFunction guest_functions[] = { { .func = va_capabilities, .func_name = "capabilities" }, { .func = va_ping, .func_name = "ping" }, + { .func = va_shutdown, + .func_name = "shutdown" }, { NULL, NULL } }; -- 1.7.0.4