[libvirt] [PATCH] qemu_agent: support qemu agent general command

Michal Privoznik mprivozn at redhat.com
Mon Jul 9 10:54:15 UTC 2012


[I am pasting your patch here again so I can point out some nits]

On 06.07.2012 03:29, MATSUDA, Daiki wrote:
> diff -uNrp libvirt-0.9.13.orig/docs/hvsupport.pl libvirt-0.9.13/docs/hvsupport.pl
> --- libvirt-0.9.13.orig/docs/hvsupport.pl	2011-06-10 15:50:11.000000000 +0900
> +++ libvirt-0.9.13/docs/hvsupport.pl	2012-07-06 09:18:36.363454752 +0900
> @@ -129,6 +129,7 @@ $apis{virDomainMigratePerform3} = "0.9.2
>  $apis{virDomainMigrateFinish3} = "0.9.2";
>  $apis{virDomainMigrateConfirm3} = "0.9.2";
>  
> +$apis{virDomainQemuSupportCommand} = "0.9.14";

This is a result of joining function prototype ...

>  
>  
>  # Now we want to get the mapping between public APIs

> diff -uNrp libvirt-0.9.13.orig/src/driver.h libvirt-0.9.13/src/driver.h
> --- libvirt-0.9.13.orig/src/driver.h	2012-06-25 16:06:18.000000000 +0900
> +++ libvirt-0.9.13/src/driver.h	2012-07-06 09:18:12.497454257 +0900
> @@ -680,7 +680,7 @@ typedef int
>                                    unsigned int flags);
>  
>  typedef int
> -    (*virDrvDomainQemuMonitorCommand)(virDomainPtr domain, const char *cmd,
> +    (*virDrvDomainQemuSupportCommand)(virDomainPtr domain, const char *cmd,
>                                        char **result, unsigned int flags);

... here. Despite QemuMonitorCommand and QemuAgentCommand having the same prototype we don't join them together.

>  
>  /* Choice of unsigned int rather than pid_t is intentional.  */
> @@ -1015,7 +1015,7 @@ struct _virDriver {
>      virDrvDomainSnapshotHasMetadata     domainSnapshotHasMetadata;
>      virDrvDomainRevertToSnapshot        domainRevertToSnapshot;
>      virDrvDomainSnapshotDelete          domainSnapshotDelete;
> -    virDrvDomainQemuMonitorCommand      qemuDomainMonitorCommand;
> +    virDrvDomainQemuSupportCommand      qemuDomainMonitorCommand;

Hence this change should not be here.

>      virDrvDomainQemuAttach              qemuDomainAttach;
>      virDrvDomainOpenConsole             domainOpenConsole;
>      virDrvDomainOpenGraphics            domainOpenGraphics;
> @@ -1041,6 +1041,7 @@ struct _virDriver {
>      virDrvDomainGetDiskErrors           domainGetDiskErrors;
>      virDrvDomainSetMetadata             domainSetMetadata;
>      virDrvDomainGetMetadata             domainGetMetadata;
> +    virDrvDomainQemuSupportCommand      qemuDomainQemuAgentCommand;

And this should be virDrvDomainQemuAgentCommand.

>  };
>  
>  typedef int

> diff -uNrp libvirt-0.9.13.orig/src/qemu/qemu_driver.c libvirt-0.9.13/src/qemu/qemu_driver.c
> --- libvirt-0.9.13.orig/src/qemu/qemu_driver.c	2012-06-27 10:44:39.000000000 +0900
> +++ libvirt-0.9.13/src/qemu/qemu_driver.c	2012-07-06 09:18:12.503579712 +0900
> @@ -13158,6 +13158,78 @@ qemuListAllDomains(virConnectPtr conn,
>      return ret;
>  }
>  
> +static int
> +qemuDomainQemuAgentCommand(virDomainPtr domain,
> +                           const char *cmd,
> +                           char **result,
> +                           unsigned int flags)
> +{
> +    struct qemud_driver *driver = domain->conn->privateData;
> +    virDomainObjPtr vm;
> +    int ret = -1;
> +    qemuDomainObjPrivatePtr priv;
> +
> +    virCheckFlags(0, -1);
> +
> +    qemuDriverLock(driver);
> +    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
> +    qemuDriverUnlock(driver);
> +
> +    if (!vm) {
> +        char uuidstr[VIR_UUID_STRING_BUFLEN];
> +        virUUIDFormat(domain->uuid, uuidstr);
> +        qemuReportError(VIR_ERR_NO_DOMAIN,
> +                         _("no domain with matching uuid '%s'"), uuidstr);
> +        goto cleanup;
> +    }
> +
> +    priv = vm->privateData;
> +
> +    if (!virDomainObjIsActive(vm)) {
> +        qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                        "%s", _("domain is not running"));
> +        goto cleanup;
> +    }
> +
> +    if (priv->agentError) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("QEMU guest agent is not available due to an error"));
> +        goto cleanup;
> +    }
> +
> +    if (!priv->agent) {
> +        qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
> +                        _("QEMU guest agent is not configured"));
> +        goto cleanup;
> +    }
> +
> +    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
> +        goto cleanup;
> +
> +    if (!virDomainObjIsActive(vm)) {
> +        qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                        "%s", _("domain is not running"));
> +        goto endjob;
> +    }
> +
> +    qemuDomainObjEnterAgent(driver, vm);
> +    ret = qemuAgentQemuAgentCommand(priv->agent, cmd, result);
> +    qemuDomainObjExitAgent(driver, vm);
> +
> +    VIR_DEBUG ("qemu-agent-command ret: '%d' domain: '%s' string: %s",
> +               ret, vm->def->name, *result);

