diff mbox

[RFC,v7,12/16] virtagent: add "shutdown" RPC to server

Message ID 1299528642-23631-13-git-send-email-mdroth@linux.vnet.ibm.com
State New
Headers show

Commit Message

Michael Roth March 7, 2011, 8:10 p.m. UTC
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtagent-server.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)
diff mbox

Patch

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 }
 };