From 26a5a793748a984284e570b8d0b96d26e42e7d1c Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Wed, 13 May 2015 03:27:22 +0000 Subject: [PATCH] Update resolvconf and iptables packages from docker Updated resolvconf and iptables packages based on upstream changes which we need for libnetwork rebase. There were docker engine changes based on this so we need this to be integrated now. Signed-off-by: Jana Radhakrishnan --- libnetwork/pkg/iptables/firewalld.go | 18 ++++------ libnetwork/pkg/iptables/iptables.go | 6 ++++ libnetwork/pkg/iptables/iptables_test.go | 40 +++++++++++++++++++++ libnetwork/pkg/resolvconf/dns/resolvconf.go | 17 +++++++++ libnetwork/pkg/resolvconf/resolvconf.go | 12 ++----- 5 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 libnetwork/pkg/resolvconf/dns/resolvconf.go diff --git a/libnetwork/pkg/iptables/firewalld.go b/libnetwork/pkg/iptables/firewalld.go index ee3fac5a7b..f2b57ae650 100644 --- a/libnetwork/pkg/iptables/firewalld.go +++ b/libnetwork/pkg/iptables/firewalld.go @@ -38,19 +38,18 @@ var ( ) // FirewalldInit initializes firewalld management code. -func FirewalldInit() { +func FirewalldInit() error { var err error - connection, err = newConnection() - - if err != nil { - logrus.Errorf("Failed to connect to D-Bus system bus: %s", err) + if connection, err = newConnection(); err != nil { + return fmt.Errorf("Failed to connect to D-Bus system bus: %v", err) } if connection != nil { go signalHandler() } firewalldRunning = checkRunning() + return nil } // New() establishes a connection to the system bus. @@ -151,7 +150,6 @@ func checkRunning() bool { logrus.Infof("Firewalld running: %t", err == nil) return err == nil } - logrus.Info("Firewalld not running") return false } @@ -160,10 +158,8 @@ func Passthrough(ipv IPV, args ...string) ([]byte, error) { var output string logrus.Debugf("Firewalld passthrough: %s, %s", ipv, args) - err := connection.sysobj.Call(dbusInterface+".direct.passthrough", 0, ipv, args).Store(&output) - if output != "" { - logrus.Debugf("passthrough output: %s", output) + if err := connection.sysobj.Call(dbusInterface+".direct.passthrough", 0, ipv, args).Store(&output); err != nil { + return nil, err } - - return []byte(output), err + return []byte(output), nil } diff --git a/libnetwork/pkg/iptables/iptables.go b/libnetwork/pkg/iptables/iptables.go index 77e117359c..75c539a815 100644 --- a/libnetwork/pkg/iptables/iptables.go +++ b/libnetwork/pkg/iptables/iptables.go @@ -8,6 +8,7 @@ import ( "regexp" "strconv" "strings" + "sync" "github.com/Sirupsen/logrus" ) @@ -36,6 +37,8 @@ const ( var ( iptablesPath string supportsXlock = false + // used to lock iptables commands if xtables lock is not supported + bestEffortLock sync.Mutex //ErrIptablesNotFound is returned when the rule is not found. ErrIptablesNotFound = errors.New("Iptables not found") ) @@ -303,6 +306,9 @@ func Raw(args ...string) ([]byte, error) { } if supportsXlock { args = append([]string{"--wait"}, args...) + } else { + bestEffortLock.Lock() + defer bestEffortLock.Unlock() } logrus.Debugf("%s, %v", iptablesPath, args) diff --git a/libnetwork/pkg/iptables/iptables_test.go b/libnetwork/pkg/iptables/iptables_test.go index f5f79c7096..594493a3ab 100644 --- a/libnetwork/pkg/iptables/iptables_test.go +++ b/libnetwork/pkg/iptables/iptables_test.go @@ -5,6 +5,7 @@ import ( "os/exec" "strconv" "strings" + "sync" "testing" _ "github.com/docker/libnetwork/netutils" @@ -171,6 +172,45 @@ func TestOutput(t *testing.T) { } } +func TestConcurrencyWithWait(t *testing.T) { + RunConcurrencyTest(t, true) +} + +func TestConcurrencyNoWait(t *testing.T) { + RunConcurrencyTest(t, false) +} + +// Runs 10 concurrent rule additions. This will fail if iptables +// is actually invoked simultaneously without --wait. +// Note that if iptables does not support the xtable lock on this +// system, then allowXlock has no effect -- it will always be off. +func RunConcurrencyTest(t *testing.T, allowXlock bool) { + var wg sync.WaitGroup + + if !allowXlock && supportsXlock { + supportsXlock = false + defer func() { supportsXlock = true }() + } + + ip := net.ParseIP("192.168.1.1") + port := 1234 + dstAddr := "172.17.0.1" + dstPort := 4321 + proto := "tcp" + + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + err := natChain.Forward(Append, ip, port, proto, dstAddr, dstPort) + if err != nil { + t.Fatal(err) + } + }() + } + wg.Wait() +} + func TestCleanup(t *testing.T) { var err error var rules []byte diff --git a/libnetwork/pkg/resolvconf/dns/resolvconf.go b/libnetwork/pkg/resolvconf/dns/resolvconf.go new file mode 100644 index 0000000000..d581a1913d --- /dev/null +++ b/libnetwork/pkg/resolvconf/dns/resolvconf.go @@ -0,0 +1,17 @@ +package dns + +import ( + "regexp" +) + +// IPLocalhost is a regex patter for localhost IP address range. +const IPLocalhost = `((127\.([0-9]{1,3}.){2}[0-9]{1,3})|(::1))` + +var localhostIPRegexp = regexp.MustCompile(IPLocalhost) + +// IsLocalhost returns true if ip matches the localhost IP regular expression. +// Used for determining if nameserver settings are being passed which are +// localhost addresses +func IsLocalhost(ip string) bool { + return localhostIPRegexp.MatchString(ip) +} diff --git a/libnetwork/pkg/resolvconf/resolvconf.go b/libnetwork/pkg/resolvconf/resolvconf.go index d491fddad2..ae6c4e676d 100644 --- a/libnetwork/pkg/resolvconf/resolvconf.go +++ b/libnetwork/pkg/resolvconf/resolvconf.go @@ -10,6 +10,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/ioutils" + "github.com/docker/libnetwork/pkg/resolvconf/dns" ) var ( @@ -24,10 +25,8 @@ var ( // For readability and sufficiency for Docker purposes this seemed more reasonable than a // 1000+ character regexp with exact and complete IPv6 validation ipv6Address = `([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})` - ipLocalhost = `((127\.([0-9]{1,3}.){2}[0-9]{1,3})|(::1))` - localhostIPRegexp = regexp.MustCompile(ipLocalhost) - localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipLocalhost + `\s*\n*`) + localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + dns.IPLocalhost + `\s*\n*`) nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`) nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`) searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`) @@ -128,13 +127,6 @@ func getLines(input []byte, commentMarker []byte) [][]byte { return output } -// IsLocalhost returns true if ip matches the localhost IP regular expression. -// Used for determining if nameserver settings are being passed which are -// localhost addresses -func IsLocalhost(ip string) bool { - return localhostIPRegexp.MatchString(ip) -} - // GetNameservers returns nameservers (if any) listed in /etc/resolv.conf func GetNameservers(resolvConf []byte) []string { nameservers := []string{}