[libvirt] [PATCH v4 01/11] Add QMP probing for TPM

Daniel P. Berrange berrange at redhat.com
Mon Apr 15 16:56:38 UTC 2013


On Fri, Apr 05, 2013 at 10:05:52AM -0400, Stefan Berger wrote:
> Probe for QEMU's QMP TPM support by querying the lists of
> supported TPM models (query-tpm-models) and backend types
> (query-tpm-types). 
> 
> The setting of the capability flags following the strings
> returned from the commands above is only provided in the
> patch where domain_conf.c gets TPM support due to dependencies
> on functions only introduced there. 
> 
> Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
> Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
> Tested-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
> 
> ---
>  src/qemu/qemu_capabilities.c |    2 
>  src/qemu/qemu_capabilities.h |    3 +
>  src/qemu/qemu_monitor.c      |   44 +++++++++++++++++++++
>  src/qemu/qemu_monitor.h      |    6 ++
>  src/qemu/qemu_monitor_json.c |   90 +++++++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_monitor_json.h |    8 +++
>  6 files changed, 153 insertions(+)
> 
> Index: libvirt/src/qemu/qemu_capabilities.c
> ===================================================================
> --- libvirt.orig/src/qemu/qemu_capabilities.c
> +++ libvirt/src/qemu/qemu_capabilities.c
> @@ -216,6 +216,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAS
>  
>                "ipv6-migration", /* 135 */
>                "machine-opt",
> +              "tpm-passthrough",
> +              "tpm-tis",
>      );
>  
>  struct _virQEMUCaps {
> Index: libvirt/src/qemu/qemu_capabilities.h
> ===================================================================
> --- libvirt.orig/src/qemu/qemu_capabilities.h
> +++ libvirt/src/qemu/qemu_capabilities.h
> @@ -176,6 +176,8 @@ enum virQEMUCapsFlags {
>      QEMU_CAPS_SCSI_MEGASAS       = 134, /* -device megasas */
>      QEMU_CAPS_IPV6_MIGRATION     = 135, /* -incoming [::] */
>      QEMU_CAPS_MACHINE_OPT        = 136, /* -machine xxxx*/
> +    QEMU_CAPS_DEVICE_TPM_PASSTHROUGH = 137, /* -tpmdev passthrough */
> +    QEMU_CAPS_DEVICE_TPM_TIS     = 138, /* -device tpm_tis */
>  
>      QEMU_CAPS_LAST,                   /* this must always be the last item */
>  };
> @@ -257,4 +259,5 @@ int virQEMUCapsParseDeviceStr(virQEMUCap
>  VIR_ENUM_DECL(virQEMUCaps);
>  
>  bool virQEMUCapsUsedQMP(virQEMUCapsPtr qemuCaps);
> +
>  #endif /* __QEMU_CAPABILITIES_H__*/
> Index: libvirt/src/qemu/qemu_monitor.c
> ===================================================================
> --- libvirt.orig/src/qemu/qemu_monitor.c
> +++ libvirt/src/qemu/qemu_monitor.c
> @@ -3525,3 +3525,47 @@ int qemuMonitorNBDServerStop(qemuMonitor
>  
>      return qemuMonitorJSONNBDServerStop(mon);
>  }
> +
> +
> +int qemuMonitorGetTPMModels(qemuMonitorPtr mon,
> +                            char ***tpmmodels)
> +{
> +    VIR_DEBUG("mon=%p tpmmodels=%p",
> +              mon, tpmmodels);
> +
> +    if (!mon) {
> +        virReportError(VIR_ERR_INVALID_ARG, "%s",
> +                       _("monitor must not be NULL"));
> +        return -1;
> +    }
> +
> +    if (!mon->json) {
> +        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
> +                       _("JSON monitor is required"));
> +        return -1;
> +    }
> +
> +    return qemuMonitorJSONGetTPMModels(mon, tpmmodels);
> +}
> +
> +
> +int qemuMonitorGetTPMTypes(qemuMonitorPtr mon,
> +                           char ***tpmtypes)
> +{
> +    VIR_DEBUG("mon=%p tpmtypes=%p",
> +              mon, tpmtypes);
> +
> +    if (!mon) {
> +        virReportError(VIR_ERR_INVALID_ARG, "%s",
> +                       _("monitor must not be NULL"));
> +        return -1;
> +    }
> +
> +    if (!mon->json) {
> +        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
> +                       _("JSON monitor is required"));
> +        return -1;
> +    }
> +
> +    return qemuMonitorJSONGetTPMTypes(mon, tpmtypes);
> +}
> Index: libvirt/src/qemu/qemu_monitor.h
> ===================================================================
> --- libvirt.orig/src/qemu/qemu_monitor.h
> +++ libvirt/src/qemu/qemu_monitor.h
> @@ -683,6 +683,12 @@ int qemuMonitorNBDServerAdd(qemuMonitorP
>                              const char *deviceID,
>                              bool writable);
>  int qemuMonitorNBDServerStop(qemuMonitorPtr);
> +int qemuMonitorGetTPMModels(qemuMonitorPtr mon,
> +                            char ***tpmmodels);
> +
> +int qemuMonitorGetTPMTypes(qemuMonitorPtr mon,
> +                           char ***tpmtypes);
> +
>  /**
>   * When running two dd process and using <> redirection, we need a
>   * shell that will not truncate files.  These two strings serve that
> Index: libvirt/src/qemu/qemu_monitor_json.c
> ===================================================================
> --- libvirt.orig/src/qemu/qemu_monitor_json.c
> +++ libvirt/src/qemu/qemu_monitor_json.c
> @@ -41,6 +41,7 @@
>  #include "datatypes.h"
>  #include "virerror.h"
>  #include "virjson.h"
> +#include "virstring.h"
>  
>  #ifdef WITH_DTRACE_PROBES
>  # include "libvirt_qemu_probes.h"
> @@ -4693,3 +4694,92 @@ qemuMonitorJSONNBDServerStop(qemuMonitor
>      virJSONValueFree(reply);
>      return ret;
>  }
> +
> +
> +static int
> +qemuMonitorJSONGetStringArray(qemuMonitorPtr mon, const char *qmpCmd,
> +                              char ***array)
> +{
> +    int ret;
> +    virJSONValuePtr cmd;
> +    virJSONValuePtr reply = NULL;
> +    virJSONValuePtr data;
> +    char **list = NULL;
> +    int n = 0;
> +    size_t i;
> +
> +    *array = NULL;
> +
> +    if (!(cmd = qemuMonitorJSONMakeCommand(qmpCmd, NULL)))
> +        return -1;
> +
> +    ret = qemuMonitorJSONCommand(mon, cmd, &reply);
> +
> +    if (ret == 0)
> +        ret = qemuMonitorJSONCheckError(cmd, reply);
> +
> +    if (ret < 0)
> +        goto cleanup;
> +
> +    ret = -1;
> +
> +    if (!(data = virJSONValueObjectGet(reply, "return"))) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("%s reply was missing return data"),
> +                       qmpCmd);
> +        goto cleanup;
> +    }
> +
> +    if ((n = virJSONValueArraySize(data)) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("%s reply data was not an array"),
> +                       qmpCmd);
> +        goto cleanup;
> +    }
> +
> +    /* null-terminated list */
> +    if (VIR_ALLOC_N(list, n + 1) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }
> +
> +    for (i = 0 ; i < n ; i++) {
> +        virJSONValuePtr child = virJSONValueArrayGet(data, i);
> +        const char *tmp;
> +
> +        if (!(tmp = virJSONValueGetString(child))) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR,
> +                           _("%s array element does not contain data"),
> +                           qmpCmd);
> +            goto cleanup;
> +        }
> +
> +        if (!(list[i] = strdup(tmp))) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +    }
> +
> +    ret = n;
> +    *array = list;
> +
> +cleanup:
> +    if (ret < 0)
> +        virStringFreeList(list);
> +    virJSONValueFree(cmd);
> +    virJSONValueFree(reply);
> +    return ret;
> +}
> +
> +int qemuMonitorJSONGetTPMModels(qemuMonitorPtr mon,
> +                                char ***tpmmodels)
> +{
> +    return qemuMonitorJSONGetStringArray(mon, "query-tpm-models", tpmmodels);
> +}
> +
> +
> +int qemuMonitorJSONGetTPMTypes(qemuMonitorPtr mon,
> +                               char ***tpmtypes)
> +{
> +    return qemuMonitorJSONGetStringArray(mon, "query-tpm-types", tpmtypes);
> +}

