Merge pull request #1095 from mrjana/ipam
Remove all netlink/osl deps from ipam/ipamutils
This commit is contained in:
commit
c891a47cb3
21 changed files with 272 additions and 254 deletions
|
@ -29,8 +29,8 @@ import (
|
|||
"github.com/docker/libnetwork/config"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/gorilla/mux"
|
||||
|
@ -429,7 +429,7 @@ func encodeData(data interface{}) (*bytes.Buffer, error) {
|
|||
}
|
||||
|
||||
func ipamOption(bridgeName string) libnetwork.NetworkOption {
|
||||
if nw, _, err := ipamutils.ElectInterfaceAddresses(bridgeName); err == nil {
|
||||
if nw, _, err := netutils.ElectInterfaceAddresses(bridgeName); err == nil {
|
||||
ipamV4Conf := &libnetwork.IpamConf{PreferredPool: nw.String()}
|
||||
hip, _ := types.GetHostPartIP(nw.IP, nw.Mask)
|
||||
if hip.IsGlobalUnicast() {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
|
@ -21,7 +22,7 @@ func init() {
|
|||
|
||||
func getIPv4Data(t *testing.T) []driverapi.IPAMData {
|
||||
ipd := driverapi.IPAMData{AddressSpace: "full"}
|
||||
nw, _, err := ipamutils.ElectInterfaceAddresses("")
|
||||
nw, _, err := netutils.ElectInterfaceAddresses("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -401,13 +401,6 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
|
|||
}
|
||||
|
||||
if !aSpace.contains(as, nw) {
|
||||
if as == localAddressSpace {
|
||||
// Check if nw overlap with system routes, name servers
|
||||
if _, err := ipamutils.FindAvailableNetwork([]*net.IPNet{nw}); err == nil {
|
||||
return nw, nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nw, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -453,27 +453,11 @@ func TestPredefinedPool(t *testing.T) {
|
|||
t.Fatalf("Expected failure for non default addr space")
|
||||
}
|
||||
|
||||
exp, err := ipamutils.FindAvailableNetwork(a.predefined[localAddressSpace])
|
||||
pid, nw, _, err := a.RequestPool(localAddressSpace, "", "", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nw, err := a.getPredefinedPool(localAddressSpace, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(nw, exp) {
|
||||
t.Fatalf("Unexpected default network returned: %s. Expected: %s", nw, exp)
|
||||
}
|
||||
|
||||
pid, nw, _, err := a.RequestPool(localAddressSpace, exp.String(), "", nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(nw, exp) {
|
||||
t.Fatalf("Unexpected default network returned: %s. Expected: %s", nw, exp)
|
||||
}
|
||||
|
||||
nw2, err := a.getPredefinedPool(localAddressSpace, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -485,14 +469,6 @@ func TestPredefinedPool(t *testing.T) {
|
|||
if err := a.ReleasePool(pid); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nw, err = a.getPredefinedPool(localAddressSpace, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(nw, exp) {
|
||||
t.Fatalf("Unexpected default network returned: %s. Expected %s", nw, exp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveSubnet(t *testing.T) {
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
// Package ipamutils provides utililty functions for ipam management
|
||||
package ipamutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/resolvconf"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// ElectInterfaceAddresses looks for an interface on the OS with the specified name
|
||||
// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist,
|
||||
// it chooses from a predifined list the first IPv4 address which does not conflict
|
||||
// with other interfaces on the system.
|
||||
func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
||||
var (
|
||||
v4Net *net.IPNet
|
||||
v6Nets []*net.IPNet
|
||||
err error
|
||||
)
|
||||
|
||||
InitNetworks()
|
||||
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
link, _ := netlink.LinkByName(name)
|
||||
if link != nil {
|
||||
v4addr, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
v6addr, err := netlink.AddrList(link, netlink.FAMILY_V6)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(v4addr) > 0 {
|
||||
v4Net = v4addr[0].IPNet
|
||||
}
|
||||
for _, nlAddr := range v6addr {
|
||||
v6Nets = append(v6Nets, nlAddr.IPNet)
|
||||
}
|
||||
}
|
||||
|
||||
if link == nil || v4Net == nil {
|
||||
// Choose from predifined broad networks
|
||||
v4Net, err = FindAvailableNetwork(PredefinedBroadNetworks)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return v4Net, v6Nets, nil
|
||||
}
|
||||
|
||||
// FindAvailableNetwork returns a network from the passed list which does not
|
||||
// overlap with existing interfaces in the system
|
||||
func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
|
||||
// We don't check for an error here, because we don't really care if we
|
||||
// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
|
||||
// is nil. It either doesn't exist, or we can't read it for some reason.
|
||||
var nameservers []string
|
||||
if rc, err := resolvconf.Get(); err == nil {
|
||||
nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
|
||||
}
|
||||
for _, nw := range list {
|
||||
if err := netutils.CheckNameserverOverlaps(nameservers, nw); err == nil {
|
||||
if err := netutils.CheckRouteOverlaps(nw); err == nil {
|
||||
return nw, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no available network")
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
package ipamutils
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
_ "github.com/docker/libnetwork/testutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -27,91 +24,3 @@ func TestGranularPredefined(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNetworkRequest(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
_, exp, err := net.ParseCIDR("172.17.0.0/16")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nw, err := FindAvailableNetwork(PredefinedBroadNetworks)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(exp, nw) {
|
||||
t.Fatalf("exected %s. got %s", exp, nw)
|
||||
}
|
||||
|
||||
_, exp, err = net.ParseCIDR("10.0.0.0/24")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
nw, err = FindAvailableNetwork(PredefinedGranularNetworks)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(exp, nw) {
|
||||
t.Fatalf("exected %s. got %s", exp, nw)
|
||||
}
|
||||
|
||||
// Add iface and ssert returned address on request
|
||||
createInterface(t, "test", "172.17.42.1/16")
|
||||
|
||||
_, exp, err = net.ParseCIDR("172.18.0.0/16")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
nw, err = FindAvailableNetwork(PredefinedBroadNetworks)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(exp, nw) {
|
||||
t.Fatalf("exected %s. got %s", exp, nw)
|
||||
}
|
||||
}
|
||||
|
||||
func TestElectInterfaceAddress(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
nws := "172.101.202.254/16"
|
||||
createInterface(t, "test", nws)
|
||||
|
||||
ipv4Nw, ipv6Nw, err := ElectInterfaceAddresses("test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ipv4Nw == nil {
|
||||
t.Fatalf("unexpected empty ipv4 network addresses")
|
||||
}
|
||||
|
||||
if len(ipv6Nw) == 0 {
|
||||
t.Fatalf("unexpected empty ipv4 network addresses")
|
||||
}
|
||||
|
||||
if nws != ipv4Nw.String() {
|
||||
t.Fatalf("expected %s. got %s", nws, ipv4Nw)
|
||||
}
|
||||
}
|
||||
|
||||
func createInterface(t *testing.T, name, nw string) {
|
||||
// Add interface
|
||||
link := &netlink.Bridge{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: "test",
|
||||
},
|
||||
}
|
||||
bip, err := types.ParseCIDR(nw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = netlink.LinkAdd(link); err != nil {
|
||||
t.Fatalf("Failed to create interface via netlink: %v", err)
|
||||
}
|
||||
if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: bip}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = netlink.LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,6 @@ import (
|
|||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
// constants for the IP address type
|
||||
const (
|
||||
IP = iota // IPv4 and IPv6
|
||||
IPv4
|
||||
IPv6
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNetworkOverlapsWithNameservers preformatted error
|
||||
ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// Package ipamutils provides utililty functions for ipam management
|
||||
package ipamutils
|
||||
package netutils
|
||||
|
||||
import (
|
||||
"net"
|
|
@ -4,9 +4,13 @@
|
|||
package netutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/resolvconf"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
@ -48,3 +52,66 @@ func GenerateIfaceName(prefix string, len int) (string, error) {
|
|||
}
|
||||
return "", types.InternalErrorf("could not generate interface name")
|
||||
}
|
||||
|
||||
// ElectInterfaceAddresses looks for an interface on the OS with the
|
||||
// specified name and returns its IPv4 and IPv6 addresses in CIDR
|
||||
// form. If the interface does not exist, it chooses from a predifined
|
||||
// list the first IPv4 address which does not conflict with other
|
||||
// interfaces on the system.
|
||||
func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
||||
var (
|
||||
v4Net *net.IPNet
|
||||
v6Nets []*net.IPNet
|
||||
err error
|
||||
)
|
||||
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
link, _ := netlink.LinkByName(name)
|
||||
if link != nil {
|
||||
v4addr, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
v6addr, err := netlink.AddrList(link, netlink.FAMILY_V6)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(v4addr) > 0 {
|
||||
v4Net = v4addr[0].IPNet
|
||||
}
|
||||
for _, nlAddr := range v6addr {
|
||||
v6Nets = append(v6Nets, nlAddr.IPNet)
|
||||
}
|
||||
}
|
||||
|
||||
if link == nil || v4Net == nil {
|
||||
// Choose from predifined broad networks
|
||||
v4Net, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return v4Net, v6Nets, nil
|
||||
}
|
||||
|
||||
// FindAvailableNetwork returns a network from the passed list which does not
|
||||
// overlap with existing interfaces in the system
|
||||
func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
|
||||
// We don't check for an error here, because we don't really care if we
|
||||
// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
|
||||
// is nil. It either doesn't exist, or we can't read it for some reason.
|
||||
var nameservers []string
|
||||
if rc, err := resolvconf.Get(); err == nil {
|
||||
nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
|
||||
}
|
||||
for _, nw := range list {
|
||||
if err := CheckNameserverOverlaps(nameservers, nw); err == nil {
|
||||
if err := CheckRouteOverlaps(nw); err == nil {
|
||||
return nw, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no available network")
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ import (
|
|||
"net"
|
||||
"testing"
|
||||
|
||||
_ "github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
|
@ -210,3 +212,95 @@ func TestUtilGenerateRandomMAC(t *testing.T) {
|
|||
t.Fatalf("mac1 %s should not equal mac2 %s", mac1, mac2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetworkRequest(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
ipamutils.InitNetworks()
|
||||
|
||||
_, exp, err := net.ParseCIDR("172.17.0.0/16")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
nw, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(exp, nw) {
|
||||
t.Fatalf("exected %s. got %s", exp, nw)
|
||||
}
|
||||
|
||||
_, exp, err = net.ParseCIDR("10.0.0.0/24")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
nw, err = FindAvailableNetwork(ipamutils.PredefinedGranularNetworks)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(exp, nw) {
|
||||
t.Fatalf("exected %s. got %s", exp, nw)
|
||||
}
|
||||
|
||||
// Add iface and ssert returned address on request
|
||||
createInterface(t, "test", "172.17.42.1/16")
|
||||
|
||||
_, exp, err = net.ParseCIDR("172.18.0.0/16")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
nw, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !types.CompareIPNet(exp, nw) {
|
||||
t.Fatalf("exected %s. got %s", exp, nw)
|
||||
}
|
||||
}
|
||||
|
||||
func TestElectInterfaceAddress(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
ipamutils.InitNetworks()
|
||||
|
||||
nws := "172.101.202.254/16"
|
||||
createInterface(t, "test", nws)
|
||||
|
||||
ipv4Nw, ipv6Nw, err := ElectInterfaceAddresses("test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ipv4Nw == nil {
|
||||
t.Fatalf("unexpected empty ipv4 network addresses")
|
||||
}
|
||||
|
||||
if len(ipv6Nw) == 0 {
|
||||
t.Fatalf("unexpected empty ipv4 network addresses")
|
||||
}
|
||||
|
||||
if nws != ipv4Nw.String() {
|
||||
t.Fatalf("expected %s. got %s", nws, ipv4Nw)
|
||||
}
|
||||
}
|
||||
|
||||
func createInterface(t *testing.T, name, nw string) {
|
||||
// Add interface
|
||||
link := &netlink.Bridge{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: "test",
|
||||
},
|
||||
}
|
||||
bip, err := types.ParseCIDR(nw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = netlink.LinkAdd(link); err != nil {
|
||||
t.Fatalf("Failed to create interface via netlink: %v", err)
|
||||
}
|
||||
if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: bip}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = netlink.LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// Package ipamutils provides utililty functions for ipam management
|
||||
package ipamutils
|
||||
package netutils
|
||||
|
||||
import (
|
||||
"net"
|
|
@ -1097,6 +1097,48 @@ func (n *network) ipamAllocate() error {
|
|||
return n.ipamAllocateVersion(6, ipam)
|
||||
}
|
||||
|
||||
func (n *network) requestPoolHelper(ipam ipamapi.Ipam, addressSpace, preferredPool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
|
||||
for {
|
||||
poolID, pool, meta, err := ipam.RequestPool(addressSpace, preferredPool, subPool, options, v6)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
}
|
||||
|
||||
// If the network belongs to global scope or the pool
|
||||
// returned is invalid, no need to perform overlap
|
||||
// check.
|
||||
if n.Scope() == datastore.GlobalScope || !types.IsIPNetValid(pool) {
|
||||
return poolID, pool, meta, nil
|
||||
}
|
||||
|
||||
// Check for overlap and if none found, we have found the right pool.
|
||||
if _, err := netutils.FindAvailableNetwork([]*net.IPNet{pool}); err == nil {
|
||||
return poolID, pool, meta, nil
|
||||
}
|
||||
|
||||
// Pool obtained in this iteration is
|
||||
// overlapping. Hold onto the pool and don't release
|
||||
// it yet, because we don't want ipam to give us back
|
||||
// the same pool over again. But make sure we still do
|
||||
// a deferred release when we have either obtained a
|
||||
// non-overlapping pool or ran out of pre-defined
|
||||
// pools.
|
||||
defer func() {
|
||||
if err := ipam.ReleasePool(poolID); err != nil {
|
||||
log.Warnf("Failed to release overlapping pool %s while returning from pool request helper for network %s", pool, n.Name())
|
||||
}
|
||||
}()
|
||||
|
||||
// If this is a preferred pool request and the network
|
||||
// is local scope and there is a overlap, we fail the
|
||||
// network creation right here. The pool will be
|
||||
// released in the defer.
|
||||
if preferredPool != "" {
|
||||
return "", nil, nil, fmt.Errorf("requested subnet %s overlaps in the host", preferredPool)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
||||
var (
|
||||
cfgList *[]*IpamConf
|
||||
|
@ -1133,7 +1175,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
|||
d := &IpamInfo{}
|
||||
(*infoList)[i] = d
|
||||
|
||||
d.PoolID, d.Pool, d.Meta, err = ipam.RequestPool(n.addrSpace, cfg.PreferredPool, cfg.SubPool, n.ipamOptions, ipVer == 6)
|
||||
d.PoolID, d.Pool, d.Meta, err = n.requestPoolHelper(ipam, n.addrSpace, cfg.PreferredPool, cfg.SubPool, n.ipamOptions, ipVer == 6)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package osl
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -9,7 +12,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
@ -25,8 +27,16 @@ const (
|
|||
sboxIfaceName = "containername"
|
||||
)
|
||||
|
||||
func generateRandomName(prefix string, size int) (string, error) {
|
||||
id := make([]byte, 32)
|
||||
if _, err := io.ReadFull(rand.Reader, id); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return prefix + hex.EncodeToString(id)[:size], nil
|
||||
}
|
||||
|
||||
func newKey(t *testing.T) (string, error) {
|
||||
name, err := netutils.GenerateRandomName("netns", 12)
|
||||
name, err := generateRandomName("netns", 12)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/resolvconf/dns"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -122,7 +122,7 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool) (*File, error) {
|
|||
}
|
||||
// if the resulting resolvConf has no more nameservers defined, add appropriate
|
||||
// default DNS servers for IPv4 and (optionally) IPv6
|
||||
if len(GetNameservers(cleanedResolvConf, netutils.IP)) == 0 {
|
||||
if len(GetNameservers(cleanedResolvConf, types.IP)) == 0 {
|
||||
logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultIPv4Dns)
|
||||
dns := defaultIPv4Dns
|
||||
if ipv6Enabled {
|
||||
|
@ -158,11 +158,11 @@ func GetNameservers(resolvConf []byte, kind int) []string {
|
|||
nameservers := []string{}
|
||||
for _, line := range getLines(resolvConf, []byte("#")) {
|
||||
var ns [][]byte
|
||||
if kind == netutils.IP {
|
||||
if kind == types.IP {
|
||||
ns = nsRegexp.FindSubmatch(line)
|
||||
} else if kind == netutils.IPv4 {
|
||||
} else if kind == types.IPv4 {
|
||||
ns = nsIPv4Regexpmatch.FindSubmatch(line)
|
||||
} else if kind == netutils.IPv6 {
|
||||
} else if kind == types.IPv6 {
|
||||
ns = nsIPv6Regexpmatch.FindSubmatch(line)
|
||||
}
|
||||
if len(ns) > 0 {
|
||||
|
@ -177,7 +177,7 @@ func GetNameservers(resolvConf []byte, kind int) []string {
|
|||
// This function's output is intended for net.ParseCIDR
|
||||
func GetNameserversAsCIDR(resolvConf []byte) []string {
|
||||
nameservers := []string{}
|
||||
for _, nameserver := range GetNameservers(resolvConf, netutils.IP) {
|
||||
for _, nameserver := range GetNameservers(resolvConf, types.IP) {
|
||||
nameservers = append(nameservers, nameserver+"/32")
|
||||
}
|
||||
return nameservers
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
_ "github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
|
@ -49,7 +49,7 @@ nameserver 1.2.3.4
|
|||
`search example.com
|
||||
nameserver 1.2.3.4 # not 4.3.2.1`: {"1.2.3.4"},
|
||||
} {
|
||||
test := GetNameservers([]byte(resolv), netutils.IP)
|
||||
test := GetNameservers([]byte(resolv), types.IP)
|
||||
if !strSlicesEqual(test, result) {
|
||||
t.Fatalf("Wrong nameserver string {%s} should be %v. Input: %s", test, result, resolv)
|
||||
}
|
||||
|
@ -84,11 +84,11 @@ func TestGetSearchDomains(t *testing.T) {
|
|||
for resolv, result := range map[string][]string{
|
||||
`search example.com`: {"example.com"},
|
||||
`search example.com # ignored`: {"example.com"},
|
||||
` search example.com `: {"example.com"},
|
||||
` search example.com # ignored`: {"example.com"},
|
||||
` search example.com `: {"example.com"},
|
||||
` search example.com # ignored`: {"example.com"},
|
||||
`search foo.example.com example.com`: {"foo.example.com", "example.com"},
|
||||
` search foo.example.com example.com `: {"foo.example.com", "example.com"},
|
||||
` search foo.example.com example.com # ignored`: {"foo.example.com", "example.com"},
|
||||
` search foo.example.com example.com `: {"foo.example.com", "example.com"},
|
||||
` search foo.example.com example.com # ignored`: {"foo.example.com", "example.com"},
|
||||
``: {},
|
||||
`# ignored`: {},
|
||||
`nameserver 1.2.3.4
|
||||
|
@ -111,12 +111,12 @@ func TestGetOptions(t *testing.T) {
|
|||
for resolv, result := range map[string][]string{
|
||||
`options opt1`: {"opt1"},
|
||||
`options opt1 # ignored`: {"opt1"},
|
||||
` options opt1 `: {"opt1"},
|
||||
` options opt1 # ignored`: {"opt1"},
|
||||
` options opt1 `: {"opt1"},
|
||||
` options opt1 # ignored`: {"opt1"},
|
||||
`options opt1 opt2 opt3`: {"opt1", "opt2", "opt3"},
|
||||
`options opt1 opt2 opt3 # ignored`: {"opt1", "opt2", "opt3"},
|
||||
` options opt1 opt2 opt3 `: {"opt1", "opt2", "opt3"},
|
||||
` options opt1 opt2 opt3 # ignored`: {"opt1", "opt2", "opt3"},
|
||||
` options opt1 opt2 opt3 `: {"opt1", "opt2", "opt3"},
|
||||
` options opt1 opt2 opt3 # ignored`: {"opt1", "opt2", "opt3"},
|
||||
``: {},
|
||||
`# ignored`: {},
|
||||
`nameserver 1.2.3.4`: {},
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
|
@ -240,7 +240,7 @@ func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.
|
|||
if len(addr) > 1 {
|
||||
addr = shuffleAddr(addr)
|
||||
}
|
||||
if ipType == netutils.IPv4 {
|
||||
if ipType == types.IPv4 {
|
||||
for _, ip := range addr {
|
||||
rr := new(dns.A)
|
||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
||||
|
@ -312,9 +312,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||
}
|
||||
name := query.Question[0].Name
|
||||
if query.Question[0].Qtype == dns.TypeA {
|
||||
resp, err = r.handleIPQuery(name, query, netutils.IPv4)
|
||||
resp, err = r.handleIPQuery(name, query, types.IPv4)
|
||||
} else if query.Question[0].Qtype == dns.TypeAAAA {
|
||||
resp, err = r.handleIPQuery(name, query, netutils.IPv6)
|
||||
resp, err = r.handleIPQuery(name, query, types.IPv6)
|
||||
} else if query.Question[0].Qtype == dns.TypePTR {
|
||||
resp, err = r.handlePTRQuery(name, query)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/etchosts"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
@ -522,7 +521,7 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
|
|||
n.Lock()
|
||||
ip, ok = sr.svcMap[name]
|
||||
|
||||
if ipType == netutils.IPv6 {
|
||||
if ipType == types.IPv6 {
|
||||
// If the name resolved to v4 address then its a valid name in
|
||||
// the docker network domain. If the network is not v6 enabled
|
||||
// set ipv6Miss to filter the DNS query from going to external
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/etchosts"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/resolvconf"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
@ -166,7 +165,7 @@ func (sb *sandbox) setupDNS() error {
|
|||
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
|
||||
var (
|
||||
err error
|
||||
dnsList = resolvconf.GetNameservers(currRC.Content, netutils.IP)
|
||||
dnsList = resolvconf.GetNameservers(currRC.Content, types.IP)
|
||||
dnsSearchList = resolvconf.GetSearchDomains(currRC.Content)
|
||||
dnsOptionsList = resolvconf.GetOptions(currRC.Content)
|
||||
)
|
||||
|
@ -275,7 +274,7 @@ func (sb *sandbox) rebuildDNS() error {
|
|||
|
||||
// localhost entries have already been filtered out from the list
|
||||
// retain only the v4 servers in sb for forwarding the DNS queries
|
||||
sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4)
|
||||
sb.extDNS = resolvconf.GetNameservers(currRC.Content, types.IPv4)
|
||||
|
||||
var (
|
||||
dnsList = []string{sb.resolver.NameServer()}
|
||||
|
@ -284,7 +283,7 @@ func (sb *sandbox) rebuildDNS() error {
|
|||
)
|
||||
|
||||
// external v6 DNS servers has to be listed in resolv.conf
|
||||
dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...)
|
||||
dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, types.IPv6)...)
|
||||
|
||||
// Resolver returns the options in the format resolv.conf expects
|
||||
dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...)
|
||||
|
|
|
@ -291,12 +291,12 @@ function test_single_network_connectivity() {
|
|||
dnet_cmd $(inst_id2port 1) container create container_1
|
||||
# connects to internal network, confirm it can't conmunicate with outside world
|
||||
net_connect 1 container_1 internal
|
||||
run runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 www.google.com"
|
||||
run runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 8.8.8.8"
|
||||
[[ "$output" == *"1 packets transmitted, 0 packets received, 100% packet loss"* ]]
|
||||
net_disconnect 1 container_1 internal
|
||||
# connects to bridge network, confirm it can conmunicate with outside world
|
||||
net_connect 1 container_1 bridge
|
||||
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 www.google.com"
|
||||
runc $(dnet_container_name 1 bridge) $(get_sbox_id 1 container_1) "ping -c 1 8.8.8.8"
|
||||
net_disconnect 1 container_1 bridge
|
||||
dnet_cmd $(inst_id2port 1) container rm container_1
|
||||
# test conmunications within internal network
|
||||
|
|
|
@ -25,6 +25,11 @@ load helpers
|
|||
test_overlay consul skip_add
|
||||
}
|
||||
|
||||
@test "Test overlay network internal network with consul" {
|
||||
skip_for_circleci
|
||||
test_overlay consul internal
|
||||
}
|
||||
|
||||
@test "Test overlay network with dnet ungraceful shutdown" {
|
||||
skip_for_circleci
|
||||
dnet_cmd $(inst_id2port 1) network create -d overlay multihost
|
||||
|
@ -32,8 +37,8 @@ load helpers
|
|||
end=3
|
||||
for i in `seq ${start} ${end}`;
|
||||
do
|
||||
dnet_cmd $(inst_id2port $i) container create container_${i}
|
||||
net_connect ${i} container_${i} multihost
|
||||
dnet_cmd $(inst_id2port $i) container create container_${i}
|
||||
net_connect ${i} container_${i} multihost
|
||||
done
|
||||
|
||||
hrun runc $(dnet_container_name 1 consul) $(get_sbox_id 1 container_1) "ifconfig eth0"
|
||||
|
@ -51,11 +56,6 @@ load helpers
|
|||
container_1_new_ip=$(echo ${output} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')
|
||||
|
||||
if [ "$container_1_ip" != "$container_1_new_ip" ]; then
|
||||
exit 1
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Test overlay network internal network with consul" {
|
||||
skip_for_circleci
|
||||
test_overlay consul internal
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// constants for the IP address type
|
||||
const (
|
||||
IP = iota // IPv4 and IPv6
|
||||
IPv4
|
||||
IPv6
|
||||
)
|
||||
|
||||
// UUID represents a globally unique ID of various resources like network and endpoint
|
||||
type UUID string
|
||||
|
||||
|
@ -323,6 +330,12 @@ func GetMinimalIPNet(nw *net.IPNet) *net.IPNet {
|
|||
return nw
|
||||
}
|
||||
|
||||
// IsIPNetValid returns true if the ipnet is a valid network/mask
|
||||
// combination. Otherwise returns false.
|
||||
func IsIPNetValid(nw *net.IPNet) bool {
|
||||
return nw.String() != "0.0.0.0/0"
|
||||
}
|
||||
|
||||
var v4inV6MaskPrefix = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||||
|
||||
// compareIPMask checks if the passed ip and mask are semantically compatible.
|
||||
|
|
Loading…
Reference in a new issue