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

Submitted by Michael Roth on Nov. 16, 2010, 4:01 p.m.

Details

Message ID 1289923320-5638-10-git-send-email-mdroth@linux.vnet.ibm.com
State New
Headers show

Commit Message

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(-)

Comments

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 hide | download patch | download mbox

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[] = {