mirror of https://github.com/k3s-io/k3s
util/iptables: fix cross-build failures due to syscall.Flock()
Fixes: https://github.com/kubernetes/kubernetes/issues/45554pull/6/head
parent
48caf95a6c
commit
a4624a0e75
|
@ -13,6 +13,7 @@ go_library(
|
||||||
srcs = [
|
srcs = [
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"iptables.go",
|
"iptables.go",
|
||||||
|
"iptables_linux.go",
|
||||||
"save_restore.go",
|
"save_restore.go",
|
||||||
],
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
|
@ -22,6 +23,7 @@ go_library(
|
||||||
"//pkg/util/version:go_default_library",
|
"//pkg/util/version:go_default_library",
|
||||||
"//vendor/github.com/godbus/dbus:go_default_library",
|
"//vendor/github.com/godbus/dbus:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
],
|
],
|
||||||
|
|
|
@ -19,18 +19,13 @@ package iptables
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
godbus "github.com/godbus/dbus"
|
godbus "github.com/godbus/dbus"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
|
||||||
utildbus "k8s.io/kubernetes/pkg/util/dbus"
|
utildbus "k8s.io/kubernetes/pkg/util/dbus"
|
||||||
utilexec "k8s.io/kubernetes/pkg/util/exec"
|
utilexec "k8s.io/kubernetes/pkg/util/exec"
|
||||||
utilversion "k8s.io/kubernetes/pkg/util/version"
|
utilversion "k8s.io/kubernetes/pkg/util/version"
|
||||||
|
@ -346,69 +341,8 @@ func (runner *runner) RestoreAll(data []byte, flush FlushFlag, counters RestoreC
|
||||||
return runner.restoreInternal(args, data, flush, counters)
|
return runner.restoreInternal(args, data, flush, counters)
|
||||||
}
|
}
|
||||||
|
|
||||||
type locker struct {
|
type iptablesLocker interface {
|
||||||
lock16 *os.File
|
Close()
|
||||||
lock14 *net.UnixListener
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *locker) Close() {
|
|
||||||
if l.lock16 != nil {
|
|
||||||
l.lock16.Close()
|
|
||||||
}
|
|
||||||
if l.lock14 != nil {
|
|
||||||
l.lock14.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (runner *runner) grabIptablesLocks() (*locker, error) {
|
|
||||||
var err error
|
|
||||||
var success bool
|
|
||||||
|
|
||||||
l := &locker{}
|
|
||||||
defer func(l *locker) {
|
|
||||||
// Clean up immediately on failure
|
|
||||||
if !success {
|
|
||||||
l.Close()
|
|
||||||
}
|
|
||||||
}(l)
|
|
||||||
|
|
||||||
if len(runner.restoreWaitFlag) > 0 {
|
|
||||||
// iptables-restore supports --wait; no need to grab locks
|
|
||||||
return l, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grab both 1.6.x and 1.4.x-style locks; we don't know what the
|
|
||||||
// iptables-restore version is if it doesn't support --wait, so we
|
|
||||||
// can't assume which lock method it'll use.
|
|
||||||
|
|
||||||
// Roughly duplicate iptables 1.6.x xtables_lock() function.
|
|
||||||
l.lock16, err = os.OpenFile(runner.lockfilePath, os.O_CREATE, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to open iptables lock %s: %v", runner.lockfilePath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := wait.PollImmediate(200*time.Millisecond, 2*time.Second, func() (bool, error) {
|
|
||||||
if err := syscall.Flock(int(l.lock16.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to acquire new iptables lock: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Roughly duplicate iptables 1.4.x xtables_lock() function.
|
|
||||||
if err := wait.PollImmediate(200*time.Millisecond, 2*time.Second, func() (bool, error) {
|
|
||||||
l.lock14, err = net.ListenUnix("unix", &net.UnixAddr{Name: "@xtables", Net: "unix"})
|
|
||||||
if err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to acquire old iptables lock: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
success = true
|
|
||||||
return l, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// restoreInternal is the shared part of Restore/RestoreAll
|
// restoreInternal is the shared part of Restore/RestoreAll
|
||||||
|
@ -426,11 +360,13 @@ func (runner *runner) restoreInternal(args []string, data []byte, flush FlushFla
|
||||||
// Grab the iptables lock to prevent iptables-restore and iptables
|
// Grab the iptables lock to prevent iptables-restore and iptables
|
||||||
// from stepping on each other. iptables-restore 1.6.2 will have
|
// from stepping on each other. iptables-restore 1.6.2 will have
|
||||||
// a --wait option like iptables itself, but that's not widely deployed.
|
// a --wait option like iptables itself, but that's not widely deployed.
|
||||||
locker, err := runner.grabIptablesLocks()
|
if len(runner.restoreWaitFlag) == 0 {
|
||||||
|
locker, err := grabIptablesLocks(runner.lockfilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer locker.Close()
|
defer locker.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// run the command and return the output or an error including the output and error
|
// run the command and return the output or an error including the output and error
|
||||||
fullArgs := append(runner.restoreWaitFlag, args...)
|
fullArgs := append(runner.restoreWaitFlag, args...)
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iptables
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
)
|
||||||
|
|
||||||
|
type locker struct {
|
||||||
|
lock16 *os.File
|
||||||
|
lock14 *net.UnixListener
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *locker) Close() {
|
||||||
|
if l.lock16 != nil {
|
||||||
|
l.lock16.Close()
|
||||||
|
}
|
||||||
|
if l.lock14 != nil {
|
||||||
|
l.lock14.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func grabIptablesLocks(lockfilePath string) (iptablesLocker, error) {
|
||||||
|
var err error
|
||||||
|
var success bool
|
||||||
|
|
||||||
|
l := &locker{}
|
||||||
|
defer func(l *locker) {
|
||||||
|
// Clean up immediately on failure
|
||||||
|
if !success {
|
||||||
|
l.Close()
|
||||||
|
}
|
||||||
|
}(l)
|
||||||
|
|
||||||
|
// Grab both 1.6.x and 1.4.x-style locks; we don't know what the
|
||||||
|
// iptables-restore version is if it doesn't support --wait, so we
|
||||||
|
// can't assume which lock method it'll use.
|
||||||
|
|
||||||
|
// Roughly duplicate iptables 1.6.x xtables_lock() function.
|
||||||
|
l.lock16, err = os.OpenFile(lockfilePath, os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open iptables lock %s: %v", lockfilePath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := wait.PollImmediate(200*time.Millisecond, 2*time.Second, func() (bool, error) {
|
||||||
|
if err := grabIptablesFileLock(l.lock16); err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to acquire new iptables lock: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roughly duplicate iptables 1.4.x xtables_lock() function.
|
||||||
|
if err := wait.PollImmediate(200*time.Millisecond, 2*time.Second, func() (bool, error) {
|
||||||
|
l.lock14, err = net.ListenUnix("unix", &net.UnixAddr{Name: "@xtables", Net: "unix"})
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to acquire old iptables lock: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
success = true
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func grabIptablesFileLock(f *os.File) error {
|
||||||
|
return unix.Flock(int(f.Fd()), unix.LOCK_EX|unix.LOCK_NB)
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -1190,7 +1189,7 @@ func TestRestoreAllGrabNewLock(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer runLock.Close()
|
defer runLock.Close()
|
||||||
|
|
||||||
if err := syscall.Flock(int(runLock.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
|
if err := grabIptablesFileLock(runLock); err != nil {
|
||||||
t.Errorf("expected to lock %s, got %v", TestLockfilePath, err)
|
t.Errorf("expected to lock %s, got %v", TestLockfilePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iptables
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func grabIptablesLocks(lockfilePath string) (iptablesLocker, error) {
|
||||||
|
return nil, fmt.Errorf("iptables unsupported on this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func grabIptablesFileLock(f *os.File) error {
|
||||||
|
return fmt.Errorf("iptables unsupported on this platform")
|
||||||
|
}
|
Loading…
Reference in New Issue