mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Update libcontainer to c8512754166539461fd860451ff
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
2742bf5cbc
commit
17ecbcf8ff
9 changed files with 215 additions and 24 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 a6044b701c166fe538fc760f9e2dcea3d737cd2a
|
||||
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')"
|
||||
|
|
|
@ -220,16 +220,16 @@ func getCgroupData(c *configs.Cgroup, pid int) (*data, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (raw *data) parent(subsystem string) (string, error) {
|
||||
func (raw *data) parent(subsystem, mountpoint string) (string, error) {
|
||||
initPath, err := cgroups.GetInitCgroupDir(subsystem)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(raw.root, subsystem, initPath), nil
|
||||
return filepath.Join(mountpoint, initPath), nil
|
||||
}
|
||||
|
||||
func (raw *data) path(subsystem string) (string, error) {
|
||||
_, err := cgroups.FindCgroupMountpoint(subsystem)
|
||||
mnt, err := cgroups.FindCgroupMountpoint(subsystem)
|
||||
// If we didn't mount the subsystem, there is no point we make the path.
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -240,7 +240,7 @@ func (raw *data) path(subsystem string) (string, error) {
|
|||
return filepath.Join(raw.root, subsystem, raw.cgroup), nil
|
||||
}
|
||||
|
||||
parent, err := raw.parent(subsystem)
|
||||
parent, err := raw.parent(subsystem, mnt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -43,6 +43,10 @@ var subsystems = map[string]subsystem{
|
|||
"freezer": &fs.FreezerGroup{},
|
||||
}
|
||||
|
||||
const (
|
||||
testScopeWait = 4
|
||||
)
|
||||
|
||||
var (
|
||||
connLock sync.Mutex
|
||||
theConn *systemd.Conn
|
||||
|
@ -86,16 +90,41 @@ func UseSystemd() bool {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure the scope name we use doesn't exist. Use the Pid to
|
||||
// avoid collisions between multiple libcontainer users on a
|
||||
// single host.
|
||||
scope := fmt.Sprintf("libcontainer-%d-systemd-test-default-dependencies.scope", os.Getpid())
|
||||
testScopeExists := true
|
||||
for i := 0; i <= testScopeWait; i++ {
|
||||
if _, err := theConn.StopUnit(scope, "replace"); err != nil {
|
||||
if dbusError, ok := err.(dbus.Error); ok {
|
||||
if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") {
|
||||
testScopeExists = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
|
||||
// Bail out if we can't kill this scope without testing for DefaultDependencies
|
||||
if testScopeExists {
|
||||
return hasStartTransientUnit
|
||||
}
|
||||
|
||||
// Assume StartTransientUnit on a scope allows DefaultDependencies
|
||||
hasTransientDefaultDependencies = true
|
||||
ddf := newProp("DefaultDependencies", false)
|
||||
if _, err := theConn.StartTransientUnit("docker-systemd-test-default-dependencies.scope", "replace", ddf); err != nil {
|
||||
if _, err := theConn.StartTransientUnit(scope, "replace", ddf); err != nil {
|
||||
if dbusError, ok := err.(dbus.Error); ok {
|
||||
if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") {
|
||||
hasTransientDefaultDependencies = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not critical because of the stop unit logic above.
|
||||
theConn.StopUnit(scope, "replace")
|
||||
}
|
||||
return hasStartTransientUnit
|
||||
}
|
||||
|
|
|
@ -193,12 +193,13 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe,
|
|||
|
||||
func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
|
||||
return &initConfig{
|
||||
Config: c.config,
|
||||
Args: process.Args,
|
||||
Env: process.Env,
|
||||
User: process.User,
|
||||
Cwd: process.Cwd,
|
||||
Console: process.consolePath,
|
||||
Config: c.config,
|
||||
Args: process.Args,
|
||||
Env: process.Env,
|
||||
User: process.User,
|
||||
Cwd: process.Cwd,
|
||||
Console: process.consolePath,
|
||||
Capabilities: process.Capabilities,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,13 +40,14 @@ type network struct {
|
|||
|
||||
// initConfig is used for transferring parameters from Exec() to Init()
|
||||
type initConfig struct {
|
||||
Args []string `json:"args"`
|
||||
Env []string `json:"env"`
|
||||
Cwd string `json:"cwd"`
|
||||
User string `json:"user"`
|
||||
Config *configs.Config `json:"config"`
|
||||
Console string `json:"console"`
|
||||
Networks []*network `json:"network"`
|
||||
Args []string `json:"args"`
|
||||
Env []string `json:"env"`
|
||||
Cwd string `json:"cwd"`
|
||||
Capabilities []string `json:"capabilities"`
|
||||
User string `json:"user"`
|
||||
Config *configs.Config `json:"config"`
|
||||
Console string `json:"console"`
|
||||
Networks []*network `json:"network"`
|
||||
}
|
||||
|
||||
type initer interface {
|
||||
|
@ -99,7 +100,12 @@ func finalizeNamespace(config *initConfig) error {
|
|||
if err := utils.CloseExecFrom(3); err != nil {
|
||||
return err
|
||||
}
|
||||
w, err := newCapWhitelist(config.Config.Capabilities)
|
||||
|
||||
capabilities := config.Config.Capabilities
|
||||
if config.Capabilities != nil {
|
||||
capabilities = config.Capabilities
|
||||
}
|
||||
w, err := newCapWhitelist(capabilities)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -395,6 +396,90 @@ func TestProcessEnv(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProcessCaps(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)
|
||||
|
||||
config := newTemplateConfig(rootfs)
|
||||
|
||||
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()
|
||||
|
||||
processCaps := append(config.Capabilities, "NET_ADMIN")
|
||||
|
||||
var stdout bytes.Buffer
|
||||
pconfig := libcontainer.Process{
|
||||
Args: []string{"sh", "-c", "cat /proc/self/status"},
|
||||
Env: standardEnvironment,
|
||||
Capabilities: processCaps,
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
}
|
||||
err = container.Start(&pconfig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Wait for process
|
||||
waitProcess(&pconfig, t)
|
||||
|
||||
outputStatus := string(stdout.Bytes())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
lines := strings.Split(outputStatus, "\n")
|
||||
|
||||
effectiveCapsLine := ""
|
||||
for _, l := range lines {
|
||||
line := strings.TrimSpace(l)
|
||||
if strings.Contains(line, "CapEff:") {
|
||||
effectiveCapsLine = line
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if effectiveCapsLine == "" {
|
||||
t.Fatal("Couldn't find effective caps: ", outputStatus)
|
||||
}
|
||||
|
||||
parts := strings.Split(effectiveCapsLine, ":")
|
||||
effectiveCapsStr := strings.TrimSpace(parts[1])
|
||||
|
||||
effectiveCaps, err := strconv.ParseUint(effectiveCapsStr, 16, 64)
|
||||
if err != nil {
|
||||
t.Fatal("Could not parse effective caps", err)
|
||||
}
|
||||
|
||||
var netAdminMask uint64
|
||||
var netAdminBit uint
|
||||
netAdminBit = 12 // from capability.h
|
||||
netAdminMask = 1 << netAdminBit
|
||||
if effectiveCaps&netAdminMask != netAdminMask {
|
||||
t.Fatal("CAP_NET_ADMIN is not set as expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFreeze(t *testing.T) {
|
||||
if testing.Short() {
|
||||
return
|
||||
|
|
57
vendor/src/github.com/docker/libcontainer/nsinit/README.md
vendored
Normal file
57
vendor/src/github.com/docker/libcontainer/nsinit/README.md
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
## nsinit
|
||||
|
||||
`nsinit` is a cli application which demonstrates the use of libcontainer.
|
||||
It is able to spawn new containers or join existing containers.
|
||||
|
||||
### How to build?
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
cd libcontainer/nsinit
|
||||
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.
|
||||
|
||||
Choose a proper place to run your container. For example we use `/busybox`.
|
||||
|
||||
```
|
||||
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 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
|
||||
```
|
||||
|
||||
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 /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.
|
||||
|
||||
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 place where
|
||||
the `container.json` file is read and where the `state.json` file will be saved.
|
|
@ -41,6 +41,10 @@ type Process struct {
|
|||
// consolePath is the path to the console allocated to the container.
|
||||
consolePath string
|
||||
|
||||
// Capabilities specify the capabilities to keep when executing the process inside the container
|
||||
// All capbilities not specified will be dropped from the processes capability mask
|
||||
Capabilities []string
|
||||
|
||||
ops processOperations
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ package libcontainer
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -44,8 +45,12 @@ func (p *setnsProcess) startTime() (string, error) {
|
|||
return system.GetProcessStartTime(p.pid())
|
||||
}
|
||||
|
||||
func (p *setnsProcess) signal(s os.Signal) error {
|
||||
return p.cmd.Process.Signal(s)
|
||||
func (p *setnsProcess) signal(sig os.Signal) error {
|
||||
s, ok := sig.(syscall.Signal)
|
||||
if !ok {
|
||||
return errors.New("os: unsupported signal type")
|
||||
}
|
||||
return syscall.Kill(p.cmd.Process.Pid, s)
|
||||
}
|
||||
|
||||
func (p *setnsProcess) start() (err error) {
|
||||
|
@ -235,6 +240,10 @@ func (p *initProcess) createNetworkInterfaces() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *initProcess) signal(s os.Signal) error {
|
||||
return p.cmd.Process.Signal(s)
|
||||
func (p *initProcess) signal(sig os.Signal) error {
|
||||
s, ok := sig.(syscall.Signal)
|
||||
if !ok {
|
||||
return errors.New("os: unsupported signal type")
|
||||
}
|
||||
return syscall.Kill(p.cmd.Process.Pid, s)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue