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