The auto-generated WWN comply with the new addressing schema of WWN: <quote> the first nibble is either hex 5 or 6 followed by a 3-byte vendor identifier and 36 bits for a vendor-specified serial number. </quote> We choose hex 5 for the first nibble. And for the 3-bytes vendor ID, we uses the OUI according to underlying hypervisor type, (invoking virConnectGetType to get the virt type). e.g. If virConnectGetType returns "QEMU", we use Qumranet's OUI (00:1A:4A), if returns ESX|VMWARE, we use VMWARE's OUI (00:05:69). Currently it only supports qemu|xen|libxl|xenapi|hyperv|esx|vmware drivers. The last 36 bits are auto-generated. --- src/conf/node_device_conf.c | 81 +++++++++++++++++++++------------ src/conf/node_device_conf.h | 9 +++- src/libvirt_private.syms | 1 + src/node_device/node_device_driver.c | 4 +- src/qemu/qemu_driver.c | 2 +- src/test/test_driver.c | 8 ++-- src/util/virrandom.c | 53 ++++++++++++++++++++++ src/util/virrandom.h | 1 + src/xen/xen_driver.c | 2 +- 9 files changed, 121 insertions(+), 40 deletions(-) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index d9dc9ac..d1befe0 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -37,6 +37,8 @@ #include "buf.h" #include "uuid.h" #include "pci.h" +#include "virrandom.h" #define VIR_FROM_THIS VIR_FROM_NODEDEV @@ -63,19 +65,12 @@ VIR_ENUM_IMPL(virNodeDevHBACap, VIR_NODE_DEV_CAP_HBA_LAST, static int virNodeDevCapsDefParseString(const char *xpath, xmlXPathContextPtr ctxt, - char **string, - virNodeDeviceDefPtr def, - const char *missing_error_fmt) + char **string) { char *s; - s = virXPathString(xpath, ctxt); - if (s == NULL) { - virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, - missing_error_fmt, - def->name); + if (!(s = virXPathString(xpath, ctxt))) return -1; - } *string = s; return 0; @@ -717,7 +712,8 @@ virNodeDevCapScsiHostParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDefPtr def, xmlNodePtr node, union _virNodeDevCapData *data, - int create) + int create, + const char *virt_type) { xmlNodePtr orignode, *nodes = NULL; int ret = -1, n = 0, i; @@ -763,20 +759,31 @@ virNodeDevCapScsiHostParseXML(xmlXPathContextPtr ctxt, if (virNodeDevCapsDefParseString("string(./wwnn[1])", ctxt, - &data->scsi_host.wwnn, - def, - _("no WWNN supplied for '%s'")) < 0) { - goto out; + &data->scsi_host.wwnn) < 0) { + if (virRandomGenerateWWN(&data->scsi_host.wwnn, virt_type) < 0) { + virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, + _("no WWNN supplied for '%s', and " + "auto-generation failed"), + def->name); + goto out; + } } if (virNodeDevCapsDefParseString("string(./wwpn[1])", ctxt, - &data->scsi_host.wwpn, - def, - _("no WWPN supplied for '%s'")) < 0) { - goto out; + &data->scsi_host.wwpn) < 0) { + if (virRandomGenerateWWN(&data->scsi_host.wwpn, virt_type) < 0) { + virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR, + _("no WWPN supplied for '%s', and " + "auto-generation failed"), + def->name); + goto out; + } } ctxt->node = orignode2; } else { @@ -1060,7 +1067,8 @@ static virNodeDevCapsDefPtr virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDefPtr def, xmlNodePtr node, - int create) + int create, + const char *virt_type) { virNodeDevCapsDefPtr caps; char *tmp; @@ -1104,7 +1112,10 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, ret = virNodeDevCapNetParseXML(ctxt, def, node, &caps->data); break; case VIR_NODE_DEV_CAP_SCSI_HOST: - ret = virNodeDevCapScsiHostParseXML(ctxt, def, node, &caps->data, create); + ret = virNodeDevCapScsiHostParseXML(ctxt, def, node, + &caps->data, + create, + virt_type); break; case VIR_NODE_DEV_CAP_SCSI_TARGET: ret = virNodeDevCapScsiTargetParseXML(ctxt, def, node, &caps->data); @@ -1133,7 +1144,9 @@ error: } static virNodeDeviceDefPtr -virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, int create) +virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, + int create, + const char *virt_type) { virNodeDeviceDefPtr def; virNodeDevCapsDefPtr *next_cap; @@ -1180,7 +1193,10 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, int create) next_cap = &def->caps; for (i = 0 ; i < n ; i++) { - *next_cap = virNodeDevCapsDefParseXML(ctxt, def, nodes[i], create); + *next_cap = virNodeDevCapsDefParseXML(ctxt, def, + nodes[i], + create, + virt_type); if (!*next_cap) { VIR_FREE(nodes); goto error; @@ -1200,7 +1216,8 @@ virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, int create) virNodeDeviceDefPtr virNodeDeviceDefParseNode(xmlDocPtr xml, xmlNodePtr root, - int create) + int create, + const char *virt_type) { xmlXPathContextPtr ctxt = NULL; virNodeDeviceDefPtr def = NULL; @@ -1220,7 +1237,7 @@ virNodeDeviceDefParseNode(xmlDocPtr xml, } ctxt->node = root; - def = virNodeDeviceDefParseXML(ctxt, create); + def = virNodeDeviceDefParseXML(ctxt, create, virt_type); cleanup: xmlXPathFreeContext(ctxt); @@ -1230,13 +1247,15 @@ cleanup: static virNodeDeviceDefPtr virNodeDeviceDefParse(const char *str, const char *filename, - int create) + int create, + const char *virt_type) { xmlDocPtr xml; virNodeDeviceDefPtr def = NULL; if ((xml = virXMLParse(filename, str, _("(node_device_definition)")))) { - def = virNodeDeviceDefParseNode(xml, xmlDocGetRootElement(xml), create); + def = virNodeDeviceDefParseNode(xml, xmlDocGetRootElement(xml), + create, virt_type); xmlFreeDoc(xml); } @@ -1245,16 +1264,18 @@ virNodeDeviceDefParse(const char *str, virNodeDeviceDefPtr virNodeDeviceDefParseString(const char *str, - int create) + int create, + const char *virt_type) { - return virNodeDeviceDefParse(str, NULL, create); + return virNodeDeviceDefParse(str, NULL, create, virt_type); } virNodeDeviceDefPtr virNodeDeviceDefParseFile(const char *filename, - int create) + int create, + const char *virt_type) { - return virNodeDeviceDefParse(NULL, filename, create); + return virNodeDeviceDefParse(NULL, filename, create, virt_type); } /* diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index a1833a0..4aaf4c8 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -234,12 +234,15 @@ void virNodeDeviceObjRemove(virNodeDeviceObjListPtr devs, char *virNodeDeviceDefFormat(const virNodeDeviceDefPtr def); virNodeDeviceDefPtr virNodeDeviceDefParseString(const char *str, - int create); + int create, + const char *virt_type); virNodeDeviceDefPtr virNodeDeviceDefParseFile(const char *filename, - int create); + int create, + const char *virt_type); virNodeDeviceDefPtr virNodeDeviceDefParseNode(xmlDocPtr xml, xmlNodePtr root, - int create); + int create, + const char *virt_type); int virNodeDeviceGetWWNs(virNodeDeviceDefPtr def, char **wwnn, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d6ad36c..421986b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1373,6 +1373,7 @@ virPidFileDeletePath; # virrandom.h virRandomBits; +virRandomGenerateWWN; virRandomInitialize; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index 681655e..b0a29cd 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -558,12 +558,14 @@ nodeDeviceCreateXML(virConnectPtr conn, char *wwnn = NULL, *wwpn = NULL; int parent_host = -1; virNodeDevicePtr dev = NULL; + const char *virt_type = NULL; virCheckFlags(0, NULL); + virt_type = virConnectGetType(conn); nodeDeviceLock(driver); - def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE); + def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type); if (def == NULL) { goto cleanup; } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3f940e8..464fd7d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9039,7 +9039,7 @@ qemudNodeDeviceGetPciInfo (virNodeDevicePtr dev, if (!xml) goto out; - def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE); + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); if (!def) goto out; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index bf6b148..39fd63d 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -608,7 +608,7 @@ static int testOpenDefault(virConnectPtr conn) { virStoragePoolObjUnlock(poolobj); /* Init default node device */ - if (!(nodedef = virNodeDeviceDefParseString(defaultNodeXML, 0))) + if (!(nodedef = virNodeDeviceDefParseString(defaultNodeXML, 0, NULL))) goto error; if (!(nodeobj = virNodeDeviceAssignDef(&privconn->devs, nodedef))) { @@ -1057,12 +1057,12 @@ static int testOpenFromFile(virConnectPtr conn, goto error; } - def = virNodeDeviceDefParseFile(absFile, 0); + def = virNodeDeviceDefParseFile(absFile, 0, NULL); VIR_FREE(absFile); if (!def) goto error; } else { - if ((def = virNodeDeviceDefParseNode(xml, devs[i], 0)) == NULL) + if ((def = virNodeDeviceDefParseNode(xml, devs[i], 0, NULL)) == NULL) goto error; } if (!(dev = virNodeDeviceAssignDef(&privconn->devs, def))) { @@ -5285,7 +5285,7 @@ testNodeDeviceCreateXML(virConnectPtr conn, testDriverLock(driver); - def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE); + def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL); if (def == NULL) { goto cleanup; } diff --git a/src/util/virrandom.c b/src/util/virrandom.c index ec0cf03..760b975 100644 --- a/src/util/virrandom.c +++ b/src/util/virrandom.c @@ -22,10 +22,20 @@ #include <config.h> #include <stdlib.h> +#include <inttypes.h> #include "virrandom.h" #include "threads.h" #include "count-one-bits.h" +#include "util.h" +#include "virterror_internal.h" +#include "conf/domain_conf.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +#define virRandomError(code, ...) \ + virReportErrorHelper(VIR_FROM_NONE, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) static char randomState[128]; static struct random_data randomData; @@ -79,3 +89,46 @@ uint64_t virRandomBits(int nbits) virMutexUnlock(&randomLock); return ret; } + +#define QUMRANET_OUI "001a4a" +#define VMWARE_OUI "000569" +#define MICROSOFT_OUI "0050f2" +#define XEN_OUI "00163e" + +int +virRandomGenerateWWN(char **wwn, + const char *virt_type) { + const char *oui = NULL; + + if (!virt_type) { + virRandomError(VIR_ERR_INVALID_ARG, "%s", + _("argument virt_type must not be NULL")); + return -1; + } + + if (STREQ(virt_type, "QEMU")) { + oui = QUMRANET_OUI; + } else if (STREQ(virt_type, "Xen") || + STREQ(virt_type, "xenlight") || + STREQ(virt_type, "XenAPI")) { + oui = XEN_OUI; + } else if (STREQ(virt_type, "ESX") || + STREQ(virt_type, "VMWARE")) { + oui = VMWARE_OUI; + } else if (STREQ(virt_type, "HYPER-V")) { + oui = MICROSOFT_OUI; + } else { + virRandomError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unsupported virt type")); + return -1; + } + + if (virAsprintf(wwn, "5" "%s%09" PRIx64, + oui, virRandomBits(36)) < 0) { + virReportOOMError(); + return -1; + } + + return 0; +} diff --git a/src/util/virrandom.h b/src/util/virrandom.h index e180a2f..24ab0b1 100644 --- a/src/util/virrandom.h +++ b/src/util/virrandom.h @@ -27,5 +27,6 @@ int virRandomInitialize(uint32_t seed) ATTRIBUTE_RETURN_CHECK; uint64_t virRandomBits(int nbits); +int virRandomGenerateWWN(char **wwn, const char *virt_type); #endif /* __VIR_RANDOM_H__ */ diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 94cafde..635f468 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1950,7 +1950,7 @@ xenUnifiedNodeDeviceGetPciInfo (virNodeDevicePtr dev, if (!xml) goto out; - def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE); + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); if (!def) goto out; -- 1.7.7.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list