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

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) ===
- Moving common functionality out of bridge driver and into common driver.
- Adds contextual logging support.
From 5f847ad62238eb7b57c7e491f520c42d1347d719 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 16 Jul 2020 10:54:44 +0100
Subject: [PATCH 1/5] lxd/network/driver/common: Adds config different and db
 update common functions

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/network/driver_common.go | 82 ++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/lxd/network/driver_common.go b/lxd/network/driver_common.go
index 85d06a52d3..7889711489 100644
--- a/lxd/network/driver_common.go
+++ b/lxd/network/driver_common.go
@@ -7,9 +7,12 @@ import (
 
        "github.com/pkg/errors"
 
+       lxd "github.com/lxc/lxd/client"
+       "github.com/lxc/lxd/lxd/cluster"
        "github.com/lxc/lxd/lxd/instance"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/api"
 )
 
 // DHCPRange represents a range of IPs from start to end.
@@ -177,3 +180,82 @@ func (n *common) DHCPv6Ranges() []DHCPRange {
 
        return dhcpRanges
 }
+
+// update applies network config to all nodes and database config (if notify 
true), and updates internal config.
+func (n *common) update(applyNetwork api.NetworkPut, notify bool) error {
+       // Notify all nodes and update the database.
+       if !notify {
+               // Notify all other nodes to update the network.
+               notifier, err := cluster.NewNotifier(n.state, 
n.state.Endpoints.NetworkCert(), cluster.NotifyAll)
+               if err != nil {
+                       return err
+               }
+
+               err = notifier(func(client lxd.InstanceServer) error {
+                       return client.UpdateNetwork(n.name, applyNetwork, "")
+               })
+               if err != nil {
+                       return err
+               }
+
+               // Update the database.
+               err = n.state.Cluster.UpdateNetwork(n.name, 
applyNetwork.Description, applyNetwork.Config)
+               if err != nil {
+                       return err
+               }
+       }
+
+       // Update internal config after database has been updated.
+       n.description = applyNetwork.Description
+       n.config = applyNetwork.Config
+
+       return nil
+}
+
+// configChanged compares supplied new config with existing config. Returns a 
boolean indicating if differences in
+// the config or description were found (and the database record needs 
updating), and a list of non-user config
+// keys that have changed, and a copy of the current internal network config 
that can be used to revert if needed.
+func (n *common) configChanged(newNetwork api.NetworkPut) (bool, []string, 
api.NetworkPut, error) {
+       // Backup the current state.
+       oldNetwork := api.NetworkPut{
+               Description: n.description,
+               Config:      map[string]string{},
+       }
+
+       err := shared.DeepCopy(&n.config, &oldNetwork.Config)
+       if err != nil {
+               return false, nil, oldNetwork, err
+       }
+
+       // Diff the configurations.
+       changedKeys := []string{}
+       dbUpdateNeeded := false
+
+       if newNetwork.Description != n.description {
+               dbUpdateNeeded = true
+       }
+
+       for k, v := range oldNetwork.Config {
+               if v != newNetwork.Config[k] {
+                       dbUpdateNeeded = true
+
+                       // Add non-user changed key to list of changed keys.
+                       if !strings.HasPrefix(k, "user.") && 
!shared.StringInSlice(k, changedKeys) {
+                               changedKeys = append(changedKeys, k)
+                       }
+               }
+       }
+
+       for k, v := range newNetwork.Config {
+               if v != oldNetwork.Config[k] {
+                       dbUpdateNeeded = true
+
+                       // Add non-user changed key to list of changed keys.
+                       if !strings.HasPrefix(k, "user.") && 
!shared.StringInSlice(k, changedKeys) {
+                               changedKeys = append(changedKeys, k)
+                       }
+               }
+       }
+
+       return dbUpdateNeeded, changedKeys, oldNetwork, nil
+}

From 9cb0b59f653bcaf2ac25b126121980ee9670f00c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 16 Jul 2020 10:55:52 +0100
Subject: [PATCH 2/5] lxd/network/driver/common: Adds contextual logger

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/network/driver_common.go | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lxd/network/driver_common.go b/lxd/network/driver_common.go
index 7889711489..63fe54812b 100644
--- a/lxd/network/driver_common.go
+++ b/lxd/network/driver_common.go
@@ -13,6 +13,9 @@ import (
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       log "github.com/lxc/lxd/shared/log15"
+       "github.com/lxc/lxd/shared/logger"
+       "github.com/lxc/lxd/shared/logging"
 )
 
 // DHCPRange represents a range of IPs from start to end.
