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(a)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)