Re: [PATCH 1/3] lxc network configuration allows setting target container NIC name

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 02.07.2014 15:57, Cédric Bosdonnat wrote:
LXC network devices can now be assigned a custom NIC device name on the
container side. For example, this is configured with:

     <interface type='network'>
       <source network='default'/>
       <guest dev="eth1"/>
     </interface>

In this example the network card will appear as eth1 in the guest.
---
  docs/schemas/domaincommon.rng      | 17 +++++++++++++++++
  src/conf/domain_conf.c             | 27 +++++++++++++++++++++++++++
  src/conf/domain_conf.h             |  2 ++
  src/lxc/lxc_container.c            | 29 +++++++++++++++++++++++++----
  src/lxc/lxc_process.c              | 25 +++++++++++++++++++++++++
  tests/lxcxml2xmldata/lxc-idmap.xml |  1 +
  6 files changed, 97 insertions(+), 4 deletions(-)

The 3/3 should be merged with this so any element addition goes with RNG schema adjustment and is documented.


diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 33d0308..e7ca992 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2165,6 +2165,23 @@
          </element>
        </optional>
        <optional>
+        <element name="guest">
+          <interleave>
+            <optional>
+              <attribute name="dev">
+                <ref name="deviceName"/>
+              </attribute>
+            </optional>
+            <optional>
+              <attribute name="actual">
+                <ref name="deviceName"/>
+              </attribute>
+            </optional>
+          </interleave>
+          <empty/>
+        </element>
+      </optional>
+      <optional>
          <element name="mac">
            <attribute name="address">
              <ref name="uniMacAddr"/>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b7aa4f5..5cd6ae6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1383,6 +1383,8 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
      VIR_FREE(def->virtPortProfile);
      VIR_FREE(def->script);
      VIR_FREE(def->ifname);
+    VIR_FREE(def->ifname_guest);
+    VIR_FREE(def->ifname_guest_actual);

      virDomainDeviceInfoClear(&def->info);

@@ -6618,6 +6620,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
      char *bridge = NULL;
      char *dev = NULL;
      char *ifname = NULL;
+    char *ifname_guest = NULL;
+    char *ifname_guest_actual = NULL;
      char *script = NULL;
      char *address = NULL;
      char *port = NULL;
@@ -6723,6 +6727,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
                      /* An auto-generated target name, blank it out */
                      VIR_FREE(ifname);
                  }
+            } else if ((!ifname_guest || !ifname_guest_actual) &&
+                       xmlStrEqual(cur->name, BAD_CAST "guest")) {
+                ifname_guest = virXMLPropString(cur, "dev");
+                ifname_guest_actual = virXMLPropString(cur, "actual");
              } else if (!linkstate &&
                         xmlStrEqual(cur->name, BAD_CAST "link")) {
                  linkstate = virXMLPropString(cur, "state");
@@ -6964,6 +6972,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
          def->ifname = ifname;
          ifname = NULL;
      }
+    if (ifname_guest != NULL) {
+        def->ifname_guest = ifname_guest;
+        ifname_guest = NULL;
+    }
+    if (ifname_guest_actual != NULL) {
+        def->ifname_guest_actual = ifname_guest_actual;
+        ifname_guest_actual = NULL;
+    }

      /* NIC model (see -net nic,model=?).  We only check that it looks
       * reasonable, not that it is a supported NIC type.  FWIW kvm
@@ -15883,6 +15899,17 @@ virDomainNetDefFormat(virBufferPtr buf,
          /* Skip auto-generated target names for inactive config. */
          virBufferEscapeString(buf, "<target dev='%s'/>\n", def->ifname);
      }
+    if (def->ifname_guest || def->ifname_guest_actual) {
+        virBufferAddLit(buf, "<guest");
+        /* Skip auto-generated target names for inactive config. */
+        if (def->ifname_guest)
+            virBufferEscapeString(buf, " dev='%s'", def->ifname_guest);
+
+        /* Only set if the host is running, so shouldn't pollute output */
+        if (def->ifname_guest_actual)
+            virBufferEscapeString(buf, " actual='%s'", def->ifname_guest_actual);
+        virBufferAddLit(buf, "/>\n");
+    }
      if (def->model) {
          virBufferEscapeString(buf, "<model type='%s'/>\n",
                                def->model);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1122eb2..60aa491 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -915,6 +915,8 @@ struct _virDomainNetDef {
      } tune;
      char *script;
      char *ifname;
+    char *ifname_guest;
+    char *ifname_guest_actual;
      virDomainDeviceInfo info;
      char *filter;
      virNWFilterHashTablePtr filterparams;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index fd8ab16..c7423db 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -464,6 +464,21 @@ static int lxcContainerSetID(virDomainDefPtr def)
  }


+static virDomainNetDefPtr
+lxcContainerGetNetDef(virDomainDefPtr vmDef, const char *devName)
+{
+    size_t i;
+    virDomainNetDefPtr netDef;
+
+    for (i = 0; i < vmDef->nnets; i++) {
+        netDef = vmDef->nets[i];
+        if (STREQ(netDef->ifname_guest_actual, devName))
+            return netDef;
+    }
+
+    return NULL;
+}
+
  /**
   * lxcContainerRenameAndEnableInterfaces:
   * @nveths: number of interfaces
@@ -475,16 +490,23 @@ static int lxcContainerSetID(virDomainDefPtr def)
   *
   * Returns 0 on success or nonzero in case of error
   */
-static int lxcContainerRenameAndEnableInterfaces(bool privNet,
+static int lxcContainerRenameAndEnableInterfaces(virDomainDefPtr vmDef,
                                                   size_t nveths,
                                                   char **veths)
  {
      int rc = 0;
      size_t i;
      char *newname = NULL;
+    virDomainNetDefPtr netDef;
+    bool privNet = vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] ==
+                   VIR_DOMAIN_FEATURE_STATE_ON;

      for (i = 0; i < nveths; i++) {
-        if (virAsprintf(&newname, "eth%zu", i) < 0) {
+        if (!(netDef = lxcContainerGetNetDef(vmDef, veths[i])))
+            return -1;
+
+        newname = netDef->ifname_guest;
+        if (!newname) {
              rc = -1;
              goto error_out;
          }
@@ -1866,8 +1888,7 @@ static int lxcContainerChild(void *data)
      }

      /* rename and enable interfaces */
-    if (lxcContainerRenameAndEnableInterfaces(vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] ==
-                                              VIR_DOMAIN_FEATURE_STATE_ON,
+    if (lxcContainerRenameAndEnableInterfaces(vmDef,
                                                argv->nveths,
                                                argv->veths) < 0) {
          goto cleanup;
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 0aef13a..d532e20 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -259,6 +259,8 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,

      if (virNetDevSetMAC(containerVeth, &net->mac) < 0)
          goto cleanup;
+    if (VIR_STRDUP(net->ifname_guest_actual, containerVeth) < 0)
+        goto cleanup;

      if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
          if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac,
@@ -369,6 +371,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
  {
      int ret = -1;
      size_t i;
+    size_t niface = 0;

      for (i = 0; i < def->nnets; i++) {
          char *veth = NULL;
@@ -451,6 +454,13 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
          }

          (*veths)[(*nveths)-1] = veth;
+
+        /* Make sure all net definitions will have a name in the container */
+        if (!def->nets[i]->ifname_guest) {
+            if (virAsprintf(&def->nets[i]->ifname_guest, "eth%zu", niface) < 0)
+                return -1;
+            niface++;
+        }
      }

      ret = 0;
@@ -470,6 +480,18 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
      return ret;
  }

+static void
+virLXCProcessCleanInterfaces(virDomainDefPtr def)
+{
+    size_t i;
+
+    for (i = 0; i < def->nnets; i++) {
+        VIR_FREE(def->nets[i]->ifname_guest_actual);
+        def->nets[i]->ifname_guest_actual = NULL;

There's no need to set the @ifname_guest_actual to NULL, VIR_FREE() has already done that.

ACK with 3/3 squashed in.

Michal

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list





[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]