Просмотр исходного кода

Merge pull request #8367 from crosbymichael/update-libcontainer-sep9

Update libconatiner to b3570267c7b7995d5d618974d8f
Victor Vieux 10 лет назад
Родитель
Сommit
b2ee63000e

+ 1 - 1
hack/vendor.sh

@@ -64,7 +64,7 @@ if [ "$1" = '--go' ]; then
 	mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar
 fi
 
-clone git github.com/docker/libcontainer c744f6470e37be5ce1f1ae09b842c15c1bee120d
+clone git github.com/docker/libcontainer b3570267c7b7995d5d618974d8f7be4fe5ab076a
 # see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file)
 rm -rf src/github.com/docker/libcontainer/vendor
 eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli')"

+ 3 - 2
vendor/src/github.com/docker/libcontainer/netlink/netlink.go

@@ -11,8 +11,9 @@ import (
 )
 
 var (
-	ErrWrongSockType = errors.New("Wrong socket type")
-	ErrShortResponse = errors.New("Got short response from netlink")
+	ErrWrongSockType   = errors.New("Wrong socket type")
+	ErrShortResponse   = errors.New("Got short response from netlink")
+	ErrInterfaceExists = errors.New("Network interface already exists")
 )
 
 // A Route is a subnet associated with the interface to reach it.

+ 11 - 1
vendor/src/github.com/docker/libcontainer/netlink/netlink_linux.go

@@ -6,6 +6,7 @@ import (
 	"io"
 	"math/rand"
 	"net"
+	"os"
 	"sync/atomic"
 	"syscall"
 	"unsafe"
@@ -708,7 +709,16 @@ func NetworkCreateVethPair(name1, name2 string) error {
 	if err := s.Send(wb); err != nil {
 		return err
 	}
-	return s.HandleAck(wb.Seq)
+
+	if err := s.HandleAck(wb.Seq); err != nil {
+		if os.IsExist(err) {
+			return ErrInterfaceExists
+		}
+
+		return err
+	}
+
+	return nil
 }
 
 // Add a new VLAN interface with masterDev as its upper device

+ 1 - 1
vendor/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go

@@ -328,7 +328,7 @@ func TestCreateBridgeWithMac(t *testing.T) {
 	}
 }
 
-func TestSetMACAddress(t *testing.T) {
+func TestSetMacAddress(t *testing.T) {
 	if testing.Short() {
 		return
 	}

+ 8 - 0
vendor/src/github.com/docker/libcontainer/network/network.go

@@ -68,6 +68,14 @@ func SetDefaultGateway(ip, ifaceName string) error {
 	return netlink.AddDefaultGw(ip, ifaceName)
 }
 
+func SetInterfaceMac(name string, macaddr string) error {
+	iface, err := net.InterfaceByName(name)
+	if err != nil {
+		return err
+	}
+	return netlink.NetworkSetMacAddress(iface, macaddr)
+}
+
 func SetInterfaceIp(name string, rawIp string) error {
 	iface, err := net.InterfaceByName(name)
 	if err != nil {

+ 3 - 0
vendor/src/github.com/docker/libcontainer/network/types.go

@@ -17,6 +17,9 @@ type Network struct {
 	// Prefix for the veth interfaces.
 	VethPrefix string `json:"veth_prefix,omitempty"`
 
+	// MacAddress contains the MAC address to set on the network interface
+	MacAddress string `json:"mac_address,omitempty"`
+
 	// Address contains the IPv4 and mask to set on the network interface
 	Address string `json:"address,omitempty"`
 

+ 25 - 10
vendor/src/github.com/docker/libcontainer/network/veth.go

@@ -5,6 +5,7 @@ package network
 import (
 	"fmt"
 
+	"github.com/docker/libcontainer/netlink"
 	"github.com/docker/libcontainer/utils"
 )
 
@@ -60,6 +61,11 @@ func (v *Veth) Initialize(config *Network, networkState *NetworkState) error {
 	if err := ChangeInterfaceName(vethChild, defaultDevice); err != nil {
 		return fmt.Errorf("change %s to %s %s", vethChild, defaultDevice, err)
 	}
+	if config.MacAddress != "" {
+		if err := SetInterfaceMac(defaultDevice, config.MacAddress); err != nil {
+			return fmt.Errorf("set %s mac %s", defaultDevice, err)
+		}
+	}
 	if err := SetInterfaceIp(defaultDevice, config.Address); err != nil {
 		return fmt.Errorf("set %s ip %s", defaultDevice, err)
 	}
@@ -91,16 +97,25 @@ func (v *Veth) Initialize(config *Network, networkState *NetworkState) error {
 // createVethPair will automatically generage two random names for
 // the veth pair and ensure that they have been created
 func createVethPair(prefix string) (name1 string, name2 string, err error) {
-	name1, err = utils.GenerateRandomName(prefix, 4)
-	if err != nil {
-		return
-	}
-	name2, err = utils.GenerateRandomName(prefix, 4)
-	if err != nil {
-		return
-	}
-	if err = CreateVethPair(name1, name2); err != nil {
-		return
+	for i := 0; i < 10; i++ {
+		if name1, err = utils.GenerateRandomName(prefix, 7); err != nil {
+			return
+		}
+
+		if name2, err = utils.GenerateRandomName(prefix, 7); err != nil {
+			return
+		}
+
+		if err = CreateVethPair(name1, name2); err != nil {
+			if err == netlink.ErrInterfaceExists {
+				continue
+			}
+
+			return
+		}
+
+		break
 	}
+
 	return
 }

+ 53 - 0
vendor/src/github.com/docker/libcontainer/network/veth_test.go

@@ -0,0 +1,53 @@
+// +build linux
+
+package network
+
+import (
+	"testing"
+
+	"github.com/docker/libcontainer/netlink"
+)
+
+func TestGenerateVethNames(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	prefix := "veth"
+
+	name1, name2, err := createVethPair(prefix)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if name1 == "" {
+		t.Fatal("name1 should not be empty")
+	}
+
+	if name2 == "" {
+		t.Fatal("name2 should not be empty")
+	}
+}
+
+func TestCreateDuplicateVethPair(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	prefix := "veth"
+
+	name1, name2, err := createVethPair(prefix)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// retry to create the name interfaces and make sure that we get the correct error
+	err = CreateVethPair(name1, name2)
+	if err == nil {
+		t.Fatal("expected error to not be nil with duplicate interface")
+	}
+
+	if err != netlink.ErrInterfaceExists {
+		t.Fatalf("expected error to be ErrInterfaceExists but received %q", err)
+	}
+}

+ 53 - 13
vendor/src/github.com/docker/libcontainer/system/xattrs_linux.go

@@ -5,8 +5,35 @@ import (
 	"unsafe"
 )
 
-// Returns a nil slice and nil error if the xattr is not set
+var _zero uintptr
+
+// Returns the size of xattrs and nil error
+// Requires path, takes allocated []byte or nil as last argument
+func Llistxattr(path string, dest []byte) (size int, err error) {
+	pathBytes, err := syscall.BytePtrFromString(path)
+	if err != nil {
+		return -1, err
+	}
+	var newpathBytes unsafe.Pointer
+	if len(dest) > 0 {
+		newpathBytes = unsafe.Pointer(&dest[0])
+	} else {
+		newpathBytes = unsafe.Pointer(&_zero)
+	}
+
+	_size, _, errno := syscall.Syscall6(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(newpathBytes), uintptr(len(dest)), 0, 0, 0)
+	size = int(_size)
+	if errno != 0 {
+		return -1, errno
+	}
+
+	return size, nil
+}
+
+// Returns a []byte slice if the xattr is set and nil otherwise
+// Requires path and its attribute as arguments
 func Lgetxattr(path string, attr string) ([]byte, error) {
+	var sz int
 	pathBytes, err := syscall.BytePtrFromString(path)
 	if err != nil {
 		return nil, err
@@ -16,26 +43,39 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
 		return nil, err
 	}
 
-	dest := make([]byte, 128)
+	// Start with a 128 length byte array
+	sz = 128
+	dest := make([]byte, sz)
 	destBytes := unsafe.Pointer(&dest[0])
-	sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
-	if errno == syscall.ENODATA {
-		return nil, nil
-	}
-	if errno == syscall.ERANGE {
+	_sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
+
+	switch {
+	case errno == syscall.ENODATA:
+		return nil, errno
+	case errno == syscall.ENOTSUP:
+		return nil, errno
+	case errno == syscall.ERANGE:
+		// 128 byte array might just not be good enough,
+		// A dummy buffer is used ``uintptr(0)`` to get real size
+		// of the xattrs on disk
+		_sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0)
+		sz = int(_sz)
+		if sz < 0 {
+			return nil, errno
+		}
 		dest = make([]byte, sz)
 		destBytes := unsafe.Pointer(&dest[0])
-		sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
-	}
-	if errno != 0 {
+		_sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
+		if errno != 0 {
+			return nil, errno
+		}
+	case errno != 0:
 		return nil, errno
 	}
-
+	sz = int(_sz)
 	return dest[:sz], nil
 }
 
-var _zero uintptr
-
 func Lsetxattr(path string, attr string, data []byte, flags int) error {
 	pathBytes, err := syscall.BytePtrFromString(path)
 	if err != nil {

+ 53 - 0
vendor/src/github.com/docker/libcontainer/xattr/xattr.go

@@ -0,0 +1,53 @@
+// +build linux
+
+package xattr
+
+import (
+	"syscall"
+
+	"github.com/docker/libcontainer/system"
+)
+
+func XattrEnabled(path string) bool {
+	if Setxattr(path, "user.test", "") == syscall.ENOTSUP {
+		return false
+	}
+	return true
+}
+
+func stringsfromByte(buf []byte) (result []string) {
+	offset := 0
+	for index, b := range buf {
+		if b == 0 {
+			result = append(result, string(buf[offset:index]))
+			offset = index + 1
+		}
+	}
+	return
+}
+
+func Listxattr(path string) ([]string, error) {
+	size, err := system.Llistxattr(path, nil)
+	if err != nil {
+		return nil, err
+	}
+	buf := make([]byte, size)
+	read, err := system.Llistxattr(path, buf)
+	if err != nil {
+		return nil, err
+	}
+	names := stringsfromByte(buf[:read])
+	return names, nil
+}
+
+func Getxattr(path, attr string) (string, error) {
+	value, err := system.Lgetxattr(path, attr)
+	if err != nil {
+		return "", err
+	}
+	return string(value), nil
+}
+
+func Setxattr(path, xattr, value string) error {
+	return system.Lsetxattr(path, xattr, []byte(value), 0)
+}

+ 77 - 0
vendor/src/github.com/docker/libcontainer/xattr/xattr_test.go

@@ -0,0 +1,77 @@
+// +build linux
+
+package xattr_test
+
+import (
+	"os"
+	"testing"
+
+	"github.com/docker/libcontainer/xattr"
+)
+
+func testXattr(t *testing.T) {
+	tmp := "xattr_test"
+	out, err := os.OpenFile(tmp, os.O_WRONLY, 0)
+	if err != nil {
+		t.Fatal("failed")
+	}
+	attr := "user.test"
+	out.Close()
+
+	if !xattr.XattrEnabled(tmp) {
+		t.Log("Disabled")
+		t.Fatal("failed")
+	}
+	t.Log("Success")
+
+	err = xattr.Setxattr(tmp, attr, "test")
+	if err != nil {
+		t.Fatal("failed")
+	}
+
+	var value string
+	value, err = xattr.Getxattr(tmp, attr)
+	if err != nil {
+		t.Fatal("failed")
+	}
+	if value != "test" {
+		t.Fatal("failed")
+	}
+	t.Log("Success")
+
+	var names []string
+	names, err = xattr.Listxattr(tmp)
+	if err != nil {
+		t.Fatal("failed")
+	}
+
+	var found int
+	for _, name := range names {
+		if name == attr {
+			found = 1
+		}
+	}
+	// Listxattr doesn't return trusted.* and system.* namespace
+	// attrs when run in unprevileged mode.
+	if found != 1 {
+		t.Fatal("failed")
+	}
+	t.Log("Success")
+
+	big := "0000000000000000000000000000000000000000000000000000000000000000000008c6419ad822dfe29283fb3ac98dcc5908810cb31f4cfe690040c42c144b7492eicompslf20dxmlpgz"
+	// Test for long xattrs larger than 128 bytes
+	err = xattr.Setxattr(tmp, attr, big)
+	if err != nil {
+		t.Fatal("failed to add long value")
+	}
+	value, err = xattr.Getxattr(tmp, attr)
+	if err != nil {
+		t.Fatal("failed to get long value")
+	}
+	t.Log("Success")
+
+	if value != big {
+		t.Fatal("failed, value doesn't match")
+	}
+	t.Log("Success")
+}