[libvirt] vTPM support in libvirt

I'm wondering if there will be vTPM support in libvirt in the near future?! Xen does support it already with the configuration "vtpm = ['instance=1,backend=0']", for example. So it would be great if the libvirt XML format supported it, too... For example like this: <devices> <vtpm instance="1" backend="xxx" /> </devices> Both attributes are optional. The backend attribute is a VM ID (on Xen, only zero for dom0 is supported) and could be implemented as a UUID?! What do you think? Are there any efforts to introducing that? Cheers Andreas

On Thu, Jun 25, 2009 at 09:16:26AM +0100, Andreas Sommer wrote:
I'm wondering if there will be vTPM support in libvirt in the near future?! Xen does support it already with the configuration "vtpm = ['instance=1,backend=0']", for example.
So it would be great if the libvirt XML format supported it, too... For example like this:
<devices> <vtpm instance="1" backend="xxx" /> </devices>
Both attributes are optional. The backend attribute is a VM ID (on Xen, only zero for dom0 is supported) and could be implemented as a UUID?!
I'd just ignore 'backend' for now - none of the other existing devices suport anything other than dom0 as the backend, so its no loss to assume dom0 for TPM too. What is 'instance' ? For element I'd prefer to just call it '<tpm>' - the 'v' is redundant since every device is virtual here :-)
What do you think? Are there any efforts to introducing that?
No one has ever asked for it before, which is why we've not supported this to date. I don't have any objection to supporting it, so patches would be welcomed. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

I agree on ignoring "backend" for now. The "instance" parameter defines a vTPM ID associated to that domain. There's a file "vtpm.db" which lists all mappings between domain UUID and vTPM ID, which means as long as you set a UUID for each of your domains, the correct vTPM is selected automatically (this is important for loading the last vTPM state). Can you please give me a short introduction on how to add this feature to libvirt? I know how to check out the code and how to change the domain RelaxNG schema, but where do I need to change the source code? Oh, and how do I need to configure it in order to install it on a machine (I guess "./configure --prefix=???" is important?!). Best regards Andreas Daniel P. Berrange wrote:
On Thu, Jun 25, 2009 at 09:16:26AM +0100, Andreas Sommer wrote:
I'm wondering if there will be vTPM support in libvirt in the near future?! Xen does support it already with the configuration "vtpm = ['instance=1,backend=0']", for example.
So it would be great if the libvirt XML format supported it, too... For example like this:
<devices> <vtpm instance="1" backend="xxx" /> </devices>
Both attributes are optional. The backend attribute is a VM ID (on Xen, only zero for dom0 is supported) and could be implemented as a UUID?!
I'd just ignore 'backend' for now - none of the other existing devices suport anything other than dom0 as the backend, so its no loss to assume dom0 for TPM too.
What is 'instance' ?
For element I'd prefer to just call it '<tpm>' - the 'v' is redundant since every device is virtual here :-)
What do you think? Are there any efforts to introducing that?
No one has ever asked for it before, which is why we've not supported this to date. I don't have any objection to supporting it, so patches would be welcomed.
Regards, Daniel

Hi again, I found out that the important files for the patch will be - domain_conf.c - util.h - domain_conf.h - xm_internal.c Guess I could figure out how to code it, but I still need to know how to install libvirt from sources. There's no documentation about it... Andreas Sommer wrote:
I agree on ignoring "backend" for now. The "instance" parameter defines a vTPM ID associated to that domain. There's a file "vtpm.db" which lists all mappings between domain UUID and vTPM ID, which means as long as you set a UUID for each of your domains, the correct vTPM is selected automatically (this is important for loading the last vTPM state).
Can you please give me a short introduction on how to add this feature to libvirt? I know how to check out the code and how to change the domain RelaxNG schema, but where do I need to change the source code? Oh, and how do I need to configure it in order to install it on a machine (I guess "./configure --prefix=???" is important?!).
Best regards Andreas
Daniel P. Berrange wrote:
On Thu, Jun 25, 2009 at 09:16:26AM +0100, Andreas Sommer wrote:
I'm wondering if there will be vTPM support in libvirt in the near future?! Xen does support it already with the configuration "vtpm = ['instance=1,backend=0']", for example.
So it would be great if the libvirt XML format supported it, too... For example like this:
<devices> <vtpm instance="1" backend="xxx" /> </devices>
Both attributes are optional. The backend attribute is a VM ID (on Xen, only zero for dom0 is supported) and could be implemented as a UUID?!
I'd just ignore 'backend' for now - none of the other existing devices suport anything other than dom0 as the backend, so its no loss to assume dom0 for TPM too.
What is 'instance' ?
For element I'd prefer to just call it '<tpm>' - the 'v' is redundant since every device is virtual here :-)
What do you think? Are there any efforts to introducing that?
No one has ever asked for it before, which is why we've not supported this to date. I don't have any objection to supporting it, so patches would be welcomed.
Regards, Daniel
-- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

Andreas Sommer wrote:
Hi again,
I found out that the important files for the patch will be - domain_conf.c - util.h - domain_conf.h - xm_internal.c
Guess I could figure out how to code it, but I still need to know how to install libvirt from sources. There's no documentation about it...
You can find the doc on how to download and build at: http://libvirt.org/downloads.html There is also some documentation on how to modify libvirt at: http://www.libvirt.org/api_extension.html It may not be entirely relevant to what you're doing, but it should provide some traction in looking at the codebase. I'd like to hear your thoughts on it, as I wrote it relatively recently. Dave
Andreas Sommer wrote:
I agree on ignoring "backend" for now. The "instance" parameter defines a vTPM ID associated to that domain. There's a file "vtpm.db" which lists all mappings between domain UUID and vTPM ID, which means as long as you set a UUID for each of your domains, the correct vTPM is selected automatically (this is important for loading the last vTPM state).
Can you please give me a short introduction on how to add this feature to libvirt? I know how to check out the code and how to change the domain RelaxNG schema, but where do I need to change the source code? Oh, and how do I need to configure it in order to install it on a machine (I guess "./configure --prefix=???" is important?!).
Best regards Andreas
Daniel P. Berrange wrote:
On Thu, Jun 25, 2009 at 09:16:26AM +0100, Andreas Sommer wrote:
I'm wondering if there will be vTPM support in libvirt in the near future?! Xen does support it already with the configuration "vtpm = ['instance=1,backend=0']", for example.
So it would be great if the libvirt XML format supported it, too... For example like this:
<devices> <vtpm instance="1" backend="xxx" /> </devices>
Both attributes are optional. The backend attribute is a VM ID (on Xen, only zero for dom0 is supported) and could be implemented as a UUID?!
I'd just ignore 'backend' for now - none of the other existing devices suport anything other than dom0 as the backend, so its no loss to assume dom0 for TPM too.
What is 'instance' ?
For element I'd prefer to just call it '<tpm>' - the 'v' is redundant since every device is virtual here :-)
What do you think? Are there any efforts to introducing that?
No one has ever asked for it before, which is why we've not supported this to date. I don't have any objection to supporting it, so patches would be welcomed.
Regards, Daniel
-- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

