mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #12161 from LK4D4/update_libcontainer
Update libcontainer
This commit is contained in:
commit
06433cf812
12 changed files with 178 additions and 41 deletions
|
@ -75,7 +75,7 @@ rm -rf src/github.com/docker/distribution
|
||||||
mkdir -p src/github.com/docker/distribution
|
mkdir -p src/github.com/docker/distribution
|
||||||
mv tmp-digest src/github.com/docker/distribution/digest
|
mv tmp-digest src/github.com/docker/distribution/digest
|
||||||
|
|
||||||
clone git github.com/docker/libcontainer d00b8369852285d6a830a8d3b966608b2ed89705
|
clone git github.com/docker/libcontainer bd8ec36106086f72b66e1be85a81202b93503e44
|
||||||
# see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file)
|
# 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
|
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' | grep -v 'github.com/Sirupsen/logrus')"
|
eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli' | grep -v 'github.com/Sirupsen/logrus')"
|
||||||
|
|
|
@ -3249,6 +3249,35 @@ func TestRunNetHost(t *testing.T) {
|
||||||
logDone("run - net host mode")
|
logDone("run - net host mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRunNetContainerWhichHost(t *testing.T) {
|
||||||
|
testRequires(t, SameHostDaemon)
|
||||||
|
defer deleteAllContainers()
|
||||||
|
|
||||||
|
hostNet, err := os.Readlink("/proc/1/ns/net")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(dockerBinary, "run", "-d", "--net=host", "--name=test", "busybox", "top")
|
||||||
|
out, _, err := runCommandWithOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = exec.Command(dockerBinary, "run", "--net=container:test", "busybox", "readlink", "/proc/self/ns/net")
|
||||||
|
out, _, err = runCommandWithOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
out = strings.Trim(out, "\n")
|
||||||
|
if hostNet != out {
|
||||||
|
t.Fatalf("Container should have host network namespace")
|
||||||
|
}
|
||||||
|
|
||||||
|
logDone("run - net container mode, where container in host mode")
|
||||||
|
}
|
||||||
|
|
||||||
func TestRunAllowPortRangeThroughPublish(t *testing.T) {
|
func TestRunAllowPortRangeThroughPublish(t *testing.T) {
|
||||||
defer deleteAllContainers()
|
defer deleteAllContainers()
|
||||||
|
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
bundles
|
||||||
nsinit/nsinit
|
nsinit/nsinit
|
||||||
|
|
|
@ -29,3 +29,5 @@ local:
|
||||||
validate:
|
validate:
|
||||||
hack/validate.sh
|
hack/validate.sh
|
||||||
|
|
||||||
|
binary: all
|
||||||
|
docker run --rm --privileged -v $(CURDIR)/bundles:/go/bin dockercore/libcontainer make direct-install
|
||||||
|
|
|
@ -141,6 +141,9 @@ container.Resume()
|
||||||
It is able to spawn new containers or join existing containers. A root
|
It is able to spawn new containers or join existing containers. A root
|
||||||
filesystem must be provided for use along with a container configuration file.
|
filesystem must be provided for use along with a container configuration file.
|
||||||
|
|
||||||
|
To build `nsinit`, run `make binary`. It will save the binary into
|
||||||
|
`bundles/nsinit`.
|
||||||
|
|
||||||
To use `nsinit`, cd into a Linux rootfs and copy a `container.json` file into
|
To use `nsinit`, cd into a Linux rootfs and copy a `container.json` file into
|
||||||
the directory with your specified configuration. Environment, networking,
|
the directory with your specified configuration. Environment, networking,
|
||||||
and different capabilities for the container are specified in this file.
|
and different capabilities for the container are specified in this file.
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
package systemd
|
package systemd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -247,6 +246,21 @@ func writeFile(dir, file, data string) error {
|
||||||
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
|
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
|
||||||
|
path, err := getSubsystemPath(c, subsystem)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err := writeFile(path, "cgroup.procs", strconv.Itoa(pid)); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
func joinCpu(c *configs.Cgroup, pid int) error {
|
func joinCpu(c *configs.Cgroup, pid int) error {
|
||||||
path, err := getSubsystemPath(c, "cpu")
|
path, err := getSubsystemPath(c, "cpu")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -266,16 +280,11 @@ func joinCpu(c *configs.Cgroup, pid int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func joinFreezer(c *configs.Cgroup, pid int) error {
|
func joinFreezer(c *configs.Cgroup, pid int) error {
|
||||||
path, err := getSubsystemPath(c, "freezer")
|
if _, err := join(c, "freezer", pid); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
|
return nil
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ioutil.WriteFile(filepath.Join(path, "cgroup.procs"), []byte(strconv.Itoa(pid)), 0700)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
|
func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
|
||||||
|
@ -303,21 +312,15 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(path, "freezer.state"), []byte(state), 0); err != nil {
|
prevState := m.Cgroups.Freezer
|
||||||
|
m.Cgroups.Freezer = state
|
||||||
|
|
||||||
|
freezer := subsystems["freezer"]
|
||||||
|
err = freezer.Set(path, m.Cgroups)
|
||||||
|
if err != nil {
|
||||||
|
m.Cgroups.Freezer = prevState
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for {
|
|
||||||
state_, err := ioutil.ReadFile(filepath.Join(path, "freezer.state"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if string(state) == string(bytes.TrimSpace(state_)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Millisecond)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Cgroups.Freezer = state
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -366,29 +369,16 @@ func getUnitName(c *configs.Cgroup) string {
|
||||||
// because systemd will re-write the device settings if it needs to re-apply the cgroup context.
|
// because systemd will re-write the device settings if it needs to re-apply the cgroup context.
|
||||||
// This happens at least for v208 when any sibling unit is started.
|
// This happens at least for v208 when any sibling unit is started.
|
||||||
func joinDevices(c *configs.Cgroup, pid int) error {
|
func joinDevices(c *configs.Cgroup, pid int) error {
|
||||||
path, err := getSubsystemPath(c, "devices")
|
path, err := join(c, "devices", pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
|
devices := subsystems["devices"]
|
||||||
|
if err := devices.Set(path, c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(path, "cgroup.procs"), []byte(strconv.Itoa(pid)), 0700); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.AllowAllDevices {
|
|
||||||
if err := writeFile(path, "devices.deny", "a"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, dev := range c.AllowedDevices {
|
|
||||||
if err := writeFile(path, "devices.allow", dev.CgroupString()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,17 @@ const (
|
||||||
NEWUSER NamespaceType = "NEWUSER"
|
NEWUSER NamespaceType = "NEWUSER"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NamespaceTypes() []NamespaceType {
|
||||||
|
return []NamespaceType{
|
||||||
|
NEWNET,
|
||||||
|
NEWPID,
|
||||||
|
NEWNS,
|
||||||
|
NEWUTS,
|
||||||
|
NEWIPC,
|
||||||
|
NEWUSER,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Namespace defines configuration for each namespace. It specifies an
|
// Namespace defines configuration for each namespace. It specifies an
|
||||||
// alternate path that is able to be joined via setns.
|
// alternate path that is able to be joined via setns.
|
||||||
type Namespace struct {
|
type Namespace struct {
|
||||||
|
|
|
@ -306,5 +306,11 @@ func (c *linuxContainer) currentState() (*State, error) {
|
||||||
for _, ns := range c.config.Namespaces {
|
for _, ns := range c.config.Namespaces {
|
||||||
state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid())
|
state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid())
|
||||||
}
|
}
|
||||||
|
for _, nsType := range configs.NamespaceTypes() {
|
||||||
|
if _, ok := state.NamespacePaths[nsType]; !ok {
|
||||||
|
ns := configs.Namespace{Type: nsType}
|
||||||
|
state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid())
|
||||||
|
}
|
||||||
|
}
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,8 @@ func TestGetContainerState(t *testing.T) {
|
||||||
{Type: configs.NEWNS},
|
{Type: configs.NEWNS},
|
||||||
{Type: configs.NEWNET, Path: expectedNetworkPath},
|
{Type: configs.NEWNET, Path: expectedNetworkPath},
|
||||||
{Type: configs.NEWUTS},
|
{Type: configs.NEWUTS},
|
||||||
{Type: configs.NEWIPC},
|
// emulate host for IPC
|
||||||
|
//{Type: configs.NEWIPC},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initProcess: &mockProcess{
|
initProcess: &mockProcess{
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/libcontainer"
|
"github.com/docker/libcontainer"
|
||||||
|
"github.com/docker/libcontainer/cgroups/systemd"
|
||||||
"github.com/docker/libcontainer/configs"
|
"github.com/docker/libcontainer/configs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -481,6 +482,17 @@ func TestProcessCaps(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFreeze(t *testing.T) {
|
func TestFreeze(t *testing.T) {
|
||||||
|
testFreeze(t, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSystemdFreeze(t *testing.T) {
|
||||||
|
if !systemd.UseSystemd() {
|
||||||
|
t.Skip("Systemd is unsupported")
|
||||||
|
}
|
||||||
|
testFreeze(t, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFreeze(t *testing.T, systemd bool) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -497,6 +509,9 @@ func TestFreeze(t *testing.T) {
|
||||||
defer remove(rootfs)
|
defer remove(rootfs)
|
||||||
|
|
||||||
config := newTemplateConfig(rootfs)
|
config := newTemplateConfig(rootfs)
|
||||||
|
if systemd {
|
||||||
|
config.Cgroups.Slice = "system.slice"
|
||||||
|
}
|
||||||
|
|
||||||
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
|
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -559,3 +574,77 @@ func TestFreeze(t *testing.T) {
|
||||||
t.Fatal(s.String())
|
t.Fatal(s.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContainerState(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root, err := newTestRoot()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(root)
|
||||||
|
|
||||||
|
rootfs, err := newRootfs()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer remove(rootfs)
|
||||||
|
|
||||||
|
l, err := os.Readlink("/proc/1/ns/ipc")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := newTemplateConfig(rootfs)
|
||||||
|
config.Namespaces = configs.Namespaces([]configs.Namespace{
|
||||||
|
{Type: configs.NEWNS},
|
||||||
|
{Type: configs.NEWUTS},
|
||||||
|
// host for IPC
|
||||||
|
//{Type: configs.NEWIPC},
|
||||||
|
{Type: configs.NEWPID},
|
||||||
|
{Type: configs.NEWNET},
|
||||||
|
})
|
||||||
|
|
||||||
|
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
container, err := factory.Create("test", config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer container.Destroy()
|
||||||
|
|
||||||
|
stdinR, stdinW, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
p := &libcontainer.Process{
|
||||||
|
Args: []string{"cat"},
|
||||||
|
Env: standardEnvironment,
|
||||||
|
Stdin: stdinR,
|
||||||
|
}
|
||||||
|
err = container.Start(p)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
stdinR.Close()
|
||||||
|
defer p.Signal(os.Kill)
|
||||||
|
|
||||||
|
st, err := container.State()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l1, err := os.Readlink(st.NamespacePaths[configs.NEWIPC])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if l1 != l {
|
||||||
|
t.Fatal("Container using non-host ipc namespace")
|
||||||
|
}
|
||||||
|
stdinW.Close()
|
||||||
|
p.Wait()
|
||||||
|
}
|
||||||
|
|
|
@ -68,9 +68,14 @@ func copyBusybox(dest string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContainer(config *configs.Config) (libcontainer.Container, error) {
|
func newContainer(config *configs.Config) (libcontainer.Container, error) {
|
||||||
|
cgm := libcontainer.Cgroupfs
|
||||||
|
if config.Cgroups != nil && config.Cgroups.Slice == "system.slice" {
|
||||||
|
cgm = libcontainer.SystemdCgroups
|
||||||
|
}
|
||||||
|
|
||||||
factory, err := libcontainer.New(".",
|
factory, err := libcontainer.New(".",
|
||||||
libcontainer.InitArgs(os.Args[0], "init", "--"),
|
libcontainer.InitArgs(os.Args[0], "init", "--"),
|
||||||
libcontainer.Cgroupfs,
|
cgm,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -13,7 +13,7 @@ func main() {
|
||||||
app.Version = "2"
|
app.Version = "2"
|
||||||
app.Author = "libcontainer maintainers"
|
app.Author = "libcontainer maintainers"
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.StringFlag{Name: "root", Value: ".", Usage: "root directory for containers"},
|
cli.StringFlag{Name: "root", Value: "/var/run/nsinit", Usage: "root directory for containers"},
|
||||||
cli.StringFlag{Name: "log-file", Value: "", Usage: "set the log file to output logs to"},
|
cli.StringFlag{Name: "log-file", Value: "", Usage: "set the log file to output logs to"},
|
||||||
cli.BoolFlag{Name: "debug", Usage: "enable debug output in the logs"},
|
cli.BoolFlag{Name: "debug", Usage: "enable debug output in the logs"},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue