Expose a host UUID in the capabilities XML

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
This commit is contained in:
Daniel P. Berrange
2010-05-25 15:33:51 +01:00
parent e596dbb32a
commit 60881161ea
15 changed files with 213 additions and 13 deletions

View File

@@ -57,6 +57,7 @@
#include "dispatch.h" #include "dispatch.h"
#include "util.h" #include "util.h"
#include "uuid.h"
#include "remote_driver.h" #include "remote_driver.h"
#include "conf.h" #include "conf.h"
#include "event.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_rw_perms = NULL;
char *unix_sock_group = NULL; char *unix_sock_group = NULL;
char *buf = NULL; char *buf = NULL;
char *host_uuid = NULL;
#if HAVE_POLKIT #if HAVE_POLKIT
/* Change the default back to no auth for non-root */ /* 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_requests);
GET_CONF_INT (conf, filename, max_client_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); virConfFree (conf);
return 0; return 0;
free_and_fail: free_and_fail:
virConfFree (conf); virConfFree (conf);
VIR_FREE(host_uuid);
VIR_FREE(mdns_name); VIR_FREE(mdns_name);
VIR_FREE(unix_sock_ro_perms); VIR_FREE(unix_sock_ro_perms);
VIR_FREE(unix_sock_rw_perms); VIR_FREE(unix_sock_rw_perms);

View File

@@ -312,3 +312,16 @@
# e.g.: # e.g.:
# log_outputs="3:syslog:libvirtd" # log_outputs="3:syslog:libvirtd"
# to log all warnings and errors to syslog under the libvirtd ident # 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"

View File

@@ -18,6 +18,11 @@
<define name='hostcaps'> <define name='hostcaps'>
<element name='host'> <element name='host'>
<optional>
<element name='uuid'>
<ref name='UUID'/>
</element>
</optional>
<element name='cpu'> <element name='cpu'>
<element name='arch'> <element name='arch'>
<ref name='archnames'/> <ref name='archnames'/>
@@ -349,4 +354,15 @@
<param name='pattern'>[a-zA-Z0-9\-_]+</param> <param name='pattern'>[a-zA-Z0-9\-_]+</param>
</data> </data>
</define> </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> </grammar>

View File

@@ -29,6 +29,7 @@ src/interface/netcf_driver.c
src/internal.h src/internal.h
src/libvirt.c src/libvirt.c
src/lxc/lxc_container.c src/lxc/lxc_container.c
src/lxc/lxc_conf.c
src/lxc/lxc_controller.c src/lxc/lxc_controller.c
src/lxc/lxc_driver.c src/lxc/lxc_driver.c
src/network/bridge_driver.c src/network/bridge_driver.c

View File

@@ -27,6 +27,7 @@
#include "buf.h" #include "buf.h"
#include "memory.h" #include "memory.h"
#include "util.h" #include "util.h"
#include "uuid.h"
#include "cpu_conf.h" #include "cpu_conf.h"
/** /**
@@ -662,9 +663,14 @@ virCapabilitiesFormatXML(virCapsPtr caps)
{ {
virBuffer xml = VIR_BUFFER_INITIALIZER; virBuffer xml = VIR_BUFFER_INITIALIZER;
int i, j, k; int i, j, k;
char host_uuid[VIR_UUID_STRING_BUFLEN];
virBufferAddLit(&xml, "<capabilities>\n\n"); virBufferAddLit(&xml, "<capabilities>\n\n");
virBufferAddLit(&xml, " <host>\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"); virBufferAddLit(&xml, " <cpu>\n");
virBufferVSprintf(&xml, " <arch>%s</arch>\n", virBufferVSprintf(&xml, " <arch>%s</arch>\n",
caps->host.arch); caps->host.arch);

View File

@@ -110,6 +110,7 @@ struct _virCapsHost {
virCapsHostNUMACellPtr *numaCell; virCapsHostNUMACellPtr *numaCell;
virCapsHostSecModel secModel; virCapsHostSecModel secModel;
virCPUDefPtr cpu; virCPUDefPtr cpu;
unsigned char host_uuid[VIR_UUID_BUFLEN];
}; };
typedef struct _virCaps virCaps; typedef struct _virCaps virCaps;

View File

@@ -708,6 +708,8 @@ usbDeviceFileIterate;
virUUIDFormat; virUUIDFormat;
virUUIDGenerate; virUUIDGenerate;
virUUIDParse; virUUIDParse;
virSetHostUUIDStr;
virGetHostUUID;
# virterror_internal.h # virterror_internal.h

View File

@@ -33,6 +33,7 @@
#include "conf.h" #include "conf.h"
#include "memory.h" #include "memory.h"
#include "logging.h" #include "logging.h"
#include "uuid.h"
#define VIR_FROM_THIS VIR_FROM_LXC #define VIR_FROM_THIS VIR_FROM_LXC
@@ -48,7 +49,7 @@ virCapsPtr lxcCapsInit(void)
if ((caps = virCapabilitiesNew(utsname.machine, if ((caps = virCapabilitiesNew(utsname.machine,
0, 0)) == NULL) 0, 0)) == NULL)
goto no_memory; goto error;
/* Some machines have problematic NUMA toplogy causing /* Some machines have problematic NUMA toplogy causing
* unexpected failures. We don't want to break the QEMU * 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"); 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 */ /* XXX shouldn't 'borrow' KVM's prefix */
virCapabilitiesSetMacPrefix(caps, (unsigned char []){ 0x52, 0x54, 0x00 }); virCapabilitiesSetMacPrefix(caps, (unsigned char []){ 0x52, 0x54, 0x00 });
@@ -70,7 +77,7 @@ virCapsPtr lxcCapsInit(void)
NULL, NULL,
0, 0,
NULL)) == NULL) NULL)) == NULL)
goto no_memory; goto error;
if (virCapabilitiesAddGuestDomain(guest, if (virCapabilitiesAddGuestDomain(guest,
"lxc", "lxc",
@@ -78,14 +85,14 @@ virCapsPtr lxcCapsInit(void)
NULL, NULL,
0, 0,
NULL) == NULL) NULL) == NULL)
goto no_memory; goto error;
/* LXC Requires an emulator in the XML */ /* LXC Requires an emulator in the XML */
virCapabilitiesSetEmulatorRequired(caps); virCapabilitiesSetEmulatorRequired(caps);
return caps; return caps;
no_memory: error:
virCapabilitiesFree(caps); virCapabilitiesFree(caps);
return NULL; return NULL;
} }

