Merge remote-tracking branch 'dotcloud/master' into dhrp/docs
Conflicts: docker/docker.go docs/sources/installation/archlinux.rst docs/sources/installation/index.rst docs/sources/installation/ubuntulinux.rst runtime.go utils.go
This commit is contained in:
commit
5a5e417d46
8 changed files with 175 additions and 84 deletions
|
@ -150,6 +150,82 @@ func TestMultipleAttachRestart(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDiff(t *testing.T) {
|
||||||
|
runtime, err := newTestRuntime()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer nuke(runtime)
|
||||||
|
|
||||||
|
// Create a container and remove a file
|
||||||
|
container1, err := runtime.Create(
|
||||||
|
&Config{
|
||||||
|
Image: GetTestImage(runtime).Id,
|
||||||
|
Cmd: []string{"/bin/rm", "/etc/passwd"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container1)
|
||||||
|
|
||||||
|
if err := container1.Run(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the changelog
|
||||||
|
c, err := container1.Changes()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
success := false
|
||||||
|
for _, elem := range c {
|
||||||
|
if elem.Path == "/etc/passwd" && elem.Kind == 2 {
|
||||||
|
success = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !success {
|
||||||
|
t.Fatalf("/etc/passwd as been removed but is not present in the diff")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit the container
|
||||||
|
rwTar, err := container1.ExportRw()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image - diff", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new container from the commited image
|
||||||
|
container2, err := runtime.Create(
|
||||||
|
&Config{
|
||||||
|
Image: img.Id,
|
||||||
|
Cmd: []string{"cat", "/etc/passwd"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container2)
|
||||||
|
|
||||||
|
if err := container2.Run(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the changelog
|
||||||
|
c, err = container2.Changes()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for _, elem := range c {
|
||||||
|
if elem.Path == "/etc/passwd" {
|
||||||
|
t.Fatalf("/etc/passwd should not be present in the diff after commit.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCommitRun(t *testing.T) {
|
func TestCommitRun(t *testing.T) {
|
||||||
runtime, err := newTestRuntime()
|
runtime, err := newTestRuntime()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,9 +7,11 @@ import (
|
||||||
"github.com/dotcloud/docker/rcli"
|
"github.com/dotcloud/docker/rcli"
|
||||||
"github.com/dotcloud/docker/term"
|
"github.com/dotcloud/docker/term"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -54,8 +56,13 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPidFile(pidfile string) error {
|
func createPidFile(pidfile string) error {
|
||||||
if _, err := os.Stat(pidfile); err == nil {
|
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
|
||||||
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
|
pid, err := strconv.Atoi(string(pidString))
|
||||||
|
if err == nil {
|
||||||
|
if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
|
||||||
|
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Create(pidfile)
|
file, err := os.Create(pidfile)
|
||||||
|
|
|
@ -56,7 +56,10 @@ There is a systemd service unit created for docker. To start the docker service
|
||||||
|
|
||||||
sudo systemctl start docker
|
sudo systemctl start docker
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> dotcloud/master
|
||||||
To start on system boot:
|
To start on system boot:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
9
getKernelVersion_darwin.go
Normal file
9
getKernelVersion_darwin.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getKernelVersion() (*KernelVersionInfo, error) {
|
||||||
|
return nil, fmt.Errorf("Kernel version detection is not available on darwin")
|
||||||
|
}
|
69
getKernelVersion_linux.go
Normal file
69
getKernelVersion_linux.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getKernelVersion() (*KernelVersionInfo, error) {
|
||||||
|
var (
|
||||||
|
uts syscall.Utsname
|
||||||
|
flavor string
|
||||||
|
kernel, major, minor int
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := syscall.Uname(&uts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
release := make([]byte, len(uts.Release))
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, c := range uts.Release {
|
||||||
|
release[i] = byte(c)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the \x00 from the release for Atoi to parse correctly
|
||||||
|
release = release[:bytes.IndexByte(release, 0)]
|
||||||
|
|
||||||
|
tmp := strings.SplitN(string(release), "-", 2)
|
||||||
|
tmp2 := strings.SplitN(tmp[0], ".", 3)
|
||||||
|
|
||||||
|
if len(tmp2) > 0 {
|
||||||
|
kernel, err = strconv.Atoi(tmp2[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tmp2) > 1 {
|
||||||
|
major, err = strconv.Atoi(tmp2[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tmp2) > 2 {
|
||||||
|
minor, err = strconv.Atoi(tmp2[2])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tmp) == 2 {
|
||||||
|
flavor = tmp[1]
|
||||||
|
} else {
|
||||||
|
flavor = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return &KernelVersionInfo{
|
||||||
|
Kernel: kernel,
|
||||||
|
Major: major,
|
||||||
|
Minor: minor,
|
||||||
|
Flavor: flavor,
|
||||||
|
}, nil
|
||||||
|
}
|
27
image.go
27
image.go
|
@ -92,7 +92,7 @@ func MountAUFS(ro []string, rw string, target string) error {
|
||||||
rwBranch := fmt.Sprintf("%v=rw", rw)
|
rwBranch := fmt.Sprintf("%v=rw", rw)
|
||||||
roBranches := ""
|
roBranches := ""
|
||||||
for _, layer := range ro {
|
for _, layer := range ro {
|
||||||
roBranches += fmt.Sprintf("%v=ro:", layer)
|
roBranches += fmt.Sprintf("%v=ro+wh:", layer)
|
||||||
}
|
}
|
||||||
branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches)
|
branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches)
|
||||||
|
|
||||||
|
@ -136,34 +136,9 @@ func (image *Image) Mount(root, rw string) error {
|
||||||
if err := os.Mkdir(rw, 0755); err != nil && !os.IsExist(err) {
|
if err := os.Mkdir(rw, 0755); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// FIXME: @creack shouldn't we do this after going over changes?
|
|
||||||
if err := MountAUFS(layers, rw, root); err != nil {
|
if err := MountAUFS(layers, rw, root); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// FIXME: Create tests for deletion
|
|
||||||
// FIXME: move this part to change.go
|
|
||||||
// Retrieve the changeset from the parent and apply it to the container
|
|
||||||
// - Retrieve the changes
|
|
||||||
changes, err := Changes(layers, layers[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Iterate on changes
|
|
||||||
for _, c := range changes {
|
|
||||||
// If there is a delete
|
|
||||||
if c.Kind == ChangeDelete {
|
|
||||||
// Make sure the directory exists
|
|
||||||
file_path, file_name := path.Dir(c.Path), path.Base(c.Path)
|
|
||||||
if err := os.MkdirAll(path.Join(rw, file_path), 0755); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// And create the whiteout (we just need to create empty file, discard the return)
|
|
||||||
if _, err := os.Create(path.Join(path.Join(rw, file_path),
|
|
||||||
".wh."+path.Base(file_name))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
runtime.go
15
runtime.go
|
@ -295,14 +295,13 @@ func NewRuntime() (*Runtime, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
k, err := GetKernelVersion()
|
if k, err := GetKernelVersion(); err != nil {
|
||||||
if err != nil {
|
log.Printf("WARNING: %s\n", err)
|
||||||
return nil, err
|
} else {
|
||||||
}
|
runtime.kernelVersion = k
|
||||||
runtime.kernelVersion = k
|
if CompareKernelVersion(k, &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 {
|
||||||
|
log.Printf("WARNING: You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String())
|
||||||
if CompareKernelVersion(k, &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 {
|
}
|
||||||
log.Printf("WARNING: You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cgroupMemoryMountpoint, err := FindCgroupMountpoint("memory"); err != nil {
|
if cgroupMemoryMountpoint, err := FindCgroupMountpoint("memory"); err != nil {
|
||||||
|
|
49
utils.go
49
utils.go
|
@ -14,10 +14,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -407,52 +405,7 @@ type KernelVersionInfo struct {
|
||||||
|
|
||||||
// FIXME: this doens't build on Darwin
|
// FIXME: this doens't build on Darwin
|
||||||
func GetKernelVersion() (*KernelVersionInfo, error) {
|
func GetKernelVersion() (*KernelVersionInfo, error) {
|
||||||
var uts syscall.Utsname
|
return getKernelVersion()
|
||||||
|
|
||||||
if err := syscall.Uname(&uts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
release := make([]byte, len(uts.Release))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for _, c := range uts.Release {
|
|
||||||
release[i] = byte(c)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp := strings.SplitN(string(release), "-", 2)
|
|
||||||
if len(tmp) != 2 {
|
|
||||||
return nil, fmt.Errorf("Unrecognized kernel version")
|
|
||||||
}
|
|
||||||
tmp2 := strings.SplitN(tmp[0], ".", 3)
|
|
||||||
if len(tmp2) != 3 {
|
|
||||||
return nil, fmt.Errorf("Unrecognized kernel version")
|
|
||||||
}
|
|
||||||
|
|
||||||
kernel, err := strconv.Atoi(tmp2[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
major, err := strconv.Atoi(tmp2[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
minor, err := strconv.Atoi(tmp2[2])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
flavor := tmp[1]
|
|
||||||
|
|
||||||
return &KernelVersionInfo{
|
|
||||||
Kernel: kernel,
|
|
||||||
Major: major,
|
|
||||||
Minor: minor,
|
|
||||||
Flavor: flavor,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KernelVersionInfo) String() string {
|
func (k *KernelVersionInfo) String() string {
|
||||||
|
|
Loading…
Reference in a new issue