On Wed, Mar 13, 2013 at 12:03:49PM -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@xxxxxxxxxxxxxxxxxx> > > --- > src/libvirt_private.syms | 1 > src/qemu/qemu_capabilities.c | 61 ++++++++++++++++++++++++++++ > src/qemu/qemu_capabilities.h | 3 + > src/qemu/qemu_monitor.c | 44 ++++++++++++++++++++ > src/qemu/qemu_monitor.h | 6 ++ > src/qemu/qemu_monitor_json.c | 91 +++++++++++++++++++++++++++++++++++++++++++ > src/qemu/qemu_monitor_json.h | 8 +++ > src/util/virutil.c | 14 ++++++ > src/util/virutil.h | 3 + > 9 files changed, 231 insertions(+) > > Index: libvirt/src/qemu/qemu_capabilities.c > =================================================================== > --- libvirt.orig/src/qemu/qemu_capabilities.c > +++ libvirt/src/qemu/qemu_capabilities.c > @@ -210,6 +210,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAS > > "rng-random", /* 130 */ > "rng-egd", > + "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 > @@ -171,6 +171,8 @@ enum virQEMUCapsFlags { > QEMU_CAPS_OBJECT_RNG_RANDOM = 130, /* the rng-random backend for > virtio rng */ > QEMU_CAPS_OBJECT_RNG_EGD = 131, /* EGD protocol daemon for rng */ > + QEMU_CAPS_DEVICE_TPM_PASSTHROUGH = 132, /* -tpmdev passthrough */ > + QEMU_CAPS_DEVICE_TPM_TIS = 133, /* -device tpm_tis */ I'm wondering whether we really need to spend 2 capability bits on this. Is it possible to build QEMU such that we have one, but not the other ? If not then one capability would suffice > Index: libvirt/src/qemu/qemu_monitor.c > =================================================================== > --- libvirt.orig/src/qemu/qemu_monitor.c > +++ libvirt/src/qemu/qemu_monitor.c > @@ -3522,3 +3522,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 > @@ -4707,3 +4707,94 @@ 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; > + } I think everything above this point should be in the main monitor APIs, and this method concern itself solely with converting the virJSONValuePtr into a string array, not actually executing command. This makes the code more portable for use in commands which need control over the command execution to handle errors / pass arguments. > + > + if ((n = virJSONValueArraySize(data)) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("%s reply data was not an array"), > + qmpCmd); > + goto cleanup; > + } > + > + if (VIR_ALLOC_N(list, n) < 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 && list) { > + for (i = 0 ; i < n ; i++) > + VIR_FREE(list[i]); > + VIR_FREE(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); > +} > Index: libvirt/src/libvirt_private.syms > =================================================================== > --- libvirt.orig/src/libvirt_private.syms > +++ libvirt/src/libvirt_private.syms > @@ -1886,6 +1886,7 @@ virSetUIDGIDWithCaps; > virSkipSpaces; > virSkipSpacesAndBackslash; > virSkipSpacesBackwards; > +virStrArrayHasString; > virStrcpy; > virStrIsPrint; > virStrncpy; > Index: libvirt/src/util/virutil.c > =================================================================== > --- libvirt.orig/src/util/virutil.c > +++ libvirt/src/util/virutil.c > @@ -3379,3 +3379,17 @@ cleanup: > VIR_FREE(buf); > return ret; > } > + > + > +bool > +virStrArrayHasString(char **strings, size_t n_strings, const char *needle) > +{ > + size_t i; > + > + for (i = 0; i < n_strings; i++) { > + if (STREQ(strings[i], needle)) > + return true; > + } > + > + return false; > +} > Index: libvirt/src/util/virutil.h > =================================================================== > --- libvirt.orig/src/util/virutil.h > +++ libvirt/src/util/virutil.h > @@ -297,4 +297,7 @@ int virGetDeviceUnprivSGIO(const char *p > char * virGetUnprivSGIOSysfsPath(const char *path, > const char *sysfs_dir); > > +bool virStrArrayHasString(char **strings, size_t n_strings, > + const char *needle); > + > #endif /* __VIR_UTIL_H__ */ The virStrArrayHasString method doesn't appear to be used in this patch. If some other patch needs this still, then it should be a separate patch from the monitor code. 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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list