[libvirt] [PATCHv2 8/9] conf: support partially-specified <virtualport> in parser and formatter

Laine Stump laine at laine.org
Tue Aug 14 07:04:44 UTC 2012


Until now, all attributes in a <virtualport> parameter list that were
acceptable for a particular type, were also required. There were no
optional attributes.

One of the aims of supporting <virtualport> in libvirt's virtual
networks and portgroups is to allow specifying the group-wide
parameters in the network's virtualport, and merge that with the
interface's virtualport, which will have the instance-specific info
(i.e. the interfaceid or instanceid).

Additionally, the guest's interface XML shouldn't need to know what
type of network connection will be used prior to runtime - it could be
openvswitch, 802.1Qbh, 802.1Qbg, or none of the above - but should
still be able to specify instance-specific info just in case it turns
out to be applicable.

Finally, up to now, the parser for virtualport has always generated a
random instanceid/interfaceid when appropriate, making it impossible
to leave it blank (which is what's required for virtualports within a
network/portprofile definition).

This patch modifies the parser and formatter of the <virtualport>
element in the following ways:

* because most of the attributes in a virNetDevVPortProfile are fixed
  size binary data with no reserved values, there is no way to embed a
  "this value wasn't specified" sentinel into the existing data. To
  solve this problem, the new *_specified fields in the
  virNetDevVPortProfile object that were added in a previous patch of
  this series are now set when the corresponding attribute is present
  during the parse.

* allow parsing/formatting a <virtualport> that has no type set. In
  this case, all fields are settable, but all are also optional.

* add a GENERATE_MISSING_DEFAULTS flag to the parser - if this flag is
  set and an instanceid/interfaceid is expected but not provided, a
  random one will be generated. This was previously the default
  behavior, but is now done only for virtualports inside an
  <interface> definition, not for those in <network> or <portgroup>.

* add a REQUIRE_ALL_ATTRIBUTES flag to the parser - if this flag is
  set the parser will call the new
  virNetDevVPortProfileCheckComplete() functions at the end of the
  parser to check for any missing attributes (based on type), and
  return failure if anything is missing. This used to be default
  behavior. Now it is only used for the virtualport defined inside an
  interface's <actual> element (by the time you've figured out the
  contents of <actual>, you should have all the necessary data to fill
  in the entire virtualport)

* add a REQUIRE_TYPE flag to the parser - if this flag is set, the
  parser will return an error if the virtualport has no type
  attribute. This also was previously the default behavior, but isn't
  needed in the case of the virtualport for a type='network' interface
  (i.e. the exact type isn't yet known), or the virtualport of a
  portgroup (i.e. the portgroup just has modifiers for the network's
  virtualport, which *does* require a type) - in those cases, the
  check will be done at domain startup, once the final virtualport is
  assembled (this is handled in the next patch).
---
 docs/schemas/networkcommon.rng                     | 114 ++++++--
 src/conf/domain_conf.c                             |  25 +-
 src/conf/netdev_vport_profile_conf.c               | 308 +++++++++++----------
 src/conf/netdev_vport_profile_conf.h               |  17 +-
 src/conf/network_conf.c                            |   7 +-
 tests/networkxml2xmlin/openvswitch-net.xml         |  16 ++
 tests/networkxml2xmlin/vepa-net.xml                |   6 +-
 tests/networkxml2xmlout/openvswitch-net.xml        |  16 ++
 tests/networkxml2xmlout/vepa-net.xml               |   6 +-
 tests/networkxml2xmltest.c                         |   1 +
 .../qemuxml2argv-net-virtio-network-portgroup.xml  |  14 +
 11 files changed, 344 insertions(+), 186 deletions(-)
 create mode 100644 tests/networkxml2xmlin/openvswitch-net.xml
 create mode 100644 tests/networkxml2xmlout/openvswitch-net.xml

diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng
index 2328892..f2c3330 100644
--- a/docs/schemas/networkcommon.rng
+++ b/docs/schemas/networkcommon.rng
@@ -15,22 +15,30 @@
           <attribute name="type">
             <value>802.1Qbg</value>
           </attribute>
-          <element name="parameters">
-            <attribute name="managerid">
-              <ref name="uint8range"/>
-            </attribute>
-            <attribute name="typeid">
-              <ref name="uint24range"/>
-            </attribute>
-            <attribute name="typeidversion">
-              <ref name="uint8range"/>
-            </attribute>
-            <optional>
-              <attribute name="instanceid">
-                <ref name="UUID"/>
-              </attribute>
-            </optional>
-          </element>
+          <optional>
+            <element name="parameters">
+              <optional>
+                <attribute name="managerid">
+                  <ref name="uint8range"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="typeid">
+                  <ref name="uint24range"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="typeidversion">
+                  <ref name="uint8range"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="instanceid">
+                  <ref name="UUID"/>
+                </attribute>
+              </optional>
+            </element>
+          </optional>
         </element>
       </group>
       <group>
@@ -38,11 +46,75 @@
           <attribute name="type">
             <value>802.1Qbh</value>
           </attribute>
-          <element name="parameters">
-            <attribute name="profileid">
-              <ref name="virtualPortProfileID"/>
-            </attribute>
-          </element>
+          <optional>
+            <element name="parameters">
+              <optional>
+                <attribute name="profileid">
+                  <ref name="virtualPortProfileID"/>
+                </attribute>
+              </optional>
+            </element>
+          </optional>
+        </element>
+      </group>
+      <group>
+        <element name="virtualport">
+          <attribute name="type">
+            <value>openvswitch</value>
+          </attribute>
+          <optional>
+            <element name="parameters">
+              <optional>
+                <attribute name="profileid">
+                  <ref name="virtualPortProfileID"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="interfaceid">
+                  <ref name="UUID"/>
+                </attribute>
+              </optional>
+            </element>
+          </optional>
+        </element>
+      </group>
+      <group>
+        <!-- use this when no type attribute is present -->
+        <element name="virtualport">
+          <optional>
+            <element name="parameters">
+              <optional>
+                <attribute name="managerid">
+                  <ref name="uint8range"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="typeid">
+                  <ref name="uint24range"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="typeidversion">
+                  <ref name="uint8range"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="instanceid">
+                  <ref name="UUID"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="profileid">
+                  <ref name="virtualPortProfileID"/>
+                </attribute>
+              </optional>
+              <optional>
+                <attribute name="interfaceid">
+                  <ref name="UUID"/>
+                </attribute>
+              </optional>
+            </element>
+          </optional>
         </element>
       </group>
     </choice>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8f1f244..0cda374 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4404,8 +4404,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 <actual> 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 {
@@ -4558,12 +4563,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 31ee9b4..1adff10 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 (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 (virtPortManagerID) {
+        unsigned int val;
 
-            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(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;
+        virtPort->managerID_specified = true;
+    }
 
-            if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                                     _("cannot parse value of typeidversion parameter"));
-                goto error;
-            }
+    if (virtPortTypeID) {
+        unsigned int val;
 
-            if (val > 0xff) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                                     _("value of typeidversion out of range"));
-                goto error;
-            }
+        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;
+    }
 
-            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;
-                }
-            }
+    if (virtPortTypeIDVersion) {
+        unsigned int val;
 
-            virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBG;
+        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;
+    }
 
-        } else {
-                    virReportError(VIR_ERR_XML_ERROR, "%s",
-                                         _("a parameter is missing for 802.1Qbg description"));
+    if (virtPortInstanceID) {
+        if (virUUIDParse(virtPortInstanceID, virtPort->instanceID) < 0) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("cannot parse instanceid parameter as a uuid"));
             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 {
+        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",
-                                 _("profileid parameter is missing for 802.1Qbh description"));
+                           _("cannot parse interfaceid parameter as a uuid"));
             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"));
-                goto error;
-            }
-        } else {
-            if (virUUIDGenerate(virtPort->interfaceID)) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("cannot generate a random uuid for interfaceid"));
+        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;
             }
+            virtPort->instanceID_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"));
+        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;
             }
-        } else {
-            virtPort->profileID[0] = '\0';
+            virtPort->interfaceID_specified = true;
         }
-        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, "<virtualport type='%s'>\n",
-                      virNetDevVPortTypeToString(virtPort->virtPortType));
-
-    switch (virtPort->virtPortType) {
-    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
-        virUUIDFormat(virtPort->instanceID,
-                      uuidstr);
-        virBufferAsprintf(buf,
-                          "  <parameters managerid='%d' typeid='%d' "
-                          "typeidversion='%d' instanceid='%s'/>\n",
-                          virtPort->managerID,
-                          virtPort->typeID,
-                          virtPort->typeIDVersion,
-                          uuidstr);
-        break;
-
-    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
-        virBufferAsprintf(buf,
-                          "  <parameters profileid='%s'/>\n",
-                          virtPort->profileID);
-        break;
-
-    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
-        virUUIDFormat(virtPort->interfaceID,
-                      uuidstr);
-        if (virtPort->profileID[0] == '\0') {
-            virBufferAsprintf(buf, "  <parameters interfaceid='%s'/>\n",
-                              uuidstr);
+    noParameters = !(virtPort->managerID_specified ||
+                     virtPort->typeID_specified ||
+                     virtPort->typeIDVersion_specified ||
+                     virtPort->instanceID_specified ||
+                     virtPort->profileID[0] ||
+                     virtPort->interfaceID_specified);
+
+    type = virtPort->virtPortType;
+    if (type == VIR_NETDEV_VPORT_PROFILE_NONE) {
+        if (noParameters)
+            return 0;
+        virBufferAddLit(buf, "<virtualport>\n");
+    } else {
+        if (noParameters) {
+            virBufferAsprintf(buf, "<virtualport type='%s'/>\n",
+                              virNetDevVPortTypeToString(type));
+            return 0;
         } else {
-            virBufferAsprintf(buf, "  <parameters interfaceid='%s' "
-                              "profileid='%s'/>\n", uuidstr,
-                              virtPort->profileID);
+            virBufferAsprintf(buf, "<virtualport type='%s'>\n",
+                              virNetDevVPortTypeToString(type));
         }
+    }
+    virBufferAddLit(buf, "  <parameters");
 
-        break;
+    if (virtPort->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, "</virtualport>\n");
     return 0;
 }
diff --git a/src/conf/netdev_vport_profile_conf.h b/src/conf/netdev_vport_profile_conf.h
index 367bdf3..caf3519 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 a3714d9..783c388 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 0000000..8aa1897
--- /dev/null
+++ b/tests/networkxml2xmlin/openvswitch-net.xml
@@ -0,0 +1,16 @@
+<network>
+  <name>openvswitch-net</name>
+  <uuid>81ff0d90-c92e-6742-64da-4a736edb9a8b</uuid>
+  <forward mode='bridge'/>
+  <virtualport type='openvswitch'/>
+  <portgroup name='bob' default='yes'>
+    <virtualport>
+      <parameters profileid='bob-profile'/>
+    </virtualport>
+  </portgroup>
+  <portgroup name='alice'>
+    <virtualport>
+      <parameters profileid='alice-profile'/>
+    </virtualport>
+  </portgroup>
+</network>
diff --git a/tests/networkxml2xmlin/vepa-net.xml b/tests/networkxml2xmlin/vepa-net.xml
index b1a40c6..030c1d1 100644
--- a/tests/networkxml2xmlin/vepa-net.xml
+++ b/tests/networkxml2xmlin/vepa-net.xml
@@ -7,16 +7,16 @@
     <interface dev="eth3"/>
   </forward>
   <virtualport type="802.1Qbg">
-    <parameters managerid="11" typeid="1193047" typeidversion="2" instanceid="b153fa89-1b87-9719-ec12-99e0054fb844"/>
+    <parameters managerid="11" typeid="1193047" typeidversion="2"/>
   </virtualport>
   <portgroup name="bob" default="yes">
     <virtualport type="802.1Qbg">
-      <parameters managerid="12" typeid="2193047" typeidversion="3" instanceid="5d00e0ba-e15c-959c-fbb6-b595b0655735"/>
+      <parameters typeid="2193047" typeidversion="3"/>
     </virtualport>
   </portgroup>
   <portgroup name="alice">
     <virtualport type="802.1Qbg">
-      <parameters managerid="13" typeid="3193047" typeidversion="4" instanceid="70bf45f9-01a8-f5ee-3c0f-e25a0a2e44a6"/>
+      <parameters managerid="13"/>
     </virtualport>
   </portgroup>
 </network>
diff --git a/tests/networkxml2xmlout/openvswitch-net.xml b/tests/networkxml2xmlout/openvswitch-net.xml
new file mode 100644
index 0000000..8aa1897
--- /dev/null
+++ b/tests/networkxml2xmlout/openvswitch-net.xml
@@ -0,0 +1,16 @@
+<network>
+  <name>openvswitch-net</name>
+  <uuid>81ff0d90-c92e-6742-64da-4a736edb9a8b</uuid>
+  <forward mode='bridge'/>
+  <virtualport type='openvswitch'/>
+  <portgroup name='bob' default='yes'>
+    <virtualport>
+      <parameters profileid='bob-profile'/>
+    </virtualport>
+  </portgroup>
+  <portgroup name='alice'>
+    <virtualport>
+      <parameters profileid='alice-profile'/>
+    </virtualport>
+  </portgroup>
+</network>
diff --git a/tests/networkxml2xmlout/vepa-net.xml b/tests/networkxml2xmlout/vepa-net.xml
index af13d0f..4d35a8a 100644
--- a/tests/networkxml2xmlout/vepa-net.xml
+++ b/tests/networkxml2xmlout/vepa-net.xml
@@ -7,16 +7,16 @@
     <interface dev='eth3'/>
   </forward>
   <virtualport type='802.1Qbg'>
-    <parameters managerid='11' typeid='1193047' typeidversion='2' instanceid='b153fa89-1b87-9719-ec12-99e0054fb844'/>
+    <parameters managerid='11' typeid='1193047' typeidversion='2'/>
   </virtualport>
   <portgroup name='bob' default='yes'>
     <virtualport type='802.1Qbg'>
-      <parameters managerid='12' typeid='2193047' typeidversion='3' instanceid='5d00e0ba-e15c-959c-fbb6-b595b0655735'/>
+      <parameters typeid='2193047' typeidversion='3'/>
     </virtualport>
   </portgroup>
   <portgroup name='alice'>
     <virtualport type='802.1Qbg'>
-      <parameters managerid='13' typeid='3193047' typeidversion='4' instanceid='70bf45f9-01a8-f5ee-3c0f-e25a0a2e44a6'/>
+      <parameters managerid='13'/>
     </virtualport>
   </portgroup>
 </network>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index 8641c41..5a5531a 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 3eb5c88..6d379a0 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml
@@ -29,6 +29,20 @@
       </virtualport>
       <model type='virtio'/>
     </interface>
+    <interface type='network'>
+      <mac address='10:11:22:33:44:55'/>
+      <source network='blue' portgroup='sam'/>
+      <virtualport>
+        <parameters instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f' interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
+      </virtualport>
+    </interface>
+    <interface type='network'>
+      <mac address='22:11:22:33:44:55'/>
+      <source network='blue' portgroup='sam'/>
+      <virtualport type='802.1Qbh'>
+        <parameters profileid='testhis99'/>
+      </virtualport>
+    </interface>
     <memballoon model='virtio'/>
   </devices>
 </domain>
-- 
1.7.11.2




More information about the libvir-list mailing list