If a guest or network does not have a UUID assigned to it, we generate a random UUID preferably using /dev/urandom, but falling back to pseudo-random number generation if that fails. Signed-off-by: Mark McLoughlin <markmc@xxxxxxxxxx> Index: libvirt/qemud/Makefile.am =================================================================== --- libvirt.orig/qemud/Makefile.am +++ libvirt/qemud/Makefile.am @@ -9,7 +9,8 @@ libvirt_qemud_SOURCES = qemud.c internal dispatch.c dispatch.h \ conf.c conf.h \ bridge.c bridge.h \ - iptables.c iptables.h + iptables.c iptables.h \ + uuid.c uuid.h #-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L libvirt_qemud_CFLAGS = \ -I$(top_srcdir)/include -I$(top_builddir)/include $(LIBXML_CFLAGS) \ Index: libvirt/qemud/conf.c =================================================================== --- libvirt.orig/qemud/conf.c +++ libvirt/qemud/conf.c @@ -45,6 +45,7 @@ #include "conf.h" #include "driver.h" #include "iptables.h" +#include "uuid.h" static int qemudParseUUID(const char *uuid, unsigned char *rawuuid) { @@ -689,11 +690,13 @@ static struct qemud_vm_def *qemudParseXM obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt); if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - /* XXX auto-generate a UUID */ - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "missing uuid element"); - goto error; - } - if (qemudParseUUID((const char *)obj->stringval, def->uuid) < 0) { + int err; + if ((err = qemudGenerateUUID(def->uuid))) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, + "Failed to generate UUID: %s", strerror(err)); + goto error; + } + } else if (qemudParseUUID((const char *)obj->stringval, def->uuid) < 0) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "malformed uuid element"); goto error; } @@ -1650,11 +1653,13 @@ static struct qemud_network_def *qemudPa obj = xmlXPathEval(BAD_CAST "string(/network/uuid[1])", ctxt); if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - /* XXX auto-generate a UUID */ - qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "missing uuid element"); - goto error; - } - if (qemudParseUUID((const char *)obj->stringval, def->uuid) < 0) { + int err; + if ((err = qemudGenerateUUID(def->uuid))) { + qemudReportError(server, VIR_ERR_INTERNAL_ERROR, + "Failed to generate UUID: %s", strerror(err)); + goto error; + } + } else if (qemudParseUUID((const char *)obj->stringval, def->uuid) < 0) { qemudReportError(server, VIR_ERR_INTERNAL_ERROR, "%s", "malformed uuid element"); goto error; } Index: libvirt/qemud/uuid.c =================================================================== --- /dev/null +++ libvirt/qemud/uuid.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Mark McLoughlin <markmc@xxxxxxxxxx> + */ + +#include "config.h" + +#include "uuid.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> + +#include "protocol.h" +#include "internal.h" + +static int +qemudGenerateRandomBytes(unsigned char *buf, + int buflen) +{ + int fd; + + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) + return errno; + + while (buflen > 0) { + int n; + + if ((n = read(fd, buf, buflen)) <= 0) { + if (errno == EINTR) + continue; + close(fd); + return n < 0 ? errno : ENODATA; + } + + buf += n; + buflen -= n; + } + + close(fd); + + return 0; +} + +static int +qemudGeneratePseudoRandomBytes(unsigned char *buf, + int buflen) +{ + srand(time(NULL)); + while (buflen > 0) { + *buf = (int) (255.0 * (rand() / (double) RAND_MAX)); + buflen--; + } + + return 0; +} + +int +qemudGenerateUUID(unsigned char *uuid) +{ + int err; + + if ((err = qemudGenerateRandomBytes(uuid, QEMUD_UUID_RAW_LEN))) + qemudLog(QEMUD_WARN, + "Falling back to pseudorandom UUID, " + "failed to generate random bytes: %s", strerror(err)); + + return qemudGeneratePseudoRandomBytes(uuid, QEMUD_UUID_RAW_LEN); +} + +/* + * Local variables: + * indent-tabs-mode: nil + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ + Index: libvirt/qemud/uuid.h =================================================================== --- /dev/null +++ libvirt/qemud/uuid.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: + * Mark McLoughlin <markmc@xxxxxxxxxx> + */ + +#ifndef __QEMUD_UUID_H__ +#define __QEMUD_UUID_H__ + +int qemudGenerateUUID(unsigned char *uuid); + +#endif /* __QEMUD_UUID_H__ */ --