I made some changes to the code and would like to try it out by installing libvirt. As you said, there's an example on how to build and install it, but how do I need to configure it in order to get it installed on my system and not in some $HOME directory?? Yesterday I tried ./configure make make install then virsh is installed but cannot find libvirt.so.0. Can you help me with that or edit the installation instructions on the website? Dave Allan wrote:
Andreas Sommer wrote:
Hi again,
I found out that the important files for the patch will be - domain_conf.c - util.h - domain_conf.h - xm_internal.c
Guess I could figure out how to code it, but I still need to know how to install libvirt from sources. There's no documentation about it...
You can find the doc on how to download and build at:
http://libvirt.org/downloads.html
There is also some documentation on how to modify libvirt at:
http://www.libvirt.org/api_extension.html
It may not be entirely relevant to what you're doing, but it should provide some traction in looking at the codebase. I'd like to hear your thoughts on it, as I wrote it relatively recently.
Dave
Andreas Sommer wrote:
I agree on ignoring "backend" for now. The "instance" parameter defines a vTPM ID associated to that domain. There's a file "vtpm.db" which lists all mappings between domain UUID and vTPM ID, which means as long as you set a UUID for each of your domains, the correct vTPM is selected automatically (this is important for loading the last vTPM state).
Can you please give me a short introduction on how to add this feature to libvirt? I know how to check out the code and how to change the domain RelaxNG schema, but where do I need to change the source code? Oh, and how do I need to configure it in order to install it on a machine (I guess "./configure --prefix=???" is important?!).
Best regards Andreas
Daniel P. Berrange wrote:
On Thu, Jun 25, 2009 at 09:16:26AM +0100, Andreas Sommer wrote:
I'm wondering if there will be vTPM support in libvirt in the near future?! Xen does support it already with the configuration "vtpm = ['instance=1,backend=0']", for example.
So it would be great if the libvirt XML format supported it, too... For example like this:
<devices> <vtpm instance="1" backend="xxx" /> </devices>
Both attributes are optional. The backend attribute is a VM ID (on Xen, only zero for dom0 is supported) and could be implemented as a UUID?!
I'd just ignore 'backend' for now - none of the other existing devices suport anything other than dom0 as the backend, so its no loss to assume dom0 for TPM too.
What is 'instance' ?
For element I'd prefer to just call it '<tpm>' - the 'v' is redundant since every device is virtual here :-)
What do you think? Are there any efforts to introducing that?
No one has ever asked for it before, which is why we've not supported this to date. I don't have any objection to supporting it, so patches would be welcomed.
Regards, Daniel
-- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Fri, Jun 26, 2009 at 09:30:53AM +0100, Andreas Sommer wrote:
I made some changes to the code and would like to try it out by installing libvirt. As you said, there's an example on how to build and install it, but how do I need to configure it in order to get it installed on my system and not in some $HOME directory?? Yesterday I tried
./configure make make install
then virsh is installed but cannot find libvirt.so.0. Can you help me with that or edit the installation instructions on the website?
If you're just doing dev changes, it is best not to install it into your main system. Instead just build and run directly from the source tree. eg, what I normally do is ./autogen.sh --enable-compile-warnings=error --prefix=/usr --localstatedir=/var --sysconfdir=/etc make And *not* make install. Then as root just stop the normal libvirtd daemon that comes with your distro, and run the one you just compiled manually, eg $ su - root # /etc/init.d/libvirtd stop # /home/berrange/work/libvirt/qemud/libvirtd And likewise, use the 'virsh' binary directly from the source tree $ cd $HOME/work/libvirt/src $ ./virsh Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Thanks for your help so far. I changed the basics needed for vTPM support, which include XML <--> native configuration stuff (you will see it in the patch). I'm not really sure what else has to be done - maybe reading from xenstore?? Hope you can give me some tips on what is still missing. I did already try "./virsh domxml-from-native xen-xm some_config_file_that_contains_the_vtpm_line" and it gave me the correct XML answer :) Please find attached the unified diff. Best regards Andreas Daniel P. Berrange wrote:
On Fri, Jun 26, 2009 at 09:30:53AM +0100, Andreas Sommer wrote:
I made some changes to the code and would like to try it out by installing libvirt. As you said, there's an example on how to build and install it, but how do I need to configure it in order to get it installed on my system and not in some $HOME directory?? Yesterday I tried
./configure make make install
then virsh is installed but cannot find libvirt.so.0. Can you help me with that or edit the installation instructions on the website?
If you're just doing dev changes, it is best not to install it into your main system. Instead just build and run directly from the source tree.
eg, what I normally do is
./autogen.sh --enable-compile-warnings=error --prefix=/usr --localstatedir=/var --sysconfdir=/etc make
And *not* make install.
Then as root just stop the normal libvirtd daemon that comes with your distro, and run the one you just compiled manually, eg
$ su - root # /etc/init.d/libvirtd stop # /home/berrange/work/libvirt/qemud/libvirtd
And likewise, use the 'virsh' binary directly from the source tree
$ cd $HOME/work/libvirt/src $ ./virsh
Daniel
Index: src/domain_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.c,v retrieving revision 1.88 diff -u -r1.88 domain_conf.c --- src/domain_conf.c 25 Jun 2009 13:55:58 -0000 1.88 +++ src/domain_conf.c 27 Jun 2009 15:12:28 -0000 @@ -461,6 +461,8 @@ for (i = 0 ; i < def->nhostdevs ; i++) virDomainHostdevDefFree(def->hostdevs[i]); VIR_FREE(def->hostdevs); + + VIR_FREE(def->tpm); VIR_FREE(def->os.type); VIR_FREE(def->os.arch); @@ -1622,6 +1624,62 @@ } +/* Parse the XML definition for a vTPM device (<tpm instance="optional_instance_number">) */ +static virDomainTpmDefPtr +virDomainTpmDefParseXML(virConnectPtr conn, + xmlNodePtr node, int flags) { + + flags = flags; /* TODO: Andreas Sommer <AndiDog@web.de> flags unused, what are they used for */ + + virDomainTpmDefPtr def; + char *instance = NULL; + + if (VIR_ALLOC(def) < 0) { + virReportOOMError(conn); + return NULL; + } + + instance = virXMLPropString(node, "instance"); + + /* Attribute "instance" is optional*/ + if (instance) { + /* "instance" is defined as a number >= 0 */ + if (!c_isdigit(*instance) || *instance == '0') { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance attribute '%s' found, but must be a number >= 0 (make sure no whitespaces or leading zeroes are contained)"), instance); + goto error; + } + + const char *check = &instance[1]; + while (*check && c_isdigit(*check)) ++check; + if (*check) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance attribute '%s' contains non-digits, must be a number >= 0 (make sure no whitespaces or leading zeroes are contained)"), instance); + goto error; + } + + int err = virStrToLong_l("instance", NULL, 10, &def->instance); + if (err) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance '%s' is not a valid number"), instance); + goto error; + } + } + else + def->instance = -1; + +cleanup: + VIR_FREE(instance); + + return def; + +error: + VIR_FREE(def); + def = NULL; + goto cleanup; +} + + static virDomainSoundDefPtr virDomainSoundDefParseXML(virConnectPtr conn, const xmlNodePtr node, @@ -2617,6 +2675,30 @@ def->inputs[def->ninputs] = input; def->ninputs++; } + + + /* analysis of the vTPM device */ + if ((n = virXPathNodeSet(conn, "./devices/tpm", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract vTPM device")); + goto error; + } + if (n > 1) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("there can only be one vTPM device")); + goto error; + } + if (n == 1) { + virDomainTpmDefPtr tpm = virDomainTpmDefParseXML(conn, + nodes[0], + flags); + + if (!tpm) + goto error; + + def->tpm = tpm; + } + VIR_FREE(nodes); /* analysis of the sound devices */ @@ -3856,6 +3938,13 @@ goto cleanup; } + if (def->tpm) { + virBufferVSprintf(&buf, " <tpm"); + if (def->tpm->instance >= 0) + virBufferVSprintf(&buf, " instance='%ld'", def->tpm->instance); + virBufferVSprintf(&buf, "/>\n"); + } + for (n = 0 ; n < def->nsounds ; n++) if (virDomainSoundDefFormat(conn, &buf, def->sounds[n]) < 0) goto cleanup; Index: src/domain_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.h,v retrieving revision 1.49 diff -u -r1.49 domain_conf.h --- src/domain_conf.h 16 Jun 2009 15:42:46 -0000 1.49 +++ src/domain_conf.h 27 Jun 2009 15:12:28 -0000 @@ -275,6 +275,21 @@ VIR_DOMAIN_GRAPHICS_TYPE_LAST, }; +typedef struct _virDomainTpmDef virDomainTpmDef; +typedef virDomainTpmDef *virDomainTpmDefPtr; +struct _virDomainTpmDef { + /* + "instance" defines the vTPM ID which should be used for the domain. This is optional + in the XML domain description. If it isn't present, the following value must be -1. + */ + long instance; + + /* + Note that the "backend" value is left out of libvirt because only dom0 is supported yet. + In the future development of Xen there might be stubdomains containing the TPM backend module. + */ +}; + typedef struct _virDomainGraphicsDef virDomainGraphicsDef; typedef virDomainGraphicsDef *virDomainGraphicsDefPtr; struct _virDomainGraphicsDef { @@ -504,6 +519,9 @@ /* Only 1 */ virDomainChrDefPtr console; virSecurityLabelDef seclabel; + + /* vTPM */ + virDomainTpmDefPtr tpm; }; /* Guest VM runtime state */ Index: src/util.c =================================================================== RCS file: /data/cvs/libvirt/src/util.c,v retrieving revision 1.111 diff -u -r1.111 util.c --- src/util.c 26 Jun 2009 15:08:04 -0000 1.111 +++ src/util.c 27 Jun 2009 15:12:29 -0000 @@ -1403,6 +1403,25 @@ return 0; } +/* Just like virStrToLong_i, above, but produce a "long" value */ +int +virStrToLong_l(char const *s, char **end_ptr, int base, long *result) +{ + long int val; + char *p; + int err; + + errno = 0; + val = strtol(s, &p, base); + err = (errno || (!end_ptr && *p) || p == s || (long) val != val); + if (end_ptr) + *end_ptr = p; + if (err) + return -1; + *result = val; + return 0; +} + /* Just like virStrToLong_i, above, but produce an "long long" value. */ int virStrToLong_ll(char const *s, char **end_ptr, int base, long long *result) Index: src/util.h =================================================================== RCS file: /data/cvs/libvirt/src/util.h,v retrieving revision 1.50 diff -u -r1.50 util.h --- src/util.h 11 Jun 2009 13:18:56 -0000 1.50 +++ src/util.h 27 Jun 2009 15:12:29 -0000 @@ -145,6 +145,10 @@ char **end_ptr, int base, unsigned int *result); +int virStrToLong_l(char const *s, + char **end_ptr, + int base, + long *result); int virStrToLong_ll(char const *s, char **end_ptr, int base, Index: src/xm_internal.c =================================================================== RCS file: /data/cvs/libvirt/src/xm_internal.c,v retrieving revision 1.128 diff -u -r1.128 xm_internal.c --- src/xm_internal.c 19 Jun 2009 12:34:31 -0000 1.128 +++ src/xm_internal.c 27 Jun 2009 15:12:30 -0000 @@ -1353,6 +1353,41 @@ } } + list = virConfGetValue(conf, "vtpm"); + if (list && list->type == VIR_CONF_LIST && list->list && + list->list->type == VIR_CONF_STRING) { + + if (VIR_ALLOC(def->tpm) < 0) + goto no_memory; + list = list->list; + + /* + "backend" options is ignored here because yet only + zero is supported (TPM backend on dom0) + */ + const char *instance; + + if (STRPREFIX(list->str, "instance=")) + instance = list->str; + else { + instance = strstr(list->str, ",instance="); + if (instance == NULL) + instance = strstr(list->str, " instance="); + if (instance == NULL) + instance = strstr(list->str, "\tinstance="); + } + + if (instance) { + /* parse instance number */ + if (virStrToLong_l(instance+10, NULL, 10, &def->tpm->instance) < 0 || + def->tpm->instance < 0) + def->tpm->instance = -1; + } + else + def->tpm->instance = -1; + } + + if (hvm) { virDomainChrDefPtr chr = NULL; @@ -2408,6 +2443,38 @@ goto no_memory; } } + + /* + vTPM configuration + + Both "instance" and "backend" values are optional. "backend" is set to zero because + the TPM backend driver is yet on dom0. In the future, there might be implementations which + have a domU that contains the backend driver. + */ + if (def->tpm) { + virConfValuePtr tpmValue = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + virConfValuePtr tmp = NULL; + + if (VIR_ALLOC(tmp) < 0) + goto no_memory; + + if (def->tpm->instance >= 0) + virBufferVSprintf(&buf, "instance=%ld,", def->tpm->instance); + + virBufferAddLit(&buf, ",backend=0"); + + tmp->type = VIR_CONF_STRING; + tmp->str = virBufferContentAndReset(&buf); + tmp->next = NULL; + + tpmValue->type = VIR_CONF_LIST; + tpmValue->list = tmp; + + if (virConfSetValue(conf, "vtpm", tpmValue) < 0) + goto no_memory; + } + /* analyze of the devices */ if (VIR_ALLOC(diskVal) < 0)

