mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-10 05:17:59 +03:00
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:
parent
8ac1f8f44a
commit
7c90026db9
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
|
@ -1373,6 +1373,7 @@ virPidFileDeletePath;
|
||||
|
||||
# virrandom.h
|
||||
virRandomBits;
|
||||
virRandomGenerateWWN;
|
||||
virRandomInitialize;
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)))
|
||||
|
Loading…
Reference in New Issue
Block a user