The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3733
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) ===
From 8ff709a719d092dc624b5f090cb30f35bfc6a8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]> Date: Mon, 28 Aug 2017 17:47:44 -0400 Subject: [PATCH 1/2] network: Allow for duplicate IPs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #3721 Signed-off-by: Stéphane Graber <[email protected]> --- lxd/container_lxc.go | 6 +-- lxd/networks.go | 2 +- lxd/networks_utils.go | 121 +++++++++++++++++++++++++++++--------------------- 3 files changed, 75 insertions(+), 54 deletions(-) diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index 5779dc179..1be813345 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -399,7 +399,7 @@ func containerLXCCreate(s *state.State, args db.ContainerArgs) (container, error } // Update lease files - networkUpdateStatic(s, "", c.name) + networkUpdateStatic(s, "") logger.Info("Created container", ctxMap) @@ -2879,7 +2879,7 @@ func (c *containerLXC) Delete() error { } // Update network files - networkUpdateStatic(c.state, "", c.name) + networkUpdateStatic(c.state, "") for k, m := range c.expandedDevices { if m["type"] != "nic" || m["nictype"] != "bridged" || (m["ipv4.address"] == "" && m["ipv6.address"] == "") { continue @@ -4073,7 +4073,7 @@ func (c *containerLXC) Update(args db.ContainerArgs, userRequested bool) error { } if needsUpdate { - networkUpdateStatic(c.state, "", c.name) + networkUpdateStatic(c.state, "") } // Success, update the closure to mark that the changes should be kept. diff --git a/lxd/networks.go b/lxd/networks.go index de0b7d840..4b36d981d 100644 --- a/lxd/networks.go +++ b/lxd/networks.go @@ -1235,7 +1235,7 @@ func (n *network) Start() error { } // Update the static leases - err = networkUpdateStatic(n.state, n.name, "") + err = networkUpdateStatic(n.state, n.name) if err != nil { return err } diff --git a/lxd/networks_utils.go b/lxd/networks_utils.go index 6022efd7d..37ab63d83 100644 --- a/lxd/networks_utils.go +++ b/lxd/networks_utils.go @@ -23,8 +23,11 @@ import ( "github.com/lxc/lxd/lxd/db" "github.com/lxc/lxd/lxd/state" "github.com/lxc/lxd/shared" + "github.com/lxc/lxd/shared/logger" ) +var networkStaticLock sync.Mutex + func networkAutoAttach(dbObj *sql.DB, devName string) error { _, dbInfo, err := db.NetworkGetInterface(dbObj, devName) if err != nil { @@ -724,17 +727,15 @@ func networkKillDnsmasq(name string, reload bool) error { return nil } -func networkUpdateStatic(s *state.State, networkName string, containerName string) error { +func networkUpdateStatic(s *state.State, networkName string) error { + // We don't want to race with ourselves here + networkStaticLock.Lock() + defer networkStaticLock.Unlock() + // Get all the containers - containers := []string{} - if containerName == "" { - var err error - containers, err = db.ContainersList(s.DB, db.CTypeRegular) - if err != nil { - return err - } - } else { - containers = []string{containerName} + containers, err := db.ContainersList(s.DB, db.CTypeRegular) + if err != nil { + return err } // Get all the networks @@ -796,61 +797,81 @@ func networkUpdateStatic(s *state.State, networkName string, containerName strin } config := n.Config() - // Clean everything up on resets - if containerName == "" { - // Wipe everything clean - entries, err := ioutil.ReadDir(shared.VarPath("networks", network, "dnsmasq.hosts")) + // Wipe everything clean + files, err := ioutil.ReadDir(shared.VarPath("networks", network, "dnsmasq.hosts")) + if err != nil { + return err + } + + for _, entry := range files { + err = os.Remove(shared.VarPath("networks", network, "dnsmasq.hosts", entry.Name())) if err != nil { return err } - - for _, entry := range entries { - err = os.Remove(shared.VarPath("networks", network, "dnsmasq.hosts", entry.Name())) - if err != nil { - return err - } - } } - if containerName != "" && len(entries) == 0 { - // Wipe the one container clean - if shared.PathExists(shared.VarPath("networks", network, "dnsmasq.hosts", containerName)) { - err = os.Remove(shared.VarPath("networks", network, "dnsmasq.hosts", containerName)) - if err != nil { - return err - } - } - } else { - // Apply the changes - for _, entry := range entries { - hwaddr := entry[0] - cName := entry[1] - ipv4Address := entry[2] - ipv6Address := entry[3] - - line := hwaddr + // Apply the changes + for entryIdx, entry := range entries { + hwaddr := entry[0] + cName := entry[1] + ipv4Address := entry[2] + ipv6Address := entry[3] + line := hwaddr - if ipv4Address != "" { - line += fmt.Sprintf(",%s", ipv4Address) - } - - if ipv6Address != "" { - line += fmt.Sprintf(",[%s]", ipv6Address) + // Look for duplicates + duplicate := false + for iIdx, i := range entries { + if entry[1] == i[1] { + // Skip ourselves + continue } - if config["dns.mode"] == "" || config["dns.mode"] == "managed" { - line += fmt.Sprintf(",%s", cName) + if entry[0] == i[0] { + // Find broken configurations + logger.Errorf("Duplicate MAC detected: %s and %s", entry[1], i[1]) } - if line == hwaddr { + if i[2] == "" && i[3] == "" { + // Skip unconfigured continue } - err := ioutil.WriteFile(shared.VarPath("networks", network, "dnsmasq.hosts", cName), []byte(line+"\n"), 0644) - if err != nil { - return err + if entry[2] == i[2] && entry[3] == i[3] { + // Find identical containers (copies with static configuration) + if entryIdx > iIdx { + duplicate = true + } else { + line = fmt.Sprintf("%s,%s", line, i[0]) + logger.Debugf("Found containers with duplicate IPv4/IPv6: %s and %s", entry[1], i[1]) + } } } + + if duplicate { + continue + } + + // Generate the dhcp-host line + if ipv4Address != "" { + line += fmt.Sprintf(",%s", ipv4Address) + } + + if ipv6Address != "" { + line += fmt.Sprintf(",[%s]", ipv6Address) + } + + if config["dns.mode"] == "" || config["dns.mode"] == "managed" { + line += fmt.Sprintf(",%s", cName) + } + + if line == hwaddr { + continue + } + + err := ioutil.WriteFile(shared.VarPath("networks", network, "dnsmasq.hosts", cName), []byte(line+"\n"), 0644) + if err != nil { + return err + } } // Signal dnsmasq From 54577b8bf651f4b3e860581c3a9a3ab73bb8ef60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]> Date: Mon, 28 Aug 2017 18:12:30 -0400 Subject: [PATCH 2/2] network: Fix bridging devies with IPv6 link-local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #3727 Closes #3728 Signed-off-by: Stéphane Graber <[email protected]> --- lxd/networks.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lxd/networks.go b/lxd/networks.go index 4b36d981d..a34e6ba27 100644 --- a/lxd/networks.go +++ b/lxd/networks.go @@ -665,8 +665,19 @@ func (n *network) Start() error { continue } + unused := true addrs, err := iface.Addrs() - if err == nil && len(addrs) != 0 { + if err == nil { + for _, addr := range addrs { + ip, _, err := net.ParseCIDR(addr.String()) + if ip != nil && err == nil && ip.IsGlobalUnicast() { + unused = false + break + } + } + } + + if !unused { return fmt.Errorf("Only unconfigured network interfaces can be bridged") }
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
