[libvirt] [PATCH 10/10 V2] qemu:send-key: Implement the driver methods

Daniel P. Berrange berrange at redhat.com
Mon Jun 13 23:06:04 UTC 2011


On Tue, Jun 07, 2011 at 05:11:17PM +0800, Lai Jiangshan wrote:
> Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
> ---
>  src/qemu/qemu_driver.c       |   50 ++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_monitor.c      |   27 ++++++++++++++++++++++
>  src/qemu/qemu_monitor.h      |    6 +++++
>  src/qemu/qemu_monitor_json.c |   15 ++++++++++++
>  src/qemu/qemu_monitor_json.h |    5 ++++
>  src/qemu/qemu_monitor_text.c |   47 +++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_monitor_text.h |    5 ++++
>  7 files changed, 155 insertions(+), 0 deletions(-)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 2957467..1678deb 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -1764,6 +1764,55 @@ cleanup:
>      return ret;
>  }
>  
> +static int qemuDomainSendKey(virDomainPtr domain,
> +                             unsigned int codeset,
> +                             unsigned int holdtime,
> +                             unsigned int *keycodes,
> +                             unsigned int nkeycodes,
> +                             unsigned int flags)
> +{
> +    struct qemud_driver *driver = domain->conn->privateData;
> +    virDomainObjPtr vm = NULL;
> +    int ret = -1;
> +    qemuDomainObjPrivatePtr priv;
> +
> +    virCheckFlags(0, -1);
> +
> +    qemuDriverLock(driver);
> +    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
> +    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;
> +    }
> +
> +    if (!virDomainObjIsActive(vm)) {
> +        qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                        "%s", _("domain is not running"));
> +        goto cleanup;
> +    }
> +
> +    priv = vm->privateData;
> +
> +    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
> +        goto cleanup;
> +    qemuDomainObjEnterMonitorWithDriver(driver, vm);
> +    ret = qemuMonitorSendKey(priv->mon, codeset, holdtime, nkeycodes, keycodes);
> +    qemuDomainObjExitMonitorWithDriver(driver, vm);
> +    if (qemuDomainObjEndJob(vm) == 0) {
> +        vm = NULL;
> +        goto cleanup;
> +    }
> +
> +cleanup:
> +    if (vm)
> +        virDomainObjUnlock(vm);
> +    qemuDriverUnlock(driver);
> +    return ret;
> +}
> +
>  static int qemudDomainGetInfo(virDomainPtr dom,
>                                virDomainInfoPtr info)
>  {
> @@ -8092,6 +8141,7 @@ static virDriver qemuDriver = {
>      .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
>      .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
>      .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
> +    .domainSendKey = qemuDomainSendKey, /* 0.9.2 */

Needs updating to 0.9.3

> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 26bb814..faab819 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -38,6 +38,8 @@
>  #include "logging.h"
>  #include "files.h"
>  
> +#include <libvirt/virtkeys.h>
> +
>  #define VIR_FROM_THIS VIR_FROM_QEMU
>  
>  #define DEBUG_IO 0
> @@ -2357,6 +2359,31 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon)
>      return ret;
>  }
>  
> +int qemuMonitorSendKey(qemuMonitorPtr mon,
> +                       unsigned int codeset,
> +                       unsigned int holdtime,
> +                       unsigned int nkeycodes,
> +                       unsigned int *keycodes)
> +{
> +    int ret;
> +
> +    VIR_DEBUG("mon=%p, codeset=%u, holdtime=%u, nkeycodes=%u",
> +              mon, codeset, holdtime, nkeycodes);
> +
> +    if (codeset != LIBVIRT_KEYCODE_XT) {
> +        qemuReportError(VIR_ERR_NO_SUPPORT,
> +                        "qemu monitor can not support the codeset: %d",
> +                        codeset);
> +        return -1;
> +    }
> +
> +    if (mon->json)
> +        ret = qemuMonitorJSONSendKey(mon, holdtime, nkeycodes, keycodes);
> +    else
> +        ret = qemuMonitorTextSendKey(mon, holdtime, nkeycodes, keycodes);
> +    return ret;
> +}
> +
>  int qemuMonitorScreendump(qemuMonitorPtr mon,
>                            const char *file)
>  {
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 910865b..64a6320 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -441,6 +441,12 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon);
>  int qemuMonitorScreendump(qemuMonitorPtr mon,
>                            const char *file);
>  
> +int qemuMonitorSendKey(qemuMonitorPtr mon,
> +                       unsigned int codeset,
> +                       unsigned int holdtime,
> +                       unsigned int nkeycodes,
> +                       unsigned int *keycodes);
> +
>  /**
>   * When running two dd process and using <> redirection, we need a
>   * shell that will not truncate files.  These two strings serve that
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index 75adf66..538e98f 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -2619,6 +2619,21 @@ cleanup:
>      return ret;
>  }
>  
> +int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
> +                           unsigned int holdtime,
> +                           unsigned int nkeycodes,
> +                           unsigned int *keycodes)
> +{
> +    /*
> +     * FIXME: qmp sendkey has not been implemented yet,
> +     * and qmp API of it can not be anticipated, so we use hmp temporary.
> +     */
> +    if (qemuMonitorCheckHMP(mon, "sendkey")) {
> +        return qemuMonitorTextSendKey(mon, holdtime, nkeycodes, keycodes);
> +    } else
> +        return -1;
> +}
> +
>  int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
>                                const char *file)
>  {
> diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
> index ec79b03..89d7515 100644
> --- a/src/qemu/qemu_monitor_json.h
> +++ b/src/qemu/qemu_monitor_json.h
> @@ -214,6 +214,11 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
>  
>  int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon);
>  
> +int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
> +                           unsigned int holdtime,
> +                           unsigned int nkeycodes,
> +                           unsigned int *keycodes);
> +
>  int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
>                                const char *file);
>  
> diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
> index 3b42e7a..1b301e4 100644
> --- a/src/qemu/qemu_monitor_text.c
> +++ b/src/qemu/qemu_monitor_text.c
> @@ -2718,6 +2718,53 @@ fail:
>      return -1;
>  }
>  
> +int qemuMonitorTextSendKey(qemuMonitorPtr mon,
> +                           unsigned int holdtime,
> +                           unsigned int nkeycodes,
> +                           unsigned int *keycodes)
> +{
> +    int i;
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
> +    char *cmd, *reply = NULL;
> +
> +    if (nkeycodes > 16 || nkeycodes == 0)
> +        return -1;
> +
> +    virBufferAddLit(&buf, "sendkey ");
> +    for (i = 0; i < nkeycodes; i++) {
> +        if (keycodes[i] > 255) {
> +            qemuReportError(VIR_ERR_OPERATION_FAILED,
> +                            _("the %dth keycode is invalid: 0x%02X"),
> +                            i, keycodes[i]);
> +            cmd = virBufferContentAndReset(&buf);
> +            VIR_FREE(cmd);

You can just replace thse two lines with virBufferFreeAndReset(&buf)
instead.

> +            return -1;
> +        }
> +
> +        if (i)
> +            virBufferAddChar(&buf, '-');
> +        virBufferAsprintf(&buf, "0x%02X", keycodes[i]);
> +    }
> +
> +    if (holdtime)
> +        virBufferAsprintf(&buf, " %u", holdtime);

You want a check here before using 'cmd':

   if (virBufferError(&buf)) {
       virReportOOMError();
       return -1;
   }
  

> +
> +    cmd = virBufferContentAndReset(&buf);
> +    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0)
> +       goto fail;
> +
> +    VIR_FREE(cmd);
> +    VIR_FREE(reply);
> +    return 0;
> +
> +fail:
> +    qemuReportError(VIR_ERR_OPERATION_FAILED,
> +                     _("failed to send key using command '%s'"),
> +                     cmd);
> +    VIR_FREE(cmd);
> +    return -1;

There's only one place which ever jumps to 'fail', so
I'd just move the code upto that place and eliminate
the extra goto.

> +}
> +
>  /* Returns -1 on error, -2 if not supported */
>  int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file)
>  {
> diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
> index 8a69105..971de83 100644
> --- a/src/qemu/qemu_monitor_text.h
> +++ b/src/qemu/qemu_monitor_text.h
> @@ -208,6 +208,11 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
>  
>  int qemuMonitorTextInjectNMI(qemuMonitorPtr mon);
>  
> +int qemuMonitorTextSendKey(qemuMonitorPtr mon,
> +                           unsigned int holdtime,
> +                           unsigned int nkeycodes,
> +                           unsigned int *keycodes);
> +
>  int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file);
>  
>  #endif /* QEMU_MONITOR_TEXT_H */

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list