@@ -23,19 +26,18 @@ type DHCPRange struct {
 
 // common represents a generic LXD network.
 type common struct {
-       // Properties
+       logger      logger.Logger
        state       *state.State
        id          int64
        name        string
        netType     string
        description string
-
-       // config
-       config map[string]string
+       config      map[string]string
 }
 
 // init initialise internal variables.
 func (n *common) init(state *state.State, id int64, name string, netType 
string, description string, config map[string]string) {
+       n.logger = logging.AddContext(logger.Log, log.Ctx{"driver": netType, 
"network": name})
        n.id = id
        n.name = name
        n.netType = netType

From 9846dc72faf7ce652957e8f6b2c24aa2848abb19 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 16 Jul 2020 10:56:57 +0100
Subject: [PATCH 3/5] lxd/network/driver/bridge: Simplifies Update function to
 use common update functions

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/network/driver_bridge.go | 144 ++++++++++-------------------------
 1 file changed, 41 insertions(+), 103 deletions(-)

diff --git a/lxd/network/driver_bridge.go b/lxd/network/driver_bridge.go
index 2d9088fc4e..0600d6fe9d 100644
--- a/lxd/network/driver_bridge.go
+++ b/lxd/network/driver_bridge.go
@@ -15,11 +15,11 @@ import (
 
        "github.com/pkg/errors"
 
-       lxd "github.com/lxc/lxd/client"
        "github.com/lxc/lxd/lxd/cluster"
        "github.com/lxc/lxd/lxd/daemon"
        "github.com/lxc/lxd/lxd/dnsmasq"
        "github.com/lxc/lxd/lxd/node"
+       "github.com/lxc/lxd/lxd/revert"
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
@@ -1292,136 +1292,74 @@ func (n *bridge) Update(newNetwork api.NetworkPut, 
notify bool) error {
        if err != nil {
                return err
        }
-       newConfig := newNetwork.Config
 
-       // Backup the current state
-       oldConfig := map[string]string{}
-       oldDescription := n.description
-       err = shared.DeepCopy(&n.config, &oldConfig)
+       dbUpdateNeeeded, changedKeys, oldNetwork, err := 
n.common.configChanged(newNetwork)
        if err != nil {
                return err
        }
 
-       // Define a function which reverts everything.  Defer this function
-       // so that it doesn't need to be explicitly called in every failing
-       // return path.  Track whether or not we want to undo the changes
-       // using a closure.
-       undoChanges := true
-       defer func() {
-               if undoChanges {
-                       // Revert changes to the struct
-                       n.config = oldConfig
-                       n.description = oldDescription
+       if !dbUpdateNeeeded {
+               return nil // Nothing changed.
+       }
 
-                       // Update the database
-                       n.state.Cluster.UpdateNetwork(n.name, n.description, 
n.config)
+       revert := revert.New()
+       defer revert.Fail()
 
-                       // Reset any change that was made to the bridge
-                       n.setup(newConfig)
-               }
-       }()
+       // Define a function which reverts everything.
+       revert.Add(func() {
+               // Reset changes to all nodes and database.
+               n.common.update(oldNetwork, notify)
 
-       // Diff the configurations
-       changedConfig := []string{}
-       userOnly := true
-       for key := range oldConfig {
-               if oldConfig[key] != newConfig[key] {
-                       if !strings.HasPrefix(key, "user.") {
-                               userOnly = false
-                       }
+               // Reset any change that was made to local bridge.
+               n.setup(newNetwork.Config)
+       })
 
-                       if !shared.StringInSlice(key, changedConfig) {
-                               changedConfig = append(changedConfig, key)
-                       }
-               }
-       }
-
-       for key := range newConfig {
-               if oldConfig[key] != newConfig[key] {
-                       if !strings.HasPrefix(key, "user.") {
-                               userOnly = false
-                       }
-
-                       if !shared.StringInSlice(key, changedConfig) {
-                               changedConfig = append(changedConfig, key)
-                       }
+       // Bring the bridge down entirely if the driver has changed.
+       if shared.StringInSlice("bridge.driver", changedKeys) && n.isRunning() {
+               err = n.Stop()
+               if err != nil {
+                       return err
                }
        }
 
-       // Skip on no change
-       if len(changedConfig) == 0 && newNetwork.Description == n.description {
-               return nil
-       }
-
-       // Update the network
-       if !userOnly {
-               if shared.StringInSlice("bridge.driver", changedConfig) && 
n.isRunning() {
-                       err = n.Stop()
-                       if err != nil {
-                               return err
-                       }
+       // Detach any external interfaces should no longer be attached.
+       if shared.StringInSlice("bridge.external_interfaces", changedKeys) && 
n.isRunning() {
+               devices := []string{}
+               for _, dev := range 
strings.Split(newNetwork.Config["bridge.external_interfaces"], ",") {
+                       dev = strings.TrimSpace(dev)
+                       devices = append(devices, dev)
                }
 
-               if shared.StringInSlice("bridge.external_interfaces", 
changedConfig) && n.isRunning() {
-                       devices := []string{}
-                       for _, dev := range 
strings.Split(newConfig["bridge.external_interfaces"], ",") {
-                               dev = strings.TrimSpace(dev)
-                               devices = append(devices, dev)
+               for _, dev := range 
strings.Split(oldNetwork.Config["bridge.external_interfaces"], ",") {
+                       dev = strings.TrimSpace(dev)
+                       if dev == "" {
+                               continue
                        }
 
-                       for _, dev := range 
strings.Split(oldConfig["bridge.external_interfaces"], ",") {
-                               dev = strings.TrimSpace(dev)
-                               if dev == "" {
-                                       continue
-                               }
-
-                               if !shared.StringInSlice(dev, devices) && 
shared.PathExists(fmt.Sprintf("/sys/class/net/%s", dev)) {
-                                       err = DetachInterface(n.name, dev)
-                                       if err != nil {
-                                               return err
-                                       }
+                       if !shared.StringInSlice(dev, devices) && 
shared.PathExists(fmt.Sprintf("/sys/class/net/%s", dev)) {
+                               err = DetachInterface(n.name, dev)
+                               if err != nil {
+                                       return err
                                }
                        }
                }
        }
 
-       // Apply changes
-       n.config = newConfig
-       n.description = newNetwork.Description
-
-       // Update the database
-       if !notify {
-               // Notify all other nodes to update the network.
-               notifier, err := cluster.NewNotifier(n.state, 
n.state.Endpoints.NetworkCert(), cluster.NotifyAll)
-               if err != nil {
-                       return err
-               }
-
-               err = notifier(func(client lxd.InstanceServer) error {
-                       return client.UpdateNetwork(n.name, newNetwork, "")
-               })
-               if err != nil {
-                       return err
-               }
-
-               // Update the database.
-               err = n.state.Cluster.UpdateNetwork(n.name, n.description, 
n.config)
-               if err != nil {
-                       return err
-               }
+       // Apply changes to database.
+       err = n.common.update(newNetwork, notify)
+       if err != nil {
+               return err
        }
 
-       // Restart the network
-       if !userOnly {
-               err = n.setup(oldConfig)
+       // Restart the network if needed.
+       if len(changedKeys) > 0 {
+               err = n.setup(oldNetwork.Config)
                if err != nil {
                        return err
                }
        }
 
-       // Success, update the closure to mark that the changes should be kept.
-       undoChanges = false
-
+       revert.Success()
        return nil
 }
 

From ea06a613dba726eecd0d746ca2e0416820b3775a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 16 Jul 2020 10:57:24 +0100
Subject: [PATCH 4/5] lxd/network/driver/bridge: Updates to use contextual
 logger

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/network/driver_bridge.go | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/lxd/network/driver_bridge.go b/lxd/network/driver_bridge.go
index 0600d6fe9d..5052ed645e 100644
--- a/lxd/network/driver_bridge.go
+++ b/lxd/network/driver_bridge.go
@@ -24,7 +24,6 @@ import (
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        log "github.com/lxc/lxd/shared/log15"
-       "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/subprocess"
        "github.com/lxc/lxd/shared/version"
 )
@@ -328,6 +327,8 @@ func (n *bridge) setup(oldConfig map[string]string) error {
                return nil
        }
 
+       n.logger.Debug("Setting up network")
+
        // Create directory
        if !shared.PathExists(shared.VarPath("networks", n.name)) {
                err := os.MkdirAll(shared.VarPath("networks", n.name), 0711)
@@ -439,13 +440,13 @@ func (n *bridge) setup(oldConfig map[string]string) error 
{
        if n.config["bridge.driver"] != "openvswitch" {
                err = BridgeVLANFilterSetStatus(n.name, "1")
                if err != nil {
-                       logger.Warnf("%v", err)
+                       n.logger.Warn(fmt.Sprintf("%v", err))
                }
 
                // Set the default PVID for new ports to 1.
                err = BridgeVLANSetDefaultPVID(n.name, "1")
                if err != nil {
-                       logger.Warnf("%v", err)
+                       n.logger.Warn(fmt.Sprintf("%v", err))
                }
        }
 
@@ -461,6 +462,7 @@ func (n *bridge) setup(oldConfig map[string]string) error {
                        entry = strings.TrimSpace(entry)
                        iface, err := net.InterfaceByName(entry)
                        if err != nil {
+                               n.logger.Warn("Skipping attaching missing 
external interface", log.Ctx{"interface": entry})
                                continue
                        }
 
@@ -711,7 +713,7 @@ func (n *bridge) setup(oldConfig map[string]string) error {
                subnetSize, _ := subnet.Mask.Size()
 
                if subnetSize > 64 {
-                       logger.Warn("IPv6 networks with a prefix larger than 64 
aren't properly supported by dnsmasq", log.Ctx{"network": n.name})
+                       n.logger.Warn("IPv6 networks with a prefix larger than 
64 aren't properly supported by dnsmasq")
                }
 
                // Update the dnsmasq config
@@ -1412,7 +1414,7 @@ func (n *bridge) HandleHeartbeat(heartbeatData 
*cluster.APIHeartbeat) error {
                return err
        }
 
-       logger.Infof("Refreshing forkdns peers for %v", n.name)
+       n.logger.Info("Refreshing forkdns peers")
 
        cert := n.state.Endpoints.NetworkCert()
        for _, node := range heartbeatData.Members {
@@ -1446,7 +1448,7 @@ func (n *bridge) HandleHeartbeat(heartbeatData 
*cluster.APIHeartbeat) error {
        curList, err := ForkdnsServersList(n.name)
        if err != nil {
                // Only warn here, but continue on to regenerate the servers 
list from cluster info.
-               logger.Warnf("Failed to load existing forkdns server list: %v", 
err)
+               n.logger.Warn("Failed to load existing forkdns server list", 
log.Ctx{"err": err})
        }
 
        // If current list is same as cluster list, nothing to do.
@@ -1459,7 +1461,7 @@ func (n *bridge) HandleHeartbeat(heartbeatData 
*cluster.APIHeartbeat) error {
                return err
        }
 
-       logger.Infof("Updated forkdns server list for '%s': %v", n.name, 
addresses)
+       n.logger.Info("Updated forkdns server list", log.Ctx{"nodes": 
addresses})
        return nil
 }
 

From e8f9c948bbb35f3ddb77e75d6f333350dead64c4 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 16 Jul 2020 10:58:37 +0100
Subject: [PATCH 5/5] lxd/network/driver/common: Removes stuttering on "common"
 in validation rules function

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/network/driver_common.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lxd/network/driver_common.go b/lxd/network/driver_common.go
index 63fe54812b..9e8762ca58 100644
--- a/lxd/network/driver_common.go
+++ b/lxd/network/driver_common.go
@@ -46,8 +46,8 @@ func (n *common) init(state *state.State, id int64, name 
string, netType string,
        n.description = description
 }
 
-// commonRules returns a map of config rules common to all drivers.
-func (n *common) commonRules() map[string]func(string) error {
+// validationRules returns a map of config rules common to all drivers.
+func (n *common) validationRules() map[string]func(string) error {
        return map[string]func(string) error{}
 }
 
@@ -56,7 +56,7 @@ func (n *common) validate(config map[string]string, 
driverRules map[string]func(
        checkedFields := map[string]struct{}{}
 
        // Get rules common for all drivers.
-       rules := n.commonRules()
+       rules := n.validationRules()
 
        // Merge driver specific rules into common rules.
        for field, validator := range driverRules {
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to