[libvirt] [PATCH v6] npiv: Auto-generate WWN if it's not specified

Osier Yang jyang at redhat.com
Tue Feb 7 13:38:50 UTC 2012


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




More information about the libvir-list mailing list