Compare commits

...

38 Commits

Author SHA1 Message Date
Solomon Hykes d42639e5c5 Bumped version to 0.2.1 2013-05-01 17:17:13 -07:00
Solomon Hykes e7fb7f13d5 new Dockerfile keyword: cmd to set a default runtime command 2013-05-01 16:43:37 -07:00
Solomon Hykes ad86dde10c * 'docker commit' inherits parent layer's run configuration by default 2013-05-01 15:45:39 -07:00
Guillaume J. Charmes a75a1b3859 When no -config is set while committing, use the config of the base image 2013-05-01 15:24:28 -07:00
Solomon Hykes 08812096f5 New Dockerfile operation 'expose' exposes default tcp ports 2013-05-01 14:16:56 -07:00
Solomon Hykes 5c30faf6f7 Set a layer's default runtime options with 'docker commit -run' instead of 'docker commit -config' 2013-05-01 12:45:45 -07:00
Solomon Hykes f7aaa06606 + Commit default runtime options with a layer 2013-05-01 11:33:21 -07:00
Guillaume J. Charmes 7ff65d40d5 Actually use the mergeConfig function 2013-05-01 11:22:06 -07:00
Solomon Hykes a3ce90b78b Added dummy script for docker-build example 2013-05-01 00:49:28 -07:00
Solomon Hykes 03b83b3210 Fix example dockerfile 2013-05-01 00:44:36 -07:00
Solomon Hykes 40ccf1d300 new Dockerfile keyword: 'push' 2013-05-01 00:42:11 -07:00
Solomon Hykes 038ca5ee39 docker-build: added support for 'maintainer' keyword 2013-05-01 00:14:52 -07:00
Solomon Hykes 957c500ac9 Merge pull request #485 from brunoqc/patch-1
* Packaging: connect to Ubuntu key server on port 80
2013-04-30 15:46:57 -07:00
Guillaume J. Charmes 62a595da5c Merge pull request #488 from tobert/cgroups-via-proc-mounts
* runtime: Use /proc/mounts instead of mount(8)
2013-04-30 14:39:14 -07:00
Guillaume J. Charmes d97661aa71 Improve crashTest 2013-04-30 11:16:26 -07:00
Al Tobey c6119da339 Use /proc/mounts instead of mount(8)
Specifically, Ubuntu Precise's cgroup-lite script uses mount -n
to mount the cgroup filesystems so they don't appear in mtab, so
detection always fails unless the admin updates mtab with /proc/mounts.

/proc/mounts is valid on just about every Linux machine in existence and
as a bonus is much easier to parse.

I also removed the regex in favor of a more accurate parser that should
also support monolitic cgroup mounts (e.g. mount -t cgroup none /cgroup).
2013-04-30 17:37:43 +00:00
Bruno Bigras 5051c20833 Use the 80 port with keyserver.ubuntu.com
Use the 80 port with keyserver.ubuntu.com so it works with corporate firewalls
2013-04-29 15:53:50 -03:00
Guillaume J. Charmes cdc2657ee9 Improve crashTest 2013-04-28 07:10:58 -07:00
Guillaume J. Charmes 76a1a7cf5b Simplify the crashTest 2013-04-28 06:23:02 -07:00
Guillaume J. Charmes 20c2a4f80f add network endpoint for crashTest 2013-04-28 03:54:22 -07:00
Guillaume J. Charmes ebe157ebb5 Update the crashTest to have the dockerpath in env 2013-04-28 01:27:56 -07:00
Solomon Hykes cb431f223f Merge pull request #484 from tianon/mkimage-debian
* Contrib: updated mkimage-debian
2013-04-29 12:12:02 -07:00
Tianon Gravi ab34115b42 Use default mirror from debootstrap when not explicitly provided, and add better target directory naming 2013-04-28 13:38:26 -06:00
Tianon Gravi 4b3354af3f Improve mkimage-debian script to also tag using the release version number of the final image (6.0.7, 7.0, etc.)
This is as discussed on #447.
2013-04-28 12:31:28 -06:00
Guillaume J. Charmes 8f81e175af Merge pull request #473 from dotcloud/26-auto_restart_containers-feature
+ runtime: Add -r flag to dockerd in order to restart previously running container....
2013-04-26 14:02:01 -07:00
Guillaume J. Charmes 636c7835d3 Merge pull request #467 from dotcloud/improve_localhost_port_test
* tests: Improve unit test to avoid unnecessary warnigns
2013-04-26 14:01:13 -07:00
Guillaume J. Charmes 6d1dd8b41a Merge pull request #478 from tianon/mkimage-debian
+ contrib: Add contrib/mkimage-debian.sh used to create the tianon/debian images
2013-04-26 13:51:47 -07:00
Guillaume J. Charmes ae97477284 Remove -command in CmdCommit and make -config use Json 2013-04-26 10:48:33 -07:00
Tianon Gravi 86ad98e72a Add contrib/mkimage-debian.sh used to create the tianon/debian images 2013-04-26 08:54:29 -06:00
Solomon Hykes 03d82922aa Merge pull request #474 from brianm/vmware_fusion_provider
Support for VMWare Fusion Provider in Vagrantfile
2013-04-26 01:31:11 -07:00
Brian McCallister 4db680fda4 don't fight the box kernel version, not worth it 2013-04-25 06:29:13 -06:00
Brian McCallister 9c7293508d get aufs dependencies into vmware image 2013-04-25 06:09:04 -06:00
Brian McCallister 9d8743a7ae vmware fusion provider config 2013-04-25 05:59:31 -06:00
Guillaume J. Charmes 50144aeb42 Add -r flag to dockerd in order to restart previously running container. Fixes #26 2013-04-24 19:01:23 -07:00
Guillaume J. Charmes 6ebb249131 Remove unecessary memeory limit within tests 2013-04-23 11:25:16 -07:00
Guillaume J. Charmes c45beabcd5 Improve TestMultipleAttachRestart to avoid unnecessary warning 2013-04-23 11:22:30 -07:00
Guillaume J. Charmes a22c78523f Wait for the container to finish in TestAttachDisconnect before destroying it 2013-04-23 11:09:48 -07:00
Guillaume J. Charmes 5a02c9ba0a Make sure the container is well started prior to perform the test 2013-04-23 11:08:31 -07:00
16 changed files with 280 additions and 98 deletions
+10
View File
@@ -1,5 +1,15 @@
# Changelog
## 0.2.1 (2012-05-01)
+ 'docker commit -run' bundles a layer with default runtime options: command, ports etc.
* Improve install process on Vagrant
+ New Dockerfile operation: "maintainer"
+ New Dockerfile operation: "expose"
+ New Dockerfile operation: "cmd"
+ Contrib script to build a Debian base layer
+ 'docker -d -r': restart crashed containers at daemon startup
* Runtime: improve test coverage
## 0.2.0 (2012-04-23)
- Runtime: ghost containers can be killed and waited for
* Documentation: update install intructions
Vendored
+9 -1
View File
@@ -10,7 +10,7 @@ Vagrant::Config.run do |config|
config.vm.box = BOX_NAME
config.vm.box_url = BOX_URI
# Add docker PPA key to the local repository and install docker
pkg_cmd = "apt-key adv --keyserver keyserver.ubuntu.com --recv-keys #{PPA_KEY}; "
pkg_cmd = "apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys #{PPA_KEY}; "
pkg_cmd << "echo 'deb http://ppa.launchpad.net/dotcloud/lxc-docker/ubuntu precise main' >>/etc/apt/sources.list; "
pkg_cmd << "apt-get update -qq; apt-get install -q -y lxc-docker"
if ARGV.include?("--provider=aws".downcase)
@@ -50,4 +50,12 @@ Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
config.vm.box = BOX_NAME
config.vm.box_url = BOX_URI
end
config.vm.provider :vmware_fusion do |vm|
config.vm.box = "precise64"
config.vm.box_url = "http://files.vagrantup.com/precise64_vmware_fusion.box"
config.vm.provision :shell, :inline => <<-UPDATE
apt-get install -y linux-image-extra-3.2.0-29-virtual
UPDATE
end
end
+10 -17
View File
@@ -18,7 +18,7 @@ import (
"unicode"
)
const VERSION = "0.2.0"
const VERSION = "0.2.1"
var (
GIT_COMMIT string
@@ -726,8 +726,7 @@ func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...stri
"Create a new image from a container's changes")
flComment := cmd.String("m", "", "Commit message")
flAuthor := cmd.String("author", "", "Author (eg. \"John Hannibal Smith <hannibal@a-team.com>\"")
flConfig := cmd.String("config", "", "Config automatically applied when the image is run. This option must be the last one.")
flCommand := cmd.String("command", "", "Command to run when starting the image")
flConfig := cmd.String("run", "", "Config automatically applied when the image is run. "+`(ex: {"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')`)
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -737,21 +736,15 @@ func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...stri
return nil
}
var config []string
var config *Config
if *flConfig != "" {
config = strings.Split(*flConfig, " ")
}
if *flCommand != "" {
config = append(config, "", "/bin/sh", "-c", *flCommand)
} else if *flConfig != "" {
config = append(config, "", "")
}
c, err := ParseRun(config, stdout, srv.runtime.capabilities)
if err != nil {
return err
config = &Config{}
if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
return err
}
}
img, err := srv.runtime.Commit(containerName, repository, tag, *flComment, *flAuthor, c)
img, err := srv.runtime.Commit(containerName, repository, tag, *flComment, *flAuthor, config)
if err != nil {
return err
}
@@ -1006,11 +999,11 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
return nil
}
func NewServer() (*Server, error) {
func NewServer(autoRestart bool) (*Server, error) {
if runtime.GOARCH != "amd64" {
log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
}
runtime, err := NewRuntime()
runtime, err := NewRuntime(autoRestart)
if err != nil {
return nil, err
}
+1
View File
@@ -394,4 +394,5 @@ func TestAttachDisconnect(t *testing.T) {
// Try to avoid the timeoout in destroy. Best effort, don't check error
cStdin, _ := container.StdinPipe()
cStdin.Close()
container.Wait()
}
+12 -24
View File
@@ -22,9 +22,8 @@ func TestIdFormat(t *testing.T) {
defer nuke(runtime)
container1, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).Id,
Cmd: []string{"/bin/sh", "-c", "echo hello world"},
Memory: 33554432,
Image: GetTestImage(runtime).Id,
Cmd: []string{"/bin/sh", "-c", "echo hello world"},
},
)
if err != nil {
@@ -50,7 +49,6 @@ func TestMultipleAttachRestart(t *testing.T) {
Image: GetTestImage(runtime).Id,
Cmd: []string{"/bin/sh", "-c",
"i=1; while [ $i -le 5 ]; do i=`expr $i + 1`; echo hello; done"},
Memory: 33554432,
},
)
if err != nil {
@@ -116,8 +114,8 @@ func TestMultipleAttachRestart(t *testing.T) {
if err := container.Start(); err != nil {
t.Fatal(err)
}
timeout := make(chan bool)
go func() {
setTimeout(t, "Timeout reading from the process", 3*time.Second, func() {
l1, err = bufio.NewReader(stdout1).ReadString('\n')
if err != nil {
t.Fatal(err)
@@ -139,15 +137,8 @@ func TestMultipleAttachRestart(t *testing.T) {
if strings.Trim(l3, " \r\n") != "hello" {
t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l3)
}
timeout <- false
}()
go func() {
time.Sleep(3 * time.Second)
timeout <- true
}()
if <-timeout {
t.Fatalf("Timeout reading from the process")
}
})
container.Wait()
}
func TestDiff(t *testing.T) {
@@ -312,9 +303,8 @@ func TestCommitRun(t *testing.T) {
defer nuke(runtime)
container1, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).Id,
Cmd: []string{"/bin/sh", "-c", "echo hello > /world"},
Memory: 33554432,
Image: GetTestImage(runtime).Id,
Cmd: []string{"/bin/sh", "-c", "echo hello > /world"},
},
)
if err != nil {
@@ -345,9 +335,8 @@ func TestCommitRun(t *testing.T) {
container2, err := runtime.Create(
&Config{
Image: img.Id,
Memory: 33554432,
Cmd: []string{"cat", "/world"},
Image: img.Id,
Cmd: []string{"cat", "/world"},
},
)
if err != nil {
@@ -432,9 +421,8 @@ func TestRun(t *testing.T) {
defer nuke(runtime)
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).Id,
Memory: 33554432,
Cmd: []string{"ls", "-al"},
Image: GetTestImage(runtime).Id,
Cmd: []string{"ls", "-al"},
},
)
if err != nil {
+37 -7
View File
@@ -1,17 +1,22 @@
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"os/exec"
"path"
"time"
)
const DOCKER_PATH = "/home/creack/dotcloud/docker/docker/docker"
var DOCKER_PATH string = path.Join(os.Getenv("DOCKERPATH"), "docker")
// WARNING: this crashTest will 1) crash your host, 2) remove all containers
func runDaemon() (*exec.Cmd, error) {
os.Remove("/var/run/docker.pid")
exec.Command("rm", "-rf", "/var/lib/docker/containers").Run()
cmd := exec.Command(DOCKER_PATH, "-d")
outPipe, err := cmd.StdoutPipe()
if err != nil {
@@ -38,19 +43,43 @@ func crashTest() error {
return err
}
var endpoint string
if ep := os.Getenv("TEST_ENDPOINT"); ep == "" {
endpoint = "192.168.56.1:7979"
} else {
endpoint = ep
}
c := make(chan bool)
var conn io.Writer
go func() {
conn, _ = net.Dial("tcp", endpoint)
c <- false
}()
go func() {
time.Sleep(2 * time.Second)
c <- true
}()
<-c
restartCount := 0
totalTestCount := 1
for {
daemon, err := runDaemon()
if err != nil {
return err
}
restartCount++
// time.Sleep(5000 * time.Millisecond)
var stop bool
go func() error {
stop = false
for i := 0; i < 100 && !stop; i++ {
for i := 0; i < 100 && !stop; {
func() error {
cmd := exec.Command(DOCKER_PATH, "run", "base", "echo", "hello", "world")
log.Printf("%d", i)
cmd := exec.Command(DOCKER_PATH, "run", "base", "echo", fmt.Sprintf("%d", totalTestCount))
i++
totalTestCount++
outPipe, err := cmd.StdoutPipe()
if err != nil {
return err
@@ -62,9 +91,10 @@ func crashTest() error {
if err := cmd.Start(); err != nil {
return err
}
go func() {
io.Copy(os.Stdout, outPipe)
}()
if conn != nil {
go io.Copy(conn, outPipe)
}
// Expecting error, do not check
inPipe.Write([]byte("hello world!!!!!\n"))
go inPipe.Write([]byte("hello world!!!!!\n"))
+43 -9
View File
@@ -49,26 +49,36 @@ def docker(args, stdin=None):
def image_exists(img):
return docker(["inspect", img]).read().strip() != ""
def run_and_commit(img_in, cmd, stdin=None):
def image_config(img):
return json.loads(docker(["inspect", img]).read()).get("config", {})
def run_and_commit(img_in, cmd, stdin=None, author=None, run=None):
run_id = docker(["run"] + (["-i", "-a", "stdin"] if stdin else ["-d"]) + [img_in, "/bin/sh", "-c", cmd], stdin=stdin).read().rstrip()
print "---> Waiting for " + run_id
result=int(docker(["wait", run_id]).read().rstrip())
if result != 0:
print "!!! '{}' return non-zero exit code '{}'. Aborting.".format(cmd, result)
sys.exit(1)
return docker(["commit", run_id]).read().rstrip()
return docker(["commit"] + (["-author", author] if author else []) + (["-run", json.dumps(run)] if run is not None else []) + [run_id]).read().rstrip()
def insert(base, src, dst):
def insert(base, src, dst, author=None):
print "COPY {} to {} in {}".format(src, dst, base)
if dst == "":
raise Exception("Missing destination path")
stdin = file(src)
stdin.seek(0)
return run_and_commit(base, "cat > {0}; chmod +x {0}".format(dst), stdin=stdin)
return run_and_commit(base, "cat > {0}; chmod +x {0}".format(dst), stdin=stdin, author=author)
def push(base, dst, author=None):
print "PUSH to {} in {}".format(dst, base)
if dst == "":
raise Exception("Missing argument to push")
tar = subprocess.Popen(["tar", "-c", "."], stdout=subprocess.PIPE).stdout
return run_and_commit(base, "mkdir -p '{0}' && tar -C '{0}' -x".format(dst), stdin=tar, author=author)
def main():
base=""
maintainer=""
steps = []
try:
for line in sys.stdin.readlines():
@@ -77,22 +87,46 @@ def main():
if line == "" or line[0] == "#":
continue
op, param = line.split(" ", 1)
print op.upper() + " " + param
if op == "from":
print "FROM " + param
base = param
steps.append(base)
elif op == "maintainer":
maintainer = param
elif op == "run":
print "RUN " + param
result = run_and_commit(base, param)
result = run_and_commit(base, param, author=maintainer)
steps.append(result)
base = result
print "===> " + base
elif op == "copy":
src, dst = param.split(" ", 1)
result = insert(base, src, dst)
result = insert(base, src, dst, author=maintainer)
steps.append(result)
base = result
print "===> " + base
elif op == "push":
result = push(base, param.strip(), author=maintainer)
steps.append(result)
base=result
print "===> " + base
elif op == "expose":
config = image_config(base)
if config.get("PortSpecs") is None:
config["PortSpecs"] = []
portspec = param.strip()
config["PortSpecs"].append(portspec)
result = run_and_commit(base, "# (nop) expose port {}".format(portspec), author=maintainer, run=config)
steps.append(result)
base=result
print "===> " + base
elif op == "cmd":
config = image_config(base)
cmd = list(json.loads(param))
config["Cmd"] = cmd
result = run_and_commit(base, "# (nop) set default command to '{}'".format(" ".join(cmd)), author=maintainer, run=config)
steps.append(result)
base=result
print "===> " + base
else:
print "Skipping uknown op " + op
except:
+5 -3
View File
@@ -1,11 +1,13 @@
# Start build from a know base image
maintainer Solomon Hykes <solomon@dotcloud.com>
from base:ubuntu-12.10
# Update ubuntu sources
run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list
run apt-get update
# Install system packages
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
# Insert files from the host (./myscript must be present in the current directory)
copy myscript /usr/local/bin/myscript
copy myscript /usr/local/bin/myscript
push /src
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
echo hello, world!
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
set -e
# these should match the names found at http://www.debian.org/releases/
stableSuite='squeeze'
testingSuite='wheezy'
unstableSuite='sid'
# if suite is equal to this, it gets the "latest" tag
latestSuite="$testingSuite"
variant='minbase'
include='iproute,iputils-ping'
repo="$1"
suite="${2:-$latestSuite}"
mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided
if [ ! "$repo" ]; then
echo >&2 "usage: $0 repo [suite [mirror]]"
echo >&2 " ie: $0 tianon/debian squeeze"
exit 1
fi
target="/tmp/docker-rootfs-debian-$suite-$$-$RANDOM"
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
returnTo="$(pwd -P)"
set -x
# bootstrap
mkdir -p "$target"
sudo debootstrap --verbose --variant="$variant" --include="$include" "$suite" "$target" "$mirror"
cd "$target"
# create the image
img=$(sudo tar -c . | docker import -)
# tag suite
docker tag $img $repo $suite
if [ "$suite" = "$latestSuite" ]; then
# tag latest
docker tag $img $repo latest
fi
# test the image
docker run -i -t $repo:$suite echo success
# unstable's version numbers match testing (since it's mostly just a sandbox for testing), so it doesn't get a version number tag
if [ "$suite" != "$unstableSuite" -a "$suite" != 'unstable' ]; then
# tag the specific version
ver=$(docker run $repo:$suite cat /etc/debian_version)
docker tag $img $repo $ver
fi
# cleanup
cd "$returnTo"
sudo rm -rf "$target"
+4 -3
View File
@@ -28,6 +28,7 @@ func main() {
// FIXME: Switch d and D ? (to be more sshd like)
flDaemon := flag.Bool("d", false, "Daemon mode")
flDebug := flag.Bool("D", false, "Debug mode")
flAutoRestart := flag.Bool("r", false, "Restart previously running containers")
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge")
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
flag.Parse()
@@ -45,7 +46,7 @@ func main() {
flag.Usage()
return
}
if err := daemon(*pidfile); err != nil {
if err := daemon(*pidfile, *flAutoRestart); err != nil {
log.Fatal(err)
}
} else {
@@ -82,7 +83,7 @@ func removePidFile(pidfile string) {
}
}
func daemon(pidfile string) error {
func daemon(pidfile string, autoRestart bool) error {
if err := createPidFile(pidfile); err != nil {
log.Fatal(err)
}
@@ -97,7 +98,7 @@ func daemon(pidfile string) error {
os.Exit(0)
}()
service, err := docker.NewServer()
service, err := docker.NewServer(autoRestart)
if err != nil {
return err
}
+5
View File
@@ -97,6 +97,11 @@ func (graph *Graph) Create(layerData Archive, container *Container, comment, aut
img.Parent = container.Image
img.Container = container.Id
img.ContainerConfig = *container.Config
if config == nil {
if parentImage, err := graph.Get(container.Image); err == nil && parentImage != nil {
img.Config = parentImage.Config
}
}
}
if err := graph.Register(layerData, img); err != nil {
return nil, err
+15
View File
@@ -1,3 +1,18 @@
lxc-docker (0.2.1-1) precise; urgency=low
- 'docker commit -run' bundles a layer with default runtime options: command, ports etc.
- Improve install process on Vagrant
- New Dockerfile operation: "maintainer"
- New Dockerfile operation: "expose"
- New Dockerfile operation: "cmd"
- Contrib script to build a Debian base layer
- 'docker -d -r': restart crashed containers at daemon startup
- Runtime: improve test coverage
-- dotCloud <ops@dotcloud.com> Wed, 1 May 2013 00:00:00 -0700
lxc-docker (0.2.0-1) precise; urgency=low
- Runtime: ghost containers can be killed and waited for
+39 -23
View File
@@ -31,6 +31,7 @@ type Runtime struct {
idIndex *TruncIndex
capabilities *Capabilities
kernelVersion *KernelVersionInfo
autoRestart bool
}
var sysInitPath string
@@ -121,9 +122,8 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) {
return nil, err
}
//runtime.mergeConfig(config, img.Config)
if img.Config != nil {
config = img.Config
runtime.mergeConfig(config, img.Config)
}
if config.Cmd == nil {
@@ -215,23 +215,6 @@ func (runtime *Runtime) Register(container *Container) error {
// init the wait lock
container.waitLock = make(chan struct{})
// FIXME: if the container is supposed to be running but is not, auto restart it?
// if so, then we need to restart monitor and init a new lock
// If the container is supposed to be running, make sure of it
if container.State.Running {
if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil {
return err
} else {
if !strings.Contains(string(output), "RUNNING") {
Debugf("Container %s was supposed to be running be is not.", container.Id)
container.State.setStopped(-127)
if err := container.ToDisk(); err != nil {
return err
}
}
}
}
// Even if not running, we init the lock (prevents races in start/stop/kill)
container.State.initLock()
@@ -250,11 +233,43 @@ func (runtime *Runtime) Register(container *Container) error {
runtime.containers.PushBack(container)
runtime.idIndex.Add(container.Id)
// When we actually restart, Start() do the monitoring.
// However, when we simply 'reattach', we have to restart a monitor
nomonitor := false
// FIXME: if the container is supposed to be running but is not, auto restart it?
// if so, then we need to restart monitor and init a new lock
// If the container is supposed to be running, make sure of it
if container.State.Running {
if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil {
return err
} else {
if !strings.Contains(string(output), "RUNNING") {
Debugf("Container %s was supposed to be running be is not.", container.Id)
if runtime.autoRestart {
Debugf("Restarting")
container.State.Ghost = false
container.State.setStopped(0)
if err := container.Start(); err != nil {
return err
}
nomonitor = true
} else {
Debugf("Marking as stopped")
container.State.setStopped(-127)
if err := container.ToDisk(); err != nil {
return err
}
}
}
}
}
// If the container is not running or just has been flagged not running
// then close the wait lock chan (will be reset upon start)
if !container.State.Running {
close(container.waitLock)
} else {
} else if !nomonitor {
container.allocateNetwork()
go container.monitor()
}
@@ -340,8 +355,8 @@ func (runtime *Runtime) restore() error {
}
// FIXME: harmonize with NewGraph()
func NewRuntime() (*Runtime, error) {
runtime, err := NewRuntimeFromDirectory("/var/lib/docker")
func NewRuntime(autoRestart bool) (*Runtime, error) {
runtime, err := NewRuntimeFromDirectory("/var/lib/docker", autoRestart)
if err != nil {
return nil, err
}
@@ -374,7 +389,7 @@ func NewRuntime() (*Runtime, error) {
return runtime, nil
}
func NewRuntimeFromDirectory(root string) (*Runtime, error) {
func NewRuntimeFromDirectory(root string, autoRestart bool) (*Runtime, error) {
runtimeRepo := path.Join(root, "containers")
if err := os.MkdirAll(runtimeRepo, 0700); err != nil && !os.IsExist(err) {
@@ -411,6 +426,7 @@ func NewRuntimeFromDirectory(root string) (*Runtime, error) {
authConfig: authConfig,
idIndex: NewTruncIndex(),
capabilities: &Capabilities{},
autoRestart: autoRestart,
}
if err := runtime.restore(); err != nil {
+15 -5
View File
@@ -63,7 +63,7 @@ func init() {
NetworkBridgeIface = "testdockbr0"
// Make it our Store root
runtime, err := NewRuntimeFromDirectory(unitTestStoreBase)
runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false)
if err != nil {
panic(err)
}
@@ -89,7 +89,7 @@ func newTestRuntime() (*Runtime, error) {
return nil, err
}
runtime, err := NewRuntimeFromDirectory(root)
runtime, err := NewRuntimeFromDirectory(root, false)
if err != nil {
return nil, err
}
@@ -275,7 +275,16 @@ func TestAllocatePortLocalhost(t *testing.T) {
t.Fatal(err)
}
defer container.Kill()
time.Sleep(600 * time.Millisecond) // Wait for the container to run
setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() {
for {
if container.State.Running {
break
}
time.Sleep(10 * time.Millisecond)
}
})
conn, err := net.Dial("tcp",
fmt.Sprintf(
"localhost:%s", container.NetworkSettings.PortMapping["5555"],
@@ -295,6 +304,7 @@ func TestAllocatePortLocalhost(t *testing.T) {
string(output),
)
}
container.Wait()
}
func TestRestore(t *testing.T) {
@@ -310,7 +320,7 @@ func TestRestore(t *testing.T) {
t.Fatal(err)
}
runtime1, err := NewRuntimeFromDirectory(root)
runtime1, err := NewRuntimeFromDirectory(root, false)
if err != nil {
t.Fatal(err)
}
@@ -369,7 +379,7 @@ func TestRestore(t *testing.T) {
// Here are are simulating a docker restart - that is, reloading all containers
// from scratch
runtime2, err := NewRuntimeFromDirectory(root)
runtime2, err := NewRuntimeFromDirectory(root, false)
if err != nil {
t.Fatal(err)
}
+11 -6
View File
@@ -12,7 +12,6 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
@@ -437,17 +436,23 @@ func CompareKernelVersion(a, b *KernelVersionInfo) int {
}
func FindCgroupMountpoint(cgroupType string) (string, error) {
output, err := exec.Command("mount").CombinedOutput()
output, err := ioutil.ReadFile("/proc/mounts")
if err != nil {
return "", err
}
reg := regexp.MustCompile(`^.* on (.*) type cgroup \(.*` + cgroupType + `[,\)]`)
// /proc/mounts has 6 fields per line, one mount per line, e.g.
// cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0
for _, line := range strings.Split(string(output), "\n") {
r := reg.FindStringSubmatch(line)
if len(r) == 2 {
return r[1], nil
parts := strings.Split(line, " ")
if parts[2] == "cgroup" {
for _, opt := range strings.Split(parts[3], ",") {
if opt == cgroupType {
return parts[1], nil
}
}
}
}
return "", fmt.Errorf("cgroup mountpoint not found for %s", cgroupType)
}