Compare commits

..

1 Commits

Author SHA1 Message Date
Jessica Frazelle 20d4e6f29e Bump version to v1.6.0
Docker-DCO-1.1-Signed-off-by: Jessie Frazelle <princess@docker.com> (github: jfrazelle)
2015-03-31 16:43:25 -07:00
11 changed files with 49 additions and 113 deletions
+1 -1
View File
@@ -1 +1 @@
1.6.0-rc4
1.6.0-rc3
+8 -16
View File
@@ -156,7 +156,11 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
startCallback(&c.ProcessConfig, pid)
}
oom := notifyOnOOM(cont)
oomKillNotification, err := cont.NotifyOOM()
if err != nil {
oomKillNotification = nil
log.Warnf("Your kernel does not support OOM notifications: %s", err)
}
waitF := p.Wait
if nss := cont.Config().Namespaces; !nss.Contains(configs.NEWPID) {
// we need such hack for tracking processes with inerited fds,
@@ -172,22 +176,10 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
ps = execErr.ProcessState
}
cont.Destroy()
_, oomKill := <-oom
return execdriver.ExitStatus{ExitCode: utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), OOMKilled: oomKill}, nil
}
// notifyOnOOM returns a channel that signals if the container received an OOM notification
// for any process. If it is unable to subscribe to OOM notifications then a closed
// channel is returned as it will be non-blocking and return the correct result when read.
func notifyOnOOM(container libcontainer.Container) <-chan struct{} {
oom, err := container.NotifyOOM()
if err != nil {
log.Warnf("Your kernel does not support OOM notifications: %s", err)
c := make(chan struct{})
close(c)
return c
}
return oom
_, oomKill := <-oomKillNotification
return execdriver.ExitStatus{ExitCode: utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), OOMKilled: oomKill}, nil
}
func waitInPIDHost(p *libcontainer.Process, c libcontainer.Container) func() (*os.ProcessState, error) {
+1 -1
View File
@@ -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 c8512754166539461fd860451ff1a0af7491c197
# 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')"
+4 -4
View File
@@ -67,12 +67,12 @@ func generateProfile(out io.Writer) error {
data := &data{
Name: "docker-default",
}
if tunablesExists() {
if tuntablesExists() {
data.Imports = append(data.Imports, "#include <tunables/global>")
} else {
data.Imports = append(data.Imports, "@{PROC}=/proc/")
}
if abstractionsExists() {
if abstrctionsEsists() {
data.InnerImports = append(data.InnerImports, "#include <abstractions/base>")
}
if err := compiled.Execute(out, data); err != nil {
@@ -82,13 +82,13 @@ func generateProfile(out io.Writer) error {
}
// check if the tunables/global exist
func tunablesExists() bool {
func tuntablesExists() bool {
_, err := os.Stat("/etc/apparmor.d/tunables/global")
return err == nil
}
// check if abstractions/base exist
func abstractionsExists() bool {
func abstrctionsEsists() bool {
_, err := os.Stat("/etc/apparmor.d/abstractions/base")
return err == nil
}
@@ -1,7 +1,6 @@
package fs
import (
"fmt"
"strings"
"time"
@@ -42,10 +41,6 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
}
time.Sleep(1 * time.Millisecond)
}
case configs.Undefined:
return nil
default:
return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Freezer))
}
return nil
@@ -1,45 +0,0 @@
package fs
import (
"testing"
"github.com/docker/libcontainer/configs"
)
func TestFreezerSetState(t *testing.T) {
helper := NewCgroupTestUtil("freezer", t)
defer helper.cleanup()
helper.writeFileContents(map[string]string{
"freezer.state": string(configs.Frozen),
})
helper.CgroupData.c.Freezer = configs.Thawed
freezer := &FreezerGroup{}
if err := freezer.Set(helper.CgroupPath, helper.CgroupData.c); err != nil {
t.Fatal(err)
}
value, err := getCgroupParamString(helper.CgroupPath, "freezer.state")
if err != nil {
t.Fatalf("Failed to parse freezer.state - %s", err)
}
if value != string(configs.Thawed) {
t.Fatal("Got the wrong value, set freezer.state failed.")
}
}
func TestFreezerSetInvalidState(t *testing.T) {
helper := NewCgroupTestUtil("freezer", t)
defer helper.cleanup()
const (
invalidArg configs.FreezerState = "Invalid"
)
helper.CgroupData.c.Freezer = invalidArg
freezer := &FreezerGroup{}
if err := freezer.Set(helper.CgroupPath, helper.CgroupData.c); err == nil {
t.Fatal("Failed to return invalid argument error")
}
}
@@ -218,7 +218,16 @@ func (m *Manager) Apply(pid int) error {
}
paths := make(map[string]string)
for sysname := range subsystems {
for _, sysname := range []string{
"devices",
"memory",
"cpu",
"cpuset",
"cpuacct",
"blkio",
"perf_event",
"freezer",
} {
subsystemPath, err := getSubsystemPath(m.Cgroups, sysname)
if err != nil {
// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
@@ -140,9 +140,7 @@ func (c *linuxContainer) commandTemplate(p *Process, childPipe *os.File) (*exec.
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.ExtraFiles = []*os.File{childPipe}
// NOTE: when running a container with no PID namespace and the parent process spawning the container is
// PID1 the pdeathsig is being delivered to the container's init process by the kernel for some reason
// even with the parent still running.
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
if c.config.ParentDeathSignal > 0 {
cmd.SysProcAttr.Pdeathsig = syscall.Signal(c.config.ParentDeathSignal)
}
+1 -2
View File
@@ -69,8 +69,7 @@ func newContainerInit(t initType, pipe *os.File) (initer, error) {
}, nil
case initStandard:
return &linuxStandardInit{
parentPid: syscall.Getppid(),
config: config,
config: config,
}, nil
}
return nil, fmt.Errorf("unknown init type %q", t)
+19 -29
View File
@@ -5,15 +5,13 @@ It is able to spawn new containers or join existing containers.
### How to build?
First add the `libcontainer/vendor` into your GOPATH. It's because libcontainer
vendors all its dependencies, so it can be built predictably.
First to add the `libcontainer/vendor` into your GOPATH. It's because something related with this [issue](https://github.com/docker/libcontainer/issues/210).
```
export GOPATH=$GOPATH:/your/path/to/libcontainer/vendor
```
Then get into the nsinit folder and get the imported file. Use `make` command
to make the nsinit binary.
Then get into the nsinit folder and get the imported file. Use `make` command to make the nsinit binary.
```
cd libcontainer/nsinit
@@ -21,8 +19,7 @@ go get
make
```
We have finished compiling the nsinit package, but a root filesystem must be
provided for use along with a container configuration file.
We have finished compiling the nsinit package, but a root filesystem must be provided for use along with a container configuration file.
Choose a proper place to run your container. For example we use `/busybox`.
@@ -31,37 +28,30 @@ mkdir /busybox
curl -sSL 'https://github.com/jpetazzo/docker-busybox/raw/buildroot-2014.11/rootfs.tar' | tar -xC /busybox
```
Then you may need to write a configuration file named `container.json` in the
`/busybox` folder. Environment, networking, and different capabilities for
the container are specified in this file. The configuration is used for each
process executed inside the container.
See the `sample_configs` folder for examples of what the container configuration
should look like.
Then you may need to write a configure file named `container.json` in the `/busybox` folder.
Environment, networking, and different capabilities for the container are specified in this file.
The configuration is used for each process executed inside the container
See the `sample_configs` folder for examples of what the container configuration should look like.
```
cp libcontainer/sample_configs/minimal.json /busybox/container.json
cd /busybox
```
You can customize `container.json` per your needs. After that, nsinit is
ready to work.
To execute `/bin/bash` in the current directory as a container just run the
following **as root**:
Now the nsinit is ready to work.
To execute `/bin/bash` in the current directory as a container just run the following **as root**:
```bash
nsinit exec --tty --config container.json /bin/bash
nsinit exec --tty /bin/bash
```
If you wish to spawn another process inside the container while your current
bash session is running, run the same command again to get another bash shell
(or change the command). If the original process (PID 1) dies, all other
processes spawned inside the container will be killed and the namespace will
be removed.
If you wish to spawn another process inside the container while your
current bash session is running, run the same command again to
get another bash shell (or change the command). If the original
process (PID 1) dies, all other processes spawned inside the container
will be killed and the namespace will be removed.
You can identify if a process is running in a container by looking to see if
`state.json` is in the root of the directory.
You can identify if a process is running in a container by
looking to see if `state.json` is in the root of the directory.
You may also specify an alternate root directory from where the `container.json`
file is read and where the `state.json` file will be saved.
You may also specify an alternate root place where
the `container.json` file is read and where the `state.json` file will be saved.
@@ -13,8 +13,7 @@ import (
)
type linuxStandardInit struct {
parentPid int
config *initConfig
config *initConfig
}
func (l *linuxStandardInit) Init() error {
@@ -86,10 +85,9 @@ func (l *linuxStandardInit) Init() error {
if err := pdeath.Restore(); err != nil {
return err
}
// compare the parent from the inital start of the init process and make sure that it did not change.
// if the parent changes that means it died and we were reparened to something else so we should
// just kill ourself and not cause problems for someone else.
if syscall.Getppid() != l.parentPid {
// Signal self if parent is already dead. Does nothing if running in a new
// PID namespace, as Getppid will always return 0.
if syscall.Getppid() == 1 {
return syscall.Kill(syscall.Getpid(), syscall.SIGKILL)
}
return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ())