[libvirt] RFC: network interface "tags" vs. portgroups

Laine Stump laine at laine.org
Tue Jun 10 10:01:18 UTC 2014


A couple releases ago (commit 7d5bf484, first appeared in 1.2.2) I
modified the domain interface status xml to show what resources are
actually in use for an interface, superseding the interface config in
the cases where they conflict with each other.

In particular, if there is an interface of type='network' that
references a portgroup of the network in the <source> element, the
interface status will not contain a <source> element showing the network
and portgroup names, but instead the <source resulting from applying the
config is shown. For example, given the following domain interface and
network definitions:


    <interface type='network'>
      <source network='mynet' portgroup='xyzzy'/>
      ...
    </interface>


    <network>
      <name>mynet</name>
      <forward mode='bridge'/>\
      <bridge name='br0'/>
      <portgroup name='xyzzy'>
        <bandwidth>
          <inbound average='1000' peak='5000' floor='200' burst='1024'/>
          <outbound average='128' peak='256' burst='256'/>
        </bandwidth>
      </portgroup>
    </network>

the status that was previously displayed when the domain was running
would be identical to the config above (except that it would also
contain the tap device name and alias). But now the status will be this:


    <interface type='bridge'>
      <source bridge='br0'/>
      <bandwidth>
        <inbound average='1000' peak='5000' floor='200' burst='1024'/>
        <outbound average='128' peak='256' burst='256'/>
      </bandwidth>
      ...
    </interface>

The advantage here is that a hook script for the domain will be able to
see the bandwidth (and vlan and physical device, if any) that are
actually being used by the domain's interface. Because the config and
status both use the same elements/attributes, we can only show one or
the other; the thinking was that normally the status will be what is
desired, and anyone who really wants to look at the config should use
the VIR_DOMAIN_XML_INACTIVE flag when calling virDomainGetXMLDesc().

As you would expect, a few months later (after the release of 1.2.4)
someone on IRC checked in with a problem caused by this change - they
had been using the portgroup name in the <source> element of the
interface to determine what action to take during migration; they didn't
even have any libvirt config stored in the portgroup, but were just
using its name as a tag. Since the portgroup name is only a part of the
<source> element when the interface is type='network', they now don't
have a tag in the xml to use for their decision (and since they aren't
explicitly calling virDomainGetXMLDesc() themselves, they can't simply
get the INACTIVE xml to solve their problem).

This use of a portgroup name struck me as potentially useful (although
it is a slight hijacking of the original intent of portgroups), so I
would like to restore that functionality. I came up with a couple
different ways to solve the problem, and am looking for opinions before
I spend any time on either.

Solution 1:

My initial thought was to just restore the portgroup name in the status
XML; that could be done by moving the portgroup name out of the
network-specific part of the object and into common data for all
interface types (this way it could show up in the <source> element no
matter what is the network type). However, once we've done that it
becomes enticing to allow specification of a portgroup even in cases
where the interface type != network; in those cases though, the
portgroup would be *only* a tag to be used by external entities; this
would lead to lax checking for existence of the specified portgroup, and
may end up with people misspelling a portgroup name, then mistakenly
believing that (e.g.) they had a bandwidth limit applied to a domain
interface when none was in fact in effect. (alternately, we could allow
it only if the interface *config* was for type='network', but that seems
somehow logically broken, and you can bet that eventually someone would
ask for us to allow it for all types)

Solution 2:

An alternate idea I had was to add a new <tag name='x'/> element to
interfaces, networks, and portgroups. An interface could have multiple
tags, and would assume the tags of its <network> when active. A <tag>
would be purely for use by external entities - it would mean nothing to
libvirt. For example, given this extreme example:

    <interface type='network'>
      <source network='mynet' portgroup='xyzzy'/>
      <tag name='wumpus'/>
      ...
    </interface>

    <network>
      <name>mynet</name>
      <tag name='twisty'/>
      <forward mode='bridge'/>\
      <bridge name='br0'/>
      <portgroup name='xyzzy'>
        <tag name='xyzzytag'/>
        <bandwidth>
          <inbound average='1000' peak='5000' floor='200' burst='1024'/>
          <outbound average='128' peak='256' burst='256'/>
        </bandwidth>
      </portgroup>
    </network>
   <network>

when the interface was active, its status xml would look like this:

    <interface type='bridge'>
      <tag name='wumpus'/>
      <tag name='twisty'/>
      <tag name='xyzzytag'/>
      <source bridge='br0'/>
      <bandwidth>
        <inbound average='1000' peak='5000' floor='200' burst='1024'/>
        <outbound average='128' peak='256' burst='256'/>
      </bandwidth>
      ...
    </interface>

These tags would mean nothing to libvirt, but would be available for
management applications to make decisions during domain
start/stop/migration/etc.

The advantages of solution 1 are that it is simpler, wouldn't require
any new XML elements, and any existing code using the portgroup name in
this manner would once again work (I don't know if anyone else uses it
this way).

The advantages of solution 2 are that it doesn't try to make a single
element work for two different functions which may not always mesh with
each other, and it allows for more than one tag per interface, so
different parts of a management application may use the tag element
without fear of breaking some other use. It may be a case of
over-engineering though :-)

So which should I do?




More information about the libvir-list mailing list