]> xenbits.xensource.com Git - libvirt.git/commitdiff
Expose a host UUID in the capabilities XML
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 25 May 2010 14:33:51 +0000 (15:33 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 25 May 2010 16:09:18 +0000 (17:09 +0100)
Allow for a host UUID in the capabilities XML. Local drivers
will initialize this from the SMBIOS data. If a sanity check
shows SMBIOS uuid is invalid, allow an override from the
libvirtd.conf configuration file

* daemon/libvirtd.c, daemon/libvirtd.conf: Support a host_uuid
  configuration option
* docs/schemas/capability.rng: Add optional host uuid field
* src/conf/capabilities.c, src/conf/capabilities.h: Include
  host UUID in XML
* src/libvirt_private.syms: Export new uuid.h functions
* src/lxc/lxc_conf.c, src/qemu/qemu_driver.c,
  src/uml/uml_conf.c: Set host UUID in capabilities
* src/util/uuid.c, src/util/uuid.h: Support for host UUIDs
* src/node_device/node_device_udev.c: Use the host UUID functions
* tests/confdata/libvirtd.conf, tests/confdata/libvirtd.out: Add
  new host_uuid config option to test

15 files changed:
daemon/libvirtd.c
daemon/libvirtd.conf
docs/schemas/capability.rng
po/POTFILES.in
src/conf/capabilities.c
src/conf/capabilities.h
src/libvirt_private.syms
src/lxc/lxc_conf.c
src/node_device/node_device_udev.c
src/qemu/qemu_driver.c
src/uml/uml_conf.c
src/util/uuid.c
src/util/uuid.h
tests/confdata/libvirtd.conf
tests/confdata/libvirtd.out

index 195c50abd77dc6730d8de063018eb5d6c48aeeab..8fa78b838cd9d755c1ee9eb9131358909d1ec047 100644 (file)
@@ -57,6 +57,7 @@
 #include "dispatch.h"
 
 #include "util.h"
+#include "uuid.h"
 #include "remote_driver.h"
 #include "conf.h"
 #include "event.h"
@@ -2718,6 +2719,7 @@ remoteReadConfigFile (struct qemud_server *server, const char *filename)
     char *unix_sock_rw_perms = NULL;
     char *unix_sock_group = NULL;
     char *buf = NULL;
+    char *host_uuid = NULL;
 
 #if HAVE_POLKIT
     /* Change the default back to no auth for non-root */
@@ -2840,11 +2842,18 @@ remoteReadConfigFile (struct qemud_server *server, const char *filename)
     GET_CONF_INT (conf, filename, max_requests);
     GET_CONF_INT (conf, filename, max_client_requests);
 
+    GET_CONF_STR (conf, filename, host_uuid);
+    if (virSetHostUUIDStr(host_uuid))
+        goto free_and_fail;
+
+    VIR_FREE(host_uuid);
+
     virConfFree (conf);
     return 0;
 
  free_and_fail:
     virConfFree (conf);
+    VIR_FREE(host_uuid);
     VIR_FREE(mdns_name);
     VIR_FREE(unix_sock_ro_perms);
     VIR_FREE(unix_sock_rw_perms);
index 49de46634964fcfbdcc4aa3ebbe08484a4c08792..d11c0fb083cf233d887d233427641a437f60ca3d 100644 (file)
 # e.g.:
 # log_outputs="3:syslog:libvirtd"
 # to log all warnings and errors to syslog under the libvirtd ident
+
+# UUID of the host:
+# Provide the UUID of the host here in case the command
+# 'dmidecode -s system-uuid' does not provide a valid uuid. In case
+# 'dmidecode' does not provide a valid UUID and none is provided here, a
+# temporary UUID will be generated.
+# Keep the format of the example UUID below. UUID must not have all digits
+# be the same.
+
+# NB This default all-zeros UUID will not work. Replace
+# it with the output of the 'uuidgen' command and then
+# uncomment this entry
+#host_uuid = "00000000-0000-0000-0000-000000000000"
index eb3c50ae143ba7adc86b66fcdb6fedc274478310..67e8cf2d810261b5f7d3dbfc1e2e3223527e529e 100644 (file)
 
   <define name='hostcaps'>
     <element name='host'>
+      <optional>
+        <element name='uuid'>
+          <ref name='UUID'/>
+        </element>
+      </optional>
       <element name='cpu'>
         <element name='arch'>
           <ref name='archnames'/>
       <param name='pattern'>[a-zA-Z0-9\-_]+</param>
     </data>
   </define>
+
+  <define name="UUID">
+    <choice>
+      <data type="string">
+        <param name="pattern">[a-fA-F0-9]{32}</param>
+      </data>
+      <data type="string">
+        <param name="pattern">[a-fA-F0-9]{8}\-([a-fA-F0-9]{4}\-){3}[a-fA-F0-9]{12}</param>
+      </data>
+    </choice>
+  </define>
 </grammar>
index baaf56fbd3a70259e815312c7feb9f4c2f2d7688..1b46d62e8314054513b5955c12f4b63bcfff041d 100644 (file)
@@ -29,6 +29,7 @@ src/interface/netcf_driver.c
 src/internal.h
 src/libvirt.c
 src/lxc/lxc_container.c
+src/lxc/lxc_conf.c
 src/lxc/lxc_controller.c
 src/lxc/lxc_driver.c
 src/network/bridge_driver.c
index dafd8214fbfa5954e1fa4e85e59a84ef37e887a1..4478d85f40095ba44d23f73d20c6cc4ae0eccf13 100644 (file)
@@ -27,6 +27,7 @@
 #include "buf.h"
 #include "memory.h"
 #include "util.h"
+#include "uuid.h"
 #include "cpu_conf.h"
 
 /**
@@ -662,9 +663,14 @@ virCapabilitiesFormatXML(virCapsPtr caps)
 {
     virBuffer xml = VIR_BUFFER_INITIALIZER;
     int i, j, k;
+    char host_uuid[VIR_UUID_STRING_BUFLEN];
 
     virBufferAddLit(&xml, "<capabilities>\n\n");
     virBufferAddLit(&xml, "  <host>\n");
+    if (virUUIDIsValid(caps->host.host_uuid)) {
+        virUUIDFormat(caps->host.host_uuid, host_uuid);
+        virBufferVSprintf(&xml,"    <uuid>%s</uuid>\n", host_uuid);
+    }
     virBufferAddLit(&xml, "    <cpu>\n");
     virBufferVSprintf(&xml, "      <arch>%s</arch>\n",
                       caps->host.arch);
index 0ed0166a035bd1f414a4e7406fda613e5986453a..bdf44faf76878df71a1cf88bee0f1db4810ce933 100644 (file)
@@ -110,6 +110,7 @@ struct _virCapsHost {
     virCapsHostNUMACellPtr *numaCell;
     virCapsHostSecModel secModel;
     virCPUDefPtr cpu;
+    unsigned char host_uuid[VIR_UUID_BUFLEN];
 };
 
 typedef struct _virCaps virCaps;
index 1e4bfd0b16e10bd382abddbb10e2a976c2b3c7a8..a30ea4f087be60dff6643c4438e243e486e5a4df 100644 (file)
@@ -708,6 +708,8 @@ usbDeviceFileIterate;
 virUUIDFormat;
 virUUIDGenerate;
 virUUIDParse;
+virSetHostUUIDStr;
+virGetHostUUID;
 
 
 # virterror_internal.h
index 8d7f69e7bcabf34693acb72a3d44f9e0bf2459b4..f4479e68ed2b258a441e745c68aac455420624ae 100644 (file)
@@ -33,6 +33,7 @@
 #include "conf.h"
 #include "memory.h"
 #include "logging.h"
+#include "uuid.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_LXC
@@ -48,7 +49,7 @@ virCapsPtr lxcCapsInit(void)
 
     if ((caps = virCapabilitiesNew(utsname.machine,
                                    0, 0)) == NULL)
-        goto no_memory;
+        goto error;
 
     /* Some machines have problematic NUMA toplogy causing
      * unexpected failures. We don't want to break the QEMU
@@ -59,6 +60,12 @@ virCapsPtr lxcCapsInit(void)
         VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
     }
 
+    if (virGetHostUUID(caps->host.host_uuid)) {
+        lxcError(VIR_ERR_INTERNAL_ERROR,
+                 "%s", _("cannot get the host uuid"));
+        goto error;
+    }
+
     /* XXX shouldn't 'borrow' KVM's prefix */
     virCapabilitiesSetMacPrefix(caps, (unsigned char []){ 0x52, 0x54, 0x00 });
 
@@ -70,7 +77,7 @@ virCapsPtr lxcCapsInit(void)
                                          NULL,
                                          0,
                                          NULL)) == NULL)
-        goto no_memory;
+        goto error;
 
     if (virCapabilitiesAddGuestDomain(guest,
                                       "lxc",
@@ -78,14 +85,14 @@ virCapsPtr lxcCapsInit(void)
                                       NULL,
                                       0,
                                       NULL) == NULL)
-        goto no_memory;
+        goto error;
 
     /* LXC Requires an emulator in the XML */
     virCapabilitiesSetEmulatorRequired(caps);
 
     return caps;
 
-no_memory:
+error:
     virCapabilitiesFree(caps);
     return NULL;
 }
index a1ced877eab6c0a18f2937d48a42d82f2e93ffcf..f0485f131a7710c61bd6a4ae39841c328ffcf09b 100644 (file)
@@ -1473,12 +1473,8 @@ udevGetDMIData(union _virNodeDevCapData *data)
         goto out;
     }
 
-    if (udevGetStringSysfsAttr(device,
-                               "product_uuid",
-                               &tmp) == PROPERTY_ERROR) {
+    if (virGetHostUUID(data->system.hardware.uuid))
         goto out;
-    }
-    virUUIDParse(tmp, data->system.hardware.uuid);
 
     if (udevGetStringSysfsAttr(device,
                                "bios_vendor",
index af63a5d81396af7346926d1fec4599e20698fe21..d90820c6baa2802c57da5c1b9b7a74784708d000 100644 (file)
@@ -1334,6 +1334,11 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
     caps->privateDataXMLFormat = qemuDomainObjPrivateXMLFormat;
     caps->privateDataXMLParse = qemuDomainObjPrivateXMLParse;
 
+    if (virGetHostUUID(caps->host.host_uuid)) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("cannot get the host uuid"));
+        goto err_exit;
+    }
 
     /* Security driver data */
     if (driver->securityPrimaryDriver) {
@@ -1355,6 +1360,7 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
 
 no_memory:
     virReportOOMError();
+err_exit:
     virCapabilitiesFree(caps);
     return NULL;
 }
index a10bca02bd1010a292f761e8985f1cbae6409c5b..785d627ab8f1e2923d2a239773c93b5123138101 100644 (file)
@@ -62,7 +62,7 @@ virCapsPtr umlCapsInit(void) {
 
     if ((caps = virCapabilitiesNew(utsname.machine,
                                    0, 0)) == NULL)
-        goto no_memory;
+        goto error;
 
     /* Some machines have problematic NUMA toplogy causing
      * unexpected failures. We don't want to break the QEMU
@@ -73,6 +73,12 @@ virCapsPtr umlCapsInit(void) {
         VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
     }
 
+    if (virGetHostUUID(caps->host.host_uuid)) {
+        umlReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("cannot get the host uuid"));
+        goto error;
+    }
+
     if ((guest = virCapabilitiesAddGuest(caps,
                                          "uml",
                                          utsname.machine,
@@ -81,7 +87,7 @@ virCapsPtr umlCapsInit(void) {
                                          NULL,
                                          0,
                                          NULL)) == NULL)
-        goto no_memory;
+        goto error;
 
     if (virCapabilitiesAddGuestDomain(guest,
                                       "uml",
@@ -89,11 +95,11 @@ virCapsPtr umlCapsInit(void) {
                                       NULL,
                                       0,
                                       NULL) == NULL)
-        goto no_memory;
+        goto error;
 
     return caps;
 
no_memory:
error:
     virCapabilitiesFree(caps);
     return NULL;
 }
index 9c626ceace45be78d06afcedf3685afdc1691f96..f18814885e538eeab54e89730bd7d8aa121507ee 100644 (file)
 #include "util.h"
 #include "virterror_internal.h"
 #include "logging.h"
+#include "memory.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+static unsigned char host_uuid[VIR_UUID_BUFLEN];
+
 static int
 virUUIDGenerateRandomBytes(unsigned char *buf,
                            int buflen)
@@ -208,3 +211,116 @@ void virUUIDFormat(const unsigned char *uuid, char *uuidstr)
              uuid[12], uuid[13], uuid[14], uuid[15]);
     uuidstr[VIR_UUID_STRING_BUFLEN-1] = '\0';
 }
+
+
+
+/**
+ * virUUIDIsValid
+ *
+ * @uuid: The UUID to test
+ *
+ * Do some basic tests to check whether the given UUID is
+ * valid as a host UUID.
+ * Basic tests:
+ *  - Not all of the digits may be equal
+ */
+int
+virUUIDIsValid(unsigned char *uuid)
+{
+    unsigned int i, ctr = 1;
+    unsigned char c;
+
+    if (!uuid)
+        return 0;
+
+    c = uuid[0];
+
+    for (i = 1; i < VIR_UUID_BUFLEN; i++)
+        if (uuid[i] == c)
+            ctr++;
+
+    return (ctr != VIR_UUID_BUFLEN);
+}
+
+static int
+getDMISystemUUID(char *uuid, int len)
+{
+    unsigned int i = 0;
+    const char *paths[] = {
+        "/sys/devices/virtual/dmi/id/product_uuid",
+        "/sys/class/dmi/id/product_uuid",
+        NULL
+    };
+
+    while (paths[i]) {
+        int fd = open(paths[i], O_RDONLY);
+        if (fd > 0) {
+            if (saferead(fd, uuid, len) == len) {
+                close(fd);
+                return 0;
+            }
+            close(fd);
+        }
+        i++;
+    }
+
+    return -1;
+}
+
+
+/**
+ * setHostUUID
+ *
+ * @host_uuid: UUID that the host is supposed to have
+ *
+ * Set the UUID of the host if it hasn't been set, yet
+ * Returns 0 in case of success, an error code in case of error.
+ */
+int
+virSetHostUUIDStr(const char *uuid)
+{
+    int rc;
+    char dmiuuid[VIR_UUID_STRING_BUFLEN];
+
+    if (virUUIDIsValid(host_uuid))
+        return EEXIST;
+
+    if (!uuid) {
+        if (!getDMISystemUUID(dmiuuid, sizeof(dmiuuid))) {
+            if (!virUUIDParse(dmiuuid, host_uuid))
+                return 0;
+        }
+
+        if (!virUUIDIsValid(host_uuid))
+            return virUUIDGenerate(host_uuid);
+    } else {
+        rc = virUUIDParse(uuid, host_uuid);
+        if (rc)
+            return rc;
+        if (!virUUIDIsValid(host_uuid))
+            return EINVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * getHostUUID:
+ *
+ * @host_uuid: memory to store the host_uuid into
+ *
+ * Get the UUID of the host. Returns 0 in case of success,
+ * an error code otherwise.
+ * Returns 0 in case of success, an error code in case of error.
+ */
+int virGetHostUUID(unsigned char *uuid)
+{
+    int ret = 0;
+
+    if (!virUUIDIsValid(host_uuid))
+        ret = virSetHostUUIDStr(NULL);
+
+    memcpy(uuid, host_uuid, sizeof(host_uuid));
+
+    return ret;
+}
index b6ac372db84c96461b44311fc30ed2ec82e1d16e..36abcfc920236f9fd1f0a5745d82e4a91a87c568 100644 (file)
 #ifndef __VIR_UUID_H__
 # define __VIR_UUID_H__
 
+int virSetHostUUIDStr(const char *host_uuid);
+int virGetHostUUID(unsigned char *host_uuid);
+
+int virUUIDIsValid(unsigned char *uuid);
+
 int virUUIDGenerate(unsigned char *uuid);
 
 int virUUIDParse(const char *uuidstr,
index 1fc875aab38cd073ba7ff0e620977f098975c098..a943bfa195b307128bd2ad665f69f3c788eb7d39 100644 (file)
@@ -218,3 +218,12 @@ tls_allowed_dn_list = ["DN1", "DN2"]
 #
 # By default, no Username's are checked
 sasl_allowed_username_list = ["joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ]
+
+# UUID of the host:
+# Provide the UUID of the host here in case the command
+# 'dmidecode -s system-uuid' does not provide a valid uuid. In case
+# 'dmidecode' does not provide a valid UUID and none is provided here, a
+# temporary UUID will be generated.
+# Keep the format of the example UUID below.
+
+host_uuid = "8510b1a1-1afa-4da6-8111-785fae202c1e"
index 685744acd8afcd1a10541dd58aa330d2c89878a4..0bebe2f1f54aa93e36e39cd8e86bed3ae51f38e9 100644 (file)
@@ -178,3 +178,10 @@ tls_allowed_dn_list = [ "DN1", "DN2" ]
 #
 # By default, no Username's are checked
 sasl_allowed_username_list = [ "joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ]
+# UUID of the host:
+# Provide the UUID of the host here in case the command
+# 'dmidecode -s system-uuid' does not provide a valid uuid. In case
+# 'dmidecode' does not provide a valid UUID and none is provided here, a
+# temporary UUID will be generated.
+# Keep the format of the example UUID below.
+host_uuid = "8510b1a1-1afa-4da6-8111-785fae202c1e"