View File

@@ -1473,12 +1473,8 @@ udevGetDMIData(union _virNodeDevCapData *data)
goto out; goto out;
} }
if (udevGetStringSysfsAttr(device, if (virGetHostUUID(data->system.hardware.uuid))
"product_uuid",
&tmp) == PROPERTY_ERROR) {
goto out; goto out;
}
virUUIDParse(tmp, data->system.hardware.uuid);
if (udevGetStringSysfsAttr(device, if (udevGetStringSysfsAttr(device,
"bios_vendor", "bios_vendor",

View File

@@ -1334,6 +1334,11 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
caps->privateDataXMLFormat = qemuDomainObjPrivateXMLFormat; caps->privateDataXMLFormat = qemuDomainObjPrivateXMLFormat;
caps->privateDataXMLParse = qemuDomainObjPrivateXMLParse; 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 */ /* Security driver data */
if (driver->securityPrimaryDriver) { if (driver->securityPrimaryDriver) {
@@ -1355,6 +1360,7 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
no_memory: no_memory:
virReportOOMError(); virReportOOMError();
err_exit:
virCapabilitiesFree(caps); virCapabilitiesFree(caps);
return NULL; return NULL;
} }

View File

@@ -62,7 +62,7 @@ virCapsPtr umlCapsInit(void) {
if ((caps = virCapabilitiesNew(utsname.machine, if ((caps = virCapabilitiesNew(utsname.machine,
0, 0)) == NULL) 0, 0)) == NULL)
goto no_memory; goto error;
/* Some machines have problematic NUMA toplogy causing /* Some machines have problematic NUMA toplogy causing
* unexpected failures. We don't want to break the QEMU * 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"); 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, if ((guest = virCapabilitiesAddGuest(caps,
"uml", "uml",
utsname.machine, utsname.machine,
@@ -81,7 +87,7 @@ virCapsPtr umlCapsInit(void) {
NULL, NULL,
0, 0,
NULL)) == NULL) NULL)) == NULL)
goto no_memory; goto error;
if (virCapabilitiesAddGuestDomain(guest, if (virCapabilitiesAddGuestDomain(guest,
"uml", "uml",
@@ -89,11 +95,11 @@ virCapsPtr umlCapsInit(void) {
NULL, NULL,
0, 0,
NULL) == NULL) NULL) == NULL)
goto no_memory; goto error;
return caps; return caps;
no_memory: error:
virCapabilitiesFree(caps); virCapabilitiesFree(caps);
return NULL; return NULL;
} }

View File

@@ -38,11 +38,14 @@
#include "util.h" #include "util.h"
#include "virterror_internal.h" #include "virterror_internal.h"
#include "logging.h" #include "logging.h"
#include "memory.h"
#ifndef ENODATA #ifndef ENODATA
# define ENODATA EIO # define ENODATA EIO
#endif #endif
static unsigned char host_uuid[VIR_UUID_BUFLEN];
static int static int
virUUIDGenerateRandomBytes(unsigned char *buf, virUUIDGenerateRandomBytes(unsigned char *buf,
int buflen) int buflen)
@@ -208,3 +211,116 @@ void virUUIDFormat(const unsigned char *uuid, char *uuidstr)
uuid[12], uuid[13], uuid[14], uuid[15]); uuid[12], uuid[13], uuid[14], uuid[15]);
uuidstr[VIR_UUID_STRING_BUFLEN-1] = '\0'; 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;
}

View File

@@ -22,6 +22,11 @@
#ifndef __VIR_UUID_H__ #ifndef __VIR_UUID_H__
# define __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 virUUIDGenerate(unsigned char *uuid);
int virUUIDParse(const char *uuidstr, int virUUIDParse(const char *uuidstr,

View File

@@ -218,3 +218,12 @@ tls_allowed_dn_list = ["DN1", "DN2"]
# #
# By default, no Username's are checked # By default, no Username's are checked
sasl_allowed_username_list = ["joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ] 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"

View File

@@ -178,3 +178,10 @@ tls_allowed_dn_list = [ "DN1", "DN2" ]
# #
# By default, no Username's are checked # By default, no Username's are checked
sasl_allowed_username_list = [ "joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ] 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"