This is unnecessary. qemuAgentQemuAgentCommand() already logged result here.

> +
> +endjob:
> +    if (qemuDomainObjEndJob(driver, vm) == 0) {
> +        vm = NULL;
> +    }
> +
> +cleanup:
> +    if (vm)
> +        virDomainObjUnlock(vm);
> +    return ret;
> +}
> +
>  static virDriver qemuDriver = {
>      .no = VIR_DRV_QEMU,
>      .name = QEMU_DRIVER_NAME,
> @@ -13323,6 +13395,7 @@ static virDriver qemuDriver = {
>      .domainPMSuspendForDuration = qemuDomainPMSuspendForDuration, /* 0.9.11 */
>      .domainPMWakeup = qemuDomainPMWakeup, /* 0.9.11 */
>      .domainGetCPUStats = qemuDomainGetCPUStats, /* 0.9.11 */
> +    .qemuDomainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.9.14 */
>  };
>  
>  

Otherwise looking good. ACK with this squashed in:


diff --git a/docs/hvsupport.pl b/docs/hvsupport.pl
index b2b6df7..b0d1f0f 100755
--- a/docs/hvsupport.pl
+++ b/docs/hvsupport.pl
@@ -129,7 +129,6 @@ $apis{virDomainMigratePerform3} = "0.9.2";
 $apis{virDomainMigrateFinish3} = "0.9.2";
 $apis{virDomainMigrateConfirm3} = "0.9.2";
 
-$apis{virDomainQemuSupportCommand} = "0.9.14";
 
 
 # Now we want to get the mapping between public APIs
diff --git a/src/driver.h b/src/driver.h
index ab9e3b4..e905e42 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -680,8 +680,11 @@ typedef int
                                   unsigned int flags);
 
 typedef int
-    (*virDrvDomainQemuSupportCommand)(virDomainPtr domain, const char *cmd,
+    (*virDrvDomainQemuMonitorCommand)(virDomainPtr domain, const char *cmd,
                                       char **result, unsigned int flags);
+typedef int
+    (*virDrvDomainQemuAgentCommand)(virDomainPtr domain, const char *cmd,
+                                    char **result, unsigned int flags);
 
 /* Choice of unsigned int rather than pid_t is intentional.  */
 typedef virDomainPtr
@@ -1015,7 +1018,7 @@ struct _virDriver {
     virDrvDomainSnapshotHasMetadata     domainSnapshotHasMetadata;
     virDrvDomainRevertToSnapshot        domainRevertToSnapshot;
     virDrvDomainSnapshotDelete          domainSnapshotDelete;
-    virDrvDomainQemuSupportCommand      qemuDomainMonitorCommand;
+    virDrvDomainQemuMonitorCommand      qemuDomainMonitorCommand;
     virDrvDomainQemuAttach              qemuDomainAttach;
     virDrvDomainOpenConsole             domainOpenConsole;
     virDrvDomainOpenGraphics            domainOpenGraphics;
@@ -1041,7 +1044,7 @@ struct _virDriver {
     virDrvDomainGetDiskErrors           domainGetDiskErrors;
     virDrvDomainSetMetadata             domainSetMetadata;
     virDrvDomainGetMetadata             domainGetMetadata;
-    virDrvDomainQemuSupportCommand      qemuDomainQemuAgentCommand;
+    virDrvDomainQemuAgentCommand        qemuDomainQemuAgentCommand;
 };
 
 typedef int
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 66bbce1..af20437 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13217,9 +13217,6 @@ qemuDomainQemuAgentCommand(virDomainPtr domain,
     ret = qemuAgentQemuAgentCommand(priv->agent, cmd, result);
     qemuDomainObjExitAgent(driver, vm);
 
-    VIR_DEBUG ("qemu-agent-command ret: '%d' domain: '%s' string: %s",
-               ret, vm->def->name, *result);
-
 endjob:
     if (qemuDomainObjEndJob(driver, vm) == 0) {
         vm = NULL;


However, I will hold the push for a while. There is one general problem with this patch. Unlike qemu monitor, guest agent has several commands which don't return any successful message (guest-suspend-* family). with current implementation libvirt takes an event on command as confirmation of success. That is - we block until an event is received. But with this patch, if user will issue such command the whole API would block endlessly. I am not sure how we should fix this. Either we will take the current implementation (what if qemu will ever come with new command which doesn't report successful run?) or we introduce a flag DONT_WAIT_FOR_REPLY (tricky, we want to wait for error response - but what timeout should we choose? moreover, timeouts are bad).

Therefore, if anybody has any suggestions I am more than happy to hear them.

Michal




More information about the libvir-list mailing list