mirror of
https://github.com/docker/cli.git
synced 2026-09-27 09:46:01 -04:00
Merge branch 'master' into pluginflag
Conflicts: pkg/cgroups/cgroups.go pkg/libcontainer/nsinit/exec.go pkg/libcontainer/nsinit/init.go pkg/libcontainer/nsinit/mount.go runconfig/hostconfig.go runconfig/parse.go runtime/execdriver/driver.go runtime/execdriver/lxc/lxc_template.go runtime/execdriver/lxc/lxc_template_unit_test.go runtime/execdriver/native/default_template.go runtime/execdriver/native/driver.go Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael) Upstream-commit: eab56ac007b263708b5526609c8be2bc19881467 Component: engine
This commit is contained in:
@@ -404,6 +404,7 @@ func populateCommand(c *Container) {
|
||||
User: c.Config.User,
|
||||
Config: driverConfig,
|
||||
Resources: resources,
|
||||
Context: c.Config.Context,
|
||||
}
|
||||
c.command.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||
}
|
||||
@@ -537,8 +538,18 @@ func (container *Container) Start() (err error) {
|
||||
|
||||
if container.Config.WorkingDir != "" {
|
||||
container.Config.WorkingDir = path.Clean(container.Config.WorkingDir)
|
||||
if err := os.MkdirAll(path.Join(container.basefs, container.Config.WorkingDir), 0755); err != nil {
|
||||
return nil
|
||||
|
||||
pthInfo, err := os.Stat(path.Join(container.basefs, container.Config.WorkingDir))
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(path.Join(container.basefs, container.Config.WorkingDir), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if pthInfo != nil && !pthInfo.IsDir() {
|
||||
return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,12 +916,20 @@ func (container *Container) Stop(seconds int) error {
|
||||
|
||||
// 1. Send a SIGTERM
|
||||
if err := container.KillSig(15); err != nil {
|
||||
return err
|
||||
utils.Debugf("Error sending kill SIGTERM: %s", err)
|
||||
log.Print("Failed to send SIGTERM to the process, force killing")
|
||||
if err := container.KillSig(9); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Wait for the process to exit on its own
|
||||
if err := container.WaitTimeout(time.Duration(seconds) * time.Second); err != nil {
|
||||
return err
|
||||
log.Printf("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds)
|
||||
// 3. If it doesn't, then send SIGKILL
|
||||
if err := container.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -952,10 +971,11 @@ func (container *Container) ExportRw() (archive.Archive, error) {
|
||||
return nil, err
|
||||
}
|
||||
return utils.NewReadCloserWrapper(archive, func() error {
|
||||
err := archive.Close()
|
||||
container.Unmount()
|
||||
return err
|
||||
}), nil
|
||||
err := archive.Close()
|
||||
container.Unmount()
|
||||
return err
|
||||
}),
|
||||
nil
|
||||
}
|
||||
|
||||
func (container *Container) Export() (archive.Archive, error) {
|
||||
@@ -969,10 +989,11 @@ func (container *Container) Export() (archive.Archive, error) {
|
||||
return nil, err
|
||||
}
|
||||
return utils.NewReadCloserWrapper(archive, func() error {
|
||||
err := archive.Close()
|
||||
container.Unmount()
|
||||
return err
|
||||
}), nil
|
||||
err := archive.Close()
|
||||
container.Unmount()
|
||||
return err
|
||||
}),
|
||||
nil
|
||||
}
|
||||
|
||||
func (container *Container) WaitTimeout(timeout time.Duration) error {
|
||||
@@ -1121,10 +1142,11 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) {
|
||||
return nil, err
|
||||
}
|
||||
return utils.NewReadCloserWrapper(archive, func() error {
|
||||
err := archive.Close()
|
||||
container.Unmount()
|
||||
return err
|
||||
}), nil
|
||||
err := archive.Close()
|
||||
container.Unmount()
|
||||
return err
|
||||
}),
|
||||
nil
|
||||
}
|
||||
|
||||
// Returns true if the container exposes a certain port
|
||||
|
||||
@@ -7,6 +7,10 @@ import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Context is a generic key value pair that allows
|
||||
// arbatrary data to be sent
|
||||
type Context map[string]string
|
||||
|
||||
var (
|
||||
ErrNotRunning = errors.New("Process could not be started")
|
||||
ErrWaitTimeoutReached = errors.New("Wait timeout reached")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lxc
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/pkg/label"
|
||||
"github.com/dotcloud/docker/runtime/execdriver"
|
||||
"strings"
|
||||
"text/template"
|
||||
@@ -29,6 +30,10 @@ lxc.pts = 1024
|
||||
|
||||
# disable the main console
|
||||
lxc.console = none
|
||||
{{if getProcessLabel .Context}}
|
||||
lxc.se_context = {{ getProcessLabel .Context}}
|
||||
{{$MOUNTLABEL := getMountLabel .Context}}
|
||||
{{end}}
|
||||
|
||||
# no controlling tty at all
|
||||
lxc.tty = 1
|
||||
@@ -85,8 +90,8 @@ lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noe
|
||||
lxc.mount.entry = {{.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw 0 0
|
||||
{{end}}
|
||||
|
||||
lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts newinstance,ptmxmode=0666,nosuid,noexec 0 0
|
||||
lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs size=65536k,nosuid,nodev,noexec 0 0
|
||||
lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts {{formatMountLabel "newinstance,ptmxmode=0666,nosuid,noexec" "$MOUNTLABEL"}} 0 0
|
||||
lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs {{formatMountLabel "size=65536k,nosuid,nodev,noexec" "$MOUNTLABEL"}} 0 0
|
||||
|
||||
{{range $value := .Mounts}}
|
||||
{{if $value.Writable}}
|
||||
@@ -142,11 +147,22 @@ func getMemorySwap(v *execdriver.Resources) int64 {
|
||||
return v.Memory * 2
|
||||
}
|
||||
|
||||
func getProcessLabel(c execdriver.Context) string {
|
||||
return c["process_label"]
|
||||
}
|
||||
|
||||
func getMountLabel(c execdriver.Context) string {
|
||||
return c["mount_label"]
|
||||
}
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
funcMap := template.FuncMap{
|
||||
"getMemorySwap": getMemorySwap,
|
||||
"getProcessLabel": getProcessLabel,
|
||||
"getMountLabel": getMountLabel,
|
||||
"escapeFstabSpaces": escapeFstabSpaces,
|
||||
"formatMountLabel": label.FormatMountLabel,
|
||||
}
|
||||
LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
|
||||
if err != nil {
|
||||
|
||||
@@ -75,10 +75,11 @@ func TestCustomLxcConfig(t *testing.T) {
|
||||
command := &execdriver.Command{
|
||||
ID: "1",
|
||||
Privileged: false,
|
||||
Config: map[string][]string{"lxc": {
|
||||
"lxc.utsname = docker",
|
||||
"lxc.cgroup.cpuset.cpus = 0,1",
|
||||
},
|
||||
Config: map[string][]string{
|
||||
"lxc": {
|
||||
"lxc.utsname = docker",
|
||||
"lxc.cgroup.cpuset.cpus = 0,1",
|
||||
},
|
||||
},
|
||||
Network: &execdriver.Network{
|
||||
Mtu: 1500,
|
||||
|
||||
@@ -134,7 +134,7 @@ func (a Driver) Exists(id string) bool {
|
||||
|
||||
// Three folders are created for each id
|
||||
// mnt, layers, and diff
|
||||
func (a *Driver) Create(id, parent string) error {
|
||||
func (a *Driver) Create(id, parent string, mountLabel string) error {
|
||||
if err := a.createDirsFor(id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ func TestCreateNewDir(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func TestCreateNewDirStructure(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ func TestRemoveImage(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ func TestGetWithoutParent(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ func TestCleanupWithDir(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ func TestMountedFalseResponse(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -204,10 +204,10 @@ func TestMountedTrueReponse(t *testing.T) {
|
||||
defer os.RemoveAll(tmp)
|
||||
defer d.Cleanup()
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := d.Create("2", "1"); err != nil {
|
||||
if err := d.Create("2", "1", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -230,10 +230,10 @@ func TestMountWithParent(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := d.Create("2", "1"); err != nil {
|
||||
if err := d.Create("2", "1", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -261,10 +261,10 @@ func TestRemoveMountedDir(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := d.Create("2", "1"); err != nil {
|
||||
if err := d.Create("2", "1", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ func TestCreateWithInvalidParent(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", "docker"); err == nil {
|
||||
if err := d.Create("1", "docker", ""); err == nil {
|
||||
t.Fatalf("Error should not be nil with parent does not exist")
|
||||
}
|
||||
}
|
||||
@@ -309,7 +309,7 @@ func TestGetDiff(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -343,10 +343,10 @@ func TestChanges(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := d.Create("2", "1"); err != nil {
|
||||
if err := d.Create("2", "1", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ func TestChanges(t *testing.T) {
|
||||
t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
|
||||
}
|
||||
|
||||
if err := d.Create("3", "2"); err != nil {
|
||||
if err := d.Create("3", "2", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mntPoint, err = d.Get("3")
|
||||
@@ -437,7 +437,7 @@ func TestDiffSize(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ func TestChildDiffSize(t *testing.T) {
|
||||
defer os.RemoveAll(tmp)
|
||||
defer d.Cleanup()
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ func TestChildDiffSize(t *testing.T) {
|
||||
t.Fatalf("Expected size to be %d got %d", size, diffSize)
|
||||
}
|
||||
|
||||
if err := d.Create("2", "1"); err != nil {
|
||||
if err := d.Create("2", "1", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -534,7 +534,7 @@ func TestExists(t *testing.T) {
|
||||
defer os.RemoveAll(tmp)
|
||||
defer d.Cleanup()
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ func TestStatus(t *testing.T) {
|
||||
defer os.RemoveAll(tmp)
|
||||
defer d.Cleanup()
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -581,7 +581,7 @@ func TestApplyDiff(t *testing.T) {
|
||||
defer os.RemoveAll(tmp)
|
||||
defer d.Cleanup()
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -607,10 +607,10 @@ func TestApplyDiff(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := d.Create("2", ""); err != nil {
|
||||
if err := d.Create("2", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := d.Create("3", "2"); err != nil {
|
||||
if err := d.Create("3", "2", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -656,7 +656,7 @@ func TestMountMoreThan42Layers(t *testing.T) {
|
||||
}
|
||||
current = hash(current)
|
||||
|
||||
if err := d.Create(current, parent); err != nil {
|
||||
if err := d.Create(current, parent, ""); err != nil {
|
||||
t.Logf("Current layer %d", i)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string) error) e
|
||||
}
|
||||
|
||||
initID := fmt.Sprintf("%s-init", id)
|
||||
if err := a.Create(initID, metadata.Image); err != nil {
|
||||
if err := a.Create(initID, metadata.Image, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ func (a *Driver) migrateContainers(pth string, setupInit func(p string) error) e
|
||||
return err
|
||||
}
|
||||
|
||||
if err := a.Create(id, initID); err != nil {
|
||||
if err := a.Create(id, initID, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func (a *Driver) migrateImage(m *metadata, pth string, migrated map[string]bool)
|
||||
return err
|
||||
}
|
||||
if !a.Exists(m.ID) {
|
||||
if err := a.Create(m.ID, m.ParentID); err != nil {
|
||||
if err := a.Create(m.ID, m.ParentID, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ func getDirFd(dir *C.DIR) uintptr {
|
||||
return uintptr(C.dirfd(dir))
|
||||
}
|
||||
|
||||
func subvolCreate(path, name string) error {
|
||||
func subvolCreate(path, name string, mountLabel string) error {
|
||||
dir, err := openDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -155,13 +155,13 @@ func (d *Driver) subvolumesDirId(id string) string {
|
||||
return path.Join(d.subvolumesDir(), id)
|
||||
}
|
||||
|
||||
func (d *Driver) Create(id string, parent string) error {
|
||||
func (d *Driver) Create(id string, parent string, mountLabel string) error {
|
||||
subvolumes := path.Join(d.home, "subvolumes")
|
||||
if err := os.MkdirAll(subvolumes, 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
if parent == "" {
|
||||
if err := subvolCreate(subvolumes, id); err != nil {
|
||||
if err := subvolCreate(subvolumes, id, mountLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/pkg/label"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -677,6 +679,12 @@ func (devices *DeviceSet) deactivateDevice(hash string) error {
|
||||
utils.Debugf("[devmapper] deactivateDevice(%s)", hash)
|
||||
defer utils.Debugf("[devmapper] deactivateDevice END")
|
||||
|
||||
// Wait for the unmount to be effective,
|
||||
// by watching the value of Info.OpenCount for the device
|
||||
if err := devices.waitClose(hash); err != nil {
|
||||
utils.Errorf("Warning: error waiting for device %s to close: %s\n", hash, err)
|
||||
}
|
||||
|
||||
info := devices.Devices[hash]
|
||||
if info == nil {
|
||||
return fmt.Errorf("Unknown device %s", hash)
|
||||
@@ -799,26 +807,20 @@ func (devices *DeviceSet) Shutdown() error {
|
||||
for _, info := range devices.Devices {
|
||||
info.lock.Lock()
|
||||
if info.mountCount > 0 {
|
||||
if err := sysUnmount(info.mountPath, 0); err != nil {
|
||||
// We use MNT_DETACH here in case it is still busy in some running
|
||||
// container. This means it'll go away from the global scope directly,
|
||||
// and the device will be released when that container dies.
|
||||
if err := sysUnmount(info.mountPath, syscall.MNT_DETACH); err != nil {
|
||||
utils.Debugf("Shutdown unmounting %s, error: %s\n", info.mountPath, err)
|
||||
}
|
||||
|
||||
if err := devices.deactivateDevice(info.Hash); err != nil {
|
||||
utils.Debugf("Shutdown deactivate %s , error: %s\n", info.Hash, err)
|
||||
}
|
||||
}
|
||||
info.lock.Unlock()
|
||||
}
|
||||
|
||||
for _, d := range devices.Devices {
|
||||
d.lock.Lock()
|
||||
|
||||
if err := devices.waitClose(d.Hash); err != nil {
|
||||
utils.Errorf("Warning: error waiting for device %s to unmount: %s\n", d.Hash, err)
|
||||
}
|
||||
if err := devices.deactivateDevice(d.Hash); err != nil {
|
||||
utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err)
|
||||
}
|
||||
|
||||
d.lock.Unlock()
|
||||
}
|
||||
|
||||
if err := devices.deactivatePool(); err != nil {
|
||||
utils.Debugf("Shutdown deactivate pool , error: %s\n", err)
|
||||
}
|
||||
@@ -826,7 +828,7 @@ func (devices *DeviceSet) Shutdown() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (devices *DeviceSet) MountDevice(hash, path string) error {
|
||||
func (devices *DeviceSet) MountDevice(hash, path string, mountLabel string) error {
|
||||
devices.Lock()
|
||||
defer devices.Unlock()
|
||||
|
||||
@@ -858,9 +860,11 @@ func (devices *DeviceSet) MountDevice(hash, path string) error {
|
||||
|
||||
var flags uintptr = sysMsMgcVal
|
||||
|
||||
err := sysMount(info.DevName(), path, "ext4", flags, "discard")
|
||||
mountOptions := label.FormatMountLabel("discard", mountLabel)
|
||||
err := sysMount(info.DevName(), path, "ext4", flags, mountOptions)
|
||||
if err != nil && err == sysEInval {
|
||||
err = sysMount(info.DevName(), path, "ext4", flags, "")
|
||||
mountOptions = label.FormatMountLabel(mountLabel, "")
|
||||
err = sysMount(info.DevName(), path, "ext4", flags, mountOptions)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err)
|
||||
@@ -920,14 +924,11 @@ func (devices *DeviceSet) UnmountDevice(hash string, mode UnmountMode) error {
|
||||
return err
|
||||
}
|
||||
utils.Debugf("[devmapper] Unmount done")
|
||||
// Wait for the unmount to be effective,
|
||||
// by watching the value of Info.OpenCount for the device
|
||||
if err := devices.waitClose(hash); err != nil {
|
||||
|
||||
if err := devices.deactivateDevice(hash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
devices.deactivateDevice(hash)
|
||||
|
||||
info.mountPath = ""
|
||||
|
||||
return nil
|
||||
|
||||
@@ -22,7 +22,8 @@ func init() {
|
||||
|
||||
type Driver struct {
|
||||
*DeviceSet
|
||||
home string
|
||||
home string
|
||||
MountLabel string
|
||||
}
|
||||
|
||||
var Init = func(home string) (graphdriver.Driver, error) {
|
||||
@@ -60,13 +61,13 @@ func (d *Driver) Cleanup() error {
|
||||
return d.DeviceSet.Shutdown()
|
||||
}
|
||||
|
||||
func (d *Driver) Create(id, parent string) error {
|
||||
func (d *Driver) Create(id, parent string, mountLabel string) error {
|
||||
d.MountLabel = mountLabel
|
||||
if err := d.DeviceSet.AddDevice(id, parent); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mp := path.Join(d.home, "mnt", id)
|
||||
if err := d.mount(id, mp); err != nil {
|
||||
if err := d.mount(id, mp, d.MountLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ func (d *Driver) Remove(id string) error {
|
||||
|
||||
func (d *Driver) Get(id string) (string, error) {
|
||||
mp := path.Join(d.home, "mnt", id)
|
||||
if err := d.mount(id, mp); err != nil {
|
||||
if err := d.mount(id, mp, d.MountLabel); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -129,13 +130,13 @@ func (d *Driver) Put(id string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) mount(id, mountPoint string) error {
|
||||
func (d *Driver) mount(id, mountPoint string, mountLabel string) error {
|
||||
// Create the target directories if they don't exist
|
||||
if err := osMkdirAll(mountPoint, 0755); err != nil && !osIsExist(err) {
|
||||
return err
|
||||
}
|
||||
// Mount the device
|
||||
return d.DeviceSet.MountDevice(id, mountPoint)
|
||||
return d.DeviceSet.MountDevice(id, mountPoint, mountLabel)
|
||||
}
|
||||
|
||||
func (d *Driver) Exists(id string) bool {
|
||||
|
||||
@@ -494,7 +494,7 @@ func TestDriverCreate(t *testing.T) {
|
||||
"?ioctl.loopctlgetfree",
|
||||
)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
calls.Assert(t,
|
||||
@@ -612,7 +612,7 @@ func TestDriverRemove(t *testing.T) {
|
||||
"?ioctl.loopctlgetfree",
|
||||
)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -668,7 +668,7 @@ func TestCleanup(t *testing.T) {
|
||||
|
||||
mountPoints := make([]string, 2)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Mount the id
|
||||
@@ -678,7 +678,7 @@ func TestCleanup(t *testing.T) {
|
||||
}
|
||||
mountPoints[0] = p
|
||||
|
||||
if err := d.Create("2", "1"); err != nil {
|
||||
if err := d.Create("2", "1", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -731,7 +731,7 @@ func TestNotMounted(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer cleanup(d)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -749,7 +749,7 @@ func TestMounted(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer cleanup(d)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := d.Get("1"); err != nil {
|
||||
@@ -769,7 +769,7 @@ func TestInitCleanedDriver(t *testing.T) {
|
||||
t.Skip("FIXME: not a unit test")
|
||||
d := newDriver(t)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := d.Get("1"); err != nil {
|
||||
@@ -797,7 +797,7 @@ func TestMountMountedDriver(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer cleanup(d)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -816,7 +816,7 @@ func TestGetReturnsValidDevice(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer cleanup(d)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -844,7 +844,7 @@ func TestDriverGetSize(t *testing.T) {
|
||||
d := newDriver(t)
|
||||
defer cleanup(d)
|
||||
|
||||
if err := d.Create("1", ""); err != nil {
|
||||
if err := d.Create("1", "", ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ type InitFunc func(root string) (Driver, error)
|
||||
type Driver interface {
|
||||
String() string
|
||||
|
||||
Create(id, parent string) error
|
||||
Create(id, parent string, mountLabel string) error
|
||||
Remove(id string) error
|
||||
|
||||
Get(id string) (dir string, err error)
|
||||
@@ -39,10 +39,9 @@ var (
|
||||
// Slice of drivers that should be used in an order
|
||||
priority = []string{
|
||||
"aufs",
|
||||
"btrfs",
|
||||
"devicemapper",
|
||||
"vfs",
|
||||
// experimental, has to be enabled manually for now
|
||||
"btrfs",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ func copyDir(src, dst string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Create(id string, parent string) error {
|
||||
func (d *Driver) Create(id string, parent string, mountLabel string) error {
|
||||
dir := d.dir(id)
|
||||
if err := os.MkdirAll(path.Dir(dir), 0700); err != nil {
|
||||
return err
|
||||
|
||||
+7
-1
@@ -1,4 +1,4 @@
|
||||
package lxc
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -93,6 +93,12 @@ func InitDriver(job *engine.Job) engine.Status {
|
||||
network = addr.(*net.IPNet)
|
||||
} else {
|
||||
network = addr.(*net.IPNet)
|
||||
// validate that the bridge ip matches the ip specified by BridgeIP
|
||||
if bridgeIP != "" {
|
||||
if !network.IP.Equal(net.ParseIP(bridgeIP)) {
|
||||
return job.Errorf("bridge ip (%s) does not match existing bridge configuration %s", network.IP, bridgeIP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Configure iptables for link support
|
||||
@@ -100,22 +100,30 @@ func ReleaseAll() error {
|
||||
}
|
||||
|
||||
func registerDynamicPort(ip net.IP, proto string) (int, error) {
|
||||
allocated := defaultAllocatedPorts[proto]
|
||||
|
||||
port := nextPort(proto)
|
||||
if port > EndPortRange {
|
||||
return 0, ErrPortExceedsRange
|
||||
}
|
||||
|
||||
if !equalsDefault(ip) {
|
||||
registerIP(ip)
|
||||
|
||||
ipAllocated := otherAllocatedPorts[ip.String()][proto]
|
||||
|
||||
port, err := findNextPort(proto, ipAllocated)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ipAllocated.Push(port)
|
||||
return port, nil
|
||||
|
||||
} else {
|
||||
|
||||
allocated := defaultAllocatedPorts[proto]
|
||||
|
||||
port, err := findNextPort(proto, allocated)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
allocated.Push(port)
|
||||
return port, nil
|
||||
}
|
||||
return port, nil
|
||||
}
|
||||
|
||||
func registerSetPort(ip net.IP, proto string, port int) error {
|
||||
@@ -142,6 +150,17 @@ func equalsDefault(ip net.IP) bool {
|
||||
return ip == nil || ip.Equal(defaultIP)
|
||||
}
|
||||
|
||||
func findNextPort(proto string, allocated *collections.OrderedIntSet) (int, error) {
|
||||
port := nextPort(proto)
|
||||
for allocated.Exists(port) {
|
||||
port = nextPort(proto)
|
||||
}
|
||||
if port > EndPortRange {
|
||||
return 0, ErrPortExceedsRange
|
||||
}
|
||||
return port, nil
|
||||
}
|
||||
|
||||
func nextPort(proto string) int {
|
||||
c := currentDynamicPort[proto] + 1
|
||||
currentDynamicPort[proto] = c
|
||||
|
||||
@@ -181,4 +181,20 @@ func TestPortAllocation(t *testing.T) {
|
||||
if _, err := RequestPort(ip, "tcp", 80); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
port, err = RequestPort(ip, "tcp", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port2, err := RequestPort(ip, "tcp", port+1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port3, err := RequestPort(ip, "tcp", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if port3 == port2 {
|
||||
t.Fatal("Requesting a dynamic port should never allocate a used port")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/dotcloud/docker/runtime/execdriver/lxc"
|
||||
"github.com/dotcloud/docker/runtime/graphdriver"
|
||||
_ "github.com/dotcloud/docker/runtime/graphdriver/vfs"
|
||||
_ "github.com/dotcloud/docker/runtime/networkdriver/lxc"
|
||||
_ "github.com/dotcloud/docker/runtime/networkdriver/bridge"
|
||||
"github.com/dotcloud/docker/runtime/networkdriver/portallocator"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"io"
|
||||
@@ -467,7 +467,7 @@ func (runtime *Runtime) Create(config *runconfig.Config, name string) (*Containe
|
||||
}
|
||||
|
||||
initID := fmt.Sprintf("%s-init", container.ID)
|
||||
if err := runtime.driver.Create(initID, img.ID); err != nil {
|
||||
if err := runtime.driver.Create(initID, img.ID, config.Context["mount_label"]); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
initPath, err := runtime.driver.Get(initID)
|
||||
@@ -480,7 +480,7 @@ func (runtime *Runtime) Create(config *runconfig.Config, name string) (*Containe
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := runtime.driver.Create(container.ID, initID); err != nil {
|
||||
if err := runtime.driver.Create(container.ID, initID, config.Context["mount_label"]); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resolvConf, err := utils.GetResolvConf()
|
||||
|
||||
@@ -28,6 +28,9 @@ func (s *State) String() string {
|
||||
}
|
||||
return fmt.Sprintf("Up %s", utils.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
|
||||
}
|
||||
if s.FinishedAt.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, utils.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user