npiv: Auto-generate WWN if it's not specified

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.
This commit is contained in:
Osier Yang 2012-02-10 12:51:47 +08:00
parent 8ac1f8f44a
commit 7c90026db9
11 changed files with 118 additions and 41 deletions

View File

@ -134,6 +134,7 @@ src/util/virnetdevvportprofile.c
src/util/virnetlink.c
src/util/virnodesuspend.c
src/util/virpidfile.c
src/util/virrandom.c
src/util/virsocketaddr.c
src/util/virterror.c
src/util/virtime.c

View File

@ -37,6 +37,7 @@
#include "buf.h"
#include "uuid.h"
#include "pci.h"
#include "virrandom.h"
#define VIR_FROM_THIS VIR_FROM_NODEDEV
@ -63,19 +64,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 +711,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,18 +758,26 @@ 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;
@ -1060,7 +1063,8 @@ static virNodeDevCapsDefPtr
virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
virNodeDeviceDefPtr def,
xmlNodePtr node,
int create)
int create,
const char *virt_type)
{
virNodeDevCapsDefPtr caps;
char *tmp;
@ -1104,7 +1108,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 +1140,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 +1189,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 +1212,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 +1233,7 @@ virNodeDeviceDefParseNode(xmlDocPtr xml,
}
ctxt->node = root;
def = virNodeDeviceDefParseXML(ctxt, create);
def = virNodeDeviceDefParseXML(ctxt, create, virt_type);
cleanup:
xmlXPathFreeContext(ctxt);
@ -1230,13 +1243,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 +1260,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);
}
/*

View File

@ -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,

View File

@ -1373,6 +1373,7 @@ virPidFileDeletePath;
# virrandom.h
virRandomBits;
virRandomGenerateWWN;
virRandomInitialize;

View File

@ -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;
}

View File

@ -9045,7 +9045,7 @@ qemudNodeDeviceGetPciInfo (virNodeDevicePtr dev,
if (!xml)
goto out;
def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE);
def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
if (!def)
goto out;

View File

@ -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;
}

View File

@ -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,45 @@ 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;
}

View File

@ -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__ */

View File

@ -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;

View File

@ -24,7 +24,7 @@ testCompareXMLToXMLFiles(const char *xml)
if (virtTestLoadFile(xml, &xmlData) < 0)
goto fail;
if (!(dev = virNodeDeviceDefParseString(xmlData, EXISTING_DEVICE)))
if (!(dev = virNodeDeviceDefParseString(xmlData, EXISTING_DEVICE, NULL)))
goto fail;
if (!(actual = virNodeDeviceDefFormat(dev)))