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
|
||||
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)
|
||||
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')"
|
||||
|
|
|
@ -3249,6 +3249,35 @@ func TestRunNetHost(t *testing.T) {
|
|||
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) {
|
||||
defer deleteAllContainers()
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
bundles
|
||||
nsinit/nsinit
|
||||
|
|
|
@ -29,3 +29,5 @@ local:
|
|||
validate:
|
||||
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
|
||||
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
|
||||
the directory with your specified configuration. Environment, networking,
|
||||
and different capabilities for the container are specified in this file.
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package systemd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -247,6 +246,21 @@ func writeFile(dir, file, data string) error {
|
|||
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 {
|
||||
path, err := getSubsystemPath(c, "cpu")
|
||||
if err != nil {
|
||||
|
@ -266,16 +280,11 @@ func joinCpu(c *configs.Cgroup, pid int) error {
|
|||
}
|
||||
|
||||
func joinFreezer(c *configs.Cgroup, pid int) error {
|
||||
path, err := getSubsystemPath(c, "freezer")
|
||||
if err != nil {
|
||||
if _, err := join(c, "freezer", pid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(filepath.Join(path, "cgroup.procs"), []byte(strconv.Itoa(pid)), 0700)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
|
||||
|
@ -303,22 +312,16 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(path, "freezer.state"), []byte(state), 0); err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
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 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.
|
||||
// This happens at least for v208 when any sibling unit is started.
|
||||
func joinDevices(c *configs.Cgroup, pid int) error {
|
||||
path, err := getSubsystemPath(c, "devices")
|
||||
path, err := join(c, "devices", pid)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,17 @@ const (
|
|||
NEWUSER NamespaceType = "NEWUSER"
|
||||
)
|
||||
|
||||
func NamespaceTypes() []NamespaceType {
|
||||
return []NamespaceType{
|
||||
NEWNET,
|
||||
NEWPID,
|
||||
NEWNS,
|
||||
NEWUTS,
|
||||
NEWIPC,
|
||||
NEWUSER,
|
||||
}
|
||||
}
|
||||
|
||||
// Namespace defines configuration for each namespace. It specifies an
|
||||
// alternate path that is able to be joined via setns.
|
||||
type Namespace struct {
|
||||
|
|
|
@ -306,5 +306,11 @@ func (c *linuxContainer) currentState() (*State, error) {
|
|||
for _, ns := range c.config.Namespaces {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -130,7 +130,8 @@ func TestGetContainerState(t *testing.T) {
|
|||
{Type: configs.NEWNS},
|
||||
{Type: configs.NEWNET, Path: expectedNetworkPath},
|
||||
{Type: configs.NEWUTS},
|
||||
{Type: configs.NEWIPC},
|
||||
// emulate host for IPC
|
||||
//{Type: configs.NEWIPC},
|
||||
},
|
||||
},
|
||||
initProcess: &mockProcess{
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/libcontainer"
|
||||
"github.com/docker/libcontainer/cgroups/systemd"
|
||||
"github.com/docker/libcontainer/configs"
|
||||
)
|
||||
|
||||
|
@ -481,6 +482,17 @@ func TestProcessCaps(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() {
|
||||
return
|
||||
}
|
||||
|
@ -497,6 +509,9 @@ func TestFreeze(t *testing.T) {
|
|||
defer remove(rootfs)
|
||||
|
||||
config := newTemplateConfig(rootfs)
|
||||
if systemd {
|
||||
config.Cgroups.Slice = "system.slice"
|
||||
}
|
||||
|
||||
factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
|
||||
if err != nil {
|
||||
|
@ -559,3 +574,77 @@ func TestFreeze(t *testing.T) {
|
|||
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) {
|
||||
cgm := libcontainer.Cgroupfs
|
||||
if config.Cgroups != nil && config.Cgroups.Slice == "system.slice" {
|
||||
cgm = libcontainer.SystemdCgroups
|
||||
}
|
||||
|
||||
factory, err := libcontainer.New(".",
|
||||
libcontainer.InitArgs(os.Args[0], "init", "--"),
|
||||
libcontainer.Cgroupfs,
|
||||
cgm,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -13,7 +13,7 @@ func main() {
|
|||
app.Version = "2"
|
||||
app.Author = "libcontainer maintainers"
|
||||
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.BoolFlag{Name: "debug", Usage: "enable debug output in the logs"},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue