The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/5789

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
This PR modifies the network up hook to run for all p2p/bridged NICs so that the boot time nic host_name can be extracted from LXC and saved into volatile data.

This is then used for post-boot updates to p2p/bridged nics, such as static routes, and network limits.

Also removes unused `getHostInterface` function.
From e3ff176bc99a5c326740af263986820a0bc55295 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <[email protected]>
Date: Wed, 22 May 2019 17:26:39 +0100
Subject: [PATCH 1/4] test: Adds further p2p nic tests for various scenarios

Signed-off-by: Thomas Parrott <[email protected]>
---
 test/suites/container_devices_nic_p2p.sh | 137 +++++++++++++++++++++++
 1 file changed, 137 insertions(+)

diff --git a/test/suites/container_devices_nic_p2p.sh 
b/test/suites/container_devices_nic_p2p.sh
index 4c1c8deed0..a3f8b12b7e 100644
--- a/test/suites/container_devices_nic_p2p.sh
+++ b/test/suites/container_devices_nic_p2p.sh
@@ -190,6 +190,143 @@ test_container_devices_nic_p2p() {
   lxc launch testimage "${ctName}"
   lxc config device add "${ctName}" eth0 nic \
     nictype=p2p
+
+  # Now add some routes
+  lxc config device set "${ctName}" eth0 ipv4.routes "192.0.2.2${ipRand}/32"
+  lxc config device set "${ctName}" eth0 ipv6.routes "2001:db8::2${ipRand}/128"
+
+  # Check routes are applied on update. The host name is dynamic, so just 
check routes exist.
+  if ! ip -4 r list | grep "192.0.2.2${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ! ip -6 r list | grep "2001:db8::2${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Now update routes, check old routes go and new routes added.
+  lxc config device set "${ctName}" eth0 ipv4.routes "192.0.2.3${ipRand}/32"
+  lxc config device set "${ctName}" eth0 ipv6.routes "2001:db8::3${ipRand}/128"
+
+  # Check routes are applied on update. The host name is dynamic, so just 
check routes exist.
+  if ! ip -4 r list | grep "192.0.2.3${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ! ip -6 r list | grep "2001:db8::3${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Check old routes removed
+  if ip -4 r list | grep "192.0.2.2${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ip -6 r list | grep "2001:db8::2${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Now remove device, check routes go
   lxc config device remove "${ctName}" eth0
+
+  if ip -4 r list | grep "192.0.2.3${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ip -6 r list | grep "2001:db8::3${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Now add a nic to a stopped container with routes.
+  lxc stop "${ctName}"
+  lxc config device add "${ctName}" eth0 nic \
+    nictype=p2p \
+    ipv4.routes="192.0.2.2${ipRand}/32" \
+    ipv6.routes="2001:db8::2${ipRand}/128"
+
+  lxc start "${ctName}"
+
+  # Check routes are applied on start. The host name is dynamic, so just check 
routes exist.
+  if ! ip -4 r list | grep "192.0.2.2${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ! ip -6 r list | grep "2001:db8::2${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Now update routes on boot time nic, check old routes go and new routes 
added.
+  lxc config device set "${ctName}" eth0 ipv4.routes "192.0.2.3${ipRand}/32"
+  lxc config device set "${ctName}" eth0 ipv6.routes "2001:db8::3${ipRand}/128"
+
+  # Check routes are applied on update. The host name is dynamic, so just 
check routes exist.
+  if ! ip -4 r list | grep "192.0.2.3${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ! ip -6 r list | grep "2001:db8::3${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Check old routes removed
+  if ip -4 r list | grep "192.0.2.2${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ip -6 r list | grep "2001:db8::2${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Now remove boot time device
+  lxc config device remove "${ctName}" eth0
+
+  # Check old routes removed
+  if ip -4 r list | grep "192.0.2.3${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ip -6 r list | grep "2001:db8::3${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Add hot plug device with routes.
+  lxc config device add "${ctName}" eth0 nic \
+    nictype=p2p
+
+  # Now update routes on hotplug nic
+  lxc config device set "${ctName}" eth0 ipv4.routes "192.0.2.2${ipRand}/32"
+  lxc config device set "${ctName}" eth0 ipv6.routes "2001:db8::2${ipRand}/128"
+
+  # Check routes are applied. The host name is dynamic, so just check routes 
exist.
+  if ! ip -4 r list | grep "192.0.2.2${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ! ip -6 r list | grep "2001:db8::2${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
+  # Now remove hotplug device
+  lxc config device remove "${ctName}" eth0
+
+  # Check old routes removed
+  if ip -4 r list | grep "192.0.2.2${ipRand}" ; then
+    echo "ipv4.routes invalid"
+    false
+  fi
+  if ip -6 r list | grep "2001:db8::2${ipRand}" ; then
+    echo "ipv6.routes invalid"
+    false
+  fi
+
   lxc delete "${ctName}" -f
 }

From 96f32106de0f126f6cc8a77522ed5d51b0c8ba1b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <[email protected]>
Date: Wed, 22 May 2019 17:28:55 +0100
Subject: [PATCH 2/4] container/lxc: Runs network up hook for all p2p and
 bridged nics

This is so that host_name info can be recorded consistently on boot.

Signed-off-by: Thomas Parrott <[email protected]>
---
 lxd/container_lxc.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index f02567325d..8447283230 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1678,8 +1678,8 @@ func (c *containerLXC) initLXC(config bool) error {
                                }
                        }
 
-                       // Check if the container has network specific keys set 
to avoid unnecessarily running the network up hook.
-                       if shared.StringMapHasStringKey(m, 
containerNetworkKeys...) && shared.StringInSlice(m["nictype"], 
[]string{"bridged", "p2p"}) {
+                       // Run network up hook for bridged and p2p nics.
+                       if shared.StringInSlice(m["nictype"], 
[]string{"bridged", "p2p"}) {
                                err = lxcSetConfigItem(cc, 
fmt.Sprintf("%s.%d.script.up", networkKeyPrefix, networkidx), fmt.Sprintf("%s 
callhook %s %d network-up %s", c.state.OS.ExecPath, shared.VarPath(""), c.id, 
k))
                                if err != nil {
                                        return err

From eb7c7e26370dd25c9a33597a32fd38fdd495a536 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <[email protected]>
Date: Wed, 22 May 2019 17:30:29 +0100
Subject: [PATCH 3/4] container/lxc: Records host_name from LXC on p2p/bridged
 nic start

Records host_name for p2p/bridged nic start in volatile data and updates routes 
and limits settings to use them.

This allows consistent boot/add/remove/update fof p2p/bridged settings even on 
older kernels.

Signed-off-by: Thomas Parrott <[email protected]>
---
 lxd/container_lxc.go | 40 +++++++++++++++++++++++++++++++---------
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 8447283230..b78669841f 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -3173,7 +3173,7 @@ func (c *containerLXC) cleanupNetworkRoutes() error {
 
                // Remove any static veth routes
                if shared.StringInSlice(m["nictype"], []string{"bridged", 
"p2p"}) {
-                       c.removeNetworkRoutes(m)
+                       c.removeNetworkRoutes(k, m)
                }
 
        }
@@ -3184,7 +3184,23 @@ func (c *containerLXC) cleanupNetworkRoutes() error {
 // OnNetworkUp is called by the LXD callhook when the LXC network up script is 
run.
 func (c *containerLXC) OnNetworkUp(deviceName string, hostName string) error {
        device := c.expandedDevices[deviceName]
-       device["host_name"] = hostName
+
+       // This hook is only for bridged and p2p nics currently.
+       if !shared.StringInSlice(device["nictype"], []string{"bridged", "p2p"}) 
{
+               return nil
+       }
+
+       // Record boot time host name of nic into volatile for use with 
routes/limits updates later.
+       // Only need to do this if host_name is not specified in nic config.
+       if device["host_name"] == "" {
+               device["host_name"] = hostName
+               hostNameKey := fmt.Sprintf("volatile.%s.host_name", deviceName)
+               err := c.VolatileSet(map[string]string{hostNameKey: hostName})
+               if err != nil {
+                       return err
+               }
+       }
+
        return c.setupHostVethDevice(deviceName, device, types.Device{})
 }
 
@@ -3192,8 +3208,8 @@ func (c *containerLXC) OnNetworkUp(deviceName string, 
hostName string) error {
 func (c *containerLXC) setupHostVethDevice(deviceName string, device 
types.Device, oldDevice types.Device) error {
        // If not populated already, check if volatile data contains the most 
recently added host_name.
        if device["host_name"] == "" {
-               configKey := fmt.Sprintf("volatile.%s.host_name", deviceName)
-               device["host_name"] = c.localConfig[configKey]
+               hostNameKey := fmt.Sprintf("volatile.%s.host_name", deviceName)
+               device["host_name"] = c.localConfig[hostNameKey]
        }
 
        // Check whether host device resolution succeeded.
@@ -3208,7 +3224,7 @@ func (c *containerLXC) setupHostVethDevice(deviceName 
string, device types.Devic
        }
 
        // Setup static routes to container
-       err = c.setNetworkRoutes(device, oldDevice)
+       err = c.setNetworkRoutes(deviceName, device, oldDevice)
        if err != nil {
                return err
        }
@@ -8299,7 +8315,7 @@ func (c *containerLXC) removeNetworkDevice(name string, m 
types.Device) error {
 
        // Remove any static veth routes
        if shared.StringInSlice(m["nictype"], []string{"bridged", "p2p"}) {
-               c.removeNetworkRoutes(m)
+               c.removeNetworkRoutes(name, m)
        }
 
        // If a veth, destroy it
@@ -8852,13 +8868,13 @@ func (c *containerLXC) getHostInterface(name string) 
string {
 }
 
 // setNetworkRoutes applies any static routes configured from the host to the 
container nic.
-func (c *containerLXC) setNetworkRoutes(m types.Device, oldDevice 
types.Device) error {
+func (c *containerLXC) setNetworkRoutes(deviceName string, m types.Device, 
oldDevice types.Device) error {
        if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", m["host_name"])) 
{
                return fmt.Errorf("Unknown or missing host side veth: %s", 
m["host_name"])
        }
 
        // Remove any old routes that were setup for this nic device.
-       c.removeNetworkRoutes(oldDevice)
+       c.removeNetworkRoutes(deviceName, oldDevice)
 
        // Decide whether the route should point to the veth parent or the 
bridge parent
        routeDev := m["host_name"]
@@ -8893,7 +8909,13 @@ func (c *containerLXC) setNetworkRoutes(m types.Device, 
oldDevice types.Device)
 
 // removeNetworkRoutes removes any routes created for this device on the host 
that were first added
 // with setNetworkRoutes(). Expects to be passed the device config from the 
oldExpandedDevices.
-func (c *containerLXC) removeNetworkRoutes(m types.Device) {
+func (c *containerLXC) removeNetworkRoutes(deviceName string, m types.Device) {
+       // If not populated already, check if volatile data contains the most 
recently added host_name.
+       if m["host_name"] == "" {
+               hostNameKey := fmt.Sprintf("volatile.%s.host_name", deviceName)
+               m["host_name"] = c.localConfig[hostNameKey]
+       }
+
        // Decide whether the route should point to the veth parent or the 
bridge parent
        routeDev := m["host_name"]
        if m["nictype"] == "bridged" {

From 7ab1162fb8cfef3a7d3241696ee0f806f20ba656 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <[email protected]>
Date: Wed, 22 May 2019 17:32:05 +0100
Subject: [PATCH 4/4] lxc/container: Removes unused getHostInterface()

Signed-off-by: Thomas Parrott <[email protected]>
---
 lxd/container_lxc.go | 50 --------------------------------------------
 1 file changed, 50 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index b78669841f..93e255d162 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -8817,56 +8817,6 @@ func (c *containerLXC) setNetworkPriority() error {
        return nil
 }
 
-func (c *containerLXC) getHostInterface(name string) string {
-       // Pull directly from kernel
-       networks := c.networkState()
-       if networks[name].HostName != "" {
-               return networks[name].HostName
-       }
-
-       // Fallback to poking LXC
-       if c.IsRunning() {
-               networkKeyPrefix := "lxc.net"
-               if !util.RuntimeLiblxcVersionAtLeast(2, 1, 0) {
-                       networkKeyPrefix = "lxc.network"
-               }
-
-               for i := 0; i < len(c.c.ConfigItem(networkKeyPrefix)); i++ {
-                       nicName := 
c.c.RunningConfigItem(fmt.Sprintf("%s.%d.name", networkKeyPrefix, i))[0]
-                       if nicName != name {
-                               continue
-                       }
-
-                       veth := 
c.c.RunningConfigItem(fmt.Sprintf("%s.%d.veth.pair", networkKeyPrefix, i))[0]
-                       if veth != "" {
-                               return veth
-                       }
-               }
-       }
-
-       // Fallback to parsing LXD config
-       for _, k := range c.expandedDevices.DeviceNames() {
-               dev := c.expandedDevices[k]
-               if dev["type"] != "nic" && dev["type"] != "infiniband" {
-                       continue
-               }
-
-               m, err := c.fillNetworkDevice(k, dev)
-               if err != nil {
-                       m = dev
-               }
-
-               if m["name"] != name {
-                       continue
-               }
-
-               return m["host_name"]
-       }
-
-       // Fail
-       return ""
-}
-
 // setNetworkRoutes applies any static routes configured from the host to the 
container nic.
 func (c *containerLXC) setNetworkRoutes(deviceName string, m types.Device, 
oldDevice types.Device) error {
        if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", m["host_name"])) 
{
_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to