Merge pull request #11333 from crosbymichael/upldate-libcontainer-mar-11

Update libcontainer to aa10040b570386c1ae311c6245b
This commit is contained in:
Jessie Frazelle 2015-03-11 13:04:51 -07:00
Родитель d010bf0d99 c553be5a4f
Коммит 586f75d61c
16 изменённых файлов: 160 добавлений и 39 удалений

Просмотреть файл

@ -68,7 +68,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 dd3cb8822352fd4acc0b8b426bd86e47e98f6853
clone git github.com/docker/libcontainer aa10040b570386c1ae311c6245b9e21295b2b83a
# 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')"

Просмотреть файл

@ -54,12 +54,10 @@ func getCgroupRoot() (string, error) {
return cgroupRoot, nil
}
// we can pick any subsystem to find the root
cpuRoot, err := cgroups.FindCgroupMountpoint("cpu")
root, err := cgroups.FindCgroupMountpointDir()
if err != nil {
return "", err
}
root := filepath.Dir(cpuRoot)
if _, err := os.Stat(root); err != nil {
return "", err
@ -231,6 +229,12 @@ func (raw *data) parent(subsystem string) (string, error) {
}
func (raw *data) path(subsystem string) (string, error) {
_, err := cgroups.FindCgroupMountpoint(subsystem)
// If we didn't mount the subsystem, there is no point we make the path.
if err != nil {
return "", err
}
// If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
if filepath.IsAbs(raw.cgroup) {
path := filepath.Join(raw.root, subsystem, raw.cgroup)

Просмотреть файл

@ -17,8 +17,12 @@ type BlkioGroup struct {
func (s *BlkioGroup) Apply(d *data) error {
dir, err := d.join("blkio")
if err != nil && !cgroups.IsNotFound(err) {
return err
if err != nil {
if cgroups.IsNotFound(err) {
return nil
} else {
return err
}
}
if err := s.Set(dir, d.c); err != nil {

Просмотреть файл

@ -18,7 +18,11 @@ func (s *CpuGroup) Apply(d *data) error {
// on a container basis
dir, err := d.join("cpu")
if err != nil {
return err
if cgroups.IsNotFound(err) {
return nil
} else {
return err
}
}
if err := s.Set(dir, d.c); err != nil {

Просмотреть файл

@ -17,7 +17,11 @@ type CpusetGroup struct {
func (s *CpusetGroup) Apply(d *data) error {
dir, err := d.path("cpuset")
if err != nil {
return err
if cgroups.IsNotFound(err) {
return nil
} else {
return err
}
}
return s.ApplyDir(dir, d.c, d.pid)
}

Просмотреть файл

@ -11,7 +11,11 @@ type DevicesGroup struct {
func (s *DevicesGroup) Apply(d *data) error {
dir, err := d.join("devices")
if err != nil {
return err
if cgroups.IsNotFound(err) {
return nil
} else {
return err
}
}
if err := s.Set(dir, d.c); err != nil {

Просмотреть файл

@ -25,7 +25,7 @@ func TestDevicesSetAllow(t *testing.T) {
defer helper.cleanup()
helper.writeFileContents(map[string]string{
"device.deny": "a",
"devices.deny": "a",
})
helper.CgroupData.c.AllowAllDevices = false
@ -35,8 +35,6 @@ func TestDevicesSetAllow(t *testing.T) {
t.Fatal(err)
}
// FIXME: this doesn't make sence, the file devices.allow under real cgroupfs
// is not allowed to read. Our test path don't have cgroupfs mounted.
value, err := getCgroupParamString(helper.CgroupPath, "devices.allow")
if err != nil {
t.Fatalf("Failed to parse devices.allow - %s", err)

Просмотреть файл

@ -13,8 +13,12 @@ type FreezerGroup struct {
func (s *FreezerGroup) Apply(d *data) error {
dir, err := d.join("freezer")
if err != nil && !cgroups.IsNotFound(err) {
return err
if err != nil {
if cgroups.IsNotFound(err) {
return nil
} else {
return err
}
}
if err := s.Set(dir, d.c); err != nil {

Просмотреть файл

@ -16,9 +16,12 @@ type MemoryGroup struct {
func (s *MemoryGroup) Apply(d *data) error {
dir, err := d.join("memory")
// only return an error for memory if it was specified
if err != nil && (d.c.Memory != 0 || d.c.MemoryReservation != 0 || d.c.MemorySwap != 0) {
return err
if err != nil {
if cgroups.IsNotFound(err) {
return nil
} else {
return err
}
}
defer func() {
if err != nil {

Просмотреть файл

@ -55,6 +55,63 @@ func TestMemorySetMemory(t *testing.T) {
}
}
func TestMemorySetMemoryswap(t *testing.T) {
helper := NewCgroupTestUtil("memory", t)
defer helper.cleanup()
const (
memoryswapBefore = 314572800 // 300M
memoryswapAfter = 524288000 // 500M
)
helper.writeFileContents(map[string]string{
"memory.memsw.limit_in_bytes": strconv.Itoa(memoryswapBefore),
})
helper.CgroupData.c.MemorySwap = memoryswapAfter
memory := &MemoryGroup{}
if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil {
t.Fatal(err)
}
value, err := getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes")
if err != nil {
t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err)
}
if value != memoryswapAfter {
t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.")
}
}
func TestMemorySetMemoryswapDefault(t *testing.T) {
helper := NewCgroupTestUtil("memory", t)
defer helper.cleanup()
const (
memoryBefore = 209715200 // 200M
memoryAfter = 314572800 // 300M
memoryswapAfter = 629145600 // 300M*2
)
helper.writeFileContents(map[string]string{
"memory.limit_in_bytes": strconv.Itoa(memoryBefore),
})
helper.CgroupData.c.Memory = memoryAfter
memory := &MemoryGroup{}
if err := memory.Set(helper.CgroupPath, helper.CgroupData.c); err != nil {
t.Fatal(err)
}
value, err := getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes")
if err != nil {
t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err)
}
if value != memoryswapAfter {
t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.")
}
}
func TestMemoryStats(t *testing.T) {
helper := NewCgroupTestUtil("memory", t)
defer helper.cleanup()

Просмотреть файл

@ -6,9 +6,9 @@ Creates a mock of the cgroup filesystem for the duration of the test.
package fs
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/docker/libcontainer/configs"
@ -31,12 +31,12 @@ func NewCgroupTestUtil(subsystem string, t *testing.T) *cgroupTestUtil {
d := &data{
c: &configs.Cgroup{},
}
tempDir, err := ioutil.TempDir("", fmt.Sprintf("%s_cgroup_test", subsystem))
tempDir, err := ioutil.TempDir("", "cgroup_test")
if err != nil {
t.Fatal(err)
}
d.root = tempDir
testCgroupPath, err := d.path(subsystem)
testCgroupPath := filepath.Join(d.root, subsystem)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -34,6 +34,21 @@ func FindCgroupMountpoint(subsystem string) (string, error) {
return "", NewNotFoundError(subsystem)
}
func FindCgroupMountpointDir() (string, error) {
mounts, err := mount.GetMounts()
if err != nil {
return "", err
}
for _, mount := range mounts {
if mount.Fstype == "cgroup" {
return filepath.Dir(mount.Mountpoint), nil
}
}
return "", NewNotFoundError("cgroup")
}
type Mount struct {
Mountpoint string
Subsystems []string

Просмотреть файл

@ -1,25 +1,12 @@
// +build linux
// +build linux,!gccgo
package nsenter
/*
#cgo CFLAGS: -Wall
extern void nsexec();
void __attribute__((constructor)) init() {
void __attribute__((constructor)) init(void) {
nsexec();
}
*/
import "C"
// AlwaysFalse is here to stay false
// (and be exported so the compiler doesn't optimize out its reference)
var AlwaysFalse bool
func init() {
if AlwaysFalse {
// by referencing this C init() in a noop test, it will ensure the compiler
// links in the C function.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65134
C.init()
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// +build linux,gccgo
package nsenter
/*
#cgo CFLAGS: -Wall
extern void nsexec();
void __attribute__((constructor)) init(void) {
nsexec();
}
*/
import "C"
// AlwaysFalse is here to stay false
// (and be exported so the compiler doesn't optimize out its reference)
var AlwaysFalse bool
func init() {
if AlwaysFalse {
// by referencing this C init() in a noop test, it will ensure the compiler
// links in the C function.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65134
C.init()
}
}

Просмотреть файл

@ -104,6 +104,10 @@ func mount(m *configs.Mount, rootfs, mountLabel string) error {
if err := os.MkdirAll(dest, 0755); err != nil && !os.IsExist(err) {
return err
}
if m.Device == "mqueue" {
// mqueue should not be labeled, otherwise the mount will fail
data = ""
}
return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
case "bind":
stat, err := os.Stat(m.Source)

Просмотреть файл

@ -37,8 +37,8 @@ var (
spaceRegex = regexp.MustCompile(`^([^=]+) (.*)$`)
mcsList = make(map[string]bool)
selinuxfs = "unknown"
selinuxEnabled = false
selinuxEnabledChecked = false
selinuxEnabled = false // Stores whether selinux is currently enabled
selinuxEnabledChecked = false // Stores whether selinux enablement has been checked or established yet
)
type SELinuxContext map[string]string
@ -48,6 +48,11 @@ func SetDisabled() {
selinuxEnabled, selinuxEnabledChecked = false, true
}
// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs
// filesystem or an empty string if no mountpoint is found. Selinuxfs is
// a proc-like pseudo-filesystem that exposes the selinux policy API to
// processes. The existence of an selinuxfs mount is used to determine
// whether selinux is currently enabled or not.
func getSelinuxMountPoint() string {
if selinuxfs != "unknown" {
return selinuxfs
@ -74,6 +79,7 @@ func getSelinuxMountPoint() string {
return selinuxfs
}
// SelinuxEnabled returns whether selinux is currently enabled.
func SelinuxEnabled() bool {
if selinuxEnabledChecked {
return selinuxEnabled
@ -145,11 +151,12 @@ func readCon(name string) (string, error) {
return val, err
}
// Setfilecon sets the SELinux label for this path or returns an error.
func Setfilecon(path string, scon string) error {
return system.Lsetxattr(path, xattrNameSelinux, []byte(scon), 0)
}
// Return the SELinux label for this path
// Getfilecon returns the SELinux label for this path or returns an error.
func Getfilecon(path string) (string, error) {
con, err := system.Lgetxattr(path, xattrNameSelinux)
return string(con), err
@ -163,11 +170,12 @@ func Getfscreatecon() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()))
}
// Return the SELinux label of the current process thread.
// Getcon returns the SELinux label of the current process thread, or an error.
func Getcon() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid()))
}
// Getpidcon returns the SELinux label of the given pid, or an error.
func Getpidcon(pid int) (string, error) {
return readCon(fmt.Sprintf("/proc/%d/attr/current", pid))
}