diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng
index 2328892f17..f2c3330744 100644
--- a/docs/schemas/networkcommon.rng
+++ b/docs/schemas/networkcommon.rng
@@ -15,22 +15,30 @@
802.1Qbg
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -38,11 +46,75 @@
802.1Qbh
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ openvswitch
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b10ffe3216..e52119b973 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4403,8 +4403,13 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
actual->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ /* the virtualport in should always already
+ * have an instanceid/interfaceid if its required,
+ * so don't let the parser generate one */
if (!(actual->virtPortProfile
- = virNetDevVPortProfileParse(virtPortNode))) {
+ = virNetDevVPortProfileParse(virtPortNode,
+ VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES |
+ VIR_VPORT_XML_REQUIRE_TYPE))) {
goto error;
}
} else {
@@ -4557,12 +4562,20 @@ virDomainNetDefParseXML(virCapsPtr caps,
mode = virXMLPropString(cur, "mode");
} else if (!def->virtPortProfile
&& xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
- if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
- def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
- def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
- def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
if (!(def->virtPortProfile
- = virNetDevVPortProfileParse(cur))) {
+ = virNetDevVPortProfileParse(cur,
+ VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS))) {
+ goto error;
+ }
+ } else if (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
+ def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ if (!(def->virtPortProfile
+ = virNetDevVPortProfileParse(cur,
+ VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS|
+ VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES|
+ VIR_VPORT_XML_REQUIRE_TYPE))) {
goto error;
}
} else {
diff --git a/src/conf/netdev_vport_profile_conf.c b/src/conf/netdev_vport_profile_conf.c
index 31ee9b4c00..1adff10815 100644
--- a/src/conf/netdev_vport_profile_conf.c
+++ b/src/conf/netdev_vport_profile_conf.c
@@ -37,7 +37,7 @@ VIR_ENUM_IMPL(virNetDevVPort, VIR_NETDEV_VPORT_PROFILE_LAST,
virNetDevVPortProfilePtr
-virNetDevVPortProfileParse(xmlNodePtr node)
+virNetDevVPortProfileParse(xmlNodePtr node, unsigned int flags)
{
char *virtPortType;
char *virtPortManagerID = NULL;
@@ -54,22 +54,22 @@ virNetDevVPortProfileParse(xmlNodePtr node)
return NULL;
}
- virtPortType = virXMLPropString(node, "type");
- if (!virtPortType) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("missing virtualportprofile type"));
+ if ((virtPortType = virXMLPropString(node, "type")) &&
+ (virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("unknown virtualport type %s"), virtPortType);
goto error;
}
- if ((virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) {
- virReportError(VIR_ERR_XML_ERROR,
- _("unknown virtualportprofile type %s"), virtPortType);
+ if ((virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE) &&
+ (flags & VIR_VPORT_XML_REQUIRE_TYPE)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing required virtualport type"));
goto error;
}
while (cur != NULL) {
if (xmlStrEqual(cur->name, BAD_CAST "parameters")) {
-
virtPortManagerID = virXMLPropString(cur, "managerid");
virtPortTypeID = virXMLPropString(cur, "typeid");
virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion");
@@ -78,132 +78,119 @@ virNetDevVPortProfileParse(xmlNodePtr node)
virtPortInterfaceID = virXMLPropString(cur, "interfaceid");
break;
}
-
cur = cur->next;
}
- switch (virtPort->virtPortType) {
- case VIR_NETDEV_VPORT_PROFILE_8021QBG:
- if (virtPortManagerID != NULL && virtPortTypeID != NULL &&
- virtPortTypeIDVersion != NULL) {
- unsigned int val;
+ if (virtPortManagerID) {
+ unsigned int val;
- if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("cannot parse value of managerid parameter"));
- goto error;
- }
-
- if (val > 0xff) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("value of managerid out of range"));
- goto error;
- }
-
- virtPort->managerID = (uint8_t)val;
-
- if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("cannot parse value of typeid parameter"));
- goto error;
- }
-
- if (val > 0xffffff) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("value for typeid out of range"));
- goto error;
- }
-
- virtPort->typeID = (uint32_t)val;
-
- if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("cannot parse value of typeidversion parameter"));
- goto error;
- }
-
- if (val > 0xff) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("value of typeidversion out of range"));
- goto error;
- }
-
- virtPort->typeIDVersion = (uint8_t)val;
-
- if (virtPortInstanceID != NULL) {
- if (virUUIDParse(virtPortInstanceID,
- virtPort->instanceID)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("cannot parse instanceid parameter as a uuid"));
- goto error;
- }
- } else {
- if (virUUIDGenerate(virtPort->instanceID)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("cannot generate a random uuid for instanceid"));
- goto error;
- }
- }
-
- virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBG;
-
- } else {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("a parameter is missing for 802.1Qbg description"));
- goto error;
- }
- break;
-
- case VIR_NETDEV_VPORT_PROFILE_8021QBH:
- if (virtPortProfileID != NULL) {
- if (virStrcpyStatic(virtPort->profileID,
- virtPortProfileID) != NULL) {
- virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBH;
- } else {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("profileid parameter too long"));
- goto error;
- }
- } else {
+ if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) {
virReportError(VIR_ERR_XML_ERROR, "%s",
- _("profileid parameter is missing for 802.1Qbh description"));
+ _("cannot parse value of managerid parameter"));
goto error;
}
- break;
- case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
- if (virtPortInterfaceID != NULL) {
- if (virUUIDParse(virtPortInterfaceID,
- virtPort->interfaceID)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("cannot parse interfaceid parameter as a uuid"));
+ if (val > 0xff) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("value of managerid out of range"));
+ goto error;
+ }
+ virtPort->managerID = (uint8_t)val;
+ virtPort->managerID_specified = true;
+ }
+
+ if (virtPortTypeID) {
+ unsigned int val;
+
+ if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse value of typeid parameter"));
+ goto error;
+ }
+ if (val > 0xffffff) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("value for typeid out of range"));
+ goto error;
+ }
+ virtPort->typeID = (uint32_t)val;
+ virtPort->typeID_specified = true;
+ }
+
+ if (virtPortTypeIDVersion) {
+ unsigned int val;
+
+ if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse value of typeidversion parameter"));
+ goto error;
+ }
+ if (val > 0xff) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("value of typeidversion out of range"));
+ goto error;
+ }
+ virtPort->typeIDVersion = (uint8_t)val;
+ virtPort->typeIDVersion_specified = true;
+ }
+
+ if (virtPortInstanceID) {
+ if (virUUIDParse(virtPortInstanceID, virtPort->instanceID) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse instanceid parameter as a uuid"));
+ goto error;
+ }
+ virtPort->instanceID_specified = true;
+ }
+
+ if (virtPortProfileID &&
+ !virStrcpyStatic(virtPort->profileID, virtPortProfileID)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("profileid parameter too long"));
+ goto error;
+ }
+
+ if (virtPortInterfaceID) {
+ if (virUUIDParse(virtPortInterfaceID, virtPort->interfaceID) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse interfaceid parameter as a uuid"));
+ goto error;
+ }
+ virtPort->interfaceID_specified = true;
+ }
+
+ /* generate default instanceID/interfaceID if appropriate */
+ if (flags & VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS) {
+ if (!virtPort->instanceID_specified &&
+ (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
+ virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ if (virUUIDGenerate(virtPort->instanceID) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot generate a random uuid for instanceid"));
goto error;
}
- } else {
- if (virUUIDGenerate(virtPort->interfaceID)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
+ virtPort->instanceID_specified = true;
+ }
+ if (!virtPort->interfaceID_specified &&
+ (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
+ virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ if (virUUIDGenerate(virtPort->interfaceID) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("cannot generate a random uuid for interfaceid"));
goto error;
}
+ virtPort->interfaceID_specified = true;
}
- /* profileid is not mandatory for Open vSwitch */
- if (virtPortProfileID != NULL) {
- if (virStrcpyStatic(virtPort->profileID,
- virtPortProfileID) == NULL) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("profileid parameter too long"));
- goto error;
- }
- } else {
- virtPort->profileID[0] = '\0';
- }
- break;
+ }
- default:
- virReportError(VIR_ERR_XML_ERROR,
- _("unexpected virtualport type %d"), virtPort->virtPortType);
+ /* check for required/unsupported attributes */
+
+ if ((flags & VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES) &&
+ (virNetDevVPortProfileCheckComplete(virtPort, false) < 0)) {
goto error;
}
+ if (virNetDevVPortProfileCheckNoExtras(virtPort) < 0)
+ goto error;
+
cleanup:
VIR_FREE(virtPortManagerID);
VIR_FREE(virtPortTypeID);
@@ -224,53 +211,76 @@ int
virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort,
virBufferPtr buf)
{
- char uuidstr[VIR_UUID_STRING_BUFLEN];
+ enum virNetDevVPortProfile type;
+ bool noParameters;
- if (!virtPort || virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)
+ if (!virtPort)
return 0;
- virBufferAsprintf(buf, "\n",
- virNetDevVPortTypeToString(virtPort->virtPortType));
+ noParameters = !(virtPort->managerID_specified ||
+ virtPort->typeID_specified ||
+ virtPort->typeIDVersion_specified ||
+ virtPort->instanceID_specified ||
+ virtPort->profileID[0] ||
+ virtPort->interfaceID_specified);
- switch (virtPort->virtPortType) {
- case VIR_NETDEV_VPORT_PROFILE_8021QBG:
- virUUIDFormat(virtPort->instanceID,
- uuidstr);
- virBufferAsprintf(buf,
- " \n",
- virtPort->managerID,
- virtPort->typeID,
- virtPort->typeIDVersion,
- uuidstr);
- break;
-
- case VIR_NETDEV_VPORT_PROFILE_8021QBH:
- virBufferAsprintf(buf,
- " \n",
- virtPort->profileID);
- break;
-
- case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
- virUUIDFormat(virtPort->interfaceID,
- uuidstr);
- if (virtPort->profileID[0] == '\0') {
- virBufferAsprintf(buf, " \n",
- uuidstr);
+ type = virtPort->virtPortType;
+ if (type == VIR_NETDEV_VPORT_PROFILE_NONE) {
+ if (noParameters)
+ return 0;
+ virBufferAddLit(buf, "\n");
+ } else {
+ if (noParameters) {
+ virBufferAsprintf(buf, "\n",
+ virNetDevVPortTypeToString(type));
+ return 0;
} else {
- virBufferAsprintf(buf, " \n", uuidstr,
- virtPort->profileID);
+ virBufferAsprintf(buf, "\n",
+ virNetDevVPortTypeToString(type));
}
+ }
+ virBufferAddLit(buf, " managerID_specified &&
+ (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
+ type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ virBufferAsprintf(buf, " managerid='%d'", virtPort->managerID);
+ }
+ if (virtPort->typeID_specified &&
+ (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
+ type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ virBufferAsprintf(buf, " typeid='%d'", virtPort->typeID);
+ }
+ if (virtPort->typeIDVersion_specified &&
+ (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
+ type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ virBufferAsprintf(buf, " typeidversion='%d'",
+ virtPort->typeIDVersion);
+ }
+ if (virtPort->instanceID_specified &&
+ (type == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
+ type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
- default:
- virReportError(VIR_ERR_XML_ERROR,
- _("unexpected virtualport type %d"), virtPort->virtPortType);
- return -1;
+ virUUIDFormat(virtPort->instanceID, uuidstr);
+ virBufferAsprintf(buf, " instanceid='%s'", uuidstr);
+ }
+ if (virtPort->interfaceID_specified &&
+ (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
+ type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(virtPort->interfaceID, uuidstr);
+ virBufferAsprintf(buf, " interfaceid='%s'", uuidstr);
+ }
+ if (virtPort->profileID[0] &&
+ (type == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
+ type == VIR_NETDEV_VPORT_PROFILE_8021QBH ||
+ type == VIR_NETDEV_VPORT_PROFILE_NONE)) {
+ virBufferAsprintf(buf, " profileid='%s'", virtPort->profileID);
}
+ virBufferAddLit(buf, "/>\n");
virBufferAddLit(buf, "\n");
return 0;
}
diff --git a/src/conf/netdev_vport_profile_conf.h b/src/conf/netdev_vport_profile_conf.h
index 367bdf307b..caf3519eca 100644
--- a/src/conf/netdev_vport_profile_conf.h
+++ b/src/conf/netdev_vport_profile_conf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 Red Hat, Inc.
+ * Copyright (C) 2009-2012 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
@@ -28,8 +28,21 @@
# include "buf.h"
# include "xml.h"
+typedef enum {
+ /* generate random defaults for interfaceID/interfaceID
+ * when appropriate
+ */
+ VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS = (1<<0),
+ /* fail if any attribute required for the specified
+ * type is missing
+ */
+ VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES = (1<<1),
+ /* fail if no type is specified */
+ VIR_VPORT_XML_REQUIRE_TYPE = (1<<2),
+} virNetDevVPortXMLFlags;
+
virNetDevVPortProfilePtr
-virNetDevVPortProfileParse(xmlNodePtr node);
+virNetDevVPortProfileParse(xmlNodePtr node, unsigned int flags);
int
virNetDevVPortProfileFormat(virNetDevVPortProfilePtr virtPort,
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index a3714d945e..783c388c45 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -899,8 +899,9 @@ virNetworkPortGroupParseXML(virPortGroupDefPtr def,
virtPortNode = virXPathNode("./virtualport", ctxt);
if (virtPortNode &&
- (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode))))
+ (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode, 0)))) {
goto error;
+ }
bandwidth_node = virXPathNode("./bandwidth", ctxt);
if (bandwidth_node &&
@@ -1010,8 +1011,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
virtPortNode = virXPathNode("./virtualport", ctxt);
if (virtPortNode &&
- (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode))))
+ (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode,
+ VIR_VPORT_XML_REQUIRE_TYPE)))) {
goto error;
+ }
nPortGroups = virXPathNodeSet("./portgroup", ctxt, &portGroupNodes);
if (nPortGroups < 0)
diff --git a/tests/networkxml2xmlin/openvswitch-net.xml b/tests/networkxml2xmlin/openvswitch-net.xml
new file mode 100644
index 0000000000..8aa1897ab4
--- /dev/null
+++ b/tests/networkxml2xmlin/openvswitch-net.xml
@@ -0,0 +1,16 @@
+
+ openvswitch-net
+ 81ff0d90-c92e-6742-64da-4a736edb9a8b
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmlin/vepa-net.xml b/tests/networkxml2xmlin/vepa-net.xml
index b1a40c6e58..030c1d1621 100644
--- a/tests/networkxml2xmlin/vepa-net.xml
+++ b/tests/networkxml2xmlin/vepa-net.xml
@@ -7,16 +7,16 @@
-
+
-
+
-
+
diff --git a/tests/networkxml2xmlout/openvswitch-net.xml b/tests/networkxml2xmlout/openvswitch-net.xml
new file mode 100644
index 0000000000..8aa1897ab4
--- /dev/null
+++ b/tests/networkxml2xmlout/openvswitch-net.xml
@@ -0,0 +1,16 @@
+
+ openvswitch-net
+ 81ff0d90-c92e-6742-64da-4a736edb9a8b
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmlout/vepa-net.xml b/tests/networkxml2xmlout/vepa-net.xml
index af13d0fd45..4d35a8af7b 100644
--- a/tests/networkxml2xmlout/vepa-net.xml
+++ b/tests/networkxml2xmlout/vepa-net.xml
@@ -7,16 +7,16 @@
-
+
-
+
-
+
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index 8641c412fc..5a5531a9dc 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -104,6 +104,7 @@ mymain(void)
DO_TEST("host-bridge-net");
DO_TEST("vepa-net");
DO_TEST("bandwidth-network");
+ DO_TEST("openvswitch-net");
DO_TEST_FULL("passthrough-pf", VIR_NETWORK_XML_INACTIVE);
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml
index 3eb5c88814..6d379a044f 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml
@@ -29,6 +29,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+