Guess you never tested this on a QEMU which lacked those commands.
Probing capabilities now fails for any QEMU using QMP which lacks
these commands

# ./daemon/libvirtd
2013-04-15 16:55:57.035+0000: 18459: info : libvirt version: 1.0.4
2013-04-15 16:55:57.035+0000: 18459: error : qemuMonitorJSONCheckError:352 : internal error unable to execute QEMU command 'query-tpm-models': The command query-tpm-models has not been found
2013-04-15 16:55:57.136+0000: 18459: error : qemuMonitorJSONCheckError:352 : internal error unable to execute QEMU command 'query-tpm-models': The command query-tpm-models has not been found
2013-04-15 16:55:57.220+0000: 18459: error : qemuMonitorJSONCheckError:352 : internal error unable to execute QEMU command 'query-tpm-models': The command query-tpm-models has not been found
2013-04-15 16:55:57.313+0000: 18459: error : qemuMonitorJSONCheckError:352 : internal error unable to execute QEMU command 'query-tpm-models': The command query-tpm-models has not been found
2013-04-15 16:55:57.415+0000: 18459: error : qemuMonitorJSONCheckError:352 : internal error unable to execute QEMU command 'query-tpm-models': The command query-tpm-models has not been found
2013-04-15 16:55:57.504+0000: 18459: error : qemuMonitorJSONCheckError:352 : internal error unable to execute QEMU command 'query-tpm-models': The command query-tpm-models has not been found


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