On Sat, Jun 27, 2009 at 09:32:27PM +0100, Andreas Sommer wrote:
Thanks for your help so far. I changed the basics needed for vTPM support, which include XML <--> native configuration stuff (you will see it in the patch). I'm not really sure what else has to be done - maybe reading from xenstore?? Hope you can give me some tips on what is still missing.
Ok, so your patch has added the generic XML handling, and also added support to the 'xm' driver which handles /etc/xen config files. The main thing you have left is adding support to the 'xend_internal.c' file which is what talks to XenD and is responsible for starting guests, and handling config of running guests.
I did already try "./virsh domxml-from-native xen-xm some_config_file_that_contains_the_vtpm_line" and it gave me the correct XML answer :)
Great. It would be nice to add a couple of test cases too. For the 'xm_internal.c' changes, you can add files to tests/xmconfigdata/ and tests/xmconfigtest.c while for the 'xend_internal' changes the tests are in tests/sexpr2xmltest.c, tests/xml2sexprtest.c. The 'sxpr' files are what you get from Xend when doing 'xm list --long GUESTNAME'.
+ + /* Attribute "instance" is optional*/ + if (instance) { + /* "instance" is defined as a number >= 0 */ + if (!c_isdigit(*instance) || *instance == '0') { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance attribute '%s' found, but must be a number >= 0 (make sure no whitespaces or leading zeroes are contained)"), instance); + goto error; + } + + const char *check = &instance[1]; + while (*check && c_isdigit(*check)) ++check; + if (*check) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance attribute '%s' contains non-digits, must be a number >= 0 (make sure no whitespaces or leading zeroes are contained)"), instance); + goto error; + }
These two loops are redundant really - virStrToLong_l does sufficient checking of data validity.
+ + int err = virStrToLong_l("instance", NULL, 10, &def->instance); + if (err) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance '%s' is not a valid number"), instance); + goto error; + } + } + else + def->instance = -1; + +cleanup: + VIR_FREE(instance); + + return def; + +error: + VIR_FREE(def); + def = NULL; + goto cleanup; +} + + static virDomainSoundDefPtr virDomainSoundDefParseXML(virConnectPtr conn, const xmlNodePtr node, @@ -2617,6 +2675,30 @@ def->inputs[def->ninputs] = input; def->ninputs++; } + + + /* analysis of the vTPM device */ + if ((n = virXPathNodeSet(conn, "./devices/tpm", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract vTPM device")); + goto error; + } + if (n > 1) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("there can only be one vTPM device")); + goto error; + } + if (n == 1) { + virDomainTpmDefPtr tpm = virDomainTpmDefParseXML(conn, + nodes[0], + flags); + + if (!tpm) + goto error; + + def->tpm = tpm; + } + VIR_FREE(nodes);
/* analysis of the sound devices */
+typedef struct _virDomainTpmDef virDomainTpmDef; +typedef virDomainTpmDef *virDomainTpmDefPtr; +struct _virDomainTpmDef { + /* + "instance" defines the vTPM ID which should be used for the domain. This is optional + in the XML domain description. If it isn't present, the following value must be -1. + */ + long instance;
+ if (def->tpm) { + virConfValuePtr tpmValue = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + virConfValuePtr tmp = NULL; + + if (VIR_ALLOC(tmp) < 0) + goto no_memory; + + if (def->tpm->instance >= 0) + virBufferVSprintf(&buf, "instance=%ld,", def->tpm->instance); + + virBufferAddLit(&buf, ",backend=0"); + + tmp->type = VIR_CONF_STRING; + tmp->str = virBufferContentAndReset(&buf); + tmp->next = NULL;
Before calling 'virBufferContentAndReset' you should do if (virBufferError(&buf)) goto no_memory; to check that there hasn't been an OOM condition in the earlier AddLit or VSprintf() calls.
+ + tpmValue->type = VIR_CONF_LIST; + tpmValue->list = tmp; + + if (virConfSetValue(conf, "vtpm", tpmValue) < 0) + goto no_memory; + } +
Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On 06/27/2009 04:32 PM, Andreas Sommer wrote:
Index: src/domain_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/domain_conf.c,v retrieving revision 1.88 diff -u -r1.88 domain_conf.c --- src/domain_conf.c 25 Jun 2009 13:55:58 -0000 1.88 +++ src/domain_conf.c 27 Jun 2009 15:12:28 -0000 @@ -461,6 +461,8 @@ for (i = 0 ; i < def->nhostdevs ; i++) virDomainHostdevDefFree(def->hostdevs[i]); VIR_FREE(def->hostdevs); + + VIR_FREE(def->tpm);
VIR_FREE(def->os.type); VIR_FREE(def->os.arch); @@ -1622,6 +1624,62 @@ }
+/* Parse the XML definition for a vTPM device (<tpm instance="optional_instance_number">) */ +static virDomainTpmDefPtr +virDomainTpmDefParseXML(virConnectPtr conn, + xmlNodePtr node, int flags) { +
Whitespace is funky here.
+ flags = flags; /* TODO: Andreas Sommer <AndiDog@web.de> flags unused, what are they used for */ +
If you change the function definition to be: virDomainTpmDefParseXML(..., int flags ATTRIBUTE_UNUSED); You will avoid the compiler warning. The flags attribute is only relevant for formatting certain XML, and they correctly don't apply here.
+ virDomainTpmDefPtr def; + char *instance = NULL; + + if (VIR_ALLOC(def) < 0) { + virReportOOMError(conn); + return NULL; + } + + instance = virXMLPropString(node, "instance"); + + /* Attribute "instance" is optional*/ + if (instance) { + /* "instance" is defined as a number >= 0 */ + if (!c_isdigit(*instance) || *instance == '0') { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance attribute '%s' found, but must be a number >= 0 (make sure no whitespaces or leading zeroes are contained)"), instance); + goto error; + } + + const char *check = &instance[1]; + while (*check && c_isdigit(*check)) ++check; + if (*check) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance attribute '%s' contains non-digits, must be a number >= 0 (make sure no whitespaces or leading zeroes are contained)"), instance); + goto error; + } + + int err = virStrToLong_l("instance", NULL, 10, &def->instance); + if (err) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("TPM instance '%s' is not a valid number"), instance); + goto error; + } + } + else + def->instance = -1; + +cleanup: + VIR_FREE(instance); + + return def; + +error: + VIR_FREE(def); + def = NULL; + goto cleanup; +} + + static virDomainSoundDefPtr virDomainSoundDefParseXML(virConnectPtr conn, const xmlNodePtr node, @@ -2617,6 +2675,30 @@ def->inputs[def->ninputs] = input; def->ninputs++; } + + + /* analysis of the vTPM device */ + if ((n = virXPathNodeSet(conn, "./devices/tpm", ctxt, &nodes)) < 0) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract vTPM device")); + goto error; + } + if (n > 1) { + virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("there can only be one vTPM device")); + goto error; + } + if (n == 1) { + virDomainTpmDefPtr tpm = virDomainTpmDefParseXML(conn, + nodes[0], + flags); + + if (!tpm) + goto error; + + def->tpm = tpm; + } + VIR_FREE(nodes);
/* analysis of the sound devices */ @@ -3856,6 +3938,13 @@ goto cleanup; }
+ if (def->tpm) { + virBufferVSprintf(&buf, " <tpm"); + if (def->tpm->instance >= 0) + virBufferVSprintf(&buf, " instance='%ld'", def->tpm->instance); + virBufferVSprintf(&buf, "/>\n"); + } +
It's a bit overkill, but I think it's better to follow existing convention and move this formatting to a function like 'virDomainTpmDefFormat'. Thanks, Cole

I'm still experimenting around with the vTPM patch, and I want to install my version of libvirt on a Debian system - not in my $HOME directory but on the default paths. I followed the autogen command below and also did "make install", but now virsh for example searches for the certificates in /usr/local/etc/pki instead of the standard path /etc/pki. How do I need to configure the project to correct that and install libvirt from source like it would be installed by a package manager? Daniel P. Berrange wrote:
If you're just doing dev changes, it is best not to install it into your main system. Instead just build and run directly from the source tree.
eg, what I normally do is
./autogen.sh --enable-compile-warnings=error --prefix=/usr --localstatedir=/var --sysconfdir=/etc make
And *not* make install.

Hey Andreas, $ apt-get source libvirt0 $ cd libvirt-* Copy your patch to debian/patches/foo.patch (no, not literally foo) and then run $ sudo apt-get build-dep libvirt0 && debuild -uc -us when it's done there will be a few .deb files in ../ Cheers, C.J. On Wed, 2009-07-01 at 22:58 +0100, Andreas Sommer wrote:
I'm still experimenting around with the vTPM patch, and I want to install my version of libvirt on a Debian system - not in my $HOME directory but on the default paths. I followed the autogen command below and also did "make install", but now virsh for example searches for the certificates in /usr/local/etc/pki instead of the standard path /etc/pki. How do I need to configure the project to correct that and install libvirt from source like it would be installed by a package manager?
Daniel P. Berrange wrote:
If you're just doing dev changes, it is best not to install it into your main system. Instead just build and run directly from the source tree.
eg, what I normally do is
./autogen.sh --enable-compile-warnings=error --prefix=/usr --localstatedir=/var --sysconfdir=/etc make
And *not* make install.
-- Libvir-list mailing list Libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Wed, Jul 01, 2009 at 10:58:57PM +0100, Andreas Sommer wrote:
I'm still experimenting around with the vTPM patch, and I want to install my version of libvirt on a Debian system - not in my $HOME directory but on the default paths. I followed the autogen command below and also did "make install", but now virsh for example searches for the certificates in /usr/local/etc/pki instead of the standard path /etc/pki. How do I need to configure the project to correct that and install libvirt from source like it would be installed by a package manager?
If it is using /usr/local/etc, then you must have missed off the --sysconfdir=/etc arg to configure. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Jul 01, 2009 at 10:58:57PM +0100, Andreas Sommer wrote:
I'm still experimenting around with the vTPM patch, and I want to install my version of libvirt on a Debian system - not in my $HOME directory but on the default paths. I followed the autogen command below and also did "make install", but now virsh for example searches for the certificates in /usr/local/etc/pki instead of the standard path /etc/pki. How do I need to configure the project to correct that and install libvirt from source like it would be installed by a package manager? Have a look how ./configure is called when building the Debian package:
https://buildd.debian.org/fetch.cgi?&pkg=libvirt&ver=0.6.4-1%2Bb1&arch=i386&stamp=1246296628&file=log cd . && CC="cc" CXX="g++" CFLAGS="-g -O2 -g -Wall -O2" CXXFLAGS="-g -O2 -g -Wall -O2" CPPFLAGS="" LDFLAGS="" /build/buildd-libvirt_0.6.4-1-i386-7BeE2u/libvirt-0.6.4/./configure --build=i486-linux-gnu --prefix=/usr --includedir="\${prefix}/include" --mandir="\${prefix}/share/man" --infodir="\${prefix}/share/info" --sysconfdir=/etc --localstatedir=/var --libexecdir="\${prefix}/lib/libvirt" --disable-maintainer-mode --disable-dependency-tracking --srcdir=. --disable-rpath --with-qemu --with-openvz --with-avahi --with-sasl --with-polkit --with-hal --with-storage-fs --with-storage-lvm --with-storage-iscsi --with-storage-disk --with-init-scripts=none --without-numactl --enable-debug --with-xen --with-vbox --with-lxc Cheers, -- Guido
participants (6)
-
Andreas Sommer
-
C.J. Adams-Collier
-
Cole Robinson
-
Daniel P. Berrange
-
Dave Allan
-
Guido Günther