Patchwork [RFC,v4,09/18] virtagent: add va_shutdown RPC

login
register
mail settings
Submitter Michael Roth
Date Nov. 16, 2010, 4:01 p.m.
Message ID <1289923320-5638-10-git-send-email-mdroth@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/71421/
State New
Headers show

Comments

Michael Roth - Nov. 16, 2010, 4:01 p.m.
RPC to initiate guest shutdown/reboot/powerdown

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtagent-daemon.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)
Jes Sorensen - Nov. 18, 2010, 2:17 p.m.
On 11/16/10 17:01, Michael Roth wrote:
> RPC to initiate guest shutdown/reboot/powerdown

Do we really need this? After all those events can be passed down via ACPI?

Cheers,
Jes
Anthony Liguori - Nov. 18, 2010, 3:35 p.m.
On 11/18/2010 08:17 AM, Jes Sorensen wrote:
> On 11/16/10 17:01, Michael Roth wrote:
>    
>> RPC to initiate guest shutdown/reboot/powerdown
>>      
> Do we really need this? After all those events can be passed down via ACPI?
>    

Reboot can't be passed by ACPI.  This is why virDomainReboot is still 
not functional in KVM.  Every other hypervisor does something identical 
to this series.

And a hypervisor initiated shutdown ought to be treated differently than 
an ACPI shutdown.  Namely, it should correspond to an immediate shut 
down vs. prompting the user.

Not all OSes response to ACPI shutdown either FWIW.

Regards,

Anthony Liguori

> Cheers,
> Jes
>
>
Jes Sorensen - Nov. 18, 2010, 3:41 p.m.
On 11/18/10 16:35, Anthony Liguori wrote:
> On 11/18/2010 08:17 AM, Jes Sorensen wrote:
>> On 11/16/10 17:01, Michael Roth wrote:
>>   
>>> RPC to initiate guest shutdown/reboot/powerdown
>>>      
>> Do we really need this? After all those events can be passed down via
>> ACPI?
>>    
> 
> Reboot can't be passed by ACPI.  This is why virDomainReboot is still
> not functional in KVM.  Every other hypervisor does something identical
> to this series.
> 
> And a hypervisor initiated shutdown ought to be treated differently than
> an ACPI shutdown.  Namely, it should correspond to an immediate shut
> down vs. prompting the user.
> 
> Not all OSes response to ACPI shutdown either FWIW.

Ok, fair enough.

I just would like to avoid duplicating functionality if we don't have to.

Cheers,
Jes

Patch

diff --git a/virtagent-daemon.c b/virtagent-daemon.c
index 0dd72c0..18992dd 100644
--- a/virtagent-daemon.c
+++ b/virtagent-daemon.c
@@ -125,6 +125,62 @@  EXIT_NOCLOSE:
     return result;
 }
 
+/* va_shutdown(): initiate guest shutdown
+ * rpc return values: none
+ */
+static xmlrpc_value *va_shutdown(xmlrpc_env *env,
+                                    xmlrpc_value *param,
+                                    void *user_data)
+{
+    int ret;
+    const char *shutdown_type, *shutdown_flag;
+    xmlrpc_value *result = xmlrpc_build_value(env, "s", "dummy"); 
+
+    TRACE("called");
+    xmlrpc_decompose_value(env, param, "(s)", &shutdown_type);
+    if (env->fault_occurred) {
+        goto out_bad;
+    }
+
+    if (strcmp(shutdown_type, "halt") == 0) {
+        shutdown_flag = "-H";
+    } else if (strcmp(shutdown_type, "powerdown") == 0) {
+        shutdown_flag = "-P";
+    } else if (strcmp(shutdown_type, "reboot") == 0) {
+        shutdown_flag = "-r";
+    } else {
+        xmlrpc_faultf(env, "invalid shutdown type: %s", shutdown_type);
+        goto out_bad;
+    }
+
+    SLOG("va_shutdown(), shutdown_type:%s", shutdown_type);
+
+    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);
+        }
+        TRACE("shouldn't be here");
+        exit(0);
+    } else if (ret < 0) {
+        xmlrpc_faultf(env, "fork() failed: %s", strerror(errno));
+    }
+
+    return result;
+out_bad:
+    return NULL;
+}
+
 static int va_accept(int listen_fd) {
     struct sockaddr_in saddr;
     struct sockaddr *addr;
@@ -156,6 +212,8 @@  static RPCFunction guest_functions[] = {
       .func_name = "getfile" },
     { .func = getdmesg,
       .func_name = "getdmesg" },
+    { .func = va_shutdown,
+      .func_name = "va_shutdown" },
     { NULL, NULL }
 };
 static RPCFunction host_functions[] = {