From f98922c6048f8466071bab13e4ac27a81a005a7e Mon Sep 17 00:00:00 2001 From: Markus Hubig Date: Wed, 18 Jun 2014 17:06:50 +0200 Subject: [PATCH 001/167] Fixes a wrong tab indent in the docopt string. Signed-off-by: Markus Hubig --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 298a5a5..5fe637a 100644 --- a/config.go +++ b/config.go @@ -212,7 +212,7 @@ Commands: delete Delete boot2docker VM and its disk image. config|cfg Show selected profile file settings. info Display detailed information of VM. - ip Display the IP address of the VM's Host-only network. + ip Display the IP address of the VM's Host-only network. status Display current state of VM. download Download boot2docker ISO image. version Display version information. From 00b6072c6c81f9d10f1c67f46e69fa2c218dab64 Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Wed, 18 Jun 2014 12:49:16 +0100 Subject: [PATCH 002/167] Fix sed command to find VM IP address in readme The `-E` flag is needed to make `+` work in the version of sed in OS X. Signed-off-by: Ben Firshman --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e93bb7..c34d61b 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ to remove it completely. You can also run commands on the remote boot2docker virtual machine: - $ boot2docker -m 123 ssh ip addr show eth1 |sed -ne 's/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p' + $ boot2docker -m 123 ssh ip addr show eth1 |sed -nEe 's/^[ \t]*inet[ \t]*([0-9.]+)\/.*$/\1/p' 192.168.59.103 In this case, the command tells you the host only interface IP address of the From 344a10495612d7b46d9da83cd5debca3197cbfaa Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 20 Jun 2014 12:08:05 +1000 Subject: [PATCH 003/167] point out that there is now a boot2docker ip command --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9aba7f8..d91760a 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,10 @@ to remove it completely. You can also run commands on the remote boot2docker virtual machine: - $ boot2docker -m 123 ssh ip addr show eth1 |sed -nEe 's/^[ \t]*inet[ \t]*([0-9.]+)\/.*$/\1/p' + $ boot2docker ssh ip addr show eth1 |sed -nEe 's/^[ \t]*inet[ \t]*([0-9.]+)\/.*$/\1/p' + 192.168.59.103 + # this example is equivalent to the built in command: + $ boot2docker ip 192.168.59.103 In this case, the command tells you the host only interface IP address of the From 428b122541b6092ae072a49cd8521e1fdca7ff22 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 20 Jun 2014 12:16:04 +1000 Subject: [PATCH 004/167] version bump --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0ec25f7..b18d465 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.0.0 +v1.0.1 From 8504054cb28f59288be4279b132dcccec86b7e3d Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 20 Jun 2014 13:30:32 +1000 Subject: [PATCH 005/167] retry one last time to get the IP address using ssh --- cmds.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmds.go b/cmds.go index 50c4461..608ea7b 100644 --- a/cmds.go +++ b/cmds.go @@ -252,7 +252,7 @@ func cmdUp() int { break } } - if err := read(natSSH, 1, 1*time.Second); err == nil { + if err := read(natSSH, 1, 2*time.Second); err == nil { IP = RequestIPFromSSH(m) break } @@ -264,7 +264,13 @@ func cmdUp() int { logf("Started.") if IP == "" { - logf("Auto detection of the VM's IP address.") + // lets try one more time + time.Sleep(3) + + IP = RequestIPFromSSH(m) + if IP == "" { + logf("Auto detection of the VM's IP address failed.") + } } switch runtime.GOOS { case "windows": @@ -484,7 +490,7 @@ func cmdIP() int { func RequestIPFromSSH(m *vbx.Machine) string { // fall back to using the NAT port forwarded ssh out, err := cmd(B2D.SSH, - //"-vvv", //TODO: add if its boot2docker -v + "-v", // please leave in - this seems to improve the chance of success "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-p", fmt.Sprintf("%d", m.SSHPort), From 3ee93d15bdbb89f68f916a1a42f76f8ec257e905 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 19 Jun 2014 22:26:49 -0700 Subject: [PATCH 006/167] It was a little weird seeing no feedback - and I'd forgotten that I'd set the DOCKER_HOST --- cmds.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmds.go b/cmds.go index 608ea7b..61a7465 100644 --- a/cmds.go +++ b/cmds.go @@ -282,6 +282,8 @@ func cmdUp() int { if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, m.DockerPort) { logf("To connect the Docker client to the Docker daemon, please set:") logf(" export DOCKER_HOST=tcp://%s:%d", IP, m.DockerPort) + } else { + logf("Your DOCKER_HOST env variable is already set correctly.") } } return 0 From 2664234915c638e3f3e463c3b1e601d13dcda305 Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Wed, 25 Jun 2014 10:55:44 -0700 Subject: [PATCH 007/167] Ignore vim *.swp files Docker-DCO-1.1-Signed-off-by: Nathan LeClaire (github: nathanleclaire) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6618d45..2d18d02 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ Thumbs.db nbproject *.sublime-project *.sublime-workspace +*.swp From d9434a89c61519e175fe5548211953a4da4c52cb Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Wed, 25 Jun 2014 11:08:27 -0700 Subject: [PATCH 008/167] Gofmt a few things Docker-DCO-1.1-Signed-off-by: Nathan LeClaire (github: nathanleclaire) --- cmds.go | 4 ++-- virtualbox/machine.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmds.go b/cmds.go index 61a7465..9b82b69 100644 --- a/cmds.go +++ b/cmds.go @@ -105,8 +105,8 @@ func cmdInit() int { } pfRules := map[string]vbx.PFRule{ - "ssh": vbx.PFRule{Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, - "docker": vbx.PFRule{Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: 2375}, + "ssh": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, + "docker": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: 2375}, } for name, rule := range pfRules { diff --git a/virtualbox/machine.go b/virtualbox/machine.go index b5b42db..e9324bd 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -262,7 +262,7 @@ func GetMachine(id string) (*Machine, error) { vals := strings.Split(val, ",") if len(vals) >= 2 { m.SerialFile = vals[1] - } + } } } if err := s.Err(); err != nil { From 1379a4e712643aea8a10c8fae37e9438f96d2d43 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 25 Jun 2014 22:50:25 -0600 Subject: [PATCH 009/167] Switch Dockerfile to be based on Debian and update it to Go 1.3 --- Dockerfile | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 34925b7..b13e784 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,23 @@ # Dockerfile to cross compile boot2docker-cli -FROM ubuntu:13.10 -MAINTAINER Riobard Zhan (@riobard) +FROM debian:jessie # Packaged dependencies -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \ - build-essential ca-certificates curl git +RUN apt-get update && apt-get install -y build-essential curl git # Install Go from binary release -RUN curl -s https://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz | tar -v -C /usr/local -xz +RUN curl -sSL http://golang.org/dl/go1.3.src.tar.gz | tar -xzC /usr/local ENV PATH /usr/local/go/bin:$PATH # Bootstrap Go for cross compilation (we have linux/amd64 by default) ENV DOCKER_CROSSPLATFORMS darwin/amd64 windows/amd64 -RUN cd /usr/local/go/src && bash -xc 'for platform in $DOCKER_CROSSPLATFORMS; do GOOS=${platform%/*} GOARCH=${platform##*/} ./make.bash --no-clean 2>&1; done' +RUN cd /usr/local/go/src && bash -xec 'for platform in $DOCKER_CROSSPLATFORMS; do GOOS=${platform%/*} GOARCH=${platform##*/} ./make.bash --no-clean 2>&1; done' -ENV GOPATH /go +ENV GOPATH /go ADD . /go/src/github.com/boot2docker/boot2docker-cli WORKDIR /go/src/github.com/boot2docker/boot2docker-cli # Download (but not install) dependencies -RUN go get -d +RUN go get -d -v + CMD ["make", "all"] From a983a5c53bfce51e5d99f075dfbdcff50276262e Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 25 Jun 2014 22:52:08 -0600 Subject: [PATCH 010/167] Fix SSH oddness by passing arguments directly through to SSH as-is Also, added "LogLevel=quiet" to suppress the fun warning that was printed every time we run "boot2docker ssh ...". --- cmds.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmds.go b/cmds.go index 9b82b69..ad68f4c 100644 --- a/cmds.go +++ b/cmds.go @@ -437,15 +437,16 @@ func cmdSSH() int { i++ } - if err := cmdInteractive(B2D.SSH, - //"-vvv", //TODO: add if its boot2docker -v + sshArgs := append([]string{ "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", + "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." "-p", fmt.Sprintf("%d", m.SSHPort), "-i", B2D.SSHKey, "docker@localhost", - strings.Join(os.Args[i:], " "), - ); err != nil { + }, os.Args[i:]...) + + if err := cmdInteractive(B2D.SSH, sshArgs...); err != nil { logf("%s", err) return 1 } From bada60adb977d75646b95afeb45e22f2c010a84e Mon Sep 17 00:00:00 2001 From: Faye Salwin Date: Fri, 27 Jun 2014 23:38:42 -0700 Subject: [PATCH 011/167] #357 use natdnshostresolver1 for DNS on VPN --- virtualbox/machine.go | 1 + 1 file changed, 1 insertion(+) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index e9324bd..cc47893 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -332,6 +332,7 @@ func (m *Machine) Modify() error { "--firmware", "bios", "--bioslogofadein", "off", "--bioslogofadeout", "off", + "--natdnshostresolver1", "on", "--bioslogodisplaytime", "0", "--biosbootmenu", "disabled", From e644797f4ca8d477e124f8867d00fda186695c5a Mon Sep 17 00:00:00 2001 From: Michael Sauter Date: Wed, 2 Jul 2014 13:50:01 +1000 Subject: [PATCH 012/167] Add download.sh file --- download.sh | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 download.sh diff --git a/download.sh b/download.sh new file mode 100644 index 0000000..dcc902e --- /dev/null +++ b/download.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Set version to latest unless set by user +if [ -z "$VERSION" ]; then + VERSION="1.0.1" +fi + +echo "Dowloading version ${VERSION}..." + +# OS information (contains e.g. Darwin x86_64) +UNAME=`uname -a` +# Determine platform +if [[ $UNAME == *"Darwin"* ]]; then + PLATFORM="darwin" +elif [[ $UNAME == *"Cygwin"* ]]; then + PLATFORM="windows" +else + PLATFORM="linux" +fi +# Determine architecture +if [[ ($UNAME == *x86_64*) || ($UNAME == *amd64*) ]] +then + ARCH="amd64" +else + echo "Currently, there are no 32bit binaries provided." + echo "You will need to go get / go install github.com/boot2docker/boot2docker-cli." + exit 1 +fi + +# Download binary +curl -L -o boot2docker "https://github.com/boot2docker/boot2docker-cli/releases/download/v${VERSION}/boot2docker-v${VERSION}-${PLATFORM}_${ARCH}" + +# Make binary executable +chmod +x boot2docker + +echo "Done." From 5ca6a8cbf075ca609325069ca22e37656c113dfa Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 2 Jul 2014 13:58:23 +1000 Subject: [PATCH 013/167] next up... --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b18d465..795460f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.0.1 +v1.1.0 From 4df82c8e2b78ccd6cf2c75dc6001d3cd5fe77e77 Mon Sep 17 00:00:00 2001 From: Michael Sauter Date: Wed, 2 Jul 2014 14:19:13 +1000 Subject: [PATCH 014/167] s/Dowloading/Downloading/ --- download.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/download.sh b/download.sh index dcc902e..9e1fecf 100644 --- a/download.sh +++ b/download.sh @@ -5,7 +5,7 @@ if [ -z "$VERSION" ]; then VERSION="1.0.1" fi -echo "Dowloading version ${VERSION}..." +echo "Downloading version ${VERSION}..." # OS information (contains e.g. Darwin x86_64) UNAME=`uname -a` From 66eefb0647d3cf3c069815233ce5a149e4811a24 Mon Sep 17 00:00:00 2001 From: Michael Sauter Date: Wed, 2 Jul 2014 14:19:33 +1000 Subject: [PATCH 015/167] Abort if errors are encountered --- download.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/download.sh b/download.sh index 9e1fecf..cfa91af 100644 --- a/download.sh +++ b/download.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -e + # Set version to latest unless set by user if [ -z "$VERSION" ]; then VERSION="1.0.1" From 10ce358e48d12bd00ca0c980854f9e50901823ae Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 2 Jul 2014 14:41:38 +1000 Subject: [PATCH 016/167] yup, using " works --- cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index ad68f4c..4c3549e 100644 --- a/cmds.go +++ b/cmds.go @@ -275,7 +275,7 @@ func cmdUp() int { switch runtime.GOOS { case "windows": logf("Docker client does not run on Windows for now. Please use") - logf(" %s ssh", os.Args[0]) + logf(" \"%s\" ssh", os.Args[0]) logf("to SSH into the VM instead.") default: // Check if $DOCKER_HOST ENV var is properly configured. From 30e5b34f783e04a494d29900e3b25b3a6a2330bd Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 4 Jul 2014 15:26:11 +1000 Subject: [PATCH 017/167] I was wondering what timescale time.Sleep() uses - and, yes, its tiny --- cmds.go | 26 ++++++++++++++++---------- util.go | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/cmds.go b/cmds.go index 4c3549e..c73eed8 100644 --- a/cmds.go +++ b/cmds.go @@ -243,7 +243,7 @@ func cmdUp() int { logf("Waiting for VM to be started...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket - time.Sleep(2) + time.Sleep(600 * time.Millisecond) natSSH := fmt.Sprintf("localhost:%d", B2D.SSHPort) IP := "" for i := 1; i < 30; i++ { @@ -265,12 +265,10 @@ func cmdUp() int { if IP == "" { // lets try one more time - time.Sleep(3) + time.Sleep(600 * time.Millisecond) + logf(" Trying to get IP one more time") IP = RequestIPFromSSH(m) - if IP == "" { - logf("Auto detection of the VM's IP address failed.") - } } switch runtime.GOOS { case "windows": @@ -278,12 +276,17 @@ func cmdUp() int { logf(" \"%s\" ssh", os.Args[0]) logf("to SSH into the VM instead.") default: - // Check if $DOCKER_HOST ENV var is properly configured. - if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, m.DockerPort) { - logf("To connect the Docker client to the Docker daemon, please set:") - logf(" export DOCKER_HOST=tcp://%s:%d", IP, m.DockerPort) + if IP == "" { + logf("Auto detection of the VM's IP address failed.") + logf("Please run `boot2docker -v up` to diagnose.") } else { - logf("Your DOCKER_HOST env variable is already set correctly.") + // Check if $DOCKER_HOST ENV var is properly configured. + if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, m.DockerPort) { + logf("To connect the Docker client to the Docker daemon, please set:") + logf(" export DOCKER_HOST=tcp://%s:%d", IP, m.DockerPort) + } else { + logf("Your DOCKER_HOST env variable is already set correctly.") + } } } return 0 @@ -505,6 +508,9 @@ func RequestIPFromSSH(m *vbx.Machine) string { if err != nil { logf("%s", err) } else { + if B2D.Verbose { + logf("SSH returned: %s\nEND SSH\n", out) + } // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 lines := strings.Split(out, "\n") for _, line := range lines { diff --git a/util.go b/util.go index 5b1ebde..0d88e1b 100644 --- a/util.go +++ b/util.go @@ -230,7 +230,7 @@ func RequestIPFromSerialPort(socket string) string { } go reader(c) //give us time reader clean up - time.Sleep(1) + time.Sleep(1 * time.Second) if IP == "" && B2D.Verbose { logf(fullLog) } From 8a9e9c98c9d70ea31d20cb591611c2ea1eff09d3 Mon Sep 17 00:00:00 2001 From: rdsubhas Date: Fri, 4 Jul 2014 22:45:56 +0300 Subject: [PATCH 018/167] Aliased destroy to delete Docker-DCO-1.1-Signed-off-by: rdsubhas (github: rdsubhas) --- config.go | 4 ++-- main.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index 9f6ab33..7983a66 100644 --- a/config.go +++ b/config.go @@ -190,7 +190,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|download|version} []\n", os.Args[0]) + errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) } @@ -209,7 +209,7 @@ Commands: restart Gracefully reboot the VM. poweroff Forcefully power off the VM (might corrupt disk image). reset Forcefully power cycle the VM (might corrupt disk image). - delete Delete boot2docker VM and its disk image. + delete|destroy Delete boot2docker VM and its disk image. config|cfg Show selected profile file settings. info Display detailed information of VM. ip Display the IP address of the VM's Host-only network. diff --git a/main.go b/main.go index 4d67534..1d0b58f 100644 --- a/main.go +++ b/main.go @@ -45,7 +45,7 @@ func run() int { return cmdRestart() case "reset": return cmdReset() - case "delete": + case "delete", "destroy": return cmdDelete() case "info": return cmdInfo() From 7fc073a4d7429a7588e6990f6304a9a9116085ec Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 9 Jul 2014 15:42:19 +1000 Subject: [PATCH 019/167] Found out that the port forwards are ordered dynamically based on the name of the forward, not its order of definition. --- virtualbox/machine.go | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index cc47893..70b1e86 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -241,28 +241,29 @@ func GetMachine(id string) (*Machine, error) { case "CfgFile": m.CfgFile = val m.BaseFolder = filepath.Dir(val) - case "Forwarding(0)": - // Forwarding(0)="docker,tcp,127.0.0.1,5555,," - vals := strings.Split(val, ",") - n, err := strconv.ParseUint(vals[3], 10, 32) - if err != nil { - return nil, err - } - m.DockerPort = uint(n) - case "Forwarding(1)": - // Forwarding(1)="ssh,tcp,127.0.0.1,2222,,22" - vals := strings.Split(val, ",") - n, err := strconv.ParseUint(vals[3], 10, 32) - if err != nil { - return nil, err - } - m.SSHPort = uint(n) case "uartmode1": // uartmode1="server,/home/sven/.boot2docker/boot2docker-vm.sock" vals := strings.Split(val, ",") if len(vals) >= 2 { m.SerialFile = vals[1] } + default: + if strings.HasPrefix(key, "Forwarding(") { + // "Forwarding(\d*)" are ordered by the name inside the val, not fixed order. + // Forwarding(0)="docker,tcp,127.0.0.1,5555,," + // Forwarding(1)="ssh,tcp,127.0.0.1,2222,,22" + vals := strings.Split(val, ",") + n, err := strconv.ParseUint(vals[3], 10, 32) + if err != nil { + return nil, err + } + switch vals[0] { + case "docker": + m.DockerPort = uint(n) + case "ssh": + m.SSHPort = uint(n) + } + } } } if err := s.Err(); err != nil { From cafb485c4a84862b78617b7d247840cbe00a1074 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 9 Jul 2014 16:12:16 +1000 Subject: [PATCH 020/167] version bump 1.1.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 795460f..56130fb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.1.0 +v1.1.1 From 9ab1783430e4ede512d032a19a4ea921e75122de Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 10 Jul 2014 13:46:52 +1000 Subject: [PATCH 021/167] Now that getting the IP is much more reliable, using the forwarded port here is much more dangerous --- cmds.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmds.go b/cmds.go index c73eed8..f502e5c 100644 --- a/cmds.go +++ b/cmds.go @@ -16,6 +16,8 @@ import ( vbx "github.com/boot2docker/boot2docker-cli/virtualbox" ) +const dockerPort = 2375 + // Initialize the boot2docker VM from scratch. func cmdInit() int { // TODO(@riobard) break up this command into multiple stages @@ -106,7 +108,7 @@ func cmdInit() int { pfRules := map[string]vbx.PFRule{ "ssh": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, - "docker": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: 2375}, + "docker": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: dockerPort}, } for name, rule := range pfRules { @@ -281,9 +283,9 @@ func cmdUp() int { logf("Please run `boot2docker -v up` to diagnose.") } else { // Check if $DOCKER_HOST ENV var is properly configured. - if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, m.DockerPort) { + if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, dockerPort) { logf("To connect the Docker client to the Docker daemon, please set:") - logf(" export DOCKER_HOST=tcp://%s:%d", IP, m.DockerPort) + logf(" export DOCKER_HOST=tcp://%s:%d", IP, dockerPort) } else { logf("Your DOCKER_HOST env variable is already set correctly.") } From 3f03ca26bf8ab94ac0491a3bd6145ee83dbc97a4 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 10 Jul 2014 14:43:57 +1000 Subject: [PATCH 022/167] B2D seems to be the theoretical cfg, and I recently changed to be the values from vbox - so wil track even when the user changes them out of band --- cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index f502e5c..d512961 100644 --- a/cmds.go +++ b/cmds.go @@ -246,7 +246,7 @@ func cmdUp() int { logf("Waiting for VM to be started...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket time.Sleep(600 * time.Millisecond) - natSSH := fmt.Sprintf("localhost:%d", B2D.SSHPort) + natSSH := fmt.Sprintf("localhost:%d", m.SSHPort) IP := "" for i := 1; i < 30; i++ { if B2D.Serial && runtime.GOOS != "windows" { From ad530e0cd32a355fe7a06e0890ced3f348430ef2 Mon Sep 17 00:00:00 2001 From: Jon Seymour Date: Wed, 9 Jul 2014 16:15:36 -0400 Subject: [PATCH 023/167] Deprecate support for --dockerport flag. As the result of long standing issues with support for half-close of inbound TCP connections to Virtual Box guests on (at least) OSX use of port-forwarded docker connections should be discouraged. So, if the user really wants to configure it, let them. Otherwise, don't set it up in the first place. See boot2docker issue #150 (and others) for details. Docker-DCO-1.1-Signed-off-by: Jon Seymour (github: jonseymour) --- cmds.go | 16 +++++++++++----- config.go | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cmds.go b/cmds.go index d512961..cfbb56b 100644 --- a/cmds.go +++ b/cmds.go @@ -27,9 +27,13 @@ func cmdInit() int { return 1 } - if ping(fmt.Sprintf("localhost:%d", B2D.DockerPort)) { - logf("--dockerport=%d on localhost is occupied. Please choose another one.", B2D.DockerPort) - return 1 + if B2D.DockerPort > 0 { + // Reference Issue boot2docker-cli issue #150, docker issues #6247, #6271, #6327 + logf("warning: VirtualBox (4.3.x) NAT port forwarding is currently unreliable. Prefer to use the host only interface if possible.") + if ping(fmt.Sprintf("localhost:%d", B2D.DockerPort)) { + logf("--dockerport=%d on localhost is occupied. Please choose another one.", B2D.DockerPort) + return 1 + } } if ping(fmt.Sprintf("localhost:%d", B2D.SSHPort)) { @@ -107,8 +111,10 @@ func cmdInit() int { } pfRules := map[string]vbx.PFRule{ - "ssh": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, - "docker": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: dockerPort}, + "ssh": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, + } + if B2D.DockerPort > 0 { + pfRules["docker"] = vbx.PFRule{Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: dockerPort} } for name, rule := range pfRules { diff --git a/config.go b/config.go index 7983a66..6dec826 100644 --- a/config.go +++ b/config.go @@ -134,7 +134,7 @@ func config() (*flag.FlagSet, error) { flags.UintVarP(&B2D.DiskSize, "disksize", "s", 20000, "boot2docker disk image size (in MB).") flags.UintVarP(&B2D.Memory, "memory", "m", 2048, "virtual machine memory size (in MB).") flags.Uint16Var(&B2D.SSHPort, "sshport", 2022, "host SSH port (forward to port 22 in VM).") - flags.Uint16Var(&B2D.DockerPort, "dockerport", 2375, "host Docker port (forward to port 2375 in VM).") + flags.Uint16Var(&B2D.DockerPort, "dockerport", 0, "host Docker port (forward to port 2375 in VM). (deprecated - use with care)") flags.IPVar(&B2D.HostIP, "hostip", net.ParseIP("192.168.59.3"), "VirtualBox host-only network IP address.") flags.IPMaskVar(&B2D.NetMask, "netmask", flag.ParseIPv4Mask("255.255.255.0"), "VirtualBox host-only network mask.") flags.BoolVar(&B2D.DHCPEnabled, "dhcp", true, "enable VirtualBox host-only network DHCP.") From 0dd3c370f26426b377444a168ce9126d4ddda148 Mon Sep 17 00:00:00 2001 From: Johan Euphrosine Date: Mon, 14 Jul 2014 16:08:14 -0700 Subject: [PATCH 024/167] README: fix installations link for Mac OSX Docker-DCO-1.1-Signed-off-by: Johan Euphrosine (github: proppy) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d91760a..24cf87a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ connect to the boot2docker VM using `boot2docker.exe ssh`. Signed installers are available for [Mac OS X](http://github.com/boot2docker/osx-installer/releases) and [Windows](http://github.com/boot2docker/windows-installer/releases). -Refer to the installation instructions for [Windows](http://docs.docker.io/installation/windows/) and [Mac OS X](http://docks.docker.io/mac/). +Refer to the installation instructions for [Windows](http://docs.docker.io/installation/windows/) and [Mac OS X](http://docs.docker.io/installation/mac/). ### Manual Installation From ca3e313a42b49b59d291d3a07233bc6c68b7706c Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Tue, 8 Jul 2014 12:42:18 -0700 Subject: [PATCH 025/167] Create driver model and refactor virtualbox dependencies into driver --- cmds.go | 256 +++--------------------------- config.go | 47 +----- driver/config.go | 38 +++++ driver/dhcp.go | 12 ++ driver/driver.go | 71 +++++++++ {virtualbox => driver}/nic.go | 2 +- {virtualbox => driver}/pfrule.go | 2 +- {virtualbox => driver}/storage.go | 2 +- dummy/machine.go | 157 ++++++++++++++++++ main.go | 2 - vbm.go | 107 ------------- virtualbox/dhcp.go | 25 ++- virtualbox/machine.go | 216 +++++++++++++++++++++---- virtualbox/vbm.go | 91 +++++++++++ 14 files changed, 591 insertions(+), 437 deletions(-) create mode 100644 driver/config.go create mode 100644 driver/dhcp.go create mode 100644 driver/driver.go rename {virtualbox => driver}/nic.go (97%) rename {virtualbox => driver}/pfrule.go (98%) rename {virtualbox => driver}/storage.go (98%) create mode 100644 dummy/machine.go delete mode 100644 vbm.go diff --git a/cmds.go b/cmds.go index d512961..6c3dded 100644 --- a/cmds.go +++ b/cmds.go @@ -1,230 +1,24 @@ package main import ( - "archive/tar" - "bytes" "encoding/json" "fmt" - "io/ioutil" - "net" "os" - "path/filepath" "runtime" "strings" "time" - vbx "github.com/boot2docker/boot2docker-cli/virtualbox" + _ "github.com/boot2docker/boot2docker-cli/dummy" + _ "github.com/boot2docker/boot2docker-cli/virtualbox" + + "github.com/boot2docker/boot2docker-cli/driver" ) const dockerPort = 2375 -// Initialize the boot2docker VM from scratch. -func cmdInit() int { - // TODO(@riobard) break up this command into multiple stages - m, err := vbx.GetMachine(B2D.VM) - if err == nil { - logf("Virtual machine %s already exists", B2D.VM) - return 1 - } - - if ping(fmt.Sprintf("localhost:%d", B2D.DockerPort)) { - logf("--dockerport=%d on localhost is occupied. Please choose another one.", B2D.DockerPort) - return 1 - } - - if ping(fmt.Sprintf("localhost:%d", B2D.SSHPort)) { - logf("--sshport=%d on localhost is occupied. Please choose another one.", B2D.SSHPort) - return 1 - } - - if _, err := os.Stat(B2D.ISO); err != nil { - if !os.IsNotExist(err) { - logf("Failed to open ISO image %q: %s", B2D.ISO, err) - return 1 - } - - if exitcode := cmdDownload(); exitcode != 0 { - return exitcode - } - } - if _, err := os.Stat(B2D.SSHKey); err != nil { - if !os.IsNotExist(err) { - logf("Something wrong with SSH Key file %q: %s", B2D.SSHKey, err) - return 1 - } - if err := cmdInteractive(B2D.SSHGen, "-t", "rsa", "-N", "", "-f", B2D.SSHKey); err != nil { - logf("Error generating new SSH Key into %s: %s", B2D.SSHKey, err) - return 1 - } - } - //TODO: print a ~/.ssh/config entry for our b2d connection that the user can c&p - - logf("Creating VM %s...", B2D.VM) - m, err = vbx.CreateMachine(B2D.VM, "") - if err != nil { - logf("FIRST: Failed to create VM %q: %s", B2D.VM, err) - // double tap. VBox will sometimes (like on initial install, or reboot) - // fail to start the service the first time. - m, err = vbx.CreateMachine(B2D.VM, "") - if err != nil { - logf("Failed to create VM %q: %s", B2D.VM, err) - return 1 - } - } - - logf("Apply interim patch to VM %s (https://www.virtualbox.org/ticket/12748)", B2D.VM) - if err := vbx.SetExtra(B2D.VM, "VBoxInternal/CPUM/EnableHVP", "1"); err != nil { - logf("Failed to patch vm: %s", err) - return 1 - } - - m.OSType = "Linux26_64" - m.CPUs = uint(runtime.NumCPU()) - m.Memory = B2D.Memory - m.SerialFile = B2D.SerialFile - - m.Flag |= vbx.F_pae - m.Flag |= vbx.F_longmode // important: use x86-64 processor - m.Flag |= vbx.F_rtcuseutc - m.Flag |= vbx.F_acpi - m.Flag |= vbx.F_ioapic - m.Flag |= vbx.F_hpet - m.Flag |= vbx.F_hwvirtex - m.Flag |= vbx.F_vtxvpid - m.Flag |= vbx.F_largepages - m.Flag |= vbx.F_nestedpaging - - m.BootOrder = []string{"dvd"} - if err := m.Modify(); err != nil { - logf("Failed to modify VM %q: %s", B2D.VM, err) - return 1 - } - - logf("Setting NIC #1 to use NAT network...") - if err := m.SetNIC(1, vbx.NIC{Network: vbx.NICNetNAT, Hardware: vbx.VirtIO}); err != nil { - logf("Failed to add network interface to VM %q: %s", B2D.VM, err) - return 1 - } - - pfRules := map[string]vbx.PFRule{ - "ssh": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, - "docker": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: dockerPort}, - } - - for name, rule := range pfRules { - if err := m.AddNATPF(1, name, rule); err != nil { - logf("Failed to add port forwarding to VM %q: %s", B2D.VM, err) - return 1 - } - logf("Port forwarding [%s] %s", name, rule) - } - - hostIFName, err := getHostOnlyNetworkInterface() - if err != nil { - logf("Failed to create host-only network interface: %s", err) - return 1 - } - - logf("Setting NIC #2 to use host-only network %q...", hostIFName) - if err := m.SetNIC(2, vbx.NIC{Network: vbx.NICNetHostonly, Hardware: vbx.VirtIO, HostonlyAdapter: hostIFName}); err != nil { - logf("Failed to add network interface to VM %q: %s", B2D.VM, err) - return 1 - } - - logf("Setting VM storage...") - if err := m.AddStorageCtl("SATA", vbx.StorageController{SysBus: vbx.SysBusSATA, HostIOCache: true, Bootable: true}); err != nil { - logf("Failed to add storage controller to VM %q: %s", B2D.VM, err) - return 1 - } - - if err := m.AttachStorage("SATA", vbx.StorageMedium{Port: 0, Device: 0, DriveType: vbx.DriveDVD, Medium: B2D.ISO}); err != nil { - logf("Failed to attach ISO image %q: %s", B2D.ISO, err) - return 1 - } - - diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", B2D.VM)) - - if _, err := os.Stat(diskImg); err != nil { - if !os.IsNotExist(err) { - logf("Failed to open disk image %q: %s", diskImg, err) - return 1 - } - - if B2D.VMDK != "" { - logf("Using %v as base VMDK", B2D.VMDK) - if err := copyDiskImage(diskImg, B2D.VMDK); err != nil { - logf("Failed to copy disk image %v from %v: %s", diskImg, B2D.VMDK, err) - return 1 - } - } else { - magicString := "boot2docker, please format-me" - - buf := new(bytes.Buffer) - tw := tar.NewWriter(buf) - - // magicString first so the automount script knows to format the disk - file := &tar.Header{Name: magicString, Size: int64(len(magicString))} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if _, err := tw.Write([]byte(magicString)); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - // .ssh/key.pub => authorized_keys - file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - pubKey, err := ioutil.ReadFile(B2D.SSHKey + ".pub") - if err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if _, err := tw.Write([]byte(pubKey)); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if _, err := tw.Write([]byte(pubKey)); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if err := tw.Close(); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - - if err := makeDiskImage(diskImg, B2D.DiskSize, buf.Bytes()); err != nil { - logf("Failed to create disk image %q: %s", diskImg, err) - return 1 - } - } - } - - if err := m.AttachStorage("SATA", vbx.StorageMedium{Port: 1, Device: 0, DriveType: vbx.DriveHDD, Medium: diskImg}); err != nil { - logf("Failed to attach disk image %q: %s", diskImg, err) - return 1 - } - - logf("Done. Type `%s up` to start the VM.", os.Args[0]) - return 0 -} - // Bring up the VM from all possible states. func cmdUp() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -238,7 +32,7 @@ func cmdUp() int { logf("Failed to start machine %q: %s", B2D.VM, err) return 1 } - if m.State != vbx.Running { + if m.GetState() != driver.Running { logf("Failed to start machine %q (run again with -v for details)", B2D.VM) return 1 } @@ -250,7 +44,7 @@ func cmdUp() int { IP := "" for i := 1; i < 30; i++ { if B2D.Serial && runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.SerialFile); IP != "" { + if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { break } } @@ -309,7 +103,7 @@ func cmdConfig() int { // Suspend and save the current state of VM on disk. func cmdSave() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -323,7 +117,7 @@ func cmdSave() int { // Gracefully stop the VM by sending ACPI shutdown signal. func cmdStop() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -338,7 +132,7 @@ func cmdStop() int { // Forcefully power off the VM (equivalent to unplug power). Might corrupt disk // image. func cmdPoweroff() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -352,7 +146,7 @@ func cmdPoweroff() int { // Gracefully stop and then start the VM. func cmdRestart() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -366,7 +160,7 @@ func cmdRestart() int { // Forcefully reset (equivalent to cold boot) the VM. Might corrupt disk image. func cmdReset() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -380,9 +174,9 @@ func cmdReset() int { // Delete the VM and associated disk image. func cmdDelete() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { - if err == vbx.ErrMachineNotExist { + if err == driver.ErrMachineNotExist { logf("Machine %q does not exist.", B2D.VM) return 0 } @@ -398,7 +192,7 @@ func cmdDelete() int { // Show detailed info of the VM. func cmdInfo() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -412,24 +206,24 @@ func cmdInfo() int { // Show the current state of the VM. func cmdStatus() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - fmt.Println(m.State) + fmt.Println(m.GetState()) return 0 } // Call the external SSH command to login into boot2docker VM. func cmdSSH() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - if m.State != vbx.Running { + if m.GetState() != driver.Running { logf("VM %q is not running.", B2D.VM) return 1 } @@ -446,7 +240,7 @@ func cmdSSH() int { "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." - "-p", fmt.Sprintf("%d", m.SSHPort), + "-p", fmt.Sprintf("%d", m.GetSSHPort()), "-i", B2D.SSHKey, "docker@localhost", }, os.Args[i:]...) @@ -459,13 +253,13 @@ func cmdSSH() int { } func cmdIP() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - if m.State != vbx.Running { + if m.GetState() != driver.Running { logf("VM %q is not running.", B2D.VM) return 1 } @@ -474,7 +268,7 @@ func cmdIP() int { if B2D.Serial { for i := 1; i < 20; i++ { if runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.SerialFile); IP != "" { + if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { break } } @@ -495,13 +289,13 @@ func cmdIP() int { return 0 } -func RequestIPFromSSH(m *vbx.Machine) string { +func RequestIPFromSSH(m driver.Machine) string { // fall back to using the NAT port forwarded ssh out, err := cmd(B2D.SSH, "-v", // please leave in - this seems to improve the chance of success "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", - "-p", fmt.Sprintf("%d", m.SSHPort), + "-p", fmt.Sprintf("%d", m.GetSSHPort()), "-i", B2D.SSHKey, "docker@localhost", "ip addr show dev eth1", diff --git a/config.go b/config.go index 7983a66..9c59564 100644 --- a/config.go +++ b/config.go @@ -10,50 +10,14 @@ import ( "runtime" toml "github.com/BurntSushi/toml" - vbx "github.com/boot2docker/boot2docker-cli/virtualbox" + "github.com/boot2docker/boot2docker-cli/driver" flag "github.com/ogier/pflag" ) -// boot2docker config. -var B2D struct { - // NOTE: separate sections with blank lines so gofmt doesn't change - // indentation all the time. - - // Gereral flags. - Verbose bool - VBM string - - // basic config - SSH string // SSH client executable - SSHGen string // SSH keygen executable - SSHKey string // SSH key to send to the vm - VM string // virtual machine name - Dir string // boot2docker directory - ISO string // boot2docker ISO image path - VMDK string // base VMDK to use as persistent disk - DiskSize uint // VM disk image size (MB) - Memory uint // VM memory size (MB) - - // NAT network: port forwarding - SSHPort uint16 // host SSH port (forward to port 22 in VM) - DockerPort uint16 // host Docker port (forward to port 2375 in VM) - - // host-only network - HostIP net.IP - DHCPIP net.IP - NetMask net.IPMask - LowerIP net.IP - UpperIP net.IP - DHCPEnabled bool - - // Serial console pipe/socket - Serial bool - SerialFile string -} - var ( // Pattern to parse a key=value line in config profile. reFlagLine = regexp.MustCompile(`^\s*(\w+)\s*=\s*([^#;]+)`) + B2D = driver.MachineConfig{} ) func getCfgDir(name string) (string, error) { @@ -126,6 +90,7 @@ func config() (*flag.FlagSet, error) { } flags.StringVar(&B2D.VBM, "vbm", vbm, "path to VirtualBox management utility.") flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") + flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") flags.StringVar(&B2D.SSH, "ssh", "ssh", "path to SSH client utility.") flags.StringVar(&B2D.SSHGen, "ssh-keygen", "ssh-keygen", "path to ssh-keygen utility.") @@ -174,9 +139,6 @@ func config() (*flag.FlagSet, error) { return nil, err } - vbx.Verbose = B2D.Verbose - vbx.VBM = B2D.VBM - if B2D.SerialFile == "" { if runtime.GOOS == "windows" { //SerialFile ~~ filepath.Join(dir, B2D.vm+".sock") @@ -190,7 +152,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) + errf("Usage: %s [] {help|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) } @@ -201,7 +163,6 @@ func usageLong(flags *flag.FlagSet) { boot2docker management utility. Commands: - init Create a new boot2docker VM. up|start|boot Start VM from any states. ssh [ssh-command] Login to VM via SSH. save|suspend Suspend VM and save state to disk. diff --git a/driver/config.go b/driver/config.go new file mode 100644 index 0000000..190f2b5 --- /dev/null +++ b/driver/config.go @@ -0,0 +1,38 @@ +package driver + +import "net" + +// Machine config. +type MachineConfig struct { + // Gereral flags. + Verbose bool + VBM string + Driver string + + // basic config + SSH string // SSH client executable + SSHGen string // SSH keygen executable + SSHKey string // SSH key to send to the vm + VM string // virtual machine name + Dir string // boot2docker directory + ISO string // boot2docker ISO image path + VMDK string // base VMDK to use as persistent disk + DiskSize uint // VM disk image size (MB) + Memory uint // VM memory size (MB) + + // NAT network: port forwarding + SSHPort uint16 // host SSH port (forward to port 22 in VM) + DockerPort uint16 // host Docker port (forward to port 2375 in VM) + + // host-only network + HostIP net.IP + DHCPIP net.IP + NetMask net.IPMask + LowerIP net.IP + UpperIP net.IP + DHCPEnabled bool + + // Serial console pipe/socket + Serial bool + SerialFile string +} diff --git a/driver/dhcp.go b/driver/dhcp.go new file mode 100644 index 0000000..f6b6316 --- /dev/null +++ b/driver/dhcp.go @@ -0,0 +1,12 @@ +package driver + +import "net" + +// DHCP server info. +type DHCP struct { + NetworkName string + IPv4 net.IPNet + LowerIP net.IP + UpperIP net.IP + Enabled bool +} diff --git a/driver/driver.go b/driver/driver.go new file mode 100644 index 0000000..d5e7886 --- /dev/null +++ b/driver/driver.go @@ -0,0 +1,71 @@ +package driver + +import ( + "errors" + "fmt" +) + +type InitFunc func(i *MachineConfig) (Machine, error) + +type MachineState string + +const ( + Poweroff = MachineState("poweroff") + Running = MachineState("running") + Paused = MachineState("paused") + Saved = MachineState("saved") + Aborted = MachineState("aborted") +) + +// Machine represents a virtual machine instance +type Machine interface { + Start() error + Save() error + Pause() error + Stop() error + Refresh() error + Poweroff() error + Restart() error + Reset() error + Delete() error + Modify() error + AddNATPF(n int, name string, rule PFRule) error + DelNATPF(n int, name string) error + SetNIC(n int, nic NIC) error + AddStorageCtl(name string, ctl StorageController) error + DelStorageCtl(name string) error + AttachStorage(ctlName string, medium StorageMedium) error + GetState() MachineState + GetSerialFile() string + GetDockerPort() uint + GetSSHPort() uint +} + +var ( + // All registred machines + machines map[string]InitFunc + + ErrNotSupported = errors.New("machine not supported") + ErrMachineNotExist = errors.New("machine not exist") + ErrPrerequisites = errors.New("prerequisites for machine not satisfied (hypervisor installed?)") +) + +func init() { + machines = make(map[string]InitFunc) +} + +func Register(driver string, initFunc InitFunc) error { + if _, exists := machines[driver]; exists { + return fmt.Errorf("Driver already registered %s", driver) + } + machines[driver] = initFunc + + return nil +} + +func GetMachine(i *MachineConfig) (Machine, error) { + if initFunc, exists := machines[i.Driver]; exists { + return initFunc(i) + } + return nil, ErrNotSupported +} diff --git a/virtualbox/nic.go b/driver/nic.go similarity index 97% rename from virtualbox/nic.go rename to driver/nic.go index 0569be5..d6c7364 100644 --- a/virtualbox/nic.go +++ b/driver/nic.go @@ -1,4 +1,4 @@ -package virtualbox +package driver // NIC represents a virtualized network interface card. type NIC struct { diff --git a/virtualbox/pfrule.go b/driver/pfrule.go similarity index 98% rename from virtualbox/pfrule.go rename to driver/pfrule.go index 89b9de7..18b8160 100644 --- a/virtualbox/pfrule.go +++ b/driver/pfrule.go @@ -1,4 +1,4 @@ -package virtualbox +package driver import ( "fmt" diff --git a/virtualbox/storage.go b/driver/storage.go similarity index 98% rename from virtualbox/storage.go rename to driver/storage.go index ae129f4..a229daf 100644 --- a/virtualbox/storage.go +++ b/driver/storage.go @@ -1,4 +1,4 @@ -package virtualbox +package driver // StorageController represents a virtualized storage controller. type StorageController struct { diff --git a/dummy/machine.go b/dummy/machine.go new file mode 100644 index 0000000..6d6a46a --- /dev/null +++ b/dummy/machine.go @@ -0,0 +1,157 @@ +package dummy + +import ( + "fmt" + + "github.com/boot2docker/boot2docker-cli/driver" +) + +func init() { + driver.Register("dummy", InitFunc) +} + +// Initialize the Machine. +func InitFunc(i *driver.MachineConfig) (driver.Machine, error) { + fmt.Printf("Init dummy %s\n", i.VM) + return &Machine{Name: i.VM, State: driver.Poweroff}, nil +} + +// Machine information. +type Machine struct { + Name string + UUID string + State driver.MachineState + CPUs uint + Memory uint // main memory (in MB) + VRAM uint // video memory (in MB) + CfgFile string + BaseFolder string + OSType string + BootOrder []string // max 4 slots, each in {none|floppy|dvd|disk|net} + DockerPort uint + SSHPort uint + SerialFile string +} + +// Refresh reloads the machine information. +func (m *Machine) Refresh() error { + fmt.Printf("Refresh %s: %s\n", m.Name, m.State) + return nil +} + +// Start starts the machine. +func (m *Machine) Start() error { + m.State = driver.Running + fmt.Printf("Start %s: %s\n", m.Name, m.State) + return nil +} + +// Suspend suspends the machine and saves its state to disk. +func (m *Machine) Save() error { + m.State = driver.Saved + fmt.Printf("Save %s: %s\n", m.Name, m.State) + return nil +} + +// Pause pauses the execution of the machine. +func (m *Machine) Pause() error { + m.State = driver.Paused + fmt.Printf("Pause %s: %s\n", m.Name, m.State) + return nil +} + +// Stop gracefully stops the machine. +func (m *Machine) Stop() error { + m.State = driver.Poweroff + fmt.Printf("Stop %s: %s\n", m.Name, m.State) + return nil +} + +// Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. +func (m *Machine) Poweroff() error { + m.State = driver.Poweroff + fmt.Printf("Poweroff %s: %s\n", m.Name, m.State) + return nil +} + +// Restart gracefully restarts the machine. +func (m *Machine) Restart() error { + m.State = driver.Running + fmt.Printf("Restart %s: %s\n", m.Name, m.State) + return nil +} + +// Reset forcefully restarts the machine. State is lost and might corrupt the disk image. +func (m *Machine) Reset() error { + m.State = driver.Running + fmt.Printf("Reset %s: %s\n", m.Name, m.State) + return nil +} + +// Get current state +func (m *Machine) GetState() driver.MachineState { + return m.State +} + +// Get serial file +func (m *Machine) GetSerialFile() string { + return m.SerialFile +} + +// Get Docker port +func (m *Machine) GetDockerPort() uint { + return m.DockerPort +} + +// Get SSH port +func (m *Machine) GetSSHPort() uint { + return m.SSHPort +} + +// Delete deletes the machine and associated disk images. +func (m *Machine) Delete() error { + fmt.Printf("Delete %s: %s\n", m.Name, m.State) + return nil +} + +// Modify changes the settings of the machine. +func (m *Machine) Modify() error { + fmt.Printf("Modify %s: %s\n", m.Name, m.State) + return m.Refresh() +} + +// AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. +func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { + fmt.Println("Add NAT PF") + return nil +} + +// DelNATPF deletes the NAT port forwarding rule with the given name from the n-th NIC. +func (m *Machine) DelNATPF(n int, name string) error { + fmt.Println("Del NAT PF") + return nil +} + +// SetNIC set the n-th NIC. +func (m *Machine) SetNIC(n int, nic driver.NIC) error { + fmt.Println("Set NIC") + return nil +} + +// AddStorageCtl adds a storage controller with the given name. +func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { + fmt.Println("Add storage ctl") + return nil +} + +// DelStorageCtl deletes the storage controller with the given name. +func (m *Machine) DelStorageCtl(name string) error { + fmt.Println("Del storage ctl") + return nil +} + +// AttachStorage attaches a storage medium to the named storage controller. +func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { + fmt.Println("Attach storage") + return nil +} diff --git a/main.go b/main.go index 1d0b58f..a28b377 100644 --- a/main.go +++ b/main.go @@ -31,8 +31,6 @@ func run() int { return cmdDownload() case "config", "cfg": return cmdConfig() - case "init": - return cmdInit() case "up", "start", "boot", "resume": return cmdUp() case "save", "suspend": diff --git a/vbm.go b/vbm.go deleted file mode 100644 index e1d9b72..0000000 --- a/vbm.go +++ /dev/null @@ -1,107 +0,0 @@ -package main - -import ( - "bytes" - "io" - "os" - "path/filepath" - - vbx "github.com/boot2docker/boot2docker-cli/virtualbox" -) - -// TODO: delete the hostonlyif and dhcpserver when we delete the vm! (need to -// reference count to make sure there are no other vms relying on them) - -// Get or create the hostonly network interface -func getHostOnlyNetworkInterface() (string, error) { - // Check if the interface/dhcp exists. - nets, err := vbx.HostonlyNets() - if err != nil { - return "", err - } - - dhcps, err := vbx.DHCPs() - if err != nil { - return "", err - } - - for _, n := range nets { - if dhcp, ok := dhcps[n.NetworkName]; ok { - if dhcp.IPv4.IP.Equal(B2D.DHCPIP) && - dhcp.IPv4.Mask.String() == B2D.NetMask.String() && - dhcp.LowerIP.Equal(B2D.LowerIP) && - dhcp.UpperIP.Equal(B2D.UpperIP) && - dhcp.Enabled == B2D.DHCPEnabled { - if B2D.Verbose { - logf("Reusing existing host-only network interface %q", n.Name) - } - return n.Name, nil - } - } - } - - // No existing host-only interface found. Create a new one. - if B2D.Verbose { - logf("Creating a new host-only network interface...") - } - hostonlyNet, err := vbx.CreateHostonlyNet() - if err != nil { - return "", err - } - hostonlyNet.IPv4.IP = B2D.HostIP - hostonlyNet.IPv4.Mask = B2D.NetMask - if err := hostonlyNet.Config(); err != nil { - return "", err - } - - // Create and add a DHCP server to the host-only network - dhcp := vbx.DHCP{} - dhcp.IPv4.IP = B2D.DHCPIP - dhcp.IPv4.Mask = B2D.NetMask - dhcp.LowerIP = B2D.LowerIP - dhcp.UpperIP = B2D.UpperIP - dhcp.Enabled = true - if err := vbx.AddHostonlyDHCP(hostonlyNet.Name, dhcp); err != nil { - return "", err - } - return hostonlyNet.Name, nil -} - -// Copy disk image from given source path to destination -func copyDiskImage(dst, src string) (err error) { - // Open source disk image - srcImg, err := os.Open(src) - if err != nil { - return err - } - closeSrcImg := func() { - if ee := srcImg.Close(); ee != nil { - err = ee - } - } - defer closeSrcImg() - dstImg, err := os.Create(dst) - if err != nil { - return err - } - closeDstImg := func() { - if ee := dstImg.Close(); ee != nil { - err = ee - } - } - defer closeDstImg() - _, err = io.Copy(dstImg, srcImg) - return err -} - -// Make a boot2docker VM disk image with the given size (in MB). -func makeDiskImage(dest string, size uint, initialBytes []byte) error { - // Create the dest dir. - if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { - return err - } - // Fill in the magic string so boot2docker VM will detect this and format - // the disk upon first boot. - raw := bytes.NewReader(initialBytes) - return vbx.MakeDiskImage(dest, size, raw) -} diff --git a/virtualbox/dhcp.go b/virtualbox/dhcp.go index d18d7a4..d686e8e 100644 --- a/virtualbox/dhcp.go +++ b/virtualbox/dhcp.go @@ -4,18 +4,11 @@ import ( "bufio" "net" "strings" -) -// DHCP server info. -type DHCP struct { - NetworkName string - IPv4 net.IPNet - LowerIP net.IP - UpperIP net.IP - Enabled bool -} + "github.com/boot2docker/boot2docker-cli/driver" +) -func addDHCP(kind, name string, d DHCP) error { +func addDHCP(kind, name string, d driver.DHCP) error { command := "modify" // On some platforms (OSX), creating a hostonlyinterface adds a default dhcpserver @@ -45,29 +38,29 @@ func addDHCP(kind, name string, d DHCP) error { } // AddInternalDHCP adds a DHCP server to an internal network. -func AddInternalDHCP(netname string, d DHCP) error { +func AddInternalDHCP(netname string, d driver.DHCP) error { return addDHCP("--netname", netname, d) } // AddHostonlyDHCP adds a DHCP server to a host-only network. -func AddHostonlyDHCP(ifname string, d DHCP) error { +func AddHostonlyDHCP(ifname string, d driver.DHCP) error { return addDHCP("--netname", "HostInterfaceNetworking-"+ifname, d) } // DHCPs gets all DHCP server settings in a map keyed by DHCP.NetworkName. -func DHCPs() (map[string]*DHCP, error) { +func DHCPs() (map[string]*driver.DHCP, error) { out, err := vbmOut("list", "dhcpservers") if err != nil { return nil, err } s := bufio.NewScanner(strings.NewReader(out)) - m := map[string]*DHCP{} - dhcp := &DHCP{} + m := map[string]*driver.DHCP{} + dhcp := &driver.DHCP{} for s.Scan() { line := s.Text() if line == "" { m[dhcp.NetworkName] = dhcp - dhcp = &DHCP{} + dhcp = &driver.DHCP{} continue } res := reColonLine.FindStringSubmatch(line) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 70b1e86..2100163 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -1,22 +1,20 @@ package virtualbox import ( + "archive/tar" "bufio" + "bytes" "fmt" + "io/ioutil" + "net" + "os" "path/filepath" + "runtime" "strconv" "strings" "time" -) - -type MachineState string -const ( - Poweroff = MachineState("poweroff") - Running = MachineState("running") - Paused = MachineState("paused") - Saved = MachineState("saved") - Aborted = MachineState("aborted") + "github.com/boot2docker/boot2docker-cli/driver" ) type Flag int @@ -40,6 +38,19 @@ const ( F_accelerate3d ) +func init() { + driver.Register("virtualbox", InitFunc) +} + +// Initialize the Machine. +func InitFunc(i *driver.MachineConfig) (driver.Machine, error) { + m, err := GetMachine(i.VM) + if err != nil { + return CreateMachine(i) + } + return m, nil +} + // Convert bool to "on"/"off" func bool2string(b bool) string { if b { @@ -57,7 +68,7 @@ func (f Flag) Get(o Flag) string { type Machine struct { Name string UUID string - State MachineState + State driver.MachineState CPUs uint Memory uint // main memory (in MB) VRAM uint // video memory (in MB) @@ -88,13 +99,13 @@ func (m *Machine) Refresh() error { // Start starts the machine. func (m *Machine) Start() error { switch m.State { - case Paused: + case driver.Paused: return vbm("controlvm", m.Name, "resume") - case Poweroff, Saved, Aborted: + case driver.Poweroff, driver.Saved, driver.Aborted: return vbm("startvm", m.Name, "--type", "headless") } if err := m.Refresh(); err == nil { - if m.State != Running { + if m.State != driver.Running { return fmt.Errorf("Failed to start", m.Name) } } @@ -104,11 +115,11 @@ func (m *Machine) Start() error { // Suspend suspends the machine and saves its state to disk. func (m *Machine) Save() error { switch m.State { - case Paused: + case driver.Paused: if err := m.Start(); err != nil { return err } - case Poweroff, Aborted, Saved: + case driver.Poweroff, driver.Aborted, driver.Saved: return nil } return vbm("controlvm", m.Name, "savestate") @@ -117,7 +128,7 @@ func (m *Machine) Save() error { // Pause pauses the execution of the machine. func (m *Machine) Pause() error { switch m.State { - case Paused, Poweroff, Aborted, Saved: + case driver.Paused, driver.Poweroff, driver.Aborted, driver.Saved: return nil } return vbm("controlvm", m.Name, "pause") @@ -126,15 +137,15 @@ func (m *Machine) Pause() error { // Stop gracefully stops the machine. func (m *Machine) Stop() error { switch m.State { - case Poweroff, Aborted, Saved: + case driver.Poweroff, driver.Aborted, driver.Saved: return nil - case Paused: + case driver.Paused: if err := m.Start(); err != nil { return err } } - for m.State != Poweroff { // busy wait until the machine is stopped + for m.State != driver.Poweroff { // busy wait until the machine is stopped if err := vbm("controlvm", m.Name, "acpipowerbutton"); err != nil { return err } @@ -149,7 +160,7 @@ func (m *Machine) Stop() error { // Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. func (m *Machine) Poweroff() error { switch m.State { - case Poweroff, Aborted, Saved: + case driver.Poweroff, driver.Aborted, driver.Saved: return nil } return vbm("controlvm", m.Name, "poweroff") @@ -158,7 +169,7 @@ func (m *Machine) Poweroff() error { // Restart gracefully restarts the machine. func (m *Machine) Restart() error { switch m.State { - case Paused, Saved: + case driver.Paused, driver.Saved: if err := m.Start(); err != nil { return err } @@ -172,7 +183,7 @@ func (m *Machine) Restart() error { // Reset forcefully restarts the machine. State is lost and might corrupt the disk image. func (m *Machine) Reset() error { switch m.State { - case Paused, Saved: + case driver.Paused, driver.Saved: if err := m.Start(); err != nil { return err } @@ -188,6 +199,26 @@ func (m *Machine) Delete() error { return vbm("unregistervm", m.Name, "--delete") } +// Get current state +func (m *Machine) GetState() driver.MachineState { + return m.State +} + +// Get serial file +func (m *Machine) GetSerialFile() string { + return m.SerialFile +} + +// Get Docker port +func (m *Machine) GetDockerPort() uint { + return m.DockerPort +} + +// Get SSH port +func (m *Machine) GetSSHPort() uint { + return m.SSHPort +} + // GetMachine finds a machine by its name or UUID. func GetMachine(id string) (*Machine, error) { stdout, stderr, err := vbmOutErr("showvminfo", id, "--machinereadable") @@ -219,7 +250,7 @@ func GetMachine(id string) (*Machine, error) { case "UUID": m.UUID = val case "VMState": - m.State = MachineState(val) + m.State = driver.MachineState(val) case "memory": n, err := strconv.ParseUint(val, 10, 32) if err != nil { @@ -294,8 +325,8 @@ func ListMachines() ([]string, error) { } // CreateMachine creates a new machine. If basefolder is empty, use default. -func CreateMachine(name, basefolder string) (*Machine, error) { - if name == "" { +func CreateMachine(i *driver.MachineConfig) (*Machine, error) { + if i.VM == "" { return nil, fmt.Errorf("machine name is empty") } @@ -305,25 +336,140 @@ func CreateMachine(name, basefolder string) (*Machine, error) { return nil, err } for _, m := range machineNames { - if m == name { + if m == i.VM { return nil, ErrMachineExist } } // Create and register the machine. - args := []string{"createvm", "--name", name, "--register"} - if basefolder != "" { - args = append(args, "--basefolder", basefolder) - } + args := []string{"createvm", "--name", i.VM, "--register"} if err := vbm(args...); err != nil { return nil, err } - m, err := GetMachine(name) + m, err := GetMachine(i.VM) if err != nil { return nil, err } + // Configure VM for Boot2docker + SetExtra(i.VM, "VBoxInternal/CPUM/EnableHVP", "1") + m.OSType = "Linux26_64" + m.CPUs = uint(runtime.NumCPU()) + m.Memory = i.Memory + m.SerialFile = i.SerialFile + + m.Flag |= F_pae + m.Flag |= F_longmode // important: use x86-64 processor + m.Flag |= F_rtcuseutc + m.Flag |= F_acpi + m.Flag |= F_ioapic + m.Flag |= F_hpet + m.Flag |= F_hwvirtex + m.Flag |= F_vtxvpid + m.Flag |= F_largepages + m.Flag |= F_nestedpaging + + // Set VM boot order + m.BootOrder = []string{"dvd"} + if err := m.Modify(); err != nil { + return m, err + } + + // Set NIC #1 to use NAT + m.SetNIC(1, driver.NIC{Network: driver.NICNetNAT, Hardware: driver.VirtIO}) + pfRules := map[string]driver.PFRule{ + "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: i.SSHPort, GuestPort: 22}, + "docker": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: i.DockerPort, GuestPort: 2375}, + } + + for name, rule := range pfRules { + if err := m.AddNATPF(1, name, rule); err != nil { + return m, err + } + } + + hostIFName, err := getHostOnlyNetworkInterface(i) + if err != nil { + return m, err + } + + // Set NIC #2 to use host-only + if err := m.SetNIC(2, driver.NIC{Network: driver.NICNetHostonly, Hardware: driver.VirtIO, HostonlyAdapter: hostIFName}); err != nil { + return m, err + } + + // Set VM storage + if err := m.AddStorageCtl("SATA", driver.StorageController{SysBus: driver.SysBusSATA, HostIOCache: true, Bootable: true}); err != nil { + return m, err + } + + // Attach ISO image + if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 0, Device: 0, DriveType: driver.DriveDVD, Medium: i.ISO}); err != nil { + return m, err + } + + diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", i.VM)) + if _, err := os.Stat(diskImg); err != nil { + if !os.IsNotExist(err) { + return m, err + } + + if i.VMDK != "" { + if err := copyDiskImage(diskImg, i.VMDK); err != nil { + return m, err + } + } else { + magicString := "boot2docker, please format-me" + + buf := new(bytes.Buffer) + tw := tar.NewWriter(buf) + + // magicString first so the automount script knows to format the disk + file := &tar.Header{Name: magicString, Size: int64(len(magicString))} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + if _, err := tw.Write([]byte(magicString)); err != nil { + return m, err + } + // .ssh/key.pub => authorized_keys + file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + pubKey, err := ioutil.ReadFile(i.SSHKey + ".pub") + if err != nil { + return m, err + } + file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + if _, err := tw.Write([]byte(pubKey)); err != nil { + return m, err + } + file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + if _, err := tw.Write([]byte(pubKey)); err != nil { + return m, err + } + if err := tw.Close(); err != nil { + return m, err + } + + if err := makeDiskImage(diskImg, i.DiskSize, buf.Bytes()); err != nil { + return m, err + } + } + } + + if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 1, Device: 0, DriveType: driver.DriveHDD, Medium: diskImg}); err != nil { + return m, err + } + return m, nil } @@ -379,7 +525,7 @@ func (m *Machine) Modify() error { } // AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. -func (m *Machine) AddNATPF(n int, name string, rule PFRule) error { +func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { return vbm("controlvm", m.Name, fmt.Sprintf("natpf%d", n), fmt.Sprintf("%s,%s", name, rule.Format())) } @@ -390,7 +536,7 @@ func (m *Machine) DelNATPF(n int, name string) error { } // SetNIC set the n-th NIC. -func (m *Machine) SetNIC(n int, nic NIC) error { +func (m *Machine) SetNIC(n int, nic driver.NIC) error { args := []string{"modifyvm", m.Name, fmt.Sprintf("--nic%d", n), string(nic.Network), fmt.Sprintf("--nictype%d", n), string(nic.Hardware), @@ -404,7 +550,7 @@ func (m *Machine) SetNIC(n int, nic NIC) error { } // AddStorageCtl adds a storage controller with the given name. -func (m *Machine) AddStorageCtl(name string, ctl StorageController) error { +func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { args := []string{"storagectl", m.Name, "--name", name} if ctl.SysBus != "" { args = append(args, "--add", string(ctl.SysBus)) @@ -426,7 +572,7 @@ func (m *Machine) DelStorageCtl(name string) error { } // AttachStorage attaches a storage medium to the named storage controller. -func (m *Machine) AttachStorage(ctlName string, medium StorageMedium) error { +func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { return vbm("storageattach", m.Name, "--storagectl", ctlName, "--port", fmt.Sprintf("%d", medium.Port), "--device", fmt.Sprintf("%d", medium.Device), diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index dd0df6f..eb73d91 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -3,6 +3,7 @@ package virtualbox import ( "bytes" "errors" + "io" "log" "os" "os/exec" @@ -10,6 +11,8 @@ import ( "regexp" "runtime" "strings" + + "github.com/boot2docker/boot2docker-cli/driver" ) var ( @@ -86,3 +89,91 @@ func vbmOutErr(args ...string) (string, string, error) { } return stdout.String(), stderr.String(), err } + +// Get or create the hostonly network interface +func getHostOnlyNetworkInterface(i *driver.MachineConfig) (string, error) { + // Check if the interface/dhcp exists. + nets, err := HostonlyNets() + if err != nil { + return "", err + } + + dhcps, err := DHCPs() + if err != nil { + return "", err + } + + for _, n := range nets { + if dhcp, ok := dhcps[n.NetworkName]; ok { + if dhcp.IPv4.IP.Equal(i.DHCPIP) && + dhcp.IPv4.Mask.String() == i.NetMask.String() && + dhcp.LowerIP.Equal(i.LowerIP) && + dhcp.UpperIP.Equal(i.UpperIP) && + dhcp.Enabled == i.DHCPEnabled { + return n.Name, nil + } + } + } + + // No existing host-only interface found. Create a new one. + hostonlyNet, err := CreateHostonlyNet() + if err != nil { + return "", err + } + hostonlyNet.IPv4.IP = i.HostIP + hostonlyNet.IPv4.Mask = i.NetMask + if err := hostonlyNet.Config(); err != nil { + return "", err + } + + // Create and add a DHCP server to the host-only network + dhcp := driver.DHCP{} + dhcp.IPv4.IP = i.DHCPIP + dhcp.IPv4.Mask = i.NetMask + dhcp.LowerIP = i.LowerIP + dhcp.UpperIP = i.UpperIP + dhcp.Enabled = true + if err := AddHostonlyDHCP(hostonlyNet.Name, dhcp); err != nil { + return "", err + } + return hostonlyNet.Name, nil +} + +// Copy disk image from given source path to destination +func copyDiskImage(dst, src string) (err error) { + // Open source disk image + srcImg, err := os.Open(src) + if err != nil { + return err + } + closeSrcImg := func() { + if ee := srcImg.Close(); ee != nil { + err = ee + } + } + defer closeSrcImg() + dstImg, err := os.Create(dst) + if err != nil { + return err + } + closeDstImg := func() { + if ee := dstImg.Close(); ee != nil { + err = ee + } + } + defer closeDstImg() + _, err = io.Copy(dstImg, srcImg) + return err +} + +// Make a boot2docker VM disk image with the given size (in MB). +func makeDiskImage(dest string, size uint, initialBytes []byte) error { + // Create the dest dir. + if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { + return err + } + // Fill in the magic string so boot2docker VM will detect this and format + // the disk upon first boot. + raw := bytes.NewReader(initialBytes) + return MakeDiskImage(dest, size, raw) +} From f2341be2ae4ac741e40cae1dd20b6323b611ba08 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Wed, 9 Jul 2014 09:28:52 -0700 Subject: [PATCH 026/167] Bring back explicit init command; add init flag to force auto initialize. --- cmds.go | 13 ++++++++++++- config.go | 4 +++- driver/config.go | 1 + main.go | 2 ++ virtualbox/machine.go | 4 ++-- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/cmds.go b/cmds.go index 6c3dded..bd72e7b 100644 --- a/cmds.go +++ b/cmds.go @@ -16,6 +16,17 @@ import ( const dockerPort = 2375 +// Initialize the boot2docker VM from scratch. +func cmdInit() int { + B2D.Init = true + _, err := driver.GetMachine(&B2D) + if err != nil { + logf("Failed to initialize machine %q: %s", B2D.VM, err) + return 1 + } + return 0 +} + // Bring up the VM from all possible states. func cmdUp() int { m, err := driver.GetMachine(&B2D) @@ -40,7 +51,7 @@ func cmdUp() int { logf("Waiting for VM to be started...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket time.Sleep(600 * time.Millisecond) - natSSH := fmt.Sprintf("localhost:%d", m.SSHPort) + natSSH := fmt.Sprintf("localhost:%d", m.GetSSHPort()) IP := "" for i := 1; i < 30; i++ { if B2D.Serial && runtime.GOOS != "windows" { diff --git a/config.go b/config.go index 9c59564..0b9f548 100644 --- a/config.go +++ b/config.go @@ -88,6 +88,7 @@ func config() (*flag.FlagSet, error) { } vbm = filepath.Join(p, "VBoxManage.exe") } + flags.BoolVarP(&B2D.Init, "init", "i", false, "auto initialize vm instance.") flags.StringVar(&B2D.VBM, "vbm", vbm, "path to VirtualBox management utility.") flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") @@ -152,7 +153,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - errf("Usage: %s [] {help|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) + errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) } @@ -163,6 +164,7 @@ func usageLong(flags *flag.FlagSet) { boot2docker management utility. Commands: + init Create a new boot2docker VM. up|start|boot Start VM from any states. ssh [ssh-command] Login to VM via SSH. save|suspend Suspend VM and save state to disk. diff --git a/driver/config.go b/driver/config.go index 190f2b5..91a1884 100644 --- a/driver/config.go +++ b/driver/config.go @@ -5,6 +5,7 @@ import "net" // Machine config. type MachineConfig struct { // Gereral flags. + Init bool Verbose bool VBM string Driver string diff --git a/main.go b/main.go index a28b377..1d0b58f 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,8 @@ func run() int { return cmdDownload() case "config", "cfg": return cmdConfig() + case "init": + return cmdInit() case "up", "start", "boot", "resume": return cmdUp() case "save", "suspend": diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 2100163..3136a99 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -45,10 +45,10 @@ func init() { // Initialize the Machine. func InitFunc(i *driver.MachineConfig) (driver.Machine, error) { m, err := GetMachine(i.VM) - if err != nil { + if err != nil && i.Init == true { return CreateMachine(i) } - return m, nil + return m, err } // Convert bool to "on"/"off" From 81de18590e0ee695fc7a2fb1c27e551decea4a03 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Wed, 16 Jul 2014 11:53:13 -0700 Subject: [PATCH 027/167] Fix machine config local variable name --- driver/driver.go | 6 +++--- virtualbox/machine.go | 42 +++++++++++++++++++++--------------------- virtualbox/vbm.go | 24 ++++++++++++------------ 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/driver/driver.go b/driver/driver.go index d5e7886..52611ad 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -63,9 +63,9 @@ func Register(driver string, initFunc InitFunc) error { return nil } -func GetMachine(i *MachineConfig) (Machine, error) { - if initFunc, exists := machines[i.Driver]; exists { - return initFunc(i) +func GetMachine(mc *MachineConfig) (Machine, error) { + if initFunc, exists := machines[mc.Driver]; exists { + return initFunc(mc) } return nil, ErrNotSupported } diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 3136a99..ae9e8a5 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -43,10 +43,10 @@ func init() { } // Initialize the Machine. -func InitFunc(i *driver.MachineConfig) (driver.Machine, error) { - m, err := GetMachine(i.VM) - if err != nil && i.Init == true { - return CreateMachine(i) +func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { + m, err := GetMachine(mc.VM) + if err != nil && mc.Init == true { + return CreateMachine(mc) } return m, err } @@ -325,8 +325,8 @@ func ListMachines() ([]string, error) { } // CreateMachine creates a new machine. If basefolder is empty, use default. -func CreateMachine(i *driver.MachineConfig) (*Machine, error) { - if i.VM == "" { +func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { + if mc.VM == "" { return nil, fmt.Errorf("machine name is empty") } @@ -336,28 +336,28 @@ func CreateMachine(i *driver.MachineConfig) (*Machine, error) { return nil, err } for _, m := range machineNames { - if m == i.VM { + if m == mc.VM { return nil, ErrMachineExist } } // Create and register the machine. - args := []string{"createvm", "--name", i.VM, "--register"} + args := []string{"createvm", "--name", mc.VM, "--register"} if err := vbm(args...); err != nil { return nil, err } - m, err := GetMachine(i.VM) + m, err := GetMachine(mc.VM) if err != nil { return nil, err } // Configure VM for Boot2docker - SetExtra(i.VM, "VBoxInternal/CPUM/EnableHVP", "1") + SetExtra(mc.VM, "VBoxInternal/CPUM/EnableHVP", "1") m.OSType = "Linux26_64" m.CPUs = uint(runtime.NumCPU()) - m.Memory = i.Memory - m.SerialFile = i.SerialFile + m.Memory = mc.Memory + m.SerialFile = mc.SerialFile m.Flag |= F_pae m.Flag |= F_longmode // important: use x86-64 processor @@ -379,8 +379,8 @@ func CreateMachine(i *driver.MachineConfig) (*Machine, error) { // Set NIC #1 to use NAT m.SetNIC(1, driver.NIC{Network: driver.NICNetNAT, Hardware: driver.VirtIO}) pfRules := map[string]driver.PFRule{ - "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: i.SSHPort, GuestPort: 22}, - "docker": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: i.DockerPort, GuestPort: 2375}, + "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: 22}, + "docker": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: 2375}, } for name, rule := range pfRules { @@ -389,7 +389,7 @@ func CreateMachine(i *driver.MachineConfig) (*Machine, error) { } } - hostIFName, err := getHostOnlyNetworkInterface(i) + hostIFName, err := getHostOnlyNetworkInterface(mc) if err != nil { return m, err } @@ -405,18 +405,18 @@ func CreateMachine(i *driver.MachineConfig) (*Machine, error) { } // Attach ISO image - if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 0, Device: 0, DriveType: driver.DriveDVD, Medium: i.ISO}); err != nil { + if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 0, Device: 0, DriveType: driver.DriveDVD, Medium: mc.ISO}); err != nil { return m, err } - diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", i.VM)) + diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", mc.VM)) if _, err := os.Stat(diskImg); err != nil { if !os.IsNotExist(err) { return m, err } - if i.VMDK != "" { - if err := copyDiskImage(diskImg, i.VMDK); err != nil { + if mc.VMDK != "" { + if err := copyDiskImage(diskImg, mc.VMDK); err != nil { return m, err } } else { @@ -438,7 +438,7 @@ func CreateMachine(i *driver.MachineConfig) (*Machine, error) { if err := tw.WriteHeader(file); err != nil { return m, err } - pubKey, err := ioutil.ReadFile(i.SSHKey + ".pub") + pubKey, err := ioutil.ReadFile(mc.SSHKey + ".pub") if err != nil { return m, err } @@ -460,7 +460,7 @@ func CreateMachine(i *driver.MachineConfig) (*Machine, error) { return m, err } - if err := makeDiskImage(diskImg, i.DiskSize, buf.Bytes()); err != nil { + if err := makeDiskImage(diskImg, mc.DiskSize, buf.Bytes()); err != nil { return m, err } } diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index eb73d91..d7392ed 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -91,7 +91,7 @@ func vbmOutErr(args ...string) (string, string, error) { } // Get or create the hostonly network interface -func getHostOnlyNetworkInterface(i *driver.MachineConfig) (string, error) { +func getHostOnlyNetworkInterface(mc *driver.MachineConfig) (string, error) { // Check if the interface/dhcp exists. nets, err := HostonlyNets() if err != nil { @@ -105,11 +105,11 @@ func getHostOnlyNetworkInterface(i *driver.MachineConfig) (string, error) { for _, n := range nets { if dhcp, ok := dhcps[n.NetworkName]; ok { - if dhcp.IPv4.IP.Equal(i.DHCPIP) && - dhcp.IPv4.Mask.String() == i.NetMask.String() && - dhcp.LowerIP.Equal(i.LowerIP) && - dhcp.UpperIP.Equal(i.UpperIP) && - dhcp.Enabled == i.DHCPEnabled { + if dhcp.IPv4.IP.Equal(mc.DHCPIP) && + dhcp.IPv4.Mask.String() == mc.NetMask.String() && + dhcp.LowerIP.Equal(mc.LowerIP) && + dhcp.UpperIP.Equal(mc.UpperIP) && + dhcp.Enabled == mc.DHCPEnabled { return n.Name, nil } } @@ -120,18 +120,18 @@ func getHostOnlyNetworkInterface(i *driver.MachineConfig) (string, error) { if err != nil { return "", err } - hostonlyNet.IPv4.IP = i.HostIP - hostonlyNet.IPv4.Mask = i.NetMask + hostonlyNet.IPv4.IP = mc.HostIP + hostonlyNet.IPv4.Mask = mc.NetMask if err := hostonlyNet.Config(); err != nil { return "", err } // Create and add a DHCP server to the host-only network dhcp := driver.DHCP{} - dhcp.IPv4.IP = i.DHCPIP - dhcp.IPv4.Mask = i.NetMask - dhcp.LowerIP = i.LowerIP - dhcp.UpperIP = i.UpperIP + dhcp.IPv4.IP = mc.DHCPIP + dhcp.IPv4.Mask = mc.NetMask + dhcp.LowerIP = mc.LowerIP + dhcp.UpperIP = mc.UpperIP dhcp.Enabled = true if err := AddHostonlyDHCP(hostonlyNet.Name, dhcp); err != nil { return "", err From b0c1b1b57c2d51aaf63e97f5291ded9548a77cad Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Wed, 16 Jul 2014 11:59:36 -0700 Subject: [PATCH 028/167] Clean deferred calls in vbm --- virtualbox/vbm.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index d7392ed..e2d34df 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -146,22 +146,20 @@ func copyDiskImage(dst, src string) (err error) { if err != nil { return err } - closeSrcImg := func() { + defer func() { if ee := srcImg.Close(); ee != nil { err = ee } - } - defer closeSrcImg() + }() dstImg, err := os.Create(dst) if err != nil { return err } - closeDstImg := func() { + defer func() { if ee := dstImg.Close(); ee != nil { err = ee } - } - defer closeDstImg() + }() _, err = io.Copy(dstImg, srcImg) return err } From 360ad9aae8c97cff5b76e210fd6398015b4b7b08 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Wed, 16 Jul 2014 12:20:29 -0700 Subject: [PATCH 029/167] Refactor known ports into driver consts --- cmds.go | 6 ++---- driver/driver.go | 5 +++++ virtualbox/machine.go | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/cmds.go b/cmds.go index bd72e7b..072b6cf 100644 --- a/cmds.go +++ b/cmds.go @@ -14,8 +14,6 @@ import ( "github.com/boot2docker/boot2docker-cli/driver" ) -const dockerPort = 2375 - // Initialize the boot2docker VM from scratch. func cmdInit() int { B2D.Init = true @@ -88,9 +86,9 @@ func cmdUp() int { logf("Please run `boot2docker -v up` to diagnose.") } else { // Check if $DOCKER_HOST ENV var is properly configured. - if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, dockerPort) { + if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, driver.DockerPort) { logf("To connect the Docker client to the Docker daemon, please set:") - logf(" export DOCKER_HOST=tcp://%s:%d", IP, dockerPort) + logf(" export DOCKER_HOST=tcp://%s:%d", IP, driver.DockerPort) } else { logf("Your DOCKER_HOST env variable is already set correctly.") } diff --git a/driver/driver.go b/driver/driver.go index 52611ad..db4f7aa 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -10,6 +10,11 @@ type InitFunc func(i *MachineConfig) (Machine, error) type MachineState string const ( + // Known ports + SSHPort = 22 + DockerPort = 2375 + + // VM states Poweroff = MachineState("poweroff") Running = MachineState("running") Paused = MachineState("paused") diff --git a/virtualbox/machine.go b/virtualbox/machine.go index ae9e8a5..cade564 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -379,8 +379,8 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { // Set NIC #1 to use NAT m.SetNIC(1, driver.NIC{Network: driver.NICNetNAT, Hardware: driver.VirtIO}) pfRules := map[string]driver.PFRule{ - "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: 22}, - "docker": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: 2375}, + "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: driver.SSHPort}, + "docker": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: driver.DockerPort}, } for name, rule := range pfRules { From 3ee246e31bce8eb9dd9ec6676ef7542271c2c2c0 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Fri, 11 Jul 2014 16:39:30 +1000 Subject: [PATCH 030/167] Upgrade the image - preserving VM state (restarting if it was running) Machine will be restarted after successful download if necessary. Docker-DCO-1.1-Signed-off-by: Michael Neale michael.neale@gmail.com (github: michaelneale) --- .gitignore | 1 + cmds.go | 14 ++++++++++++++ config.go | 4 ++-- main.go | 2 ++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2d18d02..45d168d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ nbproject *.sublime-project *.sublime-workspace *.swp +boot2docker-cli \ No newline at end of file diff --git a/cmds.go b/cmds.go index d512961..72ab184 100644 --- a/cmds.go +++ b/cmds.go @@ -350,6 +350,20 @@ func cmdPoweroff() int { return 0 } +// Upgrade the boot2docker iso - preserving server state +func cmdUpgrade() int { + m, err := vbx.GetMachine(B2D.VM) + if err == nil && m.State == vbx.Running { + if cmdDownload() == 0 && cmdStop() == 0 { + return cmdUp() + } else { + return 0 + } + } else { + return cmdDownload() + } +} + // Gracefully stop and then start the VM. func cmdRestart() int { m, err := vbx.GetMachine(B2D.VM) diff --git a/config.go b/config.go index 7983a66..1578bb2 100644 --- a/config.go +++ b/config.go @@ -190,8 +190,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) - + errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|upgrade|version} []\n", os.Args[0]) } func usageLong(flags *flag.FlagSet) { @@ -215,6 +214,7 @@ Commands: ip Display the IP address of the VM's Host-only network. status Display current state of VM. download Download boot2docker ISO image. + upgrade Upgrade the boot2docker ISO image (if vm is running it will be stopped and started). version Display version information. Options: diff --git a/main.go b/main.go index 1d0b58f..81ee6ef 100644 --- a/main.go +++ b/main.go @@ -55,6 +55,8 @@ func run() int { return cmdSSH() case "ip": return cmdIP() + case "upgrade": + return cmdUpgrade() case "version": outf("Client version: %s\nGit commit: %s\n", Version, GitSHA) return 0 From 15896ea327bd2c809665428378893cc5bc9766f3 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 18 Jul 2014 20:47:06 +1000 Subject: [PATCH 031/167] Sorry, I didn't test the effects of merging 2 PRs --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index 0e73cce..ecf7595 100644 --- a/cmds.go +++ b/cmds.go @@ -155,8 +155,8 @@ func cmdPoweroff() int { // Upgrade the boot2docker iso - preserving server state func cmdUpgrade() int { - m, err := vbx.GetMachine(B2D.VM) - if err == nil && m.State == vbx.Running { + m, err := driver.GetMachine(&B2D) + if err == nil && m.GetState() == driver.Running { if cmdDownload() == 0 && cmdStop() == 0 { return cmdUp() } else { From f79142082c191c7d007bdb6cd66365c734d32fa5 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 24 Jul 2014 13:08:51 +1000 Subject: [PATCH 032/167] bump-1.1.2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 56130fb..0f1acbd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.1.1 +v1.1.2 From 52593c6ffe17fce0881a1b015d2d38f802311391 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 24 Jul 2014 15:35:31 +1000 Subject: [PATCH 033/167] Revert "Sorry, I didn't test the effects of merging 2 PRs" --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index ecf7595..0e73cce 100644 --- a/cmds.go +++ b/cmds.go @@ -155,8 +155,8 @@ func cmdPoweroff() int { // Upgrade the boot2docker iso - preserving server state func cmdUpgrade() int { - m, err := driver.GetMachine(&B2D) - if err == nil && m.GetState() == driver.Running { + m, err := vbx.GetMachine(B2D.VM) + if err == nil && m.State == vbx.Running { if cmdDownload() == 0 && cmdStop() == 0 { return cmdUp() } else { From 98a3e94c48bacacb2d931d90f9eda60a87ce80ce Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 24 Jul 2014 15:37:49 +1000 Subject: [PATCH 034/167] Revert "Create driver model and refactor virtualbox dependencies into driver" --- cmds.go | 259 ++++++++++++++++++++++++++---- config.go | 45 +++++- driver/config.go | 39 ----- driver/dhcp.go | 12 -- driver/driver.go | 76 --------- dummy/machine.go | 157 ------------------ vbm.go | 107 ++++++++++++ virtualbox/dhcp.go | 25 +-- virtualbox/machine.go | 216 ++++--------------------- {driver => virtualbox}/nic.go | 2 +- {driver => virtualbox}/pfrule.go | 2 +- {driver => virtualbox}/storage.go | 2 +- virtualbox/vbm.go | 89 ---------- 13 files changed, 430 insertions(+), 601 deletions(-) delete mode 100644 driver/config.go delete mode 100644 driver/dhcp.go delete mode 100644 driver/driver.go delete mode 100644 dummy/machine.go create mode 100644 vbm.go rename {driver => virtualbox}/nic.go (97%) rename {driver => virtualbox}/pfrule.go (98%) rename {driver => virtualbox}/storage.go (98%) diff --git a/cmds.go b/cmds.go index ecf7595..62db7fc 100644 --- a/cmds.go +++ b/cmds.go @@ -1,33 +1,230 @@ package main import ( + "archive/tar" + "bytes" "encoding/json" "fmt" + "io/ioutil" + "net" "os" + "path/filepath" "runtime" "strings" "time" - _ "github.com/boot2docker/boot2docker-cli/dummy" - _ "github.com/boot2docker/boot2docker-cli/virtualbox" - - "github.com/boot2docker/boot2docker-cli/driver" + vbx "github.com/boot2docker/boot2docker-cli/virtualbox" ) +const dockerPort = 2375 + // Initialize the boot2docker VM from scratch. func cmdInit() int { - B2D.Init = true - _, err := driver.GetMachine(&B2D) + // TODO(@riobard) break up this command into multiple stages + m, err := vbx.GetMachine(B2D.VM) + if err == nil { + logf("Virtual machine %s already exists", B2D.VM) + return 1 + } + + if ping(fmt.Sprintf("localhost:%d", B2D.DockerPort)) { + logf("--dockerport=%d on localhost is occupied. Please choose another one.", B2D.DockerPort) + return 1 + } + + if ping(fmt.Sprintf("localhost:%d", B2D.SSHPort)) { + logf("--sshport=%d on localhost is occupied. Please choose another one.", B2D.SSHPort) + return 1 + } + + if _, err := os.Stat(B2D.ISO); err != nil { + if !os.IsNotExist(err) { + logf("Failed to open ISO image %q: %s", B2D.ISO, err) + return 1 + } + + if exitcode := cmdDownload(); exitcode != 0 { + return exitcode + } + } + if _, err := os.Stat(B2D.SSHKey); err != nil { + if !os.IsNotExist(err) { + logf("Something wrong with SSH Key file %q: %s", B2D.SSHKey, err) + return 1 + } + if err := cmdInteractive(B2D.SSHGen, "-t", "rsa", "-N", "", "-f", B2D.SSHKey); err != nil { + logf("Error generating new SSH Key into %s: %s", B2D.SSHKey, err) + return 1 + } + } + //TODO: print a ~/.ssh/config entry for our b2d connection that the user can c&p + + logf("Creating VM %s...", B2D.VM) + m, err = vbx.CreateMachine(B2D.VM, "") if err != nil { - logf("Failed to initialize machine %q: %s", B2D.VM, err) + logf("FIRST: Failed to create VM %q: %s", B2D.VM, err) + // double tap. VBox will sometimes (like on initial install, or reboot) + // fail to start the service the first time. + m, err = vbx.CreateMachine(B2D.VM, "") + if err != nil { + logf("Failed to create VM %q: %s", B2D.VM, err) + return 1 + } + } + + logf("Apply interim patch to VM %s (https://www.virtualbox.org/ticket/12748)", B2D.VM) + if err := vbx.SetExtra(B2D.VM, "VBoxInternal/CPUM/EnableHVP", "1"); err != nil { + logf("Failed to patch vm: %s", err) + return 1 + } + + m.OSType = "Linux26_64" + m.CPUs = uint(runtime.NumCPU()) + m.Memory = B2D.Memory + m.SerialFile = B2D.SerialFile + + m.Flag |= vbx.F_pae + m.Flag |= vbx.F_longmode // important: use x86-64 processor + m.Flag |= vbx.F_rtcuseutc + m.Flag |= vbx.F_acpi + m.Flag |= vbx.F_ioapic + m.Flag |= vbx.F_hpet + m.Flag |= vbx.F_hwvirtex + m.Flag |= vbx.F_vtxvpid + m.Flag |= vbx.F_largepages + m.Flag |= vbx.F_nestedpaging + + m.BootOrder = []string{"dvd"} + if err := m.Modify(); err != nil { + logf("Failed to modify VM %q: %s", B2D.VM, err) + return 1 + } + + logf("Setting NIC #1 to use NAT network...") + if err := m.SetNIC(1, vbx.NIC{Network: vbx.NICNetNAT, Hardware: vbx.VirtIO}); err != nil { + logf("Failed to add network interface to VM %q: %s", B2D.VM, err) + return 1 + } + + pfRules := map[string]vbx.PFRule{ + "ssh": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, + "docker": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: dockerPort}, + } + + for name, rule := range pfRules { + if err := m.AddNATPF(1, name, rule); err != nil { + logf("Failed to add port forwarding to VM %q: %s", B2D.VM, err) + return 1 + } + logf("Port forwarding [%s] %s", name, rule) + } + + hostIFName, err := getHostOnlyNetworkInterface() + if err != nil { + logf("Failed to create host-only network interface: %s", err) + return 1 + } + + logf("Setting NIC #2 to use host-only network %q...", hostIFName) + if err := m.SetNIC(2, vbx.NIC{Network: vbx.NICNetHostonly, Hardware: vbx.VirtIO, HostonlyAdapter: hostIFName}); err != nil { + logf("Failed to add network interface to VM %q: %s", B2D.VM, err) + return 1 + } + + logf("Setting VM storage...") + if err := m.AddStorageCtl("SATA", vbx.StorageController{SysBus: vbx.SysBusSATA, HostIOCache: true, Bootable: true}); err != nil { + logf("Failed to add storage controller to VM %q: %s", B2D.VM, err) + return 1 + } + + if err := m.AttachStorage("SATA", vbx.StorageMedium{Port: 0, Device: 0, DriveType: vbx.DriveDVD, Medium: B2D.ISO}); err != nil { + logf("Failed to attach ISO image %q: %s", B2D.ISO, err) return 1 } + + diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", B2D.VM)) + + if _, err := os.Stat(diskImg); err != nil { + if !os.IsNotExist(err) { + logf("Failed to open disk image %q: %s", diskImg, err) + return 1 + } + + if B2D.VMDK != "" { + logf("Using %v as base VMDK", B2D.VMDK) + if err := copyDiskImage(diskImg, B2D.VMDK); err != nil { + logf("Failed to copy disk image %v from %v: %s", diskImg, B2D.VMDK, err) + return 1 + } + } else { + magicString := "boot2docker, please format-me" + + buf := new(bytes.Buffer) + tw := tar.NewWriter(buf) + + // magicString first so the automount script knows to format the disk + file := &tar.Header{Name: magicString, Size: int64(len(magicString))} + if err := tw.WriteHeader(file); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + if _, err := tw.Write([]byte(magicString)); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + // .ssh/key.pub => authorized_keys + file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700} + if err := tw.WriteHeader(file); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + pubKey, err := ioutil.ReadFile(B2D.SSHKey + ".pub") + if err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644} + if err := tw.WriteHeader(file); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + if _, err := tw.Write([]byte(pubKey)); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644} + if err := tw.WriteHeader(file); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + if _, err := tw.Write([]byte(pubKey)); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + if err := tw.Close(); err != nil { + logf("Error making tarfile: %s", err) + return 1 + } + + if err := makeDiskImage(diskImg, B2D.DiskSize, buf.Bytes()); err != nil { + logf("Failed to create disk image %q: %s", diskImg, err) + return 1 + } + } + } + + if err := m.AttachStorage("SATA", vbx.StorageMedium{Port: 1, Device: 0, DriveType: vbx.DriveHDD, Medium: diskImg}); err != nil { + logf("Failed to attach disk image %q: %s", diskImg, err) + return 1 + } + + logf("Done. Type `%s up` to start the VM.", os.Args[0]) return 0 } // Bring up the VM from all possible states. func cmdUp() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -41,7 +238,7 @@ func cmdUp() int { logf("Failed to start machine %q: %s", B2D.VM, err) return 1 } - if m.GetState() != driver.Running { + if m.State != vbx.Running { logf("Failed to start machine %q (run again with -v for details)", B2D.VM) return 1 } @@ -49,11 +246,11 @@ func cmdUp() int { logf("Waiting for VM to be started...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket time.Sleep(600 * time.Millisecond) - natSSH := fmt.Sprintf("localhost:%d", m.GetSSHPort()) + natSSH := fmt.Sprintf("localhost:%d", m.SSHPort) IP := "" for i := 1; i < 30; i++ { if B2D.Serial && runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { + if IP = RequestIPFromSerialPort(m.SerialFile); IP != "" { break } } @@ -86,9 +283,9 @@ func cmdUp() int { logf("Please run `boot2docker -v up` to diagnose.") } else { // Check if $DOCKER_HOST ENV var is properly configured. - if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, driver.DockerPort) { + if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, dockerPort) { logf("To connect the Docker client to the Docker daemon, please set:") - logf(" export DOCKER_HOST=tcp://%s:%d", IP, driver.DockerPort) + logf(" export DOCKER_HOST=tcp://%s:%d", IP, dockerPort) } else { logf("Your DOCKER_HOST env variable is already set correctly.") } @@ -112,7 +309,7 @@ func cmdConfig() int { // Suspend and save the current state of VM on disk. func cmdSave() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -126,7 +323,7 @@ func cmdSave() int { // Gracefully stop the VM by sending ACPI shutdown signal. func cmdStop() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -141,7 +338,7 @@ func cmdStop() int { // Forcefully power off the VM (equivalent to unplug power). Might corrupt disk // image. func cmdPoweroff() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -169,7 +366,7 @@ func cmdUpgrade() int { // Gracefully stop and then start the VM. func cmdRestart() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -183,7 +380,7 @@ func cmdRestart() int { // Forcefully reset (equivalent to cold boot) the VM. Might corrupt disk image. func cmdReset() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -197,9 +394,9 @@ func cmdReset() int { // Delete the VM and associated disk image. func cmdDelete() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { - if err == driver.ErrMachineNotExist { + if err == vbx.ErrMachineNotExist { logf("Machine %q does not exist.", B2D.VM) return 0 } @@ -215,7 +412,7 @@ func cmdDelete() int { // Show detailed info of the VM. func cmdInfo() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -229,24 +426,24 @@ func cmdInfo() int { // Show the current state of the VM. func cmdStatus() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - fmt.Println(m.GetState()) + fmt.Println(m.State) return 0 } // Call the external SSH command to login into boot2docker VM. func cmdSSH() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - if m.GetState() != driver.Running { + if m.State != vbx.Running { logf("VM %q is not running.", B2D.VM) return 1 } @@ -263,7 +460,7 @@ func cmdSSH() int { "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." - "-p", fmt.Sprintf("%d", m.GetSSHPort()), + "-p", fmt.Sprintf("%d", m.SSHPort), "-i", B2D.SSHKey, "docker@localhost", }, os.Args[i:]...) @@ -276,13 +473,13 @@ func cmdSSH() int { } func cmdIP() int { - m, err := driver.GetMachine(&B2D) + m, err := vbx.GetMachine(B2D.VM) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - if m.GetState() != driver.Running { + if m.State != vbx.Running { logf("VM %q is not running.", B2D.VM) return 1 } @@ -291,7 +488,7 @@ func cmdIP() int { if B2D.Serial { for i := 1; i < 20; i++ { if runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { + if IP = RequestIPFromSerialPort(m.SerialFile); IP != "" { break } } @@ -312,13 +509,13 @@ func cmdIP() int { return 0 } -func RequestIPFromSSH(m driver.Machine) string { +func RequestIPFromSSH(m *vbx.Machine) string { // fall back to using the NAT port forwarded ssh out, err := cmd(B2D.SSH, "-v", // please leave in - this seems to improve the chance of success "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", - "-p", fmt.Sprintf("%d", m.GetSSHPort()), + "-p", fmt.Sprintf("%d", m.SSHPort), "-i", B2D.SSHKey, "docker@localhost", "ip addr show dev eth1", diff --git a/config.go b/config.go index 1208450..1578bb2 100644 --- a/config.go +++ b/config.go @@ -10,14 +10,50 @@ import ( "runtime" toml "github.com/BurntSushi/toml" - "github.com/boot2docker/boot2docker-cli/driver" + vbx "github.com/boot2docker/boot2docker-cli/virtualbox" flag "github.com/ogier/pflag" ) +// boot2docker config. +var B2D struct { + // NOTE: separate sections with blank lines so gofmt doesn't change + // indentation all the time. + + // Gereral flags. + Verbose bool + VBM string + + // basic config + SSH string // SSH client executable + SSHGen string // SSH keygen executable + SSHKey string // SSH key to send to the vm + VM string // virtual machine name + Dir string // boot2docker directory + ISO string // boot2docker ISO image path + VMDK string // base VMDK to use as persistent disk + DiskSize uint // VM disk image size (MB) + Memory uint // VM memory size (MB) + + // NAT network: port forwarding + SSHPort uint16 // host SSH port (forward to port 22 in VM) + DockerPort uint16 // host Docker port (forward to port 2375 in VM) + + // host-only network + HostIP net.IP + DHCPIP net.IP + NetMask net.IPMask + LowerIP net.IP + UpperIP net.IP + DHCPEnabled bool + + // Serial console pipe/socket + Serial bool + SerialFile string +} + var ( // Pattern to parse a key=value line in config profile. reFlagLine = regexp.MustCompile(`^\s*(\w+)\s*=\s*([^#;]+)`) - B2D = driver.MachineConfig{} ) func getCfgDir(name string) (string, error) { @@ -88,10 +124,8 @@ func config() (*flag.FlagSet, error) { } vbm = filepath.Join(p, "VBoxManage.exe") } - flags.BoolVarP(&B2D.Init, "init", "i", false, "auto initialize vm instance.") flags.StringVar(&B2D.VBM, "vbm", vbm, "path to VirtualBox management utility.") flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") - flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") flags.StringVar(&B2D.SSH, "ssh", "ssh", "path to SSH client utility.") flags.StringVar(&B2D.SSHGen, "ssh-keygen", "ssh-keygen", "path to ssh-keygen utility.") @@ -140,6 +174,9 @@ func config() (*flag.FlagSet, error) { return nil, err } + vbx.Verbose = B2D.Verbose + vbx.VBM = B2D.VBM + if B2D.SerialFile == "" { if runtime.GOOS == "windows" { //SerialFile ~~ filepath.Join(dir, B2D.vm+".sock") diff --git a/driver/config.go b/driver/config.go deleted file mode 100644 index 91a1884..0000000 --- a/driver/config.go +++ /dev/null @@ -1,39 +0,0 @@ -package driver - -import "net" - -// Machine config. -type MachineConfig struct { - // Gereral flags. - Init bool - Verbose bool - VBM string - Driver string - - // basic config - SSH string // SSH client executable - SSHGen string // SSH keygen executable - SSHKey string // SSH key to send to the vm - VM string // virtual machine name - Dir string // boot2docker directory - ISO string // boot2docker ISO image path - VMDK string // base VMDK to use as persistent disk - DiskSize uint // VM disk image size (MB) - Memory uint // VM memory size (MB) - - // NAT network: port forwarding - SSHPort uint16 // host SSH port (forward to port 22 in VM) - DockerPort uint16 // host Docker port (forward to port 2375 in VM) - - // host-only network - HostIP net.IP - DHCPIP net.IP - NetMask net.IPMask - LowerIP net.IP - UpperIP net.IP - DHCPEnabled bool - - // Serial console pipe/socket - Serial bool - SerialFile string -} diff --git a/driver/dhcp.go b/driver/dhcp.go deleted file mode 100644 index f6b6316..0000000 --- a/driver/dhcp.go +++ /dev/null @@ -1,12 +0,0 @@ -package driver - -import "net" - -// DHCP server info. -type DHCP struct { - NetworkName string - IPv4 net.IPNet - LowerIP net.IP - UpperIP net.IP - Enabled bool -} diff --git a/driver/driver.go b/driver/driver.go deleted file mode 100644 index db4f7aa..0000000 --- a/driver/driver.go +++ /dev/null @@ -1,76 +0,0 @@ -package driver - -import ( - "errors" - "fmt" -) - -type InitFunc func(i *MachineConfig) (Machine, error) - -type MachineState string - -const ( - // Known ports - SSHPort = 22 - DockerPort = 2375 - - // VM states - Poweroff = MachineState("poweroff") - Running = MachineState("running") - Paused = MachineState("paused") - Saved = MachineState("saved") - Aborted = MachineState("aborted") -) - -// Machine represents a virtual machine instance -type Machine interface { - Start() error - Save() error - Pause() error - Stop() error - Refresh() error - Poweroff() error - Restart() error - Reset() error - Delete() error - Modify() error - AddNATPF(n int, name string, rule PFRule) error - DelNATPF(n int, name string) error - SetNIC(n int, nic NIC) error - AddStorageCtl(name string, ctl StorageController) error - DelStorageCtl(name string) error - AttachStorage(ctlName string, medium StorageMedium) error - GetState() MachineState - GetSerialFile() string - GetDockerPort() uint - GetSSHPort() uint -} - -var ( - // All registred machines - machines map[string]InitFunc - - ErrNotSupported = errors.New("machine not supported") - ErrMachineNotExist = errors.New("machine not exist") - ErrPrerequisites = errors.New("prerequisites for machine not satisfied (hypervisor installed?)") -) - -func init() { - machines = make(map[string]InitFunc) -} - -func Register(driver string, initFunc InitFunc) error { - if _, exists := machines[driver]; exists { - return fmt.Errorf("Driver already registered %s", driver) - } - machines[driver] = initFunc - - return nil -} - -func GetMachine(mc *MachineConfig) (Machine, error) { - if initFunc, exists := machines[mc.Driver]; exists { - return initFunc(mc) - } - return nil, ErrNotSupported -} diff --git a/dummy/machine.go b/dummy/machine.go deleted file mode 100644 index 6d6a46a..0000000 --- a/dummy/machine.go +++ /dev/null @@ -1,157 +0,0 @@ -package dummy - -import ( - "fmt" - - "github.com/boot2docker/boot2docker-cli/driver" -) - -func init() { - driver.Register("dummy", InitFunc) -} - -// Initialize the Machine. -func InitFunc(i *driver.MachineConfig) (driver.Machine, error) { - fmt.Printf("Init dummy %s\n", i.VM) - return &Machine{Name: i.VM, State: driver.Poweroff}, nil -} - -// Machine information. -type Machine struct { - Name string - UUID string - State driver.MachineState - CPUs uint - Memory uint // main memory (in MB) - VRAM uint // video memory (in MB) - CfgFile string - BaseFolder string - OSType string - BootOrder []string // max 4 slots, each in {none|floppy|dvd|disk|net} - DockerPort uint - SSHPort uint - SerialFile string -} - -// Refresh reloads the machine information. -func (m *Machine) Refresh() error { - fmt.Printf("Refresh %s: %s\n", m.Name, m.State) - return nil -} - -// Start starts the machine. -func (m *Machine) Start() error { - m.State = driver.Running - fmt.Printf("Start %s: %s\n", m.Name, m.State) - return nil -} - -// Suspend suspends the machine and saves its state to disk. -func (m *Machine) Save() error { - m.State = driver.Saved - fmt.Printf("Save %s: %s\n", m.Name, m.State) - return nil -} - -// Pause pauses the execution of the machine. -func (m *Machine) Pause() error { - m.State = driver.Paused - fmt.Printf("Pause %s: %s\n", m.Name, m.State) - return nil -} - -// Stop gracefully stops the machine. -func (m *Machine) Stop() error { - m.State = driver.Poweroff - fmt.Printf("Stop %s: %s\n", m.Name, m.State) - return nil -} - -// Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. -func (m *Machine) Poweroff() error { - m.State = driver.Poweroff - fmt.Printf("Poweroff %s: %s\n", m.Name, m.State) - return nil -} - -// Restart gracefully restarts the machine. -func (m *Machine) Restart() error { - m.State = driver.Running - fmt.Printf("Restart %s: %s\n", m.Name, m.State) - return nil -} - -// Reset forcefully restarts the machine. State is lost and might corrupt the disk image. -func (m *Machine) Reset() error { - m.State = driver.Running - fmt.Printf("Reset %s: %s\n", m.Name, m.State) - return nil -} - -// Get current state -func (m *Machine) GetState() driver.MachineState { - return m.State -} - -// Get serial file -func (m *Machine) GetSerialFile() string { - return m.SerialFile -} - -// Get Docker port -func (m *Machine) GetDockerPort() uint { - return m.DockerPort -} - -// Get SSH port -func (m *Machine) GetSSHPort() uint { - return m.SSHPort -} - -// Delete deletes the machine and associated disk images. -func (m *Machine) Delete() error { - fmt.Printf("Delete %s: %s\n", m.Name, m.State) - return nil -} - -// Modify changes the settings of the machine. -func (m *Machine) Modify() error { - fmt.Printf("Modify %s: %s\n", m.Name, m.State) - return m.Refresh() -} - -// AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. -func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { - fmt.Println("Add NAT PF") - return nil -} - -// DelNATPF deletes the NAT port forwarding rule with the given name from the n-th NIC. -func (m *Machine) DelNATPF(n int, name string) error { - fmt.Println("Del NAT PF") - return nil -} - -// SetNIC set the n-th NIC. -func (m *Machine) SetNIC(n int, nic driver.NIC) error { - fmt.Println("Set NIC") - return nil -} - -// AddStorageCtl adds a storage controller with the given name. -func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { - fmt.Println("Add storage ctl") - return nil -} - -// DelStorageCtl deletes the storage controller with the given name. -func (m *Machine) DelStorageCtl(name string) error { - fmt.Println("Del storage ctl") - return nil -} - -// AttachStorage attaches a storage medium to the named storage controller. -func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { - fmt.Println("Attach storage") - return nil -} diff --git a/vbm.go b/vbm.go new file mode 100644 index 0000000..e1d9b72 --- /dev/null +++ b/vbm.go @@ -0,0 +1,107 @@ +package main + +import ( + "bytes" + "io" + "os" + "path/filepath" + + vbx "github.com/boot2docker/boot2docker-cli/virtualbox" +) + +// TODO: delete the hostonlyif and dhcpserver when we delete the vm! (need to +// reference count to make sure there are no other vms relying on them) + +// Get or create the hostonly network interface +func getHostOnlyNetworkInterface() (string, error) { + // Check if the interface/dhcp exists. + nets, err := vbx.HostonlyNets() + if err != nil { + return "", err + } + + dhcps, err := vbx.DHCPs() + if err != nil { + return "", err + } + + for _, n := range nets { + if dhcp, ok := dhcps[n.NetworkName]; ok { + if dhcp.IPv4.IP.Equal(B2D.DHCPIP) && + dhcp.IPv4.Mask.String() == B2D.NetMask.String() && + dhcp.LowerIP.Equal(B2D.LowerIP) && + dhcp.UpperIP.Equal(B2D.UpperIP) && + dhcp.Enabled == B2D.DHCPEnabled { + if B2D.Verbose { + logf("Reusing existing host-only network interface %q", n.Name) + } + return n.Name, nil + } + } + } + + // No existing host-only interface found. Create a new one. + if B2D.Verbose { + logf("Creating a new host-only network interface...") + } + hostonlyNet, err := vbx.CreateHostonlyNet() + if err != nil { + return "", err + } + hostonlyNet.IPv4.IP = B2D.HostIP + hostonlyNet.IPv4.Mask = B2D.NetMask + if err := hostonlyNet.Config(); err != nil { + return "", err + } + + // Create and add a DHCP server to the host-only network + dhcp := vbx.DHCP{} + dhcp.IPv4.IP = B2D.DHCPIP + dhcp.IPv4.Mask = B2D.NetMask + dhcp.LowerIP = B2D.LowerIP + dhcp.UpperIP = B2D.UpperIP + dhcp.Enabled = true + if err := vbx.AddHostonlyDHCP(hostonlyNet.Name, dhcp); err != nil { + return "", err + } + return hostonlyNet.Name, nil +} + +// Copy disk image from given source path to destination +func copyDiskImage(dst, src string) (err error) { + // Open source disk image + srcImg, err := os.Open(src) + if err != nil { + return err + } + closeSrcImg := func() { + if ee := srcImg.Close(); ee != nil { + err = ee + } + } + defer closeSrcImg() + dstImg, err := os.Create(dst) + if err != nil { + return err + } + closeDstImg := func() { + if ee := dstImg.Close(); ee != nil { + err = ee + } + } + defer closeDstImg() + _, err = io.Copy(dstImg, srcImg) + return err +} + +// Make a boot2docker VM disk image with the given size (in MB). +func makeDiskImage(dest string, size uint, initialBytes []byte) error { + // Create the dest dir. + if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { + return err + } + // Fill in the magic string so boot2docker VM will detect this and format + // the disk upon first boot. + raw := bytes.NewReader(initialBytes) + return vbx.MakeDiskImage(dest, size, raw) +} diff --git a/virtualbox/dhcp.go b/virtualbox/dhcp.go index d686e8e..d18d7a4 100644 --- a/virtualbox/dhcp.go +++ b/virtualbox/dhcp.go @@ -4,11 +4,18 @@ import ( "bufio" "net" "strings" - - "github.com/boot2docker/boot2docker-cli/driver" ) -func addDHCP(kind, name string, d driver.DHCP) error { +// DHCP server info. +type DHCP struct { + NetworkName string + IPv4 net.IPNet + LowerIP net.IP + UpperIP net.IP + Enabled bool +} + +func addDHCP(kind, name string, d DHCP) error { command := "modify" // On some platforms (OSX), creating a hostonlyinterface adds a default dhcpserver @@ -38,29 +45,29 @@ func addDHCP(kind, name string, d driver.DHCP) error { } // AddInternalDHCP adds a DHCP server to an internal network. -func AddInternalDHCP(netname string, d driver.DHCP) error { +func AddInternalDHCP(netname string, d DHCP) error { return addDHCP("--netname", netname, d) } // AddHostonlyDHCP adds a DHCP server to a host-only network. -func AddHostonlyDHCP(ifname string, d driver.DHCP) error { +func AddHostonlyDHCP(ifname string, d DHCP) error { return addDHCP("--netname", "HostInterfaceNetworking-"+ifname, d) } // DHCPs gets all DHCP server settings in a map keyed by DHCP.NetworkName. -func DHCPs() (map[string]*driver.DHCP, error) { +func DHCPs() (map[string]*DHCP, error) { out, err := vbmOut("list", "dhcpservers") if err != nil { return nil, err } s := bufio.NewScanner(strings.NewReader(out)) - m := map[string]*driver.DHCP{} - dhcp := &driver.DHCP{} + m := map[string]*DHCP{} + dhcp := &DHCP{} for s.Scan() { line := s.Text() if line == "" { m[dhcp.NetworkName] = dhcp - dhcp = &driver.DHCP{} + dhcp = &DHCP{} continue } res := reColonLine.FindStringSubmatch(line) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index cade564..70b1e86 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -1,20 +1,22 @@ package virtualbox import ( - "archive/tar" "bufio" - "bytes" "fmt" - "io/ioutil" - "net" - "os" "path/filepath" - "runtime" "strconv" "strings" "time" +) + +type MachineState string - "github.com/boot2docker/boot2docker-cli/driver" +const ( + Poweroff = MachineState("poweroff") + Running = MachineState("running") + Paused = MachineState("paused") + Saved = MachineState("saved") + Aborted = MachineState("aborted") ) type Flag int @@ -38,19 +40,6 @@ const ( F_accelerate3d ) -func init() { - driver.Register("virtualbox", InitFunc) -} - -// Initialize the Machine. -func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { - m, err := GetMachine(mc.VM) - if err != nil && mc.Init == true { - return CreateMachine(mc) - } - return m, err -} - // Convert bool to "on"/"off" func bool2string(b bool) string { if b { @@ -68,7 +57,7 @@ func (f Flag) Get(o Flag) string { type Machine struct { Name string UUID string - State driver.MachineState + State MachineState CPUs uint Memory uint // main memory (in MB) VRAM uint // video memory (in MB) @@ -99,13 +88,13 @@ func (m *Machine) Refresh() error { // Start starts the machine. func (m *Machine) Start() error { switch m.State { - case driver.Paused: + case Paused: return vbm("controlvm", m.Name, "resume") - case driver.Poweroff, driver.Saved, driver.Aborted: + case Poweroff, Saved, Aborted: return vbm("startvm", m.Name, "--type", "headless") } if err := m.Refresh(); err == nil { - if m.State != driver.Running { + if m.State != Running { return fmt.Errorf("Failed to start", m.Name) } } @@ -115,11 +104,11 @@ func (m *Machine) Start() error { // Suspend suspends the machine and saves its state to disk. func (m *Machine) Save() error { switch m.State { - case driver.Paused: + case Paused: if err := m.Start(); err != nil { return err } - case driver.Poweroff, driver.Aborted, driver.Saved: + case Poweroff, Aborted, Saved: return nil } return vbm("controlvm", m.Name, "savestate") @@ -128,7 +117,7 @@ func (m *Machine) Save() error { // Pause pauses the execution of the machine. func (m *Machine) Pause() error { switch m.State { - case driver.Paused, driver.Poweroff, driver.Aborted, driver.Saved: + case Paused, Poweroff, Aborted, Saved: return nil } return vbm("controlvm", m.Name, "pause") @@ -137,15 +126,15 @@ func (m *Machine) Pause() error { // Stop gracefully stops the machine. func (m *Machine) Stop() error { switch m.State { - case driver.Poweroff, driver.Aborted, driver.Saved: + case Poweroff, Aborted, Saved: return nil - case driver.Paused: + case Paused: if err := m.Start(); err != nil { return err } } - for m.State != driver.Poweroff { // busy wait until the machine is stopped + for m.State != Poweroff { // busy wait until the machine is stopped if err := vbm("controlvm", m.Name, "acpipowerbutton"); err != nil { return err } @@ -160,7 +149,7 @@ func (m *Machine) Stop() error { // Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. func (m *Machine) Poweroff() error { switch m.State { - case driver.Poweroff, driver.Aborted, driver.Saved: + case Poweroff, Aborted, Saved: return nil } return vbm("controlvm", m.Name, "poweroff") @@ -169,7 +158,7 @@ func (m *Machine) Poweroff() error { // Restart gracefully restarts the machine. func (m *Machine) Restart() error { switch m.State { - case driver.Paused, driver.Saved: + case Paused, Saved: if err := m.Start(); err != nil { return err } @@ -183,7 +172,7 @@ func (m *Machine) Restart() error { // Reset forcefully restarts the machine. State is lost and might corrupt the disk image. func (m *Machine) Reset() error { switch m.State { - case driver.Paused, driver.Saved: + case Paused, Saved: if err := m.Start(); err != nil { return err } @@ -199,26 +188,6 @@ func (m *Machine) Delete() error { return vbm("unregistervm", m.Name, "--delete") } -// Get current state -func (m *Machine) GetState() driver.MachineState { - return m.State -} - -// Get serial file -func (m *Machine) GetSerialFile() string { - return m.SerialFile -} - -// Get Docker port -func (m *Machine) GetDockerPort() uint { - return m.DockerPort -} - -// Get SSH port -func (m *Machine) GetSSHPort() uint { - return m.SSHPort -} - // GetMachine finds a machine by its name or UUID. func GetMachine(id string) (*Machine, error) { stdout, stderr, err := vbmOutErr("showvminfo", id, "--machinereadable") @@ -250,7 +219,7 @@ func GetMachine(id string) (*Machine, error) { case "UUID": m.UUID = val case "VMState": - m.State = driver.MachineState(val) + m.State = MachineState(val) case "memory": n, err := strconv.ParseUint(val, 10, 32) if err != nil { @@ -325,8 +294,8 @@ func ListMachines() ([]string, error) { } // CreateMachine creates a new machine. If basefolder is empty, use default. -func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { - if mc.VM == "" { +func CreateMachine(name, basefolder string) (*Machine, error) { + if name == "" { return nil, fmt.Errorf("machine name is empty") } @@ -336,140 +305,25 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { return nil, err } for _, m := range machineNames { - if m == mc.VM { + if m == name { return nil, ErrMachineExist } } // Create and register the machine. - args := []string{"createvm", "--name", mc.VM, "--register"} + args := []string{"createvm", "--name", name, "--register"} + if basefolder != "" { + args = append(args, "--basefolder", basefolder) + } if err := vbm(args...); err != nil { return nil, err } - m, err := GetMachine(mc.VM) + m, err := GetMachine(name) if err != nil { return nil, err } - // Configure VM for Boot2docker - SetExtra(mc.VM, "VBoxInternal/CPUM/EnableHVP", "1") - m.OSType = "Linux26_64" - m.CPUs = uint(runtime.NumCPU()) - m.Memory = mc.Memory - m.SerialFile = mc.SerialFile - - m.Flag |= F_pae - m.Flag |= F_longmode // important: use x86-64 processor - m.Flag |= F_rtcuseutc - m.Flag |= F_acpi - m.Flag |= F_ioapic - m.Flag |= F_hpet - m.Flag |= F_hwvirtex - m.Flag |= F_vtxvpid - m.Flag |= F_largepages - m.Flag |= F_nestedpaging - - // Set VM boot order - m.BootOrder = []string{"dvd"} - if err := m.Modify(); err != nil { - return m, err - } - - // Set NIC #1 to use NAT - m.SetNIC(1, driver.NIC{Network: driver.NICNetNAT, Hardware: driver.VirtIO}) - pfRules := map[string]driver.PFRule{ - "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: driver.SSHPort}, - "docker": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: driver.DockerPort}, - } - - for name, rule := range pfRules { - if err := m.AddNATPF(1, name, rule); err != nil { - return m, err - } - } - - hostIFName, err := getHostOnlyNetworkInterface(mc) - if err != nil { - return m, err - } - - // Set NIC #2 to use host-only - if err := m.SetNIC(2, driver.NIC{Network: driver.NICNetHostonly, Hardware: driver.VirtIO, HostonlyAdapter: hostIFName}); err != nil { - return m, err - } - - // Set VM storage - if err := m.AddStorageCtl("SATA", driver.StorageController{SysBus: driver.SysBusSATA, HostIOCache: true, Bootable: true}); err != nil { - return m, err - } - - // Attach ISO image - if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 0, Device: 0, DriveType: driver.DriveDVD, Medium: mc.ISO}); err != nil { - return m, err - } - - diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", mc.VM)) - if _, err := os.Stat(diskImg); err != nil { - if !os.IsNotExist(err) { - return m, err - } - - if mc.VMDK != "" { - if err := copyDiskImage(diskImg, mc.VMDK); err != nil { - return m, err - } - } else { - magicString := "boot2docker, please format-me" - - buf := new(bytes.Buffer) - tw := tar.NewWriter(buf) - - // magicString first so the automount script knows to format the disk - file := &tar.Header{Name: magicString, Size: int64(len(magicString))} - if err := tw.WriteHeader(file); err != nil { - return m, err - } - if _, err := tw.Write([]byte(magicString)); err != nil { - return m, err - } - // .ssh/key.pub => authorized_keys - file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700} - if err := tw.WriteHeader(file); err != nil { - return m, err - } - pubKey, err := ioutil.ReadFile(mc.SSHKey + ".pub") - if err != nil { - return m, err - } - file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644} - if err := tw.WriteHeader(file); err != nil { - return m, err - } - if _, err := tw.Write([]byte(pubKey)); err != nil { - return m, err - } - file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644} - if err := tw.WriteHeader(file); err != nil { - return m, err - } - if _, err := tw.Write([]byte(pubKey)); err != nil { - return m, err - } - if err := tw.Close(); err != nil { - return m, err - } - - if err := makeDiskImage(diskImg, mc.DiskSize, buf.Bytes()); err != nil { - return m, err - } - } - } - - if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 1, Device: 0, DriveType: driver.DriveHDD, Medium: diskImg}); err != nil { - return m, err - } - return m, nil } @@ -525,7 +379,7 @@ func (m *Machine) Modify() error { } // AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. -func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { +func (m *Machine) AddNATPF(n int, name string, rule PFRule) error { return vbm("controlvm", m.Name, fmt.Sprintf("natpf%d", n), fmt.Sprintf("%s,%s", name, rule.Format())) } @@ -536,7 +390,7 @@ func (m *Machine) DelNATPF(n int, name string) error { } // SetNIC set the n-th NIC. -func (m *Machine) SetNIC(n int, nic driver.NIC) error { +func (m *Machine) SetNIC(n int, nic NIC) error { args := []string{"modifyvm", m.Name, fmt.Sprintf("--nic%d", n), string(nic.Network), fmt.Sprintf("--nictype%d", n), string(nic.Hardware), @@ -550,7 +404,7 @@ func (m *Machine) SetNIC(n int, nic driver.NIC) error { } // AddStorageCtl adds a storage controller with the given name. -func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { +func (m *Machine) AddStorageCtl(name string, ctl StorageController) error { args := []string{"storagectl", m.Name, "--name", name} if ctl.SysBus != "" { args = append(args, "--add", string(ctl.SysBus)) @@ -572,7 +426,7 @@ func (m *Machine) DelStorageCtl(name string) error { } // AttachStorage attaches a storage medium to the named storage controller. -func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { +func (m *Machine) AttachStorage(ctlName string, medium StorageMedium) error { return vbm("storageattach", m.Name, "--storagectl", ctlName, "--port", fmt.Sprintf("%d", medium.Port), "--device", fmt.Sprintf("%d", medium.Device), diff --git a/driver/nic.go b/virtualbox/nic.go similarity index 97% rename from driver/nic.go rename to virtualbox/nic.go index d6c7364..0569be5 100644 --- a/driver/nic.go +++ b/virtualbox/nic.go @@ -1,4 +1,4 @@ -package driver +package virtualbox // NIC represents a virtualized network interface card. type NIC struct { diff --git a/driver/pfrule.go b/virtualbox/pfrule.go similarity index 98% rename from driver/pfrule.go rename to virtualbox/pfrule.go index 18b8160..89b9de7 100644 --- a/driver/pfrule.go +++ b/virtualbox/pfrule.go @@ -1,4 +1,4 @@ -package driver +package virtualbox import ( "fmt" diff --git a/driver/storage.go b/virtualbox/storage.go similarity index 98% rename from driver/storage.go rename to virtualbox/storage.go index a229daf..ae129f4 100644 --- a/driver/storage.go +++ b/virtualbox/storage.go @@ -1,4 +1,4 @@ -package driver +package virtualbox // StorageController represents a virtualized storage controller. type StorageController struct { diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index e2d34df..dd0df6f 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -3,7 +3,6 @@ package virtualbox import ( "bytes" "errors" - "io" "log" "os" "os/exec" @@ -11,8 +10,6 @@ import ( "regexp" "runtime" "strings" - - "github.com/boot2docker/boot2docker-cli/driver" ) var ( @@ -89,89 +86,3 @@ func vbmOutErr(args ...string) (string, string, error) { } return stdout.String(), stderr.String(), err } - -// Get or create the hostonly network interface -func getHostOnlyNetworkInterface(mc *driver.MachineConfig) (string, error) { - // Check if the interface/dhcp exists. - nets, err := HostonlyNets() - if err != nil { - return "", err - } - - dhcps, err := DHCPs() - if err != nil { - return "", err - } - - for _, n := range nets { - if dhcp, ok := dhcps[n.NetworkName]; ok { - if dhcp.IPv4.IP.Equal(mc.DHCPIP) && - dhcp.IPv4.Mask.String() == mc.NetMask.String() && - dhcp.LowerIP.Equal(mc.LowerIP) && - dhcp.UpperIP.Equal(mc.UpperIP) && - dhcp.Enabled == mc.DHCPEnabled { - return n.Name, nil - } - } - } - - // No existing host-only interface found. Create a new one. - hostonlyNet, err := CreateHostonlyNet() - if err != nil { - return "", err - } - hostonlyNet.IPv4.IP = mc.HostIP - hostonlyNet.IPv4.Mask = mc.NetMask - if err := hostonlyNet.Config(); err != nil { - return "", err - } - - // Create and add a DHCP server to the host-only network - dhcp := driver.DHCP{} - dhcp.IPv4.IP = mc.DHCPIP - dhcp.IPv4.Mask = mc.NetMask - dhcp.LowerIP = mc.LowerIP - dhcp.UpperIP = mc.UpperIP - dhcp.Enabled = true - if err := AddHostonlyDHCP(hostonlyNet.Name, dhcp); err != nil { - return "", err - } - return hostonlyNet.Name, nil -} - -// Copy disk image from given source path to destination -func copyDiskImage(dst, src string) (err error) { - // Open source disk image - srcImg, err := os.Open(src) - if err != nil { - return err - } - defer func() { - if ee := srcImg.Close(); ee != nil { - err = ee - } - }() - dstImg, err := os.Create(dst) - if err != nil { - return err - } - defer func() { - if ee := dstImg.Close(); ee != nil { - err = ee - } - }() - _, err = io.Copy(dstImg, srcImg) - return err -} - -// Make a boot2docker VM disk image with the given size (in MB). -func makeDiskImage(dest string, size uint, initialBytes []byte) error { - // Create the dest dir. - if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { - return err - } - // Fill in the magic string so boot2docker VM will detect this and format - // the disk upon first boot. - raw := bytes.NewReader(initialBytes) - return MakeDiskImage(dest, size, raw) -} From 426c4aab14ee6fe551b71cd47c77308d9a1ada65 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 24 Jul 2014 16:01:20 +1000 Subject: [PATCH 035/167] Sorry, windows won't let you move that file aside while vbox is using it --- cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index 72ab184..f927581 100644 --- a/cmds.go +++ b/cmds.go @@ -354,7 +354,7 @@ func cmdPoweroff() int { func cmdUpgrade() int { m, err := vbx.GetMachine(B2D.VM) if err == nil && m.State == vbx.Running { - if cmdDownload() == 0 && cmdStop() == 0 { + if cmdStop() == 0 && cmdDownload() == 0 { return cmdUp() } else { return 0 From 2e6eba565036041335b7ea9f42c07b3f0e119883 Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Mon, 28 Jul 2014 16:29:50 -0700 Subject: [PATCH 036/167] Add copyright holder to license Signed-off-by: Ben Firshman --- LICENSE | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/LICENSE b/LICENSE index e06d208..2744858 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,5 @@ -Apache License + + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -175,18 +176,7 @@ Apache License END OF TERMS AND CONDITIONS - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2014 Docker, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -199,4 +189,3 @@ Apache License WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - From f8a9d86ef8732e57daeebba91633fd84abe655ac Mon Sep 17 00:00:00 2001 From: Michael Hobbs Date: Wed, 30 Jul 2014 15:44:28 -0700 Subject: [PATCH 037/167] closes #204. tested locally --- cmds.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmds.go b/cmds.go index f927581..e6bce3c 100644 --- a/cmds.go +++ b/cmds.go @@ -457,6 +457,7 @@ func cmdSSH() int { } sshArgs := append([]string{ + "-o", "IdentitiesOnly=yes", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." @@ -513,6 +514,7 @@ func RequestIPFromSSH(m *vbx.Machine) string { // fall back to using the NAT port forwarded ssh out, err := cmd(B2D.SSH, "-v", // please leave in - this seems to improve the chance of success + "-o", "IdentitiesOnly=yes", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-p", fmt.Sprintf("%d", m.SSHPort), From 9935fda0d9ad944f8f5cabba23c21655a65cd298 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Tue, 8 Jul 2014 12:42:18 -0700 Subject: [PATCH 038/167] Create driver model and refactor virtualbox dependencies into driver Conflicts: config.go --- cmds.go | 265 ++++-------------------------- config.go | 47 +----- driver/config.go | 39 +++++ driver/dhcp.go | 12 ++ driver/driver.go | 76 +++++++++ {virtualbox => driver}/nic.go | 2 +- {virtualbox => driver}/pfrule.go | 2 +- {virtualbox => driver}/storage.go | 2 +- dummy/machine.go | 157 ++++++++++++++++++ vbm.go | 107 ------------ virtualbox/dhcp.go | 25 +-- virtualbox/machine.go | 218 ++++++++++++++++++++---- virtualbox/vbm.go | 89 ++++++++++ 13 files changed, 604 insertions(+), 437 deletions(-) create mode 100644 driver/config.go create mode 100644 driver/dhcp.go create mode 100644 driver/driver.go rename {virtualbox => driver}/nic.go (97%) rename {virtualbox => driver}/pfrule.go (98%) rename {virtualbox => driver}/storage.go (98%) create mode 100644 dummy/machine.go delete mode 100644 vbm.go diff --git a/cmds.go b/cmds.go index 51d63ce..35fc9aa 100644 --- a/cmds.go +++ b/cmds.go @@ -1,236 +1,33 @@ package main import ( - "archive/tar" - "bytes" "encoding/json" "fmt" - "io/ioutil" - "net" "os" - "path/filepath" "runtime" "strings" "time" - vbx "github.com/boot2docker/boot2docker-cli/virtualbox" -) + _ "github.com/boot2docker/boot2docker-cli/dummy" + _ "github.com/boot2docker/boot2docker-cli/virtualbox" -const dockerPort = 2375 + "github.com/boot2docker/boot2docker-cli/driver" +) // Initialize the boot2docker VM from scratch. func cmdInit() int { - // TODO(@riobard) break up this command into multiple stages - m, err := vbx.GetMachine(B2D.VM) - if err == nil { - logf("Virtual machine %s already exists", B2D.VM) - return 1 - } - - if B2D.DockerPort > 0 { - // Reference Issue boot2docker-cli issue #150, docker issues #6247, #6271, #6327 - logf("warning: VirtualBox (4.3.x) NAT port forwarding is currently unreliable. Prefer to use the host only interface if possible.") - if ping(fmt.Sprintf("localhost:%d", B2D.DockerPort)) { - logf("--dockerport=%d on localhost is occupied. Please choose another one.", B2D.DockerPort) - return 1 - } - } - - if ping(fmt.Sprintf("localhost:%d", B2D.SSHPort)) { - logf("--sshport=%d on localhost is occupied. Please choose another one.", B2D.SSHPort) - return 1 - } - - if _, err := os.Stat(B2D.ISO); err != nil { - if !os.IsNotExist(err) { - logf("Failed to open ISO image %q: %s", B2D.ISO, err) - return 1 - } - - if exitcode := cmdDownload(); exitcode != 0 { - return exitcode - } - } - if _, err := os.Stat(B2D.SSHKey); err != nil { - if !os.IsNotExist(err) { - logf("Something wrong with SSH Key file %q: %s", B2D.SSHKey, err) - return 1 - } - if err := cmdInteractive(B2D.SSHGen, "-t", "rsa", "-N", "", "-f", B2D.SSHKey); err != nil { - logf("Error generating new SSH Key into %s: %s", B2D.SSHKey, err) - return 1 - } - } - //TODO: print a ~/.ssh/config entry for our b2d connection that the user can c&p - - logf("Creating VM %s...", B2D.VM) - m, err = vbx.CreateMachine(B2D.VM, "") - if err != nil { - logf("FIRST: Failed to create VM %q: %s", B2D.VM, err) - // double tap. VBox will sometimes (like on initial install, or reboot) - // fail to start the service the first time. - m, err = vbx.CreateMachine(B2D.VM, "") - if err != nil { - logf("Failed to create VM %q: %s", B2D.VM, err) - return 1 - } - } - - logf("Apply interim patch to VM %s (https://www.virtualbox.org/ticket/12748)", B2D.VM) - if err := vbx.SetExtra(B2D.VM, "VBoxInternal/CPUM/EnableHVP", "1"); err != nil { - logf("Failed to patch vm: %s", err) - return 1 - } - - m.OSType = "Linux26_64" - m.CPUs = uint(runtime.NumCPU()) - m.Memory = B2D.Memory - m.SerialFile = B2D.SerialFile - - m.Flag |= vbx.F_pae - m.Flag |= vbx.F_longmode // important: use x86-64 processor - m.Flag |= vbx.F_rtcuseutc - m.Flag |= vbx.F_acpi - m.Flag |= vbx.F_ioapic - m.Flag |= vbx.F_hpet - m.Flag |= vbx.F_hwvirtex - m.Flag |= vbx.F_vtxvpid - m.Flag |= vbx.F_largepages - m.Flag |= vbx.F_nestedpaging - - m.BootOrder = []string{"dvd"} - if err := m.Modify(); err != nil { - logf("Failed to modify VM %q: %s", B2D.VM, err) - return 1 - } - - logf("Setting NIC #1 to use NAT network...") - if err := m.SetNIC(1, vbx.NIC{Network: vbx.NICNetNAT, Hardware: vbx.VirtIO}); err != nil { - logf("Failed to add network interface to VM %q: %s", B2D.VM, err) - return 1 - } - - pfRules := map[string]vbx.PFRule{ - "ssh": {Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.SSHPort, GuestPort: 22}, - } - if B2D.DockerPort > 0 { - pfRules["docker"] = vbx.PFRule{Proto: vbx.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: B2D.DockerPort, GuestPort: dockerPort} - } - - for name, rule := range pfRules { - if err := m.AddNATPF(1, name, rule); err != nil { - logf("Failed to add port forwarding to VM %q: %s", B2D.VM, err) - return 1 - } - logf("Port forwarding [%s] %s", name, rule) - } - - hostIFName, err := getHostOnlyNetworkInterface() + B2D.Init = true + _, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to create host-only network interface: %s", err) - return 1 - } - - logf("Setting NIC #2 to use host-only network %q...", hostIFName) - if err := m.SetNIC(2, vbx.NIC{Network: vbx.NICNetHostonly, Hardware: vbx.VirtIO, HostonlyAdapter: hostIFName}); err != nil { - logf("Failed to add network interface to VM %q: %s", B2D.VM, err) + logf("Failed to initialize machine %q: %s", B2D.VM, err) return 1 } - - logf("Setting VM storage...") - if err := m.AddStorageCtl("SATA", vbx.StorageController{SysBus: vbx.SysBusSATA, HostIOCache: true, Bootable: true}); err != nil { - logf("Failed to add storage controller to VM %q: %s", B2D.VM, err) - return 1 - } - - if err := m.AttachStorage("SATA", vbx.StorageMedium{Port: 0, Device: 0, DriveType: vbx.DriveDVD, Medium: B2D.ISO}); err != nil { - logf("Failed to attach ISO image %q: %s", B2D.ISO, err) - return 1 - } - - diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", B2D.VM)) - - if _, err := os.Stat(diskImg); err != nil { - if !os.IsNotExist(err) { - logf("Failed to open disk image %q: %s", diskImg, err) - return 1 - } - - if B2D.VMDK != "" { - logf("Using %v as base VMDK", B2D.VMDK) - if err := copyDiskImage(diskImg, B2D.VMDK); err != nil { - logf("Failed to copy disk image %v from %v: %s", diskImg, B2D.VMDK, err) - return 1 - } - } else { - magicString := "boot2docker, please format-me" - - buf := new(bytes.Buffer) - tw := tar.NewWriter(buf) - - // magicString first so the automount script knows to format the disk - file := &tar.Header{Name: magicString, Size: int64(len(magicString))} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if _, err := tw.Write([]byte(magicString)); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - // .ssh/key.pub => authorized_keys - file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - pubKey, err := ioutil.ReadFile(B2D.SSHKey + ".pub") - if err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if _, err := tw.Write([]byte(pubKey)); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644} - if err := tw.WriteHeader(file); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if _, err := tw.Write([]byte(pubKey)); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - if err := tw.Close(); err != nil { - logf("Error making tarfile: %s", err) - return 1 - } - - if err := makeDiskImage(diskImg, B2D.DiskSize, buf.Bytes()); err != nil { - logf("Failed to create disk image %q: %s", diskImg, err) - return 1 - } - } - } - - if err := m.AttachStorage("SATA", vbx.StorageMedium{Port: 1, Device: 0, DriveType: vbx.DriveHDD, Medium: diskImg}); err != nil { - logf("Failed to attach disk image %q: %s", diskImg, err) - return 1 - } - - logf("Done. Type `%s up` to start the VM.", os.Args[0]) return 0 } // Bring up the VM from all possible states. func cmdUp() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -244,7 +41,7 @@ func cmdUp() int { logf("Failed to start machine %q: %s", B2D.VM, err) return 1 } - if m.State != vbx.Running { + if m.GetState() != driver.Running { logf("Failed to start machine %q (run again with -v for details)", B2D.VM) return 1 } @@ -252,11 +49,11 @@ func cmdUp() int { logf("Waiting for VM to be started...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket time.Sleep(600 * time.Millisecond) - natSSH := fmt.Sprintf("localhost:%d", m.SSHPort) + natSSH := fmt.Sprintf("localhost:%d", m.GetSSHPort()) IP := "" for i := 1; i < 30; i++ { if B2D.Serial && runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.SerialFile); IP != "" { + if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { break } } @@ -289,9 +86,9 @@ func cmdUp() int { logf("Please run `boot2docker -v up` to diagnose.") } else { // Check if $DOCKER_HOST ENV var is properly configured. - if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, dockerPort) { + if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, driver.DockerPort) { logf("To connect the Docker client to the Docker daemon, please set:") - logf(" export DOCKER_HOST=tcp://%s:%d", IP, dockerPort) + logf(" export DOCKER_HOST=tcp://%s:%d", IP, driver.DockerPort) } else { logf("Your DOCKER_HOST env variable is already set correctly.") } @@ -315,7 +112,7 @@ func cmdConfig() int { // Suspend and save the current state of VM on disk. func cmdSave() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -329,7 +126,7 @@ func cmdSave() int { // Gracefully stop the VM by sending ACPI shutdown signal. func cmdStop() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -344,7 +141,7 @@ func cmdStop() int { // Forcefully power off the VM (equivalent to unplug power). Might corrupt disk // image. func cmdPoweroff() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -372,7 +169,7 @@ func cmdUpgrade() int { // Gracefully stop and then start the VM. func cmdRestart() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -386,7 +183,7 @@ func cmdRestart() int { // Forcefully reset (equivalent to cold boot) the VM. Might corrupt disk image. func cmdReset() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -400,9 +197,9 @@ func cmdReset() int { // Delete the VM and associated disk image. func cmdDelete() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { - if err == vbx.ErrMachineNotExist { + if err == driver.ErrMachineNotExist { logf("Machine %q does not exist.", B2D.VM) return 0 } @@ -418,7 +215,7 @@ func cmdDelete() int { // Show detailed info of the VM. func cmdInfo() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 @@ -432,24 +229,24 @@ func cmdInfo() int { // Show the current state of the VM. func cmdStatus() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - fmt.Println(m.State) + fmt.Println(m.GetState()) return 0 } // Call the external SSH command to login into boot2docker VM. func cmdSSH() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - if m.State != vbx.Running { + if m.GetState() != driver.Running { logf("VM %q is not running.", B2D.VM) return 1 } @@ -467,7 +264,7 @@ func cmdSSH() int { "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." - "-p", fmt.Sprintf("%d", m.SSHPort), + "-p", fmt.Sprintf("%d", m.GetSSHPort()), "-i", B2D.SSHKey, "docker@localhost", }, os.Args[i:]...) @@ -480,13 +277,13 @@ func cmdSSH() int { } func cmdIP() int { - m, err := vbx.GetMachine(B2D.VM) + m, err := driver.GetMachine(&B2D) if err != nil { logf("Failed to get machine %q: %s", B2D.VM, err) return 2 } - if m.State != vbx.Running { + if m.GetState() != driver.Running { logf("VM %q is not running.", B2D.VM) return 1 } @@ -495,7 +292,7 @@ func cmdIP() int { if B2D.Serial { for i := 1; i < 20; i++ { if runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.SerialFile); IP != "" { + if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { break } } @@ -516,14 +313,14 @@ func cmdIP() int { return 0 } -func RequestIPFromSSH(m *vbx.Machine) string { +func RequestIPFromSSH(m driver.Machine) string { // fall back to using the NAT port forwarded ssh out, err := cmd(B2D.SSH, "-v", // please leave in - this seems to improve the chance of success "-o", "IdentitiesOnly=yes", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", - "-p", fmt.Sprintf("%d", m.SSHPort), + "-p", fmt.Sprintf("%d", m.GetSSHPort()), "-i", B2D.SSHKey, "docker@localhost", "ip addr show dev eth1", diff --git a/config.go b/config.go index dee0434..eea9c8b 100644 --- a/config.go +++ b/config.go @@ -10,50 +10,14 @@ import ( "runtime" toml "github.com/BurntSushi/toml" - vbx "github.com/boot2docker/boot2docker-cli/virtualbox" + "github.com/boot2docker/boot2docker-cli/driver" flag "github.com/ogier/pflag" ) -// boot2docker config. -var B2D struct { - // NOTE: separate sections with blank lines so gofmt doesn't change - // indentation all the time. - - // Gereral flags. - Verbose bool - VBM string - - // basic config - SSH string // SSH client executable - SSHGen string // SSH keygen executable - SSHKey string // SSH key to send to the vm - VM string // virtual machine name - Dir string // boot2docker directory - ISO string // boot2docker ISO image path - VMDK string // base VMDK to use as persistent disk - DiskSize uint // VM disk image size (MB) - Memory uint // VM memory size (MB) - - // NAT network: port forwarding - SSHPort uint16 // host SSH port (forward to port 22 in VM) - DockerPort uint16 // host Docker port (forward to port 2375 in VM) - - // host-only network - HostIP net.IP - DHCPIP net.IP - NetMask net.IPMask - LowerIP net.IP - UpperIP net.IP - DHCPEnabled bool - - // Serial console pipe/socket - Serial bool - SerialFile string -} - var ( // Pattern to parse a key=value line in config profile. reFlagLine = regexp.MustCompile(`^\s*(\w+)\s*=\s*([^#;]+)`) + B2D = driver.MachineConfig{} ) func getCfgDir(name string) (string, error) { @@ -124,8 +88,10 @@ func config() (*flag.FlagSet, error) { } vbm = filepath.Join(p, "VBoxManage.exe") } + flags.BoolVarP(&B2D.Init, "init", "i", false, "auto initialize vm instance.") flags.StringVar(&B2D.VBM, "vbm", vbm, "path to VirtualBox management utility.") flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") + flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") flags.StringVar(&B2D.SSH, "ssh", "ssh", "path to SSH client utility.") flags.StringVar(&B2D.SSHGen, "ssh-keygen", "ssh-keygen", "path to ssh-keygen utility.") @@ -174,9 +140,6 @@ func config() (*flag.FlagSet, error) { return nil, err } - vbx.Verbose = B2D.Verbose - vbx.VBM = B2D.VBM - if B2D.SerialFile == "" { if runtime.GOOS == "windows" { //SerialFile ~~ filepath.Join(dir, B2D.vm+".sock") @@ -190,7 +153,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|upgrade|version} []\n", os.Args[0]) + errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) } func usageLong(flags *flag.FlagSet) { diff --git a/driver/config.go b/driver/config.go new file mode 100644 index 0000000..91a1884 --- /dev/null +++ b/driver/config.go @@ -0,0 +1,39 @@ +package driver + +import "net" + +// Machine config. +type MachineConfig struct { + // Gereral flags. + Init bool + Verbose bool + VBM string + Driver string + + // basic config + SSH string // SSH client executable + SSHGen string // SSH keygen executable + SSHKey string // SSH key to send to the vm + VM string // virtual machine name + Dir string // boot2docker directory + ISO string // boot2docker ISO image path + VMDK string // base VMDK to use as persistent disk + DiskSize uint // VM disk image size (MB) + Memory uint // VM memory size (MB) + + // NAT network: port forwarding + SSHPort uint16 // host SSH port (forward to port 22 in VM) + DockerPort uint16 // host Docker port (forward to port 2375 in VM) + + // host-only network + HostIP net.IP + DHCPIP net.IP + NetMask net.IPMask + LowerIP net.IP + UpperIP net.IP + DHCPEnabled bool + + // Serial console pipe/socket + Serial bool + SerialFile string +} diff --git a/driver/dhcp.go b/driver/dhcp.go new file mode 100644 index 0000000..f6b6316 --- /dev/null +++ b/driver/dhcp.go @@ -0,0 +1,12 @@ +package driver + +import "net" + +// DHCP server info. +type DHCP struct { + NetworkName string + IPv4 net.IPNet + LowerIP net.IP + UpperIP net.IP + Enabled bool +} diff --git a/driver/driver.go b/driver/driver.go new file mode 100644 index 0000000..db4f7aa --- /dev/null +++ b/driver/driver.go @@ -0,0 +1,76 @@ +package driver + +import ( + "errors" + "fmt" +) + +type InitFunc func(i *MachineConfig) (Machine, error) + +type MachineState string + +const ( + // Known ports + SSHPort = 22 + DockerPort = 2375 + + // VM states + Poweroff = MachineState("poweroff") + Running = MachineState("running") + Paused = MachineState("paused") + Saved = MachineState("saved") + Aborted = MachineState("aborted") +) + +// Machine represents a virtual machine instance +type Machine interface { + Start() error + Save() error + Pause() error + Stop() error + Refresh() error + Poweroff() error + Restart() error + Reset() error + Delete() error + Modify() error + AddNATPF(n int, name string, rule PFRule) error + DelNATPF(n int, name string) error + SetNIC(n int, nic NIC) error + AddStorageCtl(name string, ctl StorageController) error + DelStorageCtl(name string) error + AttachStorage(ctlName string, medium StorageMedium) error + GetState() MachineState + GetSerialFile() string + GetDockerPort() uint + GetSSHPort() uint +} + +var ( + // All registred machines + machines map[string]InitFunc + + ErrNotSupported = errors.New("machine not supported") + ErrMachineNotExist = errors.New("machine not exist") + ErrPrerequisites = errors.New("prerequisites for machine not satisfied (hypervisor installed?)") +) + +func init() { + machines = make(map[string]InitFunc) +} + +func Register(driver string, initFunc InitFunc) error { + if _, exists := machines[driver]; exists { + return fmt.Errorf("Driver already registered %s", driver) + } + machines[driver] = initFunc + + return nil +} + +func GetMachine(mc *MachineConfig) (Machine, error) { + if initFunc, exists := machines[mc.Driver]; exists { + return initFunc(mc) + } + return nil, ErrNotSupported +} diff --git a/virtualbox/nic.go b/driver/nic.go similarity index 97% rename from virtualbox/nic.go rename to driver/nic.go index 0569be5..d6c7364 100644 --- a/virtualbox/nic.go +++ b/driver/nic.go @@ -1,4 +1,4 @@ -package virtualbox +package driver // NIC represents a virtualized network interface card. type NIC struct { diff --git a/virtualbox/pfrule.go b/driver/pfrule.go similarity index 98% rename from virtualbox/pfrule.go rename to driver/pfrule.go index 89b9de7..18b8160 100644 --- a/virtualbox/pfrule.go +++ b/driver/pfrule.go @@ -1,4 +1,4 @@ -package virtualbox +package driver import ( "fmt" diff --git a/virtualbox/storage.go b/driver/storage.go similarity index 98% rename from virtualbox/storage.go rename to driver/storage.go index ae129f4..a229daf 100644 --- a/virtualbox/storage.go +++ b/driver/storage.go @@ -1,4 +1,4 @@ -package virtualbox +package driver // StorageController represents a virtualized storage controller. type StorageController struct { diff --git a/dummy/machine.go b/dummy/machine.go new file mode 100644 index 0000000..6d6a46a --- /dev/null +++ b/dummy/machine.go @@ -0,0 +1,157 @@ +package dummy + +import ( + "fmt" + + "github.com/boot2docker/boot2docker-cli/driver" +) + +func init() { + driver.Register("dummy", InitFunc) +} + +// Initialize the Machine. +func InitFunc(i *driver.MachineConfig) (driver.Machine, error) { + fmt.Printf("Init dummy %s\n", i.VM) + return &Machine{Name: i.VM, State: driver.Poweroff}, nil +} + +// Machine information. +type Machine struct { + Name string + UUID string + State driver.MachineState + CPUs uint + Memory uint // main memory (in MB) + VRAM uint // video memory (in MB) + CfgFile string + BaseFolder string + OSType string + BootOrder []string // max 4 slots, each in {none|floppy|dvd|disk|net} + DockerPort uint + SSHPort uint + SerialFile string +} + +// Refresh reloads the machine information. +func (m *Machine) Refresh() error { + fmt.Printf("Refresh %s: %s\n", m.Name, m.State) + return nil +} + +// Start starts the machine. +func (m *Machine) Start() error { + m.State = driver.Running + fmt.Printf("Start %s: %s\n", m.Name, m.State) + return nil +} + +// Suspend suspends the machine and saves its state to disk. +func (m *Machine) Save() error { + m.State = driver.Saved + fmt.Printf("Save %s: %s\n", m.Name, m.State) + return nil +} + +// Pause pauses the execution of the machine. +func (m *Machine) Pause() error { + m.State = driver.Paused + fmt.Printf("Pause %s: %s\n", m.Name, m.State) + return nil +} + +// Stop gracefully stops the machine. +func (m *Machine) Stop() error { + m.State = driver.Poweroff + fmt.Printf("Stop %s: %s\n", m.Name, m.State) + return nil +} + +// Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. +func (m *Machine) Poweroff() error { + m.State = driver.Poweroff + fmt.Printf("Poweroff %s: %s\n", m.Name, m.State) + return nil +} + +// Restart gracefully restarts the machine. +func (m *Machine) Restart() error { + m.State = driver.Running + fmt.Printf("Restart %s: %s\n", m.Name, m.State) + return nil +} + +// Reset forcefully restarts the machine. State is lost and might corrupt the disk image. +func (m *Machine) Reset() error { + m.State = driver.Running + fmt.Printf("Reset %s: %s\n", m.Name, m.State) + return nil +} + +// Get current state +func (m *Machine) GetState() driver.MachineState { + return m.State +} + +// Get serial file +func (m *Machine) GetSerialFile() string { + return m.SerialFile +} + +// Get Docker port +func (m *Machine) GetDockerPort() uint { + return m.DockerPort +} + +// Get SSH port +func (m *Machine) GetSSHPort() uint { + return m.SSHPort +} + +// Delete deletes the machine and associated disk images. +func (m *Machine) Delete() error { + fmt.Printf("Delete %s: %s\n", m.Name, m.State) + return nil +} + +// Modify changes the settings of the machine. +func (m *Machine) Modify() error { + fmt.Printf("Modify %s: %s\n", m.Name, m.State) + return m.Refresh() +} + +// AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. +func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { + fmt.Println("Add NAT PF") + return nil +} + +// DelNATPF deletes the NAT port forwarding rule with the given name from the n-th NIC. +func (m *Machine) DelNATPF(n int, name string) error { + fmt.Println("Del NAT PF") + return nil +} + +// SetNIC set the n-th NIC. +func (m *Machine) SetNIC(n int, nic driver.NIC) error { + fmt.Println("Set NIC") + return nil +} + +// AddStorageCtl adds a storage controller with the given name. +func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { + fmt.Println("Add storage ctl") + return nil +} + +// DelStorageCtl deletes the storage controller with the given name. +func (m *Machine) DelStorageCtl(name string) error { + fmt.Println("Del storage ctl") + return nil +} + +// AttachStorage attaches a storage medium to the named storage controller. +func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { + fmt.Println("Attach storage") + return nil +} diff --git a/vbm.go b/vbm.go deleted file mode 100644 index e1d9b72..0000000 --- a/vbm.go +++ /dev/null @@ -1,107 +0,0 @@ -package main - -import ( - "bytes" - "io" - "os" - "path/filepath" - - vbx "github.com/boot2docker/boot2docker-cli/virtualbox" -) - -// TODO: delete the hostonlyif and dhcpserver when we delete the vm! (need to -// reference count to make sure there are no other vms relying on them) - -// Get or create the hostonly network interface -func getHostOnlyNetworkInterface() (string, error) { - // Check if the interface/dhcp exists. - nets, err := vbx.HostonlyNets() - if err != nil { - return "", err - } - - dhcps, err := vbx.DHCPs() - if err != nil { - return "", err - } - - for _, n := range nets { - if dhcp, ok := dhcps[n.NetworkName]; ok { - if dhcp.IPv4.IP.Equal(B2D.DHCPIP) && - dhcp.IPv4.Mask.String() == B2D.NetMask.String() && - dhcp.LowerIP.Equal(B2D.LowerIP) && - dhcp.UpperIP.Equal(B2D.UpperIP) && - dhcp.Enabled == B2D.DHCPEnabled { - if B2D.Verbose { - logf("Reusing existing host-only network interface %q", n.Name) - } - return n.Name, nil - } - } - } - - // No existing host-only interface found. Create a new one. - if B2D.Verbose { - logf("Creating a new host-only network interface...") - } - hostonlyNet, err := vbx.CreateHostonlyNet() - if err != nil { - return "", err - } - hostonlyNet.IPv4.IP = B2D.HostIP - hostonlyNet.IPv4.Mask = B2D.NetMask - if err := hostonlyNet.Config(); err != nil { - return "", err - } - - // Create and add a DHCP server to the host-only network - dhcp := vbx.DHCP{} - dhcp.IPv4.IP = B2D.DHCPIP - dhcp.IPv4.Mask = B2D.NetMask - dhcp.LowerIP = B2D.LowerIP - dhcp.UpperIP = B2D.UpperIP - dhcp.Enabled = true - if err := vbx.AddHostonlyDHCP(hostonlyNet.Name, dhcp); err != nil { - return "", err - } - return hostonlyNet.Name, nil -} - -// Copy disk image from given source path to destination -func copyDiskImage(dst, src string) (err error) { - // Open source disk image - srcImg, err := os.Open(src) - if err != nil { - return err - } - closeSrcImg := func() { - if ee := srcImg.Close(); ee != nil { - err = ee - } - } - defer closeSrcImg() - dstImg, err := os.Create(dst) - if err != nil { - return err - } - closeDstImg := func() { - if ee := dstImg.Close(); ee != nil { - err = ee - } - } - defer closeDstImg() - _, err = io.Copy(dstImg, srcImg) - return err -} - -// Make a boot2docker VM disk image with the given size (in MB). -func makeDiskImage(dest string, size uint, initialBytes []byte) error { - // Create the dest dir. - if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { - return err - } - // Fill in the magic string so boot2docker VM will detect this and format - // the disk upon first boot. - raw := bytes.NewReader(initialBytes) - return vbx.MakeDiskImage(dest, size, raw) -} diff --git a/virtualbox/dhcp.go b/virtualbox/dhcp.go index d18d7a4..d686e8e 100644 --- a/virtualbox/dhcp.go +++ b/virtualbox/dhcp.go @@ -4,18 +4,11 @@ import ( "bufio" "net" "strings" -) -// DHCP server info. -type DHCP struct { - NetworkName string - IPv4 net.IPNet - LowerIP net.IP - UpperIP net.IP - Enabled bool -} + "github.com/boot2docker/boot2docker-cli/driver" +) -func addDHCP(kind, name string, d DHCP) error { +func addDHCP(kind, name string, d driver.DHCP) error { command := "modify" // On some platforms (OSX), creating a hostonlyinterface adds a default dhcpserver @@ -45,29 +38,29 @@ func addDHCP(kind, name string, d DHCP) error { } // AddInternalDHCP adds a DHCP server to an internal network. -func AddInternalDHCP(netname string, d DHCP) error { +func AddInternalDHCP(netname string, d driver.DHCP) error { return addDHCP("--netname", netname, d) } // AddHostonlyDHCP adds a DHCP server to a host-only network. -func AddHostonlyDHCP(ifname string, d DHCP) error { +func AddHostonlyDHCP(ifname string, d driver.DHCP) error { return addDHCP("--netname", "HostInterfaceNetworking-"+ifname, d) } // DHCPs gets all DHCP server settings in a map keyed by DHCP.NetworkName. -func DHCPs() (map[string]*DHCP, error) { +func DHCPs() (map[string]*driver.DHCP, error) { out, err := vbmOut("list", "dhcpservers") if err != nil { return nil, err } s := bufio.NewScanner(strings.NewReader(out)) - m := map[string]*DHCP{} - dhcp := &DHCP{} + m := map[string]*driver.DHCP{} + dhcp := &driver.DHCP{} for s.Scan() { line := s.Text() if line == "" { m[dhcp.NetworkName] = dhcp - dhcp = &DHCP{} + dhcp = &driver.DHCP{} continue } res := reColonLine.FindStringSubmatch(line) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 70b1e86..2cbd9ce 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -1,22 +1,20 @@ package virtualbox import ( + "archive/tar" "bufio" + "bytes" "fmt" + "io/ioutil" + "net" + "os" "path/filepath" + "runtime" "strconv" "strings" "time" -) - -type MachineState string -const ( - Poweroff = MachineState("poweroff") - Running = MachineState("running") - Paused = MachineState("paused") - Saved = MachineState("saved") - Aborted = MachineState("aborted") + "github.com/boot2docker/boot2docker-cli/driver" ) type Flag int @@ -40,6 +38,19 @@ const ( F_accelerate3d ) +func init() { + driver.Register("virtualbox", InitFunc) +} + +// Initialize the Machine. +func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { + m, err := GetMachine(mc.VM) + if err != nil && mc.Init == true { + return CreateMachine(mc) + } + return m, err +} + // Convert bool to "on"/"off" func bool2string(b bool) string { if b { @@ -57,7 +68,7 @@ func (f Flag) Get(o Flag) string { type Machine struct { Name string UUID string - State MachineState + State driver.MachineState CPUs uint Memory uint // main memory (in MB) VRAM uint // video memory (in MB) @@ -88,13 +99,13 @@ func (m *Machine) Refresh() error { // Start starts the machine. func (m *Machine) Start() error { switch m.State { - case Paused: + case driver.Paused: return vbm("controlvm", m.Name, "resume") - case Poweroff, Saved, Aborted: + case driver.Poweroff, driver.Saved, driver.Aborted: return vbm("startvm", m.Name, "--type", "headless") } if err := m.Refresh(); err == nil { - if m.State != Running { + if m.State != driver.Running { return fmt.Errorf("Failed to start", m.Name) } } @@ -104,11 +115,11 @@ func (m *Machine) Start() error { // Suspend suspends the machine and saves its state to disk. func (m *Machine) Save() error { switch m.State { - case Paused: + case driver.Paused: if err := m.Start(); err != nil { return err } - case Poweroff, Aborted, Saved: + case driver.Poweroff, driver.Aborted, driver.Saved: return nil } return vbm("controlvm", m.Name, "savestate") @@ -117,7 +128,7 @@ func (m *Machine) Save() error { // Pause pauses the execution of the machine. func (m *Machine) Pause() error { switch m.State { - case Paused, Poweroff, Aborted, Saved: + case driver.Paused, driver.Poweroff, driver.Aborted, driver.Saved: return nil } return vbm("controlvm", m.Name, "pause") @@ -126,15 +137,15 @@ func (m *Machine) Pause() error { // Stop gracefully stops the machine. func (m *Machine) Stop() error { switch m.State { - case Poweroff, Aborted, Saved: + case driver.Poweroff, driver.Aborted, driver.Saved: return nil - case Paused: + case driver.Paused: if err := m.Start(); err != nil { return err } } - for m.State != Poweroff { // busy wait until the machine is stopped + for m.State != driver.Poweroff { // busy wait until the machine is stopped if err := vbm("controlvm", m.Name, "acpipowerbutton"); err != nil { return err } @@ -149,7 +160,7 @@ func (m *Machine) Stop() error { // Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. func (m *Machine) Poweroff() error { switch m.State { - case Poweroff, Aborted, Saved: + case driver.Poweroff, driver.Aborted, driver.Saved: return nil } return vbm("controlvm", m.Name, "poweroff") @@ -158,7 +169,7 @@ func (m *Machine) Poweroff() error { // Restart gracefully restarts the machine. func (m *Machine) Restart() error { switch m.State { - case Paused, Saved: + case driver.Paused, driver.Saved: if err := m.Start(); err != nil { return err } @@ -172,7 +183,7 @@ func (m *Machine) Restart() error { // Reset forcefully restarts the machine. State is lost and might corrupt the disk image. func (m *Machine) Reset() error { switch m.State { - case Paused, Saved: + case driver.Paused, driver.Saved: if err := m.Start(); err != nil { return err } @@ -188,6 +199,26 @@ func (m *Machine) Delete() error { return vbm("unregistervm", m.Name, "--delete") } +// Get current state +func (m *Machine) GetState() driver.MachineState { + return m.State +} + +// Get serial file +func (m *Machine) GetSerialFile() string { + return m.SerialFile +} + +// Get Docker port +func (m *Machine) GetDockerPort() uint { + return m.DockerPort +} + +// Get SSH port +func (m *Machine) GetSSHPort() uint { + return m.SSHPort +} + // GetMachine finds a machine by its name or UUID. func GetMachine(id string) (*Machine, error) { stdout, stderr, err := vbmOutErr("showvminfo", id, "--machinereadable") @@ -219,7 +250,7 @@ func GetMachine(id string) (*Machine, error) { case "UUID": m.UUID = val case "VMState": - m.State = MachineState(val) + m.State = driver.MachineState(val) case "memory": n, err := strconv.ParseUint(val, 10, 32) if err != nil { @@ -294,8 +325,8 @@ func ListMachines() ([]string, error) { } // CreateMachine creates a new machine. If basefolder is empty, use default. -func CreateMachine(name, basefolder string) (*Machine, error) { - if name == "" { +func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { + if mc.VM == "" { return nil, fmt.Errorf("machine name is empty") } @@ -305,25 +336,142 @@ func CreateMachine(name, basefolder string) (*Machine, error) { return nil, err } for _, m := range machineNames { - if m == name { + if m == mc.VM { return nil, ErrMachineExist } } // Create and register the machine. - args := []string{"createvm", "--name", name, "--register"} - if basefolder != "" { - args = append(args, "--basefolder", basefolder) - } + args := []string{"createvm", "--name", mc.VM, "--register"} if err := vbm(args...); err != nil { return nil, err } - m, err := GetMachine(name) + m, err := GetMachine(mc.VM) if err != nil { return nil, err } + // Configure VM for Boot2docker + SetExtra(mc.VM, "VBoxInternal/CPUM/EnableHVP", "1") + m.OSType = "Linux26_64" + m.CPUs = uint(runtime.NumCPU()) + m.Memory = mc.Memory + m.SerialFile = mc.SerialFile + + m.Flag |= F_pae + m.Flag |= F_longmode // important: use x86-64 processor + m.Flag |= F_rtcuseutc + m.Flag |= F_acpi + m.Flag |= F_ioapic + m.Flag |= F_hpet + m.Flag |= F_hwvirtex + m.Flag |= F_vtxvpid + m.Flag |= F_largepages + m.Flag |= F_nestedpaging + + // Set VM boot order + m.BootOrder = []string{"dvd"} + if err := m.Modify(); err != nil { + return m, err + } + + // Set NIC #1 to use NAT + m.SetNIC(1, driver.NIC{Network: driver.NICNetNAT, Hardware: driver.VirtIO}) + pfRules := map[string]driver.PFRule{ + "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: driver.SSHPort}, + } + if driver.DockerPort > 0 { + pfRules["docker"] = vbx.PFRule{Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: driver.dockerPort} + } + + for name, rule := range pfRules { + if err := m.AddNATPF(1, name, rule); err != nil { + return m, err + } + } + + hostIFName, err := getHostOnlyNetworkInterface(mc) + if err != nil { + return m, err + } + + // Set NIC #2 to use host-only + if err := m.SetNIC(2, driver.NIC{Network: driver.NICNetHostonly, Hardware: driver.VirtIO, HostonlyAdapter: hostIFName}); err != nil { + return m, err + } + + // Set VM storage + if err := m.AddStorageCtl("SATA", driver.StorageController{SysBus: driver.SysBusSATA, HostIOCache: true, Bootable: true}); err != nil { + return m, err + } + + // Attach ISO image + if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 0, Device: 0, DriveType: driver.DriveDVD, Medium: mc.ISO}); err != nil { + return m, err + } + + diskImg := filepath.Join(m.BaseFolder, fmt.Sprintf("%s.vmdk", mc.VM)) + if _, err := os.Stat(diskImg); err != nil { + if !os.IsNotExist(err) { + return m, err + } + + if mc.VMDK != "" { + if err := copyDiskImage(diskImg, mc.VMDK); err != nil { + return m, err + } + } else { + magicString := "boot2docker, please format-me" + + buf := new(bytes.Buffer) + tw := tar.NewWriter(buf) + + // magicString first so the automount script knows to format the disk + file := &tar.Header{Name: magicString, Size: int64(len(magicString))} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + if _, err := tw.Write([]byte(magicString)); err != nil { + return m, err + } + // .ssh/key.pub => authorized_keys + file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + pubKey, err := ioutil.ReadFile(mc.SSHKey + ".pub") + if err != nil { + return m, err + } + file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + if _, err := tw.Write([]byte(pubKey)); err != nil { + return m, err + } + file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644} + if err := tw.WriteHeader(file); err != nil { + return m, err + } + if _, err := tw.Write([]byte(pubKey)); err != nil { + return m, err + } + if err := tw.Close(); err != nil { + return m, err + } + + if err := makeDiskImage(diskImg, mc.DiskSize, buf.Bytes()); err != nil { + return m, err + } + } + } + + if err := m.AttachStorage("SATA", driver.StorageMedium{Port: 1, Device: 0, DriveType: driver.DriveHDD, Medium: diskImg}); err != nil { + return m, err + } + return m, nil } @@ -379,7 +527,7 @@ func (m *Machine) Modify() error { } // AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. -func (m *Machine) AddNATPF(n int, name string, rule PFRule) error { +func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { return vbm("controlvm", m.Name, fmt.Sprintf("natpf%d", n), fmt.Sprintf("%s,%s", name, rule.Format())) } @@ -390,7 +538,7 @@ func (m *Machine) DelNATPF(n int, name string) error { } // SetNIC set the n-th NIC. -func (m *Machine) SetNIC(n int, nic NIC) error { +func (m *Machine) SetNIC(n int, nic driver.NIC) error { args := []string{"modifyvm", m.Name, fmt.Sprintf("--nic%d", n), string(nic.Network), fmt.Sprintf("--nictype%d", n), string(nic.Hardware), @@ -404,7 +552,7 @@ func (m *Machine) SetNIC(n int, nic NIC) error { } // AddStorageCtl adds a storage controller with the given name. -func (m *Machine) AddStorageCtl(name string, ctl StorageController) error { +func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { args := []string{"storagectl", m.Name, "--name", name} if ctl.SysBus != "" { args = append(args, "--add", string(ctl.SysBus)) @@ -426,7 +574,7 @@ func (m *Machine) DelStorageCtl(name string) error { } // AttachStorage attaches a storage medium to the named storage controller. -func (m *Machine) AttachStorage(ctlName string, medium StorageMedium) error { +func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { return vbm("storageattach", m.Name, "--storagectl", ctlName, "--port", fmt.Sprintf("%d", medium.Port), "--device", fmt.Sprintf("%d", medium.Device), diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index dd0df6f..e2d34df 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -3,6 +3,7 @@ package virtualbox import ( "bytes" "errors" + "io" "log" "os" "os/exec" @@ -10,6 +11,8 @@ import ( "regexp" "runtime" "strings" + + "github.com/boot2docker/boot2docker-cli/driver" ) var ( @@ -86,3 +89,89 @@ func vbmOutErr(args ...string) (string, string, error) { } return stdout.String(), stderr.String(), err } + +// Get or create the hostonly network interface +func getHostOnlyNetworkInterface(mc *driver.MachineConfig) (string, error) { + // Check if the interface/dhcp exists. + nets, err := HostonlyNets() + if err != nil { + return "", err + } + + dhcps, err := DHCPs() + if err != nil { + return "", err + } + + for _, n := range nets { + if dhcp, ok := dhcps[n.NetworkName]; ok { + if dhcp.IPv4.IP.Equal(mc.DHCPIP) && + dhcp.IPv4.Mask.String() == mc.NetMask.String() && + dhcp.LowerIP.Equal(mc.LowerIP) && + dhcp.UpperIP.Equal(mc.UpperIP) && + dhcp.Enabled == mc.DHCPEnabled { + return n.Name, nil + } + } + } + + // No existing host-only interface found. Create a new one. + hostonlyNet, err := CreateHostonlyNet() + if err != nil { + return "", err + } + hostonlyNet.IPv4.IP = mc.HostIP + hostonlyNet.IPv4.Mask = mc.NetMask + if err := hostonlyNet.Config(); err != nil { + return "", err + } + + // Create and add a DHCP server to the host-only network + dhcp := driver.DHCP{} + dhcp.IPv4.IP = mc.DHCPIP + dhcp.IPv4.Mask = mc.NetMask + dhcp.LowerIP = mc.LowerIP + dhcp.UpperIP = mc.UpperIP + dhcp.Enabled = true + if err := AddHostonlyDHCP(hostonlyNet.Name, dhcp); err != nil { + return "", err + } + return hostonlyNet.Name, nil +} + +// Copy disk image from given source path to destination +func copyDiskImage(dst, src string) (err error) { + // Open source disk image + srcImg, err := os.Open(src) + if err != nil { + return err + } + defer func() { + if ee := srcImg.Close(); ee != nil { + err = ee + } + }() + dstImg, err := os.Create(dst) + if err != nil { + return err + } + defer func() { + if ee := dstImg.Close(); ee != nil { + err = ee + } + }() + _, err = io.Copy(dstImg, srcImg) + return err +} + +// Make a boot2docker VM disk image with the given size (in MB). +func makeDiskImage(dest string, size uint, initialBytes []byte) error { + // Create the dest dir. + if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { + return err + } + // Fill in the magic string so boot2docker VM will detect this and format + // the disk upon first boot. + raw := bytes.NewReader(initialBytes) + return MakeDiskImage(dest, size, raw) +} From 165937c52ec0b1e45790111a219ed44d507c26a2 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 18 Jul 2014 20:47:06 +1000 Subject: [PATCH 039/167] Small fixes to merge in updates --- cmds.go | 5 +++-- virtualbox/machine.go | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cmds.go b/cmds.go index 35fc9aa..ac38577 100644 --- a/cmds.go +++ b/cmds.go @@ -155,8 +155,9 @@ func cmdPoweroff() int { // Upgrade the boot2docker iso - preserving server state func cmdUpgrade() int { - m, err := vbx.GetMachine(B2D.VM) - if err == nil && m.State == vbx.Running { + m, err := driver.GetMachine(&B2D) + if err == nil && m.GetState() == driver.Running { + // Windows won't let us move the iso aside while its in use if cmdStop() == 0 && cmdDownload() == 0 { return cmdUp() } else { diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 2cbd9ce..33ed364 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -381,8 +381,8 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { pfRules := map[string]driver.PFRule{ "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: driver.SSHPort}, } - if driver.DockerPort > 0 { - pfRules["docker"] = vbx.PFRule{Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: driver.dockerPort} + if mc.DockerPort > 0 { + pfRules["docker"] = driver.PFRule{Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: driver.DockerPort} } for name, rule := range pfRules { From d2f1bc3b967d6a0df82bf9b4ffde2b10ad5abd45 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 31 Jul 2014 16:50:21 +1000 Subject: [PATCH 040/167] address gmlewis's nits --- cmds.go | 4 ++-- virtualbox/machine.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmds.go b/cmds.go index ac38577..f5e0615 100644 --- a/cmds.go +++ b/cmds.go @@ -153,11 +153,11 @@ func cmdPoweroff() int { return 0 } -// Upgrade the boot2docker iso - preserving server state +// Upgrade the boot2docker ISO - preserving server state func cmdUpgrade() int { m, err := driver.GetMachine(&B2D) if err == nil && m.GetState() == driver.Running { - // Windows won't let us move the iso aside while its in use + // Windows won't let us move the ISO aside while it's in use if cmdStop() == 0 && cmdDownload() == 0 { return cmdUp() } else { diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 33ed364..15129f8 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -45,7 +45,7 @@ func init() { // Initialize the Machine. func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { m, err := GetMachine(mc.VM) - if err != nil && mc.Init == true { + if err != nil && mc.Init { return CreateMachine(mc) } return m, err From d98b10d08fd91f2dac6ff406bf598397ea303f11 Mon Sep 17 00:00:00 2001 From: Zarko Hristovski Date: Mon, 4 Aug 2014 13:53:34 +0200 Subject: [PATCH 041/167] Small doc correction for USERPROFILE on Windows systems --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24cf87a..b284f88 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ boot2docker vm, which you can then use to access ports you map from your contain The `boot2docker` binary reads configuration from `$BOOT2DOCKER_PROFILE` if set, or `$BOOT2DOCKER_DIR/profile` or `$HOME/.boot2docker/profile` or (on Windows) -`$USERPROFILE/.boot2docker/profile`. `boot2docker config` will +`%USERPROFILE%/.boot2docker/profile`. `boot2docker config` will tell you where it is looking for the file, and will also output the settings that are in use, so you can initialise a default file to customise using `boot2docker config > /home/sven/.boot2docker/profile`. From c4149ae9450b826d5b11505821ade76b9d02663d Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 10 Jul 2014 00:56:22 -0600 Subject: [PATCH 042/167] Add Travis configuration file --- .travis.yml | 24 ++++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 26 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3391bd5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: go + +# this should be exactly the same as what's in the Dockerfile +go: 1.3 + +# let us have pretty experimental Docker-based Travis workers +sudo: false + +env: + - _GOOS=linux _GOARCH=amd64 + - _GOOS=darwin _GOARCH=amd64 + - _GOOS=windows _GOARCH=amd64 + +install: + - env | sort + - gvm cross "$_GOOS" "$_GOARCH" + - export GOOS="$_GOOS" GOARCH="$_GOARCH" + - go env + - go get -d -v ./... + +script: + # TODO - some gofmt magic + - go build -v ./... + # TODO - go test -v ./... # (we first need to skip all the meaty vbox tests when "VBoxManage" isn't available, or mock it) diff --git a/README.md b/README.md index 24cf87a..9950f87 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,8 @@ the same as the command-line flags with long names. ## Contribution +[![Build Status](https://travis-ci.org/boot2docker/boot2docker-cli.svg?branch=master)](https://travis-ci.org/boot2docker/boot2docker-cli) + We are implementing the same process as [Docker merge approval](https://github.com/dotcloud/docker/blob/master/CONTRIBUTING.md#merge-approval), so all commits need to be done via pull requests, and will need three or more From cb62ba09f84b4b7e205217957b44e99f0642d9f5 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 6 Aug 2014 09:37:08 -0600 Subject: [PATCH 043/167] Update Dockerfile to use the new "golang:1.3-cross" image --- Dockerfile | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index b13e784..71515cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,11 @@ # Dockerfile to cross compile boot2docker-cli -FROM debian:jessie +FROM golang:1.3-cross -# Packaged dependencies -RUN apt-get update && apt-get install -y build-essential curl git - -# Install Go from binary release -RUN curl -sSL http://golang.org/dl/go1.3.src.tar.gz | tar -xzC /usr/local -ENV PATH /usr/local/go/bin:$PATH - -# Bootstrap Go for cross compilation (we have linux/amd64 by default) -ENV DOCKER_CROSSPLATFORMS darwin/amd64 windows/amd64 -RUN cd /usr/local/go/src && bash -xec 'for platform in $DOCKER_CROSSPLATFORMS; do GOOS=${platform%/*} GOARCH=${platform##*/} ./make.bash --no-clean 2>&1; done' - -ENV GOPATH /go ADD . /go/src/github.com/boot2docker/boot2docker-cli WORKDIR /go/src/github.com/boot2docker/boot2docker-cli # Download (but not install) dependencies -RUN go get -d -v +RUN go get -d -v ./... CMD ["make", "all"] From d153e4dd6d1525fc3bd62c98b5c491faf2d7cb6a Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 31 Jul 2014 16:15:42 +1000 Subject: [PATCH 044/167] rearrange building docs to note that you need go 1.3 --- README.md | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 24cf87a..846a169 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,26 @@ Refer to the installation instructions for [Windows](http://docs.docker.io/insta You can dowload binary releases at https://github.com/boot2docker/boot2docker-cli/releases +### Docker container build + +The most reliable way to cross-compile boot2docker for all 3 platforms, is to +use the Dockerfile (and Docker) + +```sh +git clone https://github.com/boot2docker/boot2docker-cli +cd boot2docker-cli +make +``` + +Built binaries will be available in the current directory. + +This assumes you have an accessible Docker daemon (local or remote with `DOCKER_HOST` set) +and `make` installed. + + ### Install from source -You need to have [Go compiler](http://golang.org) installed, and `$GOPATH` +You need to have the [Go compiler (v1.3 or higher)](http://golang.org) installed, and `$GOPATH` [properly setup](http://golang.org/doc/code.html#GOPATH). Then run go get github.com/boot2docker/boot2docker-cli @@ -52,6 +69,9 @@ You can cross compile to OS X, Windows, and Linux. For that you need to first [make your Go compiler ready for cross compiling to the target platforms](http://stackoverflow.com/questions/12168873/cross-compile-go-on-osx). +Please make sure you build with golang v1.3 or later - it is required for +`boot2docker download` to work on OS X. + We provide a Makefile to make the process a bit easier. ```sh @@ -65,28 +85,6 @@ make clean # clean up the built binaries Built binaries will be available in the current directory. -### Docker build - -You can also build in a Docker container. - -```sh -make dockerbuild -``` - -Built binaries will be available in the current directory. - - -### Caveats - -Currently the binary cross-compiled from Windows/Linux to OS X has a [TLS -issue](https://github.com/boot2docker/boot2docker-cli/issues/11), and as a -result - - $ boot2docker download - -will fail. You need to do a native OS X build to avoid this problem. - - ## Usage To initialize a new boot2docker VM, run From 541163ee63beb82b9cf8c5215d894265e79cec07 Mon Sep 17 00:00:00 2001 From: Moghedrin Date: Fri, 8 Aug 2014 14:33:59 -0600 Subject: [PATCH 045/167] Exit on driver initialization error --- virtualbox/machine.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 15129f8..4cd6cd4 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -39,7 +39,10 @@ const ( ) func init() { - driver.Register("virtualbox", InitFunc) + if err := driver.Register("virtualbox", InitFunc); err != nil { + fmt.Printf("Failed to initialize driver. Error : %s", err.Error()) + os.Exit(1) + } } // Initialize the Machine. From 1155526d45d010e5431440b58f405d060f5d538e Mon Sep 17 00:00:00 2001 From: Moghedrin Date: Fri, 8 Aug 2014 14:56:28 -0600 Subject: [PATCH 046/167] Redirect dummy and virtualbox driver init errors to stderr --- dummy/machine.go | 6 +++++- virtualbox/machine.go | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/dummy/machine.go b/dummy/machine.go index 6d6a46a..ce38ce5 100644 --- a/dummy/machine.go +++ b/dummy/machine.go @@ -2,12 +2,16 @@ package dummy import ( "fmt" + "os" "github.com/boot2docker/boot2docker-cli/driver" ) func init() { - driver.Register("dummy", InitFunc) + if err := driver.Register("dummy", InitFunc); err != nil { + fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) + os.Exit(1) + } } // Initialize the Machine. diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 4cd6cd4..f488b76 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -40,7 +40,7 @@ const ( func init() { if err := driver.Register("virtualbox", InitFunc); err != nil { - fmt.Printf("Failed to initialize driver. Error : %s", err.Error()) + fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) os.Exit(1) } } From 1ca10ae7e1dd8d0e2e69f5f065043c77b5af38e9 Mon Sep 17 00:00:00 2001 From: Moghedrin Date: Mon, 11 Aug 2014 15:17:09 -0600 Subject: [PATCH 047/167] Remove the errf and outf utility functions in favor of calling the appropriate fmt functions directly for clearer and more idiomatic code --- cmds.go | 8 ++++---- config.go | 6 +++--- main.go | 11 +++++++---- util.go | 10 ---------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/cmds.go b/cmds.go index f5e0615..a168565 100644 --- a/cmds.go +++ b/cmds.go @@ -304,12 +304,12 @@ func cmdIP() int { IP = RequestIPFromSSH(m) } if IP != "" { - errf("\nThe VM's Host only interface IP address is: ") + fmt.Fprintf(os.Stderr, "\nThe VM's Host only interface IP address is: ") fmt.Printf("%s", IP) - errf("\n\n") + fmt.Fprintf(os.Stderr, "\n\n") } else { - errf("\nFailed to get VM Host only IP address.\n") - errf("\tWas the VM initilized using boot2docker?\n") + fmt.Fprintf(os.Stderr, "\nFailed to get VM Host only IP address.\n") + fmt.Fprintf(os.Stderr, "\tWas the VM initilized using boot2docker?\n") } return 0 } diff --git a/config.go b/config.go index eea9c8b..ec476d1 100644 --- a/config.go +++ b/config.go @@ -153,12 +153,12 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - errf("Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) } func usageLong(flags *flag.FlagSet) { // NOTE: the help message uses spaces, not tabs for indentation! - errf(`Usage: %s [] [] + fmt.Fprintf(os.Stderr, `Usage: %s [] [] boot2docker management utility. @@ -177,7 +177,7 @@ Commands: ip Display the IP address of the VM's Host-only network. status Display current state of VM. download Download boot2docker ISO image. - upgrade Upgrade the boot2docker ISO image (if vm is running it will be stopped and started). + upgrade Upgrade the boot2docker ISO image (if vm is running it will be stopped and started). version Display version information. Options: diff --git a/main.go b/main.go index 81ee6ef..6e42d98 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,9 @@ package main -import "os" +import ( + "os" + "fmt" +) // The following vars will be injected during the build process. var ( @@ -22,7 +25,7 @@ func main() { func run() int { flags, err := config() if err != nil { - errf("config error: %v\n", err) + fmt.Fprintf(os.Stderr, "config error: %v\n", err) return 1 } @@ -58,7 +61,7 @@ func run() int { case "upgrade": return cmdUpgrade() case "version": - outf("Client version: %s\nGit commit: %s\n", Version, GitSHA) + fmt.Printf("Client version: %s\nGit commit: %s\n", Version, GitSHA) return 0 case "help": flags.Usage() @@ -67,7 +70,7 @@ func run() int { usageShort() return 0 default: - errf("Unknown command %q\n", cmd) + fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) usageShort() return 1 } diff --git a/util.go b/util.go index 0d88e1b..92693e0 100644 --- a/util.go +++ b/util.go @@ -15,16 +15,6 @@ import ( "time" ) -// fmt.Printf to stdout. Convention is to outf info intended for scripting. -func outf(f string, v ...interface{}) { - fmt.Printf(f, v...) -} - -// fmt.Printf to stderr. Convention is to errf info intended for human. -func errf(f string, v ...interface{}) { - fmt.Fprintf(os.Stderr, f, v...) -} - // Verbose output for debugging. func logf(fmt string, v ...interface{}) { log.Printf(fmt, v...) From 07e11c3a116fab490e241a77d6fed3bf371ad27a Mon Sep 17 00:00:00 2001 From: Moghedrin Date: Mon, 11 Aug 2014 16:39:30 -0600 Subject: [PATCH 048/167] Removed utility function logf and changed cmd functions to return an error value rather than an error code. --- cmds.go | 183 ++++++++++++++++++++++++-------------------------------- main.go | 21 ++++--- util.go | 11 +--- 3 files changed, 93 insertions(+), 122 deletions(-) diff --git a/cmds.go b/cmds.go index a168565..10b7393 100644 --- a/cmds.go +++ b/cmds.go @@ -15,38 +15,33 @@ import ( ) // Initialize the boot2docker VM from scratch. -func cmdInit() int { +func cmdInit() error { B2D.Init = true _, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to initialize machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to initialize machine %q: %s", B2D.VM, err) } - return 0 + return nil } // Bring up the VM from all possible states. -func cmdUp() int { +func cmdUp() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := m.Start(); err != nil { - logf("Failed to start machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to start machine %q: %s", B2D.VM, err) } if err := m.Refresh(); err != nil { - logf("Failed to start machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to start machine %q: %s", B2D.VM, err) } if m.GetState() != driver.Running { - logf("Failed to start machine %q (run again with -v for details)", B2D.VM) - return 1 + return fmt.Errorf("Failed to start machine %q (run again with -v for details)", B2D.VM) } - logf("Waiting for VM to be started...") + fmt.Printf("Waiting for VM to be started...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket time.Sleep(600 * time.Millisecond) natSSH := fmt.Sprintf("localhost:%d", m.GetSSHPort()) @@ -66,102 +61,95 @@ func cmdUp() int { } print("\n") - logf("Started.") + fmt.Printf("Started.") if IP == "" { // lets try one more time time.Sleep(600 * time.Millisecond) - logf(" Trying to get IP one more time") + fmt.Printf(" Trying to get IP one more time") IP = RequestIPFromSSH(m) } switch runtime.GOOS { case "windows": - logf("Docker client does not run on Windows for now. Please use") - logf(" \"%s\" ssh", os.Args[0]) - logf("to SSH into the VM instead.") + fmt.Printf("Docker client does not run on Windows for now. Please use") + fmt.Printf(" \"%s\" ssh", os.Args[0]) + fmt.Printf("to SSH into the VM instead.") default: if IP == "" { - logf("Auto detection of the VM's IP address failed.") - logf("Please run `boot2docker -v up` to diagnose.") + fmt.Printf("Auto detection of the VM's IP address failed.") + fmt.Printf("Please run `boot2docker -v up` to diagnose.") } else { // Check if $DOCKER_HOST ENV var is properly configured. if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, driver.DockerPort) { - logf("To connect the Docker client to the Docker daemon, please set:") - logf(" export DOCKER_HOST=tcp://%s:%d", IP, driver.DockerPort) + fmt.Printf("To connect the Docker client to the Docker daemon, please set:") + fmt.Printf(" export DOCKER_HOST=tcp://%s:%d", IP, driver.DockerPort) } else { - logf("Your DOCKER_HOST env variable is already set correctly.") + fmt.Printf("Your DOCKER_HOST env variable is already set correctly.") } } } - return 0 + return nil } // Tell the user the config (and later let them set it?) -func cmdConfig() int { +func cmdConfig() error { dir, err := getCfgDir(".boot2docker") if err != nil { - logf("Error working out Profile file location: %s", err) - return 1 + return fmt.Errorf("Error working out Profile file location: %s", err) } filename := getCfgFilename(dir) - logf("boot2docker profile filename: %s", filename) + fmt.Printf("boot2docker profile filename: %s", filename) fmt.Println(printConfig()) - return 0 + return nil } // Suspend and save the current state of VM on disk. -func cmdSave() int { +func cmdSave() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := m.Save(); err != nil { - logf("Failed to save machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to save machine %q: %s", B2D.VM, err) } - return 0 + return nil } // Gracefully stop the VM by sending ACPI shutdown signal. -func cmdStop() int { +func cmdStop() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := m.Stop(); err != nil { - logf("Failed to stop machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to stop machine %q: %s", B2D.VM, err) } - return 0 + return nil } // Forcefully power off the VM (equivalent to unplug power). Might corrupt disk // image. -func cmdPoweroff() int { +func cmdPoweroff() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := m.Poweroff(); err != nil { - logf("Failed to poweroff machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to poweroff machine %q: %s", B2D.VM, err) } - return 0 + return nil } // Upgrade the boot2docker ISO - preserving server state -func cmdUpgrade() int { +func cmdUpgrade() error { m, err := driver.GetMachine(&B2D) if err == nil && m.GetState() == driver.Running { // Windows won't let us move the ISO aside while it's in use - if cmdStop() == 0 && cmdDownload() == 0 { + if cmdStop() == nil && cmdDownload() == nil { return cmdUp() } else { - return 0 + return nil } } else { return cmdDownload() @@ -169,87 +157,75 @@ func cmdUpgrade() int { } // Gracefully stop and then start the VM. -func cmdRestart() int { +func cmdRestart() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := m.Restart(); err != nil { - logf("Failed to restart machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to restart machine %q: %s", B2D.VM, err) } - return 0 + return nil } // Forcefully reset (equivalent to cold boot) the VM. Might corrupt disk image. -func cmdReset() int { +func cmdReset() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := m.Reset(); err != nil { - logf("Failed to reset machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to reset machine %q: %s", B2D.VM, err) } - return 0 + return nil } // Delete the VM and associated disk image. -func cmdDelete() int { +func cmdDelete() error { m, err := driver.GetMachine(&B2D) if err != nil { if err == driver.ErrMachineNotExist { - logf("Machine %q does not exist.", B2D.VM) - return 0 + return fmt.Errorf("Machine %q does not exist.", B2D.VM) } - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := m.Delete(); err != nil { - logf("Failed to delete machine %q: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to delete machine %q: %s", B2D.VM, err) } - return 0 + return nil } // Show detailed info of the VM. -func cmdInfo() int { +func cmdInfo() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if err := json.NewEncoder(os.Stdout).Encode(m); err != nil { - logf("Failed to encode machine %q info: %s", B2D.VM, err) - return 1 + return fmt.Errorf("Failed to encode machine %q info: %s", B2D.VM, err) } - return 0 + return nil } // Show the current state of the VM. -func cmdStatus() int { +func cmdStatus() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } fmt.Println(m.GetState()) - return 0 + return nil } // Call the external SSH command to login into boot2docker VM. -func cmdSSH() int { +func cmdSSH() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if m.GetState() != driver.Running { - logf("VM %q is not running.", B2D.VM) - return 1 + return fmt.Errorf("VM %q is not running.", B2D.VM) } // find the ssh cmd string and then pass any remaining strings to ssh @@ -271,22 +247,19 @@ func cmdSSH() int { }, os.Args[i:]...) if err := cmdInteractive(B2D.SSH, sshArgs...); err != nil { - logf("%s", err) - return 1 + return fmt.Errorf("%s", err) } - return 0 + return nil } -func cmdIP() int { +func cmdIP() error { m, err := driver.GetMachine(&B2D) if err != nil { - logf("Failed to get machine %q: %s", B2D.VM, err) - return 2 + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } if m.GetState() != driver.Running { - logf("VM %q is not running.", B2D.VM) - return 1 + return fmt.Errorf("VM %q is not running.", B2D.VM) } IP := "" @@ -311,7 +284,7 @@ func cmdIP() int { fmt.Fprintf(os.Stderr, "\nFailed to get VM Host only IP address.\n") fmt.Fprintf(os.Stderr, "\tWas the VM initilized using boot2docker?\n") } - return 0 + return nil } func RequestIPFromSSH(m driver.Machine) string { @@ -328,10 +301,10 @@ func RequestIPFromSSH(m driver.Machine) string { ) IP := "" if err != nil { - logf("%s", err) + fmt.Printf("%s", err) } else { if B2D.Verbose { - logf("SSH returned: %s\nEND SSH\n", out) + fmt.Printf("SSH returned: %s\nEND SSH\n", out) } // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 lines := strings.Split(out, "\n") @@ -347,21 +320,19 @@ func RequestIPFromSSH(m driver.Machine) string { } // Download the boot2docker ISO image. -func cmdDownload() int { - logf("Downloading boot2docker ISO image...") +func cmdDownload() error { + fmt.Printf("Downloading boot2docker ISO image...") url := "https://api.github.com/repos/boot2docker/boot2docker/releases" tag, err := getLatestReleaseName(url) if err != nil { - logf("Failed to get latest release: %s", err) - return 1 + return fmt.Errorf("Failed to get latest release: %s", err) } - logf("Latest release is %s", tag) + fmt.Printf("Latest release is %s", tag) url = fmt.Sprintf("https://github.com/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", tag) if err := download(B2D.ISO, url); err != nil { - logf("Failed to download ISO image: %s", err) - return 1 + return fmt.Errorf("Failed to download ISO image: %s", err) } - logf("Success: downloaded %s\n\tto %s", url, B2D.ISO) - return 0 + fmt.Printf("Success: downloaded %s\n\tto %s", url, B2D.ISO) + return nil } diff --git a/main.go b/main.go index 6e42d98..d4f0f9f 100644 --- a/main.go +++ b/main.go @@ -18,15 +18,20 @@ func main() { // wrapper. Be careful not to indirectly trigger os.Exit() in the program, // notably via log.Fatal() and on flag.Parse() where the default behavior // is ExitOnError. - os.Exit(run()) + err := run() + if err != nil { + os.Exit(0) + } else { + fmt.Fprintf(os.Stderr, "%s\n", err.Error()) + os.Exit(1) + } } // Run the program and return exit code. -func run() int { +func run() error { flags, err := config() if err != nil { - fmt.Fprintf(os.Stderr, "config error: %v\n", err) - return 1 + return fmt.Errorf("config error: %v\n", err) } switch cmd := flags.Arg(0); cmd { @@ -62,16 +67,16 @@ func run() int { return cmdUpgrade() case "version": fmt.Printf("Client version: %s\nGit commit: %s\n", Version, GitSHA) - return 0 + return nil case "help": flags.Usage() - return 0 + return nil case "": usageShort() - return 0 + return nil default: fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) usageShort() - return 1 + return fmt.Errorf("Unknown command %q\n", cmd) } } diff --git a/util.go b/util.go index 92693e0..921b035 100644 --- a/util.go +++ b/util.go @@ -15,17 +15,12 @@ import ( "time" ) -// Verbose output for debugging. -func logf(fmt string, v ...interface{}) { - log.Printf(fmt, v...) -} - // Try if addr tcp://addr is readable for n times at wait interval. func read(addr string, n int, wait time.Duration) error { var lastErr error for i := 0; i < n; i++ { if B2D.Verbose { - logf("Connecting to tcp://%v (attempt #%d)", addr, i) + fmt.Printf("Connecting to tcp://%v (attempt #%d)", addr, i) } conn, err := net.DialTimeout("tcp", addr, 1*time.Second) if err != nil { @@ -130,7 +125,7 @@ func cmd(name string, args ...string) (string, error) { func cmdInteractive(name string, args ...string) error { cmd := exec.Command(name, args...) if B2D.Verbose { - logf("executing: %v %v", name, strings.Join(args, " ")) + fmt.Printf("executing: %v %v", name, strings.Join(args, " ")) } cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout @@ -222,7 +217,7 @@ func RequestIPFromSerialPort(socket string) string { //give us time reader clean up time.Sleep(1 * time.Second) if IP == "" && B2D.Verbose { - logf(fullLog) + fmt.Printf(fullLog) } return IP From 8a11c5d951307bcdc3bcd8ee0ccc8d6d7142c3d6 Mon Sep 17 00:00:00 2001 From: Moghedrin Date: Tue, 12 Aug 2014 16:34:54 -0600 Subject: [PATCH 049/167] Change a few prints to go to stderr, and avoid printing duplicate error message for the unknown command error. --- cmds.go | 6 +++--- main.go | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/cmds.go b/cmds.go index 10b7393..7d40ac6 100644 --- a/cmds.go +++ b/cmds.go @@ -77,8 +77,8 @@ func cmdUp() error { fmt.Printf("to SSH into the VM instead.") default: if IP == "" { - fmt.Printf("Auto detection of the VM's IP address failed.") - fmt.Printf("Please run `boot2docker -v up` to diagnose.") + fmt.Fprintf(os.Stderr, "Auto detection of the VM's IP address failed.") + fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.") } else { // Check if $DOCKER_HOST ENV var is properly configured. if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, driver.DockerPort) { @@ -301,7 +301,7 @@ func RequestIPFromSSH(m driver.Machine) string { ) IP := "" if err != nil { - fmt.Printf("%s", err) + fmt.Fprintf(os.Stderr, "request ip from ssh error: %v", err) } else { if B2D.Verbose { fmt.Printf("SSH returned: %s\nEND SSH\n", out) diff --git a/main.go b/main.go index d4f0f9f..ccfa311 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,13 @@ var ( GitSHA string ) +type unknownCommandError struct { + cmd string +} +func (e unknownCommandError) Error() string { + return fmt.Sprintf("Unknown command: %s", e.cmd) +} + func main() { // os.Exit will terminate the program at the place of call without running // any deferred cleanup statements. It might cause unintended effects. To @@ -18,11 +25,13 @@ func main() { // wrapper. Be careful not to indirectly trigger os.Exit() in the program, // notably via log.Fatal() and on flag.Parse() where the default behavior // is ExitOnError. - err := run() - if err != nil { + if err := run(); err == nil { os.Exit(0) } else { - fmt.Fprintf(os.Stderr, "%s\n", err.Error()) + fmt.Fprintf(os.Stderr, "error in run: %v\n", err) + if _, ok := err.(unknownCommandError); ok { + usageShort() + } os.Exit(1) } } @@ -75,8 +84,6 @@ func run() error { usageShort() return nil default: - fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) - usageShort() - return fmt.Errorf("Unknown command %q\n", cmd) + return unknownCommandError{cmd: cmd} } } From 17262b4a7ee2da63292a5d35f292c39f66b361f9 Mon Sep 17 00:00:00 2001 From: Moghedrin Date: Wed, 13 Aug 2014 14:44:51 -0600 Subject: [PATCH 050/167] Refactor main to remove unnecessary else statement --- main.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index ccfa311..ff50df1 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ var ( type unknownCommandError struct { cmd string } + func (e unknownCommandError) Error() string { return fmt.Sprintf("Unknown command: %s", e.cmd) } @@ -25,9 +26,7 @@ func main() { // wrapper. Be careful not to indirectly trigger os.Exit() in the program, // notably via log.Fatal() and on flag.Parse() where the default behavior // is ExitOnError. - if err := run(); err == nil { - os.Exit(0) - } else { + if err := run(); err != nil { fmt.Fprintf(os.Stderr, "error in run: %v\n", err) if _, ok := err.(unknownCommandError); ok { usageShort() From c19a372a832ea52d943d7f45f35ef4b49e45d9b7 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Mon, 11 Aug 2014 17:34:53 +1000 Subject: [PATCH 051/167] copy the client certs to the local system on 'docker up' - report the actual Docker port in use - add 'docker socket' command that can be used in scripts --- cmds.go | 75 ++++++++++------------------ config.go | 32 ++++++++---- main.go | 4 +- util.go | 147 +++++++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 180 insertions(+), 78 deletions(-) diff --git a/cmds.go b/cmds.go index 7d40ac6..58fabc2 100644 --- a/cmds.go +++ b/cmds.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "runtime" - "strings" "time" _ "github.com/boot2docker/boot2docker-cli/dummy" @@ -70,6 +69,7 @@ func cmdUp() error { IP = RequestIPFromSSH(m) } + _ = RequestCertsUsingSSH(m) switch runtime.GOOS { case "windows": fmt.Printf("Docker client does not run on Windows for now. Please use") @@ -81,9 +81,10 @@ func cmdUp() error { fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.") } else { // Check if $DOCKER_HOST ENV var is properly configured. - if os.Getenv("DOCKER_HOST") != fmt.Sprintf("tcp://%s:%d", IP, driver.DockerPort) { + socket := RequestSocketFromSSH(m) + if os.Getenv("DOCKER_HOST") != socket { fmt.Printf("To connect the Docker client to the Docker daemon, please set:") - fmt.Printf(" export DOCKER_HOST=tcp://%s:%d", IP, driver.DockerPort) + fmt.Printf(" export DOCKER_HOST=%s", socket) } else { fmt.Printf("Your DOCKER_HOST env variable is already set correctly.") } @@ -94,11 +95,11 @@ func cmdUp() error { // Tell the user the config (and later let them set it?) func cmdConfig() error { - dir, err := getCfgDir(".boot2docker") + dir, err := cfgDir(".boot2docker") if err != nil { return fmt.Errorf("Error working out Profile file location: %s", err) } - filename := getCfgFilename(dir) + filename := cfgFilename(dir) fmt.Printf("boot2docker profile filename: %s", filename) fmt.Println(printConfig()) return nil @@ -217,6 +218,26 @@ func cmdStatus() error { return nil } +// tell the User the Docker socket to connect to +func cmdSocket() error { + m, err := driver.GetMachine(&B2D) + if err != nil { + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) + } + + if m.GetState() != driver.Running { + return fmt.Errorf("VM %q is not running.", B2D.VM) + } + + Socket := RequestSocketFromSSH(m) + + fmt.Fprintf(os.Stderr, "\n\t export DOCKER_HOST=") + fmt.Printf("%s", Socket) + fmt.Fprintf(os.Stderr, "\n\n") + + return nil +} + // Call the external SSH command to login into boot2docker VM. func cmdSSH() error { m, err := driver.GetMachine(&B2D) @@ -236,17 +257,7 @@ func cmdSSH() error { i++ } - sshArgs := append([]string{ - "-o", "IdentitiesOnly=yes", - "-o", "StrictHostKeyChecking=no", - "-o", "UserKnownHostsFile=/dev/null", - "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." - "-p", fmt.Sprintf("%d", m.GetSSHPort()), - "-i", B2D.SSHKey, - "docker@localhost", - }, os.Args[i:]...) - - if err := cmdInteractive(B2D.SSH, sshArgs...); err != nil { + if err := cmdInteractive(m, os.Args[i:]...); err != nil { return fmt.Errorf("%s", err) } return nil @@ -287,38 +298,6 @@ func cmdIP() error { return nil } -func RequestIPFromSSH(m driver.Machine) string { - // fall back to using the NAT port forwarded ssh - out, err := cmd(B2D.SSH, - "-v", // please leave in - this seems to improve the chance of success - "-o", "IdentitiesOnly=yes", - "-o", "StrictHostKeyChecking=no", - "-o", "UserKnownHostsFile=/dev/null", - "-p", fmt.Sprintf("%d", m.GetSSHPort()), - "-i", B2D.SSHKey, - "docker@localhost", - "ip addr show dev eth1", - ) - IP := "" - if err != nil { - fmt.Fprintf(os.Stderr, "request ip from ssh error: %v", err) - } else { - if B2D.Verbose { - fmt.Printf("SSH returned: %s\nEND SSH\n", out) - } - // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 - lines := strings.Split(out, "\n") - for _, line := range lines { - vals := strings.Split(strings.TrimSpace(line), " ") - if len(vals) >= 2 && vals[0] == "inet" { - IP = vals[1][:strings.Index(vals[1], "/")] - break - } - } - } - return IP -} - // Download the boot2docker ISO image. func cmdDownload() error { fmt.Printf("Downloading boot2docker ISO image...") diff --git a/config.go b/config.go index ec476d1..33234a3 100644 --- a/config.go +++ b/config.go @@ -20,11 +20,7 @@ var ( B2D = driver.MachineConfig{} ) -func getCfgDir(name string) (string, error) { - if b2dDir := os.Getenv("BOOT2DOCKER_DIR"); b2dDir != "" { - return b2dDir, nil - } - +func homeDir() (string, error) { dir := "" // *nix and MSYS Windows @@ -35,6 +31,21 @@ func getCfgDir(name string) (string, error) { if _, err := os.Stat(dir); err != nil { return "", err } + + return dir, nil +} + +func cfgDir(name string) (string, error) { + if name == ".boot2docker" { + if b2dDir := os.Getenv("BOOT2DOCKER_DIR"); b2dDir != "" { + return b2dDir, nil + } + } + + dir, err := homeDir() + if err != nil { + return "", err + } dir = filepath.Join(dir, name) if err := os.MkdirAll(dir, 0755); err != nil { return "", err @@ -42,7 +53,7 @@ func getCfgDir(name string) (string, error) { return dir, nil } -func getCfgFilename(dir string) string { +func cfgFilename(dir string) string { filename := os.Getenv("BOOT2DOCKER_PROFILE") if filename == "" { filename = filepath.Join(dir, "profile") @@ -64,7 +75,7 @@ func printConfig() string { // Read configuration from both profile and flags. Flags override profile. func config() (*flag.FlagSet, error) { - dir, err := getCfgDir(".boot2docker") + dir, err := cfgDir(".boot2docker") if err != nil { return nil, fmt.Errorf("failed to get boot2docker directory: %s", err) } @@ -95,7 +106,7 @@ func config() (*flag.FlagSet, error) { flags.StringVar(&B2D.SSH, "ssh", "ssh", "path to SSH client utility.") flags.StringVar(&B2D.SSHGen, "ssh-keygen", "ssh-keygen", "path to ssh-keygen utility.") - sshdir, _ := getCfgDir(".ssh") + sshdir, _ := cfgDir(".ssh") flags.StringVar(&B2D.SSHKey, "sshkey", filepath.Join(sshdir, "id_boot2docker"), "path to SSH key to use.") flags.UintVarP(&B2D.DiskSize, "disksize", "s", 20000, "boot2docker disk image size (in MB).") flags.UintVarP(&B2D.Memory, "memory", "m", 2048, "virtual machine memory size (in MB).") @@ -121,7 +132,7 @@ func config() (*flag.FlagSet, error) { return nil, err } // Over-ride from the profile file - filename := getCfgFilename(B2D.Dir) + filename := cfgFilename(B2D.Dir) if _, err := os.Lstat(filename); err == nil { if _, err := toml.DecodeFile(filename, &B2D); err != nil { return nil, err @@ -153,7 +164,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|delete|destroy|download|version} []\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|socket|delete|destroy|download|version} []\n", os.Args[0]) } func usageLong(flags *flag.FlagSet) { @@ -175,6 +186,7 @@ Commands: config|cfg Show selected profile file settings. info Display detailed information of VM. ip Display the IP address of the VM's Host-only network. + socket Display the DOCKER_HOST socket to connect to. status Display current state of VM. download Download boot2docker ISO image. upgrade Upgrade the boot2docker ISO image (if vm is running it will be stopped and started). diff --git a/main.go b/main.go index ff50df1..a72bf74 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,8 @@ package main import ( - "os" "fmt" + "os" ) // The following vars will be injected during the build process. @@ -65,6 +65,8 @@ func run() error { return cmdDelete() case "info": return cmdInfo() + case "socket": + return cmdSocket() case "status": return cmdStatus() case "ssh": diff --git a/util.go b/util.go index 921b035..b3be04d 100644 --- a/util.go +++ b/util.go @@ -1,6 +1,9 @@ package main import ( + "archive/tar" + "bufio" + "bytes" "encoding/json" "fmt" "io" @@ -13,6 +16,8 @@ import ( "regexp" "strings" "time" + + "github.com/boot2docker/boot2docker-cli/driver" ) // Try if addr tcp://addr is readable for n times at wait interval. @@ -110,23 +115,8 @@ func getLatestReleaseName(url string) (string, error) { return t[0].TagName, nil } -// Convenient function to exec a command. -func cmd(name string, args ...string) (string, error) { - cmd := exec.Command(name, args...) - if B2D.Verbose { - cmd.Stderr = os.Stderr - log.Printf("executing: %v %v", name, strings.Join(args, " ")) - } - - b, err := cmd.Output() - return string(b), err -} - -func cmdInteractive(name string, args ...string) error { - cmd := exec.Command(name, args...) - if B2D.Verbose { - fmt.Printf("executing: %v %v", name, strings.Join(args, " ")) - } +func cmdInteractive(m driver.Machine, args ...string) error { + cmd := getSSHCommand(m, args...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -164,6 +154,76 @@ func reader(r io.Reader) { } } +func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { + + DefaultSSHArgs := []string{ + "-o", "IdentitiesOnly=yes", + "-o", "StrictHostKeyChecking=no", + "-o", "UserKnownHostsFile=/dev/null", + "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." + "-p", fmt.Sprintf("%d", m.GetSSHPort()), + "-i", B2D.SSHKey, + "docker@localhost", + } + + sshArgs := append(DefaultSSHArgs, args...) + cmd := exec.Command(B2D.SSH, sshArgs...) + if B2D.Verbose { + cmd.Stderr = os.Stderr + log.Printf("executing: %v %v", B2D.SSH, strings.Join(sshArgs, " ")) + } + + return cmd +} + +func RequestIPFromSSH(m driver.Machine) string { + cmd := getSSHCommand(m, "ip addr show dev eth1") + + b, err := cmd.Output() + IP := "" + if err != nil { + fmt.Printf("%s", err) + } else { + out := string(b) + if B2D.Verbose { + fmt.Printf("SSH returned: %s\nEND SSH\n", out) + } + // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 + lines := strings.Split(out, "\n") + for _, line := range lines { + vals := strings.Split(strings.TrimSpace(line), " ") + if len(vals) >= 2 && vals[0] == "inet" { + IP = vals[1][:strings.Index(vals[1], "/")] + break + } + } + } + return IP +} + +func RequestSocketFromSSH(m driver.Machine) string { + cmd := getSSHCommand(m, "grep tcp:// /proc/$(cat /var/run/docker.pid)/cmdline") + + b, err := cmd.Output() + if err != nil { + fmt.Printf("%s", err) + } else { + out := string(b) + if B2D.Verbose { + fmt.Printf("SSH returned: %s\nEND SSH\n", out) + } + // Lets only use the first one - its possible to specify more than one... + lines := strings.Split(out, "\n") + tcpRE := regexp.MustCompile(`^(tcp://)(0.0.0.0)(:.*)`) + if s := tcpRE.FindStringSubmatch(lines[0]); s != nil { + IP := RequestIPFromSSH(m) + return s[1] + IP + s[3] + } + return lines[0] + } + return "" +} + // use the serial port socket to ask what the VM's host only IP is func RequestIPFromSerialPort(socket string) string { c, err := net.Dial("unix", socket) @@ -200,8 +260,8 @@ func RequestIPFromSerialPort(socket string) string { //go looking for the string we want, and chomp line to after the \n if i := strings.IndexAny(line, "\n"); i != -1 { // inet 10.180.1.3/16 brd 10.180.255.255 scope global wlan0 - inet := regexp.MustCompile(`^[\t ]*inet ([0-9.]*).*$`) - if ip := inet.FindStringSubmatch(line[:i]); ip != nil { + inetRE := regexp.MustCompile(`^[\t ]*inet ([0-9.]*).*$`) + if ip := inetRE.FindStringSubmatch(line[:i]); ip != nil { IP = ip[1] // clean up break @@ -222,3 +282,52 @@ func RequestIPFromSerialPort(socket string) string { return IP } + +// TODO: need to add or abstract to get a Serial coms version +func RequestCertsUsingSSH(m driver.Machine) string { + cmd := getSSHCommand(m, "tar c /home/docker/.docker/*.pem") + + b, err := cmd.Output() + if err != nil { + fmt.Printf("%s", err) + } else { + dir, err := cfgDir(".docker") + if err != nil { + return "" + } + + // Open the tar archive for reading. + r := bytes.NewReader(b) + tr := tar.NewReader(r) + + // Iterate through the files in the archive. + for { + hdr, err := tr.Next() + if err == io.EOF { + // end of tar archive + break + } + if err != nil { + fmt.Printf("%s", err) + return "" + } + filename := filepath.Base(hdr.Name) + certpath := filepath.Join(dir, filename) + fmt.Printf("Writing %s:\n", certpath) + // TODO: this is unsafe - would be better to put in ~/.docker/boot2docker/ + // sadly, last time i tested the CERT_PATH setting also wasn't reliable. + f, err := os.Create(certpath) + if err != nil { + fmt.Printf("%s", err) + return "" + } + w := bufio.NewWriter(f) + if _, err := io.Copy(w, tr); err != nil { + fmt.Printf("%s", err) + return "" + } + w.Flush() + } + } + return "OK" +} From 05b9c619a4075a2f4f35269ef4a501354410d2c9 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 15 Aug 2014 13:31:10 +1000 Subject: [PATCH 052/167] use a subdir to put the b2d certs into so we're less likely to annoy advanced users --- cmds.go | 28 ++++++++++++++++------------ driver/driver.go | 1 + dummy/machine.go | 5 +++++ util.go | 17 +++++++++++------ virtualbox/machine.go | 5 +++++ 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/cmds.go b/cmds.go index 58fabc2..46fc360 100644 --- a/cmds.go +++ b/cmds.go @@ -60,36 +60,40 @@ func cmdUp() error { } print("\n") - fmt.Printf("Started.") + fmt.Printf("Started.\n") if IP == "" { // lets try one more time time.Sleep(600 * time.Millisecond) - fmt.Printf(" Trying to get IP one more time") + fmt.Printf(" Trying to get IP one more time\n") IP = RequestIPFromSSH(m) } - _ = RequestCertsUsingSSH(m) + // Copying the certs here - someone might have have written a Windows API client. + certPath := RequestCertsUsingSSH(m) switch runtime.GOOS { case "windows": - fmt.Printf("Docker client does not run on Windows for now. Please use") - fmt.Printf(" \"%s\" ssh", os.Args[0]) - fmt.Printf("to SSH into the VM instead.") + fmt.Printf("Docker client does not run on Windows for now. Please use\n") + fmt.Printf(" \"%s\" ssh\n", os.Args[0]) + fmt.Printf("to SSH into the VM instead.\n") default: if IP == "" { - fmt.Fprintf(os.Stderr, "Auto detection of the VM's IP address failed.") - fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.") + fmt.Fprintf(os.Stderr, "Auto detection of the VM's IP address failed.\n") + fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.\n") } else { // Check if $DOCKER_HOST ENV var is properly configured. socket := RequestSocketFromSSH(m) - if os.Getenv("DOCKER_HOST") != socket { - fmt.Printf("To connect the Docker client to the Docker daemon, please set:") - fmt.Printf(" export DOCKER_HOST=%s", socket) + if os.Getenv("DOCKER_HOST") != socket || os.Getenv("DOCKER_CERT_PATH") != certPath { + fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") + fmt.Printf(" export DOCKER_HOST=%s\n", socket) + // Assume Docker 1.2.0 with TLS on... + fmt.Printf(" export DOCKER_CERT_PATH=%s\n", certPath) } else { - fmt.Printf("Your DOCKER_HOST env variable is already set correctly.") + fmt.Printf("Your DOCKER_HOST env variable is already set correctly.\n") } } } + fmt.Printf("\n") return nil } diff --git a/driver/driver.go b/driver/driver.go index db4f7aa..1111fc9 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -41,6 +41,7 @@ type Machine interface { DelStorageCtl(name string) error AttachStorage(ctlName string, medium StorageMedium) error GetState() MachineState + GetName() string GetSerialFile() string GetDockerPort() uint GetSSHPort() uint diff --git a/dummy/machine.go b/dummy/machine.go index ce38ce5..0c8d822 100644 --- a/dummy/machine.go +++ b/dummy/machine.go @@ -92,6 +92,11 @@ func (m *Machine) Reset() error { return nil } +// Get current name +func (m *Machine) GetName() string { + return m.Name +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State diff --git a/util.go b/util.go index b3be04d..b2c2ed4 100644 --- a/util.go +++ b/util.go @@ -287,6 +287,8 @@ func RequestIPFromSerialPort(socket string) string { func RequestCertsUsingSSH(m driver.Machine) string { cmd := getSSHCommand(m, "tar c /home/docker/.docker/*.pem") + certDir := "" + b, err := cmd.Output() if err != nil { fmt.Printf("%s", err) @@ -312,11 +314,14 @@ func RequestCertsUsingSSH(m driver.Machine) string { return "" } filename := filepath.Base(hdr.Name) - certpath := filepath.Join(dir, filename) - fmt.Printf("Writing %s:\n", certpath) - // TODO: this is unsafe - would be better to put in ~/.docker/boot2docker/ - // sadly, last time i tested the CERT_PATH setting also wasn't reliable. - f, err := os.Create(certpath) + certDir = filepath.Join(dir, m.GetName()) + if err := os.MkdirAll(certDir, 0755); err != nil { + fmt.Printf("%s", err) + return "" + } + certFile := filepath.Join(certDir, filename) + fmt.Printf("Writing %s:\n", certFile) + f, err := os.Create(certFile) if err != nil { fmt.Printf("%s", err) return "" @@ -329,5 +334,5 @@ func RequestCertsUsingSSH(m driver.Machine) string { w.Flush() } } - return "OK" + return certDir } diff --git a/virtualbox/machine.go b/virtualbox/machine.go index f488b76..e431a53 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -202,6 +202,11 @@ func (m *Machine) Delete() error { return vbm("unregistervm", m.Name, "--delete") } +// Get current state +func (m *Machine) GetName() string { + return m.Name +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State From c29f5187df0fab2a3ad6b38a1e9d706cf130735c Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 15 Aug 2014 16:09:49 +1000 Subject: [PATCH 053/167] Expand the github error message - and show the JSON payload if even that fails --- util.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/util.go b/util.go index b2c2ed4..5b5c894 100644 --- a/util.go +++ b/util.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "log" "net" "net/http" @@ -106,9 +107,21 @@ func getLatestReleaseName(url string) (string, error) { var t []struct { TagName string `json:"tag_name"` } - if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil { + body, err := ioutil.ReadAll(rsp.Body) + if err != nil { return "", err } + + if err := json.Unmarshal(body, &t); err != nil { + var e struct { + Message string + DocumentationUrl string + } + if err := json.Unmarshal(body, &e); err != nil { + return "", fmt.Errorf("Error decoding %s\nbody: %s", err, body) + } + return "", fmt.Errorf("Error getting releases: %s\n see %s", e.Message, e.DocumentationUrl) + } if len(t) == 0 { return "", fmt.Errorf("no releases found") } From 3489aa659df4f299cbec2f0195e4bd352fd08351 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 21 Aug 2014 11:00:27 +1000 Subject: [PATCH 054/167] bump to 1.2.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0f1acbd..79127d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.1.2 +v1.2.0 From 4cb66f02488cea28c6518f87823734e739b54119 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 21 Aug 2014 15:17:44 +1000 Subject: [PATCH 055/167] Fix script on Windows --- download.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/download.sh b/download.sh index cfa91af..1137abd 100644 --- a/download.sh +++ b/download.sh @@ -4,8 +4,9 @@ set -e # Set version to latest unless set by user if [ -z "$VERSION" ]; then - VERSION="1.0.1" + VERSION="1.1.2" fi +EXTENSION="" echo "Downloading version ${VERSION}..." @@ -14,13 +15,15 @@ UNAME=`uname -a` # Determine platform if [[ $UNAME == *"Darwin"* ]]; then PLATFORM="darwin" -elif [[ $UNAME == *"Cygwin"* ]]; then +elif [[ ($UNAME == *MINGW*) || ($UNAME == *Cygwin*) ]]; then PLATFORM="windows" + EXTENSION=".exe" + UNAME="${PROCESSOR_ARCHITEW6432}" else PLATFORM="linux" fi # Determine architecture -if [[ ($UNAME == *x86_64*) || ($UNAME == *amd64*) ]] +if [[ ($UNAME == *x86_64*) || ($UNAME == *amd64*) || ($UNAME == *AMD64*) ]] then ARCH="amd64" else @@ -30,9 +33,11 @@ else fi # Download binary -curl -L -o boot2docker "https://github.com/boot2docker/boot2docker-cli/releases/download/v${VERSION}/boot2docker-v${VERSION}-${PLATFORM}_${ARCH}" +URL="https://github.com/boot2docker/boot2docker-cli/releases/download/v${VERSION}/boot2docker-v${VERSION}-${PLATFORM}-${ARCH}${EXTENSION}" +echo "Downloading $URL" +curl -L -o "boot2docker${EXTENSION}" "$URL" # Make binary executable -chmod +x boot2docker +chmod +x "boot2docker${EXTENSION}" echo "Done." From 978ae5151ffa359d0a160ca1862b33470199cc52 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 21 Aug 2014 15:00:24 +1000 Subject: [PATCH 056/167] Don't error when failing to get certificates that may not be there --- cmds.go | 26 ++++++++++++++++++-------- util.go | 22 ++++++++-------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/cmds.go b/cmds.go index 46fc360..cb4472a 100644 --- a/cmds.go +++ b/cmds.go @@ -40,7 +40,7 @@ func cmdUp() error { return fmt.Errorf("Failed to start machine %q (run again with -v for details)", B2D.VM) } - fmt.Printf("Waiting for VM to be started...") + fmt.Println("Waiting for VM to be started...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket time.Sleep(600 * time.Millisecond) natSSH := fmt.Sprintf("localhost:%d", m.GetSSHPort()) @@ -70,7 +70,11 @@ func cmdUp() error { IP = RequestIPFromSSH(m) } // Copying the certs here - someone might have have written a Windows API client. - certPath := RequestCertsUsingSSH(m) + certPath, err := RequestCertsUsingSSH(m) + if err != nil && B2D.Verbose { + // These errors are not fatal + fmt.Printf("Error copying Certificates: %s\n", err) + } switch runtime.GOOS { case "windows": fmt.Printf("Docker client does not run on Windows for now. Please use\n") @@ -86,8 +90,14 @@ func cmdUp() error { if os.Getenv("DOCKER_HOST") != socket || os.Getenv("DOCKER_CERT_PATH") != certPath { fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") fmt.Printf(" export DOCKER_HOST=%s\n", socket) - // Assume Docker 1.2.0 with TLS on... - fmt.Printf(" export DOCKER_CERT_PATH=%s\n", certPath) + if certPath == "" { + if os.Getenv("DOCKER_CERT_PATH") != "" { + fmt.Println(" unset DOCKER_CERT_PATH") + } + } else { + // Assume Docker 1.2.0 with TLS on... + fmt.Printf(" export DOCKER_CERT_PATH=%s\n", certPath) + } } else { fmt.Printf("Your DOCKER_HOST env variable is already set correctly.\n") } @@ -104,7 +114,7 @@ func cmdConfig() error { return fmt.Errorf("Error working out Profile file location: %s", err) } filename := cfgFilename(dir) - fmt.Printf("boot2docker profile filename: %s", filename) + fmt.Printf("boot2docker profile filename: %s\n", filename) fmt.Println(printConfig()) return nil } @@ -304,18 +314,18 @@ func cmdIP() error { // Download the boot2docker ISO image. func cmdDownload() error { - fmt.Printf("Downloading boot2docker ISO image...") + fmt.Println("Downloading boot2docker ISO image...") url := "https://api.github.com/repos/boot2docker/boot2docker/releases" tag, err := getLatestReleaseName(url) if err != nil { return fmt.Errorf("Failed to get latest release: %s", err) } - fmt.Printf("Latest release is %s", tag) + fmt.Printf("Latest release is %s\n", tag) url = fmt.Sprintf("https://github.com/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", tag) if err := download(B2D.ISO, url); err != nil { return fmt.Errorf("Failed to download ISO image: %s", err) } - fmt.Printf("Success: downloaded %s\n\tto %s", url, B2D.ISO) + fmt.Printf("Success: downloaded %s\n\tto %s\n", url, B2D.ISO) return nil } diff --git a/util.go b/util.go index 5b5c894..cef893b 100644 --- a/util.go +++ b/util.go @@ -297,18 +297,16 @@ func RequestIPFromSerialPort(socket string) string { } // TODO: need to add or abstract to get a Serial coms version -func RequestCertsUsingSSH(m driver.Machine) string { +func RequestCertsUsingSSH(m driver.Machine) (string, error) { cmd := getSSHCommand(m, "tar c /home/docker/.docker/*.pem") certDir := "" b, err := cmd.Output() - if err != nil { - fmt.Printf("%s", err) - } else { + if err == nil { dir, err := cfgDir(".docker") if err != nil { - return "" + return "", err } // Open the tar archive for reading. @@ -323,29 +321,25 @@ func RequestCertsUsingSSH(m driver.Machine) string { break } if err != nil { - fmt.Printf("%s", err) - return "" + return "", err } filename := filepath.Base(hdr.Name) certDir = filepath.Join(dir, m.GetName()) if err := os.MkdirAll(certDir, 0755); err != nil { - fmt.Printf("%s", err) - return "" + return "", err } certFile := filepath.Join(certDir, filename) fmt.Printf("Writing %s:\n", certFile) f, err := os.Create(certFile) if err != nil { - fmt.Printf("%s", err) - return "" + return "", err } w := bufio.NewWriter(f) if _, err := io.Copy(w, tr); err != nil { - fmt.Printf("%s", err) - return "" + return "", err } w.Flush() } } - return certDir + return certDir, nil } From e66454cb4e3a6e6a74a25eb37180be252eb63553 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 20 Aug 2014 15:58:43 +1000 Subject: [PATCH 057/167] Need to allow the pflags and config to set both VBM and Verbose - this is the minimal change to make windows work --- virtualbox/machine.go | 8 ++++++++ virtualbox/vbm.go | 9 --------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index e431a53..c06f26f 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -38,6 +38,11 @@ const ( F_accelerate3d ) +var ( + VBM string // Path to VBoxManage utility. + Verbose bool // Verbose mode. +) + func init() { if err := driver.Register("virtualbox", InitFunc); err != nil { fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) @@ -47,6 +52,9 @@ func init() { // Initialize the Machine. func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { + VBM = mc.VBM + Verbose = mc.Verbose + m, err := GetMachine(mc.VM) if err != nil && mc.Init { return CreateMachine(mc) diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index e2d34df..773f63a 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -9,22 +9,13 @@ import ( "os/exec" "path/filepath" "regexp" - "runtime" "strings" "github.com/boot2docker/boot2docker-cli/driver" ) -var ( - VBM string // Path to VBoxManage utility. - Verbose bool // Verbose mode. -) func init() { - VBM = "VBoxManage" - if p := os.Getenv("VBOX_INSTALL_PATH"); p != "" && runtime.GOOS == "windows" { - VBM = filepath.Join(p, "VBoxManage.exe") - } } var ( From 751e7b9dc23fafc10c2d3947cf3f9e6a3cd6d91e Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 20 Aug 2014 16:48:15 +1000 Subject: [PATCH 058/167] Extract VirtualBox specific cfg parameters to the driver --- cmds.go | 8 +++--- config.go | 58 ++++++++++++++++++++++++++----------------- driver/config.go | 36 ++++++++++++++++++++++++--- driver/driver.go | 1 + virtualbox/machine.go | 30 +++++++++++++++++++--- 5 files changed, 99 insertions(+), 34 deletions(-) diff --git a/cmds.go b/cmds.go index 46fc360..6ee9468 100644 --- a/cmds.go +++ b/cmds.go @@ -101,10 +101,10 @@ func cmdUp() error { func cmdConfig() error { dir, err := cfgDir(".boot2docker") if err != nil { - return fmt.Errorf("Error working out Profile file location: %s", err) + return fmt.Errorf("Error working out Profile file location: %s\n", err) } filename := cfgFilename(dir) - fmt.Printf("boot2docker profile filename: %s", filename) + fmt.Printf("boot2docker profile filename: %s\n", filename) fmt.Println(printConfig()) return nil } @@ -113,10 +113,10 @@ func cmdConfig() error { func cmdSave() error { m, err := driver.GetMachine(&B2D) if err != nil { - return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) + return fmt.Errorf("Failed to get machine %q: %s\n", B2D.VM, err) } if err := m.Save(); err != nil { - return fmt.Errorf("Failed to save machine %q: %s", B2D.VM, err) + return fmt.Errorf("Failed to save machine %q: %s\n", B2D.VM, err) } return nil } diff --git a/config.go b/config.go index 33234a3..bfd806e 100644 --- a/config.go +++ b/config.go @@ -83,26 +83,45 @@ func config() (*flag.FlagSet, error) { flags := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) flags.Usage = func() { usageLong(flags) } + // Find out which driver we're usng and add its flags + flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") + flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") + + if err := flags.Parse([]string{}); err != nil { + return nil, err + } + // Over-ride from the profile file + filename := cfgFilename(B2D.Dir) + if _, err := os.Lstat(filename); err == nil { + if _, err := toml.DecodeFile(filename, &B2D); err != nil { + return nil, err + } + } + // for cmd==ssh only: + // only pass the params up to and including the `ssh` command - after that, + // there might be other -flags that are destined for the ssh cmd + sshIdx := 1 + for sshIdx < len(os.Args) && os.Args[sshIdx-1] != "ssh" { + sshIdx++ + } + // Command-line overrides profile config. + if err := flags.Parse(os.Args[1:sshIdx]); err != nil { + return nil, err + } + if B2D.Verbose { + fmt.Printf("Using %s driver\n", B2D.Driver) + } + driver.ConfigFlags(&B2D, flags) + + // Add the generic flags + flags.StringVar(&B2D.VM, "vm", "boot2docker-vm", "virtual machine name.") // removed for now, requires re-parsing a new config file which is too messy //flags.StringVarP(&B2D.Dir, "dir", "d", dir, "boot2docker config directory.") B2D.Dir = dir flags.StringVar(&B2D.ISO, "iso", filepath.Join(dir, "boot2docker.iso"), "path to boot2docker ISO image.") - flags.StringVar(&B2D.VMDK, "basevmdk", "", "Path to VMDK to use as base for persistent partition") - vbm := "VBoxManage" - if runtime.GOOS == "windows" { - p := "C:\\Program Files\\Oracle\\VirtualBox" - if t := os.Getenv("VBOX_INSTALL_PATH"); t != "" { - p = t - } else if t = os.Getenv("VBOX_MSI_INSTALL_PATH"); t != "" { - p = t - } - vbm = filepath.Join(p, "VBoxManage.exe") - } + flags.BoolVarP(&B2D.Init, "init", "i", false, "auto initialize vm instance.") - flags.StringVar(&B2D.VBM, "vbm", vbm, "path to VirtualBox management utility.") - flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") - flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") flags.StringVar(&B2D.SSH, "ssh", "ssh", "path to SSH client utility.") flags.StringVar(&B2D.SSHGen, "ssh-keygen", "ssh-keygen", "path to ssh-keygen utility.") @@ -132,22 +151,15 @@ func config() (*flag.FlagSet, error) { return nil, err } // Over-ride from the profile file - filename := cfgFilename(B2D.Dir) + //filename := cfgFilename(B2D.Dir) if _, err := os.Lstat(filename); err == nil { if _, err := toml.DecodeFile(filename, &B2D); err != nil { return nil, err } } - // for cmd==ssh only: - // only pass the params up to and including the `ssh` command - after that, - // there might be other -flags that are destined for the ssh cmd - i := 1 - for i < len(os.Args) && os.Args[i-1] != "ssh" { - i++ - } // Command-line overrides profile config. - if err := flags.Parse(os.Args[1:i]); err != nil { + if err := flags.Parse(os.Args[1:sshIdx]); err != nil { return nil, err } diff --git a/driver/config.go b/driver/config.go index 91a1884..292a8a5 100644 --- a/driver/config.go +++ b/driver/config.go @@ -1,13 +1,16 @@ package driver -import "net" +import ( + "fmt" + "net" + flag "github.com/ogier/pflag" +) // Machine config. type MachineConfig struct { // Gereral flags. Init bool Verbose bool - VBM string Driver string // basic config @@ -17,7 +20,6 @@ type MachineConfig struct { VM string // virtual machine name Dir string // boot2docker directory ISO string // boot2docker ISO image path - VMDK string // base VMDK to use as persistent disk DiskSize uint // VM disk image size (MB) Memory uint // VM memory size (MB) @@ -37,3 +39,31 @@ type MachineConfig struct { Serial bool SerialFile string } + +type ConfigFunc func(B2D *MachineConfig, flags *flag.FlagSet) (error) + +var ( + // All registred machines + configs map[string]ConfigFunc +) + +func init() { + configs = make(map[string]ConfigFunc) +} + +// optional - allows a driver to add its own commandline parameters +func RegisterConfig(driver string, configFunc ConfigFunc) error { + if _, exists := configs[driver]; exists { + return fmt.Errorf("Driver already registered %s", driver) + } + configs[driver] = configFunc + + return nil +} + +func ConfigFlags(B2D *MachineConfig, flags *flag.FlagSet) error { + if configFunc, exists := configs[B2D.Driver]; exists { + return configFunc(B2D, flags) + } + return nil +} diff --git a/driver/driver.go b/driver/driver.go index 1111fc9..1310cf5 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -75,3 +75,4 @@ func GetMachine(mc *MachineConfig) (Machine, error) { } return nil, ErrNotSupported } + diff --git a/virtualbox/machine.go b/virtualbox/machine.go index c06f26f..b03eb9e 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -15,6 +15,7 @@ import ( "time" "github.com/boot2docker/boot2docker-cli/driver" + flag "github.com/ogier/pflag" ) type Flag int @@ -40,7 +41,8 @@ const ( var ( VBM string // Path to VBoxManage utility. - Verbose bool // Verbose mode. + VMDK string // base VMDK to use as persistent disk. + Verbose bool // Verbose mode (Local copy of B2D.Verbose). ) func init() { @@ -48,11 +50,14 @@ func init() { fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) os.Exit(1) } + if err := driver.RegisterConfig("virtualbox", ConfigFlags); err != nil { + fmt.Fprintf(os.Stderr, "Failed to initialize driver config. Error : %s", err.Error()) + os.Exit(1) + } } // Initialize the Machine. func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { - VBM = mc.VBM Verbose = mc.Verbose m, err := GetMachine(mc.VM) @@ -62,6 +67,23 @@ func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { return m, err } +func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { + flags.StringVar(&VMDK, "basevmdk", "", "Path to VMDK to use as base for persistent partition") + vbm := "VBoxManage" + if runtime.GOOS == "windows" { + p := "C:\\Program Files\\Oracle\\VirtualBox" + if t := os.Getenv("VBOX_INSTALL_PATH"); t != "" { + p = t + } else if t = os.Getenv("VBOX_MSI_INSTALL_PATH"); t != "" { + p = t + } + vbm = filepath.Join(p, "VBoxManage.exe") + } + flags.StringVar(&VBM, "vbm", vbm, "path to VirtualBox management utility.") + + return nil +} + // Convert bool to "on"/"off" func bool2string(b bool) string { if b { @@ -433,8 +455,8 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { return m, err } - if mc.VMDK != "" { - if err := copyDiskImage(diskImg, mc.VMDK); err != nil { + if VMDK != "" { + if err := copyDiskImage(diskImg, VMDK); err != nil { return m, err } } else { From d0939274c0accfcc123eae0054460ebba33996c2 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 20 Aug 2014 16:57:17 +1000 Subject: [PATCH 059/167] yeah, don't need that line --- config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/config.go b/config.go index bfd806e..ee3d5d0 100644 --- a/config.go +++ b/config.go @@ -151,7 +151,6 @@ func config() (*flag.FlagSet, error) { return nil, err } // Over-ride from the profile file - //filename := cfgFilename(B2D.Dir) if _, err := os.Lstat(filename); err == nil { if _, err := toml.DecodeFile(filename, &B2D); err != nil { return nil, err From d01799898327c730e3d925f6ce51613c3fa6a93f Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 21 Aug 2014 09:51:42 +1000 Subject: [PATCH 060/167] address gmlewis's comments --- driver/config.go | 9 +++------ driver/driver.go | 1 - virtualbox/disk.go | 2 +- virtualbox/machine.go | 8 ++++---- virtualbox/vbm.go | 7 +++---- virtualbox/vbm_test.go | 2 +- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/driver/config.go b/driver/config.go index 292a8a5..314a715 100644 --- a/driver/config.go +++ b/driver/config.go @@ -2,8 +2,8 @@ package driver import ( "fmt" - "net" flag "github.com/ogier/pflag" + "net" ) // Machine config. @@ -40,12 +40,9 @@ type MachineConfig struct { SerialFile string } -type ConfigFunc func(B2D *MachineConfig, flags *flag.FlagSet) (error) +type ConfigFunc func(B2D *MachineConfig, flags *flag.FlagSet) error -var ( - // All registred machines - configs map[string]ConfigFunc -) +var configs map[string]ConfigFunc // optional map of driver ConfigFunc func init() { configs = make(map[string]ConfigFunc) diff --git a/driver/driver.go b/driver/driver.go index 1310cf5..1111fc9 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -75,4 +75,3 @@ func GetMachine(mc *MachineConfig) (Machine, error) { } return nil, ErrNotSupported } - diff --git a/virtualbox/disk.go b/virtualbox/disk.go index 988dae8..6e1d254 100644 --- a/virtualbox/disk.go +++ b/virtualbox/disk.go @@ -15,7 +15,7 @@ func MakeDiskImage(dest string, size uint, r io.Reader) error { cmd := exec.Command(VBM, "convertfromraw", "stdin", dest, fmt.Sprintf("%d", sizeBytes), "--format", "VMDK") - if Verbose { + if verbose { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr } diff --git a/virtualbox/machine.go b/virtualbox/machine.go index b03eb9e..7171bd0 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -41,8 +41,8 @@ const ( var ( VBM string // Path to VBoxManage utility. - VMDK string // base VMDK to use as persistent disk. - Verbose bool // Verbose mode (Local copy of B2D.Verbose). + VMDK string // base VMDK to use as persistent disk. + verbose bool // Verbose mode (Local copy of B2D.Verbose). ) func init() { @@ -58,7 +58,7 @@ func init() { // Initialize the Machine. func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { - Verbose = mc.Verbose + verbose = mc.Verbose m, err := GetMachine(mc.VM) if err != nil && mc.Init { @@ -417,7 +417,7 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { // Set NIC #1 to use NAT m.SetNIC(1, driver.NIC{Network: driver.NICNetNAT, Hardware: driver.VirtIO}) pfRules := map[string]driver.PFRule{ - "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: driver.SSHPort}, + "ssh": {Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.SSHPort, GuestPort: driver.SSHPort}, } if mc.DockerPort > 0 { pfRules["docker"] = driver.PFRule{Proto: driver.PFTCP, HostIP: net.ParseIP("127.0.0.1"), HostPort: mc.DockerPort, GuestPort: driver.DockerPort} diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index 773f63a..e1cd1c3 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -14,7 +14,6 @@ import ( "github.com/boot2docker/boot2docker-cli/driver" ) - func init() { } @@ -33,7 +32,7 @@ var ( func vbm(args ...string) error { cmd := exec.Command(VBM, args...) - if Verbose { + if verbose { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr log.Printf("executing: %v %v", VBM, strings.Join(args, " ")) @@ -49,7 +48,7 @@ func vbm(args ...string) error { func vbmOut(args ...string) (string, error) { cmd := exec.Command(VBM, args...) - if Verbose { + if verbose { cmd.Stderr = os.Stderr log.Printf("executing: %v %v", VBM, strings.Join(args, " ")) } @@ -65,7 +64,7 @@ func vbmOut(args ...string) (string, error) { func vbmOutErr(args ...string) (string, string, error) { cmd := exec.Command(VBM, args...) - if Verbose { + if verbose { log.Printf("executing: %v %v", VBM, strings.Join(args, " ")) } var stdout bytes.Buffer diff --git a/virtualbox/vbm_test.go b/virtualbox/vbm_test.go index 0355a11..2ebe150 100644 --- a/virtualbox/vbm_test.go +++ b/virtualbox/vbm_test.go @@ -5,7 +5,7 @@ import ( ) func init() { - Verbose = true + verbose = true } func TestVBMOut(t *testing.T) { From 51821eb4a23f4c6ee03abdefef88cd8e7660893f Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 21 Aug 2014 17:04:45 +1000 Subject: [PATCH 061/167] make setting up the DOCKER_HOST, and optionally DOCKER_CERT_PATH as easy as '' --- cmds.go | 51 +++++++++++++++++++++++++++++++++++++++------------ config.go | 3 ++- main.go | 2 ++ util.go | 5 +++++ 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/cmds.go b/cmds.go index 5a0e87d..88a95eb 100644 --- a/cmds.go +++ b/cmds.go @@ -73,7 +73,7 @@ func cmdUp() error { certPath, err := RequestCertsUsingSSH(m) if err != nil && B2D.Verbose { // These errors are not fatal - fmt.Printf("Error copying Certificates: %s\n", err) + fmt.Fprintf(os.Stderr, "Error copying Certificates: %s\n", err) } switch runtime.GOOS { case "windows": @@ -89,15 +89,7 @@ func cmdUp() error { socket := RequestSocketFromSSH(m) if os.Getenv("DOCKER_HOST") != socket || os.Getenv("DOCKER_CERT_PATH") != certPath { fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") - fmt.Printf(" export DOCKER_HOST=%s\n", socket) - if certPath == "" { - if os.Getenv("DOCKER_CERT_PATH") != "" { - fmt.Println(" unset DOCKER_CERT_PATH") - } - } else { - // Assume Docker 1.2.0 with TLS on... - fmt.Printf(" export DOCKER_CERT_PATH=%s\n", certPath) - } + printExport(socket, certPath) } else { fmt.Printf("Your DOCKER_HOST env variable is already set correctly.\n") } @@ -107,6 +99,41 @@ func cmdUp() error { return nil } +// Give the user the exact command to run to set the env. +func cmdShellInit() error { + m, err := driver.GetMachine(&B2D) + if err != nil { + return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) + } + + if m.GetState() != driver.Running { + return fmt.Errorf("VM %q is not running.", B2D.VM) + } + + socket := RequestSocketFromSSH(m) + + certPath, err := RequestCertsUsingSSH(m) + if err != nil && B2D.Verbose { + // These errors are not fatal + fmt.Fprintf(os.Stderr, "Error copying Certificates: %s\n", err) + } + printExport(socket, certPath) + + return nil +} + +func printExport(socket, certPath string) { + fmt.Printf(" export DOCKER_HOST=%s\n", socket) + if certPath == "" { + if os.Getenv("DOCKER_CERT_PATH") != "" { + fmt.Println(" unset DOCKER_CERT_PATH") + } + } else { + // Assume Docker 1.2.0 with TLS on... + fmt.Printf(" export DOCKER_CERT_PATH=%s\n", certPath) + } +} + // Tell the user the config (and later let them set it?) func cmdConfig() error { dir, err := cfgDir(".boot2docker") @@ -243,10 +270,10 @@ func cmdSocket() error { return fmt.Errorf("VM %q is not running.", B2D.VM) } - Socket := RequestSocketFromSSH(m) + socket := RequestSocketFromSSH(m) fmt.Fprintf(os.Stderr, "\n\t export DOCKER_HOST=") - fmt.Printf("%s", Socket) + fmt.Printf("%s", socket) fmt.Fprintf(os.Stderr, "\n\n") return nil diff --git a/config.go b/config.go index ee3d5d0..eb6bcb8 100644 --- a/config.go +++ b/config.go @@ -175,7 +175,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|socket|delete|destroy|download|version} []\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|socket|shellinit|delete|destroy|download|version} []\n", os.Args[0]) } func usageLong(flags *flag.FlagSet) { @@ -198,6 +198,7 @@ Commands: info Display detailed information of VM. ip Display the IP address of the VM's Host-only network. socket Display the DOCKER_HOST socket to connect to. + shellinit Display the Environment export shell command needed to set up the Docker client. status Display current state of VM. download Download boot2docker ISO image. upgrade Upgrade the boot2docker ISO image (if vm is running it will be stopped and started). diff --git a/main.go b/main.go index a72bf74..3594d8e 100644 --- a/main.go +++ b/main.go @@ -67,6 +67,8 @@ func run() error { return cmdInfo() case "socket": return cmdSocket() + case "shellinit": + return cmdShellInit() case "status": return cmdStatus() case "ssh": diff --git a/util.go b/util.go index cef893b..4db14c6 100644 --- a/util.go +++ b/util.go @@ -297,6 +297,11 @@ func RequestIPFromSerialPort(socket string) string { } // TODO: need to add or abstract to get a Serial coms version +// RequestCertsUsingSSH requests certs using SSH. +// The assumption is that if the certs are in b2d:/home/docker/.docker +// then the daemon is using TLS. We can't assume that because there are +// certs in the local host's user dir, that the server is using them, so +// for now, make sure things are updated from the server. (for `docker shellinit`) func RequestCertsUsingSSH(m driver.Machine) (string, error) { cmd := getSSHCommand(m, "tar c /home/docker/.docker/*.pem") From c9049a612686b102ba27037ab90a7476123b4469 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 22 Aug 2014 09:48:35 +1000 Subject: [PATCH 062/167] reflow the help to work ok on 80 char terminals --- config.go | 38 +++++++++++++++++++------------------- util.go | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/config.go b/config.go index eb6bcb8..e44a4a5 100644 --- a/config.go +++ b/config.go @@ -182,27 +182,27 @@ func usageLong(flags *flag.FlagSet) { // NOTE: the help message uses spaces, not tabs for indentation! fmt.Fprintf(os.Stderr, `Usage: %s [] [] -boot2docker management utility. +Boot2Docker management utility. Commands: - init Create a new boot2docker VM. - up|start|boot Start VM from any states. - ssh [ssh-command] Login to VM via SSH. - save|suspend Suspend VM and save state to disk. - down|stop|halt Gracefully shutdown the VM. - restart Gracefully reboot the VM. - poweroff Forcefully power off the VM (might corrupt disk image). - reset Forcefully power cycle the VM (might corrupt disk image). - delete|destroy Delete boot2docker VM and its disk image. - config|cfg Show selected profile file settings. - info Display detailed information of VM. - ip Display the IP address of the VM's Host-only network. - socket Display the DOCKER_HOST socket to connect to. - shellinit Display the Environment export shell command needed to set up the Docker client. - status Display current state of VM. - download Download boot2docker ISO image. - upgrade Upgrade the boot2docker ISO image (if vm is running it will be stopped and started). - version Display version information. + init Create a new Boot2Docker VM. + up|start|boot Start VM from any states. + ssh [ssh-command] Login to VM via SSH. + save|suspend Suspend VM and save state to disk. + down|stop|halt Gracefully shutdown the VM. + restart Gracefully reboot the VM. + poweroff Forcefully power off the VM (may corrupt disk image). + reset Forcefully power cycle the VM (may corrupt disk image). + delete|destroy Delete Boot2Docker VM and its disk image. + config|cfg Show selected profile file settings. + info Display detailed information of VM. + ip Display the IP address of the VM's Host-only network. + socket Display the DOCKER_HOST socket to connect to. + shellinit Display the shell command to set up the Docker client. + status Display current state of VM. + download Download Boot2Docker ISO image. + upgrade Upgrade the Boot2Docker ISO image (restart if running). + version Display version information. Options: `, os.Args[0]) diff --git a/util.go b/util.go index 4db14c6..cf4176b 100644 --- a/util.go +++ b/util.go @@ -297,7 +297,7 @@ func RequestIPFromSerialPort(socket string) string { } // TODO: need to add or abstract to get a Serial coms version -// RequestCertsUsingSSH requests certs using SSH. +// RequestCertsUsingSSH requests certs using SSH. // The assumption is that if the certs are in b2d:/home/docker/.docker // then the daemon is using TLS. We can't assume that because there are // certs in the local host's user dir, that the server is using them, so From 4b80b04e854be2dfb1ba06152dd581ad7fbcd013 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 22 Aug 2014 12:18:32 +1000 Subject: [PATCH 063/167] Add a sleep-loop to get the Docker daemon's tcp socket - the pid file isn't ready the first time we ask for it on one slower box I have --- cmds.go | 68 ++++++++++++++++++++++++++++++++++--------------- util.go | 79 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 87 insertions(+), 60 deletions(-) diff --git a/cmds.go b/cmds.go index 88a95eb..c9a1c30 100644 --- a/cmds.go +++ b/cmds.go @@ -40,34 +40,51 @@ func cmdUp() error { return fmt.Errorf("Failed to start machine %q (run again with -v for details)", B2D.VM) } - fmt.Println("Waiting for VM to be started...") + fmt.Println("Waiting for VM and Docker daemon to start...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket time.Sleep(600 * time.Millisecond) natSSH := fmt.Sprintf("localhost:%d", m.GetSSHPort()) IP := "" for i := 1; i < 30; i++ { + print(".") if B2D.Serial && runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { + if IP, err = RequestIPFromSerialPort(m.GetSerialFile()); err == nil { break } } - if err := read(natSSH, 1, 2*time.Second); err == nil { - IP = RequestIPFromSSH(m) - break + if err := read(natSSH, 1, 300*time.Millisecond); err == nil { + if IP, err = RequestIPFromSSH(m); err == nil { + break + } } + } + if B2D.Verbose { + fmt.Printf("VM Host-only IP address: %s", IP) + fmt.Printf("\nWaiting for Docker daemon to start...\n") + } + time.Sleep(300 * time.Millisecond) + socket := "" + for i := 1; i < 30; i++ { print(".") + if socket, err = RequestSocketFromSSH(m); err == nil { + break + } + if B2D.Verbose { + fmt.Printf("Error requesting socket: %s\n", err) + } + time.Sleep(300 * time.Millisecond) } - print("\n") + fmt.Printf("\nStarted.\n") - fmt.Printf("Started.\n") - - if IP == "" { + if socket == "" { // lets try one more time time.Sleep(600 * time.Millisecond) - fmt.Printf(" Trying to get IP one more time\n") + fmt.Printf(" Trying to get Docker socket one more time\n") - IP = RequestIPFromSSH(m) + if socket, err = RequestSocketFromSSH(m); err != nil { + fmt.Printf("Error requesting socket: %s\n", err) + } } // Copying the certs here - someone might have have written a Windows API client. certPath, err := RequestCertsUsingSSH(m) @@ -81,12 +98,11 @@ func cmdUp() error { fmt.Printf(" \"%s\" ssh\n", os.Args[0]) fmt.Printf("to SSH into the VM instead.\n") default: - if IP == "" { - fmt.Fprintf(os.Stderr, "Auto detection of the VM's IP address failed.\n") + if socket == "" { + fmt.Fprintf(os.Stderr, "Auto detection of the VM's Docker socket failed.\n") fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.\n") } else { // Check if $DOCKER_HOST ENV var is properly configured. - socket := RequestSocketFromSSH(m) if os.Getenv("DOCKER_HOST") != socket || os.Getenv("DOCKER_CERT_PATH") != certPath { fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") printExport(socket, certPath) @@ -110,7 +126,10 @@ func cmdShellInit() error { return fmt.Errorf("VM %q is not running.", B2D.VM) } - socket := RequestSocketFromSSH(m) + socket, err := RequestSocketFromSSH(m) + if err != nil { + return fmt.Errorf("Error requesting socket: %s\n", err) + } certPath, err := RequestCertsUsingSSH(m) if err != nil && B2D.Verbose { @@ -270,7 +289,10 @@ func cmdSocket() error { return fmt.Errorf("VM %q is not running.", B2D.VM) } - socket := RequestSocketFromSSH(m) + socket, err := RequestSocketFromSSH(m) + if err != nil { + return fmt.Errorf("Error requesting socket: %s\n", err) + } fmt.Fprintf(os.Stderr, "\n\t export DOCKER_HOST=") fmt.Printf("%s", socket) @@ -316,17 +338,21 @@ func cmdIP() error { IP := "" if B2D.Serial { - for i := 1; i < 20; i++ { - if runtime.GOOS != "windows" { - if IP = RequestIPFromSerialPort(m.GetSerialFile()); IP != "" { - break + if runtime.GOOS != "windows" { + if IP, err = RequestIPFromSerialPort(m.GetSerialFile()); err != nil { + if B2D.Verbose { + fmt.Printf("Error getting IP via Serial: %s\n", err) } } } } if IP == "" { - IP = RequestIPFromSSH(m) + if IP, err = RequestIPFromSSH(m); err != nil { + if B2D.Verbose { + fmt.Printf("Error getting IP via SSH: %s\n", err) + } + } } if IP != "" { fmt.Fprintf(os.Stderr, "\nThe VM's Host only interface IP address is: ") diff --git a/util.go b/util.go index 4db14c6..5f89931 100644 --- a/util.go +++ b/util.go @@ -189,60 +189,62 @@ func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { return cmd } -func RequestIPFromSSH(m driver.Machine) string { +func RequestIPFromSSH(m driver.Machine) (string, error) { cmd := getSSHCommand(m, "ip addr show dev eth1") b, err := cmd.Output() - IP := "" if err != nil { - fmt.Printf("%s", err) - } else { - out := string(b) - if B2D.Verbose { - fmt.Printf("SSH returned: %s\nEND SSH\n", out) - } - // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 - lines := strings.Split(out, "\n") - for _, line := range lines { - vals := strings.Split(strings.TrimSpace(line), " ") - if len(vals) >= 2 && vals[0] == "inet" { - IP = vals[1][:strings.Index(vals[1], "/")] - break - } + return "", err + } + out := string(b) + if B2D.Verbose { + fmt.Printf("SSH returned: %s\nEND SSH\n", out) + } + // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 + lines := strings.Split(out, "\n") + for _, line := range lines { + vals := strings.Split(strings.TrimSpace(line), " ") + if len(vals) >= 2 && vals[0] == "inet" { + return vals[1][:strings.Index(vals[1], "/")], nil } } - return IP + + return "", fmt.Errorf("No IP address found %s", out) } -func RequestSocketFromSSH(m driver.Machine) string { +func RequestSocketFromSSH(m driver.Machine) (string, error) { cmd := getSSHCommand(m, "grep tcp:// /proc/$(cat /var/run/docker.pid)/cmdline") b, err := cmd.Output() if err != nil { - fmt.Printf("%s", err) - } else { - out := string(b) - if B2D.Verbose { - fmt.Printf("SSH returned: %s\nEND SSH\n", out) - } - // Lets only use the first one - its possible to specify more than one... - lines := strings.Split(out, "\n") - tcpRE := regexp.MustCompile(`^(tcp://)(0.0.0.0)(:.*)`) - if s := tcpRE.FindStringSubmatch(lines[0]); s != nil { - IP := RequestIPFromSSH(m) - return s[1] + IP + s[3] + return "", err + } + out := string(b) + if B2D.Verbose { + fmt.Printf("SSH returned: %s\nEND SSH\n", out) + } + // Lets only use the first one - its possible to specify more than one... + lines := strings.Split(out, "\n") + tcpRE := regexp.MustCompile(`^(tcp://)(0.0.0.0)(:.*)`) + if s := tcpRE.FindStringSubmatch(lines[0]); s != nil { + IP, err := RequestIPFromSSH(m) + if err != nil { + return "", err } - return lines[0] + return s[1] + IP + s[3], nil + } + if !strings.HasPrefix(lines[0], "tcp://") { + return "", fmt.Errorf("Error requesting Docker Socket: %s", lines[0]) } - return "" + return lines[0], nil } // use the serial port socket to ask what the VM's host only IP is -func RequestIPFromSerialPort(socket string) string { +func RequestIPFromSerialPort(socket string) (string, error) { c, err := net.Dial("unix", socket) if err != nil { - return "" + return "", err } defer c.Close() c.SetDeadline(time.Now().Add(time.Second)) @@ -257,15 +259,14 @@ func RequestIPFromSerialPort(socket string) string { for IP == "" { _, err := c.Write([]byte("ip addr show dev eth1\r")) if err != nil { - println(err) - break + return "", err } time.Sleep(1 * time.Second) buf := make([]byte, 1024) for { n, err := c.Read(buf[:]) if err != nil { - return IP + return "", err } line = line + string(buf[0:n]) fullLog += string(buf[0:n]) @@ -293,11 +294,11 @@ func RequestIPFromSerialPort(socket string) string { fmt.Printf(fullLog) } - return IP + return IP, nil } // TODO: need to add or abstract to get a Serial coms version -// RequestCertsUsingSSH requests certs using SSH. +// RequestCertsUsingSSH requests certs using SSH. // The assumption is that if the certs are in b2d:/home/docker/.docker // then the daemon is using TLS. We can't assume that because there are // certs in the local host's user dir, that the server is using them, so From d7b0e1b495cdc36f7a06be24e0bf1ceef9d556f3 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 22 Aug 2014 21:05:56 +1000 Subject: [PATCH 064/167] The multi-hypervisor refactor lost the ssh key creation code. --- cmds.go | 24 ++++++++++++++++++++++++ util.go | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index c9a1c30..9f5b6b6 100644 --- a/cmds.go +++ b/cmds.go @@ -4,7 +4,9 @@ import ( "encoding/json" "fmt" "os" + "os/exec" "runtime" + "strings" "time" _ "github.com/boot2docker/boot2docker-cli/dummy" @@ -15,6 +17,28 @@ import ( // Initialize the boot2docker VM from scratch. func cmdInit() error { + + if _, err := os.Stat(B2D.SSHKey); err != nil { + if !os.IsNotExist(err) { + return fmt.Errorf("Something wrong with SSH Key file %q: %s", B2D.SSHKey, err) + } + + cmd := exec.Command(B2D.SSHGen, "-t", "rsa", "-N", "", "-f", B2D.SSHKey) + if B2D.Verbose { + cmd.Stderr = os.Stderr + fmt.Printf("executing: %v %v", cmd.Path, strings.Join(cmd.Args, " ")) + } + b, err := cmd.Output() + if err != nil { + return fmt.Errorf("Error generating new SSH Key into %s: %s", B2D.SSHKey, err) + } + out := string(b) + if B2D.Verbose { + fmt.Printf("%s returned: %s\nEND\n", B2D.SSHKey, out) + } + } + //TODO: print a ~/.ssh/config entry for our b2d connection that the user can c&p + B2D.Init = true _, err := driver.GetMachine(&B2D) if err != nil { diff --git a/util.go b/util.go index 5f89931..19f245f 100644 --- a/util.go +++ b/util.go @@ -183,7 +183,7 @@ func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { cmd := exec.Command(B2D.SSH, sshArgs...) if B2D.Verbose { cmd.Stderr = os.Stderr - log.Printf("executing: %v %v", B2D.SSH, strings.Join(sshArgs, " ")) + log.Printf("executing: %v %v", cmd.Path, strings.Join(cmd.Args, " ")) } return cmd From d660b11078bb4cc56f66668bf3ee0162dc94cf82 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 22 Aug 2014 23:00:37 +1000 Subject: [PATCH 065/167] Bring back the Download code as before (and simplify the ssh key gen to be more like before) --- cmds.go | 31 +++++++++++++++++++++++-------- config.go | 7 ++++++- virtualbox/machine.go | 4 ++++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/cmds.go b/cmds.go index 9f5b6b6..d0a4675 100644 --- a/cmds.go +++ b/cmds.go @@ -17,6 +17,22 @@ import ( // Initialize the boot2docker VM from scratch. func cmdInit() error { + B2D.Init = false + _, err := driver.GetMachine(&B2D) + if err == nil { + fmt.Printf("Virtual machine %s already exists\n", B2D.VM) + return nil + } + + if _, err := os.Stat(B2D.ISO); err != nil { + if !os.IsNotExist(err) { + return fmt.Errorf("Failed to open ISO image %q: %s", B2D.ISO, err) + } + + if err := cmdDownload(); err != nil { + return err + } + } if _, err := os.Stat(B2D.SSHKey); err != nil { if !os.IsNotExist(err) { @@ -24,23 +40,22 @@ func cmdInit() error { } cmd := exec.Command(B2D.SSHGen, "-t", "rsa", "-N", "", "-f", B2D.SSHKey) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr if B2D.Verbose { cmd.Stderr = os.Stderr - fmt.Printf("executing: %v %v", cmd.Path, strings.Join(cmd.Args, " ")) + fmt.Printf("executing: %v %v\n", cmd.Path, strings.Join(cmd.Args, " ")) } - b, err := cmd.Output() - if err != nil { + + if err := cmd.Run(); err != nil { return fmt.Errorf("Error generating new SSH Key into %s: %s", B2D.SSHKey, err) } - out := string(b) - if B2D.Verbose { - fmt.Printf("%s returned: %s\nEND\n", B2D.SSHKey, out) - } } //TODO: print a ~/.ssh/config entry for our b2d connection that the user can c&p B2D.Init = true - _, err := driver.GetMachine(&B2D) + _, err = driver.GetMachine(&B2D) if err != nil { return fmt.Errorf("Failed to initialize machine %q: %s", B2D.VM, err) } diff --git a/config.go b/config.go index e44a4a5..0a45b13 100644 --- a/config.go +++ b/config.go @@ -121,7 +121,12 @@ func config() (*flag.FlagSet, error) { B2D.Dir = dir flags.StringVar(&B2D.ISO, "iso", filepath.Join(dir, "boot2docker.iso"), "path to boot2docker ISO image.") - flags.BoolVarP(&B2D.Init, "init", "i", false, "auto initialize vm instance.") + // Sven disabled this, as it is broken - if I user with a fresh computer downloads + // just the boot2docker-cli, and then runs `boot2docker --init ip`, we create a vm + // which cannot run, because it fails to have have the boot2docker.iso and the ssh keys + B2D.Init = false + //flags.BoolVarP(&B2D.Init, "init", "i", false, "auto initialize vm instance.") + flags.StringVar(&B2D.SSH, "ssh", "ssh", "path to SSH client utility.") flags.StringVar(&B2D.SSHGen, "ssh-keygen", "ssh-keygen", "path to ssh-keygen utility.") diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 7171bd0..183a37d 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -503,6 +503,10 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { if err := makeDiskImage(diskImg, mc.DiskSize, buf.Bytes()); err != nil { return m, err } + if verbose { + fmt.Println("Initializing disk with ssh keys") + fmt.Printf("WRITING: %s\n-----\n", buf) + } } } From 23621ad0f20de49a951742cd0e1cbd3cf33e9fc4 Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 25 Aug 2014 12:47:17 -0700 Subject: [PATCH 066/167] Update machine.go --- virtualbox/machine.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 183a37d..0ffcf59 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -393,7 +393,11 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { // Configure VM for Boot2docker SetExtra(mc.VM, "VBoxInternal/CPUM/EnableHVP", "1") m.OSType = "Linux26_64" - m.CPUs = uint(runtime.NumCPU()) + cpus := uint(runtime.NumCPU()) + if cpus > 32 { + cpus = 32 + } + m.CPUs = cpus m.Memory = mc.Memory m.SerialFile = mc.SerialFile From bbf3cf809b661fe71507e5772a97cf85f355379d Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 25 Aug 2014 22:06:18 -0700 Subject: [PATCH 067/167] max cpu cap of 32 --- virtualbox/machine.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 0ffcf59..99b7f2b 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -393,11 +393,10 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { // Configure VM for Boot2docker SetExtra(mc.VM, "VBoxInternal/CPUM/EnableHVP", "1") m.OSType = "Linux26_64" - cpus := uint(runtime.NumCPU()) - if cpus > 32 { - cpus = 32 + m.CPUs = uint(runtime.NumCPU()) + if m.CPUs > 32 { + m.CPUs = 32 } - m.CPUs = cpus m.Memory = mc.Memory m.SerialFile = mc.SerialFile From 1a8a97404696993b3c366ad956e32f828cfb0f9c Mon Sep 17 00:00:00 2001 From: Danny Lockard Date: Tue, 26 Aug 2014 23:36:48 -0500 Subject: [PATCH 068/167] This makes cli arguments other than verbose and driver function again. (cherry picked from commit d066c7b7a8f409ca935b486d887a133e91068e86) --- config.go | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/config.go b/config.go index 0a45b13..ce6f5c7 100644 --- a/config.go +++ b/config.go @@ -97,17 +97,6 @@ func config() (*flag.FlagSet, error) { return nil, err } } - // for cmd==ssh only: - // only pass the params up to and including the `ssh` command - after that, - // there might be other -flags that are destined for the ssh cmd - sshIdx := 1 - for sshIdx < len(os.Args) && os.Args[sshIdx-1] != "ssh" { - sshIdx++ - } - // Command-line overrides profile config. - if err := flags.Parse(os.Args[1:sshIdx]); err != nil { - return nil, err - } if B2D.Verbose { fmt.Printf("Using %s driver\n", B2D.Driver) } @@ -162,11 +151,6 @@ func config() (*flag.FlagSet, error) { } } - // Command-line overrides profile config. - if err := flags.Parse(os.Args[1:sshIdx]); err != nil { - return nil, err - } - if B2D.SerialFile == "" { if runtime.GOOS == "windows" { //SerialFile ~~ filepath.Join(dir, B2D.vm+".sock") @@ -175,6 +159,17 @@ func config() (*flag.FlagSet, error) { B2D.SerialFile = filepath.Join(dir, B2D.VM+".sock") } } + // for cmd==ssh only: + // only pass the params up to and including the `ssh` command - after that, + // there might be other -flags that are destined for the ssh cmd + sshIdx := 1 + for sshIdx < len(os.Args) && os.Args[sshIdx-1] != "ssh" { + sshIdx++ + } + // Command-line overrides profile config. + if err := flags.Parse(os.Args[1:sshIdx]); err != nil { + return nil, err + } return flags, nil } From 362f11ec54dc124496eed45a2ed58be6f87e2ce2 Mon Sep 17 00:00:00 2001 From: Danny Lockard Date: Tue, 26 Aug 2014 17:12:47 -0500 Subject: [PATCH 069/167] Fixes the priority of defaults -> configfile -> cli arguments (cherry picked from commit a55a8abd4d643c9875687cbc32e3f5a983431a55) Conflicts: config.go --- config.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/config.go b/config.go index ce6f5c7..fcdd671 100644 --- a/config.go +++ b/config.go @@ -90,13 +90,6 @@ func config() (*flag.FlagSet, error) { if err := flags.Parse([]string{}); err != nil { return nil, err } - // Over-ride from the profile file - filename := cfgFilename(B2D.Dir) - if _, err := os.Lstat(filename); err == nil { - if _, err := toml.DecodeFile(filename, &B2D); err != nil { - return nil, err - } - } if B2D.Verbose { fmt.Printf("Using %s driver\n", B2D.Driver) } @@ -145,6 +138,7 @@ func config() (*flag.FlagSet, error) { return nil, err } // Over-ride from the profile file + filename := cfgFilename(B2D.Dir) if _, err := os.Lstat(filename); err == nil { if _, err := toml.DecodeFile(filename, &B2D); err != nil { return nil, err From 59fd7e476ff99392679053c1e9f92f774f985f9a Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Mon, 1 Sep 2014 13:28:31 +1000 Subject: [PATCH 070/167] Tell us the version when users show us debug logs --- config.go | 6 ++++++ main.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/config.go b/config.go index 0a45b13..3a18e2a 100644 --- a/config.go +++ b/config.go @@ -176,6 +176,12 @@ func config() (*flag.FlagSet, error) { } } + leftovers := flags.Args() + + if B2D.Verbose || (len(leftovers) > 0 && leftovers[0] == "version") { + fmt.Printf("Boot2Docker-cli version: %s\nGit commit: %s\n", Version, GitSHA) + } + return flags, nil } diff --git a/main.go b/main.go index 3594d8e..d062da2 100644 --- a/main.go +++ b/main.go @@ -78,7 +78,7 @@ func run() error { case "upgrade": return cmdUpgrade() case "version": - fmt.Printf("Client version: %s\nGit commit: %s\n", Version, GitSHA) + // Version is now printed by the call to config() return nil case "help": flags.Usage() From 387619804d2c3fb83b31fe23f8801ae380c61850 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 28 Aug 2014 11:08:50 +1000 Subject: [PATCH 071/167] Unconditionally load the flags for all drivers. --- config.go | 12 ++---------- driver/config.go | 8 ++++++-- dummy/machine.go | 25 +++++++++++++++++++++++++ virtualbox/disk.go | 2 +- virtualbox/machine.go | 26 +++++++++++++++++--------- virtualbox/vbm.go | 12 ++++++------ 6 files changed, 57 insertions(+), 28 deletions(-) diff --git a/config.go b/config.go index fcdd671..99db276 100644 --- a/config.go +++ b/config.go @@ -83,16 +83,6 @@ func config() (*flag.FlagSet, error) { flags := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) flags.Usage = func() { usageLong(flags) } - // Find out which driver we're usng and add its flags - flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") - flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") - - if err := flags.Parse([]string{}); err != nil { - return nil, err - } - if B2D.Verbose { - fmt.Printf("Using %s driver\n", B2D.Driver) - } driver.ConfigFlags(&B2D, flags) // Add the generic flags @@ -109,6 +99,8 @@ func config() (*flag.FlagSet, error) { B2D.Init = false //flags.BoolVarP(&B2D.Init, "init", "i", false, "auto initialize vm instance.") + flags.BoolVarP(&B2D.Verbose, "verbose", "v", false, "display verbose command invocations.") + flags.StringVar(&B2D.Driver, "driver", "virtualbox", "hypervisor driver.") flags.StringVar(&B2D.SSH, "ssh", "ssh", "path to SSH client utility.") flags.StringVar(&B2D.SSHGen, "ssh-keygen", "ssh-keygen", "path to ssh-keygen utility.") diff --git a/driver/config.go b/driver/config.go index 314a715..5d11167 100644 --- a/driver/config.go +++ b/driver/config.go @@ -38,6 +38,8 @@ type MachineConfig struct { // Serial console pipe/socket Serial bool SerialFile string + + DriverCfg map[string]interface{} } type ConfigFunc func(B2D *MachineConfig, flags *flag.FlagSet) error @@ -59,8 +61,10 @@ func RegisterConfig(driver string, configFunc ConfigFunc) error { } func ConfigFlags(B2D *MachineConfig, flags *flag.FlagSet) error { - if configFunc, exists := configs[B2D.Driver]; exists { - return configFunc(B2D, flags) + for _, configFunc := range configs { + if err := configFunc(B2D, flags); err != nil { + return err + } } return nil } diff --git a/dummy/machine.go b/dummy/machine.go index 0c8d822..cfc3f1d 100644 --- a/dummy/machine.go +++ b/dummy/machine.go @@ -5,6 +5,17 @@ import ( "os" "github.com/boot2docker/boot2docker-cli/driver" + flag "github.com/ogier/pflag" +) + +type DriverCfg struct { + DummyParam string // Example string for dummy driver + hiddenParam string +} + +var ( + verbose bool // Verbose mode (Local copy of B2D.Verbose). + cfg DriverCfg ) func init() { @@ -12,14 +23,28 @@ func init() { fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) os.Exit(1) } + if err := driver.RegisterConfig("dummy", ConfigFlags); err != nil { + fmt.Fprintf(os.Stderr, "Failed to initialize driver config. Error : %s", err.Error()) + os.Exit(1) + } } // Initialize the Machine. func InitFunc(i *driver.MachineConfig) (driver.Machine, error) { + verbose = i.Verbose + fmt.Printf("Init dummy %s\n", i.VM) return &Machine{Name: i.VM, State: driver.Poweroff}, nil } +// Add cmdline params for this driver +func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { + //B2D.DriverCfg["dummy"] = cfg + flags.StringVar(&cfg.DummyParam, "no-dummy", "", "Example parameter for the dummy driver.") + + return nil +} + // Machine information. type Machine struct { Name string diff --git a/virtualbox/disk.go b/virtualbox/disk.go index 6e1d254..d67703a 100644 --- a/virtualbox/disk.go +++ b/virtualbox/disk.go @@ -12,7 +12,7 @@ import ( func MakeDiskImage(dest string, size uint, r io.Reader) error { // Convert a raw image from stdin to the dest VMDK image. sizeBytes := int64(size) << 20 // usually won't fit in 32-bit int (max 2GB) - cmd := exec.Command(VBM, "convertfromraw", "stdin", dest, + cmd := exec.Command(cfg.VBM, "convertfromraw", "stdin", dest, fmt.Sprintf("%d", sizeBytes), "--format", "VMDK") if verbose { diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 99b7f2b..c69f5a6 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -39,10 +39,14 @@ const ( F_accelerate3d ) +type DriverCfg struct { + VBM string // Path to VBoxManage utility. + VMDK string // base VMDK to use as persistent disk. +} + var ( - VBM string // Path to VBoxManage utility. - VMDK string // base VMDK to use as persistent disk. - verbose bool // Verbose mode (Local copy of B2D.Verbose). + verbose bool // Verbose mode (Local copy of B2D.Verbose). + cfg DriverCfg ) func init() { @@ -67,9 +71,13 @@ func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { return m, err } +// Add cmdline params for this driver func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { - flags.StringVar(&VMDK, "basevmdk", "", "Path to VMDK to use as base for persistent partition") - vbm := "VBoxManage" + //B2D.DriverCfg["virtualbox"] = cfg + + flags.StringVar(&cfg.VMDK, "basevmdk", "", "Path to VMDK to use as base for persistent partition") + + cfg.VBM = "VBoxManage" if runtime.GOOS == "windows" { p := "C:\\Program Files\\Oracle\\VirtualBox" if t := os.Getenv("VBOX_INSTALL_PATH"); t != "" { @@ -77,9 +85,9 @@ func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { } else if t = os.Getenv("VBOX_MSI_INSTALL_PATH"); t != "" { p = t } - vbm = filepath.Join(p, "VBoxManage.exe") + cfg.VBM = filepath.Join(p, "VBoxManage.exe") } - flags.StringVar(&VBM, "vbm", vbm, "path to VirtualBox management utility.") + flags.StringVar(&cfg.VBM, "vbm", cfg.VBM, "path to VirtualBox management utility.") return nil } @@ -458,8 +466,8 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { return m, err } - if VMDK != "" { - if err := copyDiskImage(diskImg, VMDK); err != nil { + if cfg.VMDK != "" { + if err := copyDiskImage(diskImg, cfg.VMDK); err != nil { return m, err } } else { diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index e1cd1c3..641c071 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -31,11 +31,11 @@ var ( ) func vbm(args ...string) error { - cmd := exec.Command(VBM, args...) + cmd := exec.Command(cfg.VBM, args...) if verbose { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - log.Printf("executing: %v %v", VBM, strings.Join(args, " ")) + log.Printf("executing: %v %v", cfg.VBM, strings.Join(args, " ")) } if err := cmd.Run(); err != nil { if ee, ok := err.(*exec.Error); ok && ee == exec.ErrNotFound { @@ -47,10 +47,10 @@ func vbm(args ...string) error { } func vbmOut(args ...string) (string, error) { - cmd := exec.Command(VBM, args...) + cmd := exec.Command(cfg.VBM, args...) if verbose { cmd.Stderr = os.Stderr - log.Printf("executing: %v %v", VBM, strings.Join(args, " ")) + log.Printf("executing: %v %v", cfg.VBM, strings.Join(args, " ")) } b, err := cmd.Output() @@ -63,9 +63,9 @@ func vbmOut(args ...string) (string, error) { } func vbmOutErr(args ...string) (string, string, error) { - cmd := exec.Command(VBM, args...) + cmd := exec.Command(cfg.VBM, args...) if verbose { - log.Printf("executing: %v %v", VBM, strings.Join(args, " ")) + log.Printf("executing: %v %v", cfg.VBM, strings.Join(args, " ")) } var stdout bytes.Buffer var stderr bytes.Buffer From 5ecb1b77553cd75ac648e49c0a5783397a94e692 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 2 Sep 2014 15:41:11 +1000 Subject: [PATCH 072/167] Lets upgrade all running, saved and paused vm's and restart them, and also tell the user if there was an error. --- cmds.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cmds.go b/cmds.go index d0a4675..4f4ebdd 100644 --- a/cmds.go +++ b/cmds.go @@ -244,16 +244,18 @@ func cmdPoweroff() error { // Upgrade the boot2docker ISO - preserving server state func cmdUpgrade() error { m, err := driver.GetMachine(&B2D) - if err == nil && m.GetState() == driver.Running { - // Windows won't let us move the ISO aside while it's in use - if cmdStop() == nil && cmdDownload() == nil { - return cmdUp() - } else { - return nil + if err == nil { + if m.GetState() == driver.Running || m.GetState() == driver.Saved || m.GetState() == driver.Paused { + // Windows won't let us move the ISO aside while it's in use + if err = cmdStop(); err == nil { + if err = cmdDownload(); err == nil { + err = cmdUp() + } + } + return err } - } else { - return cmdDownload() } + return cmdDownload() } // Gracefully stop and then start the VM. From 133528cc496dc65cdb73ec84b4397a4f5845648a Mon Sep 17 00:00:00 2001 From: shalecraig Date: Thu, 4 Sep 2014 00:21:13 -0700 Subject: [PATCH 073/167] Set OS X and Windows in consistent order. ...pedantic mode: activated. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5209203..423bbf6 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ connect to the boot2docker VM using `boot2docker.exe ssh`. Signed installers are available for [Mac OS X](http://github.com/boot2docker/osx-installer/releases) and [Windows](http://github.com/boot2docker/windows-installer/releases). -Refer to the installation instructions for [Windows](http://docs.docker.io/installation/windows/) and [Mac OS X](http://docs.docker.io/installation/mac/). +Refer to the installation instructions for [Mac OS X](http://docs.docker.io/installation/mac/) and [Windows](http://docs.docker.io/installation/windows/). ### Manual Installation From febce42693c3d0dbb36b70ffd4f62c779e49db50 Mon Sep 17 00:00:00 2001 From: Joey Geiger Date: Fri, 12 Sep 2014 14:27:08 -0600 Subject: [PATCH 074/167] Fix typos in README.md Fix typos in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 423bbf6..dc15748 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Refer to the installation instructions for [Mac OS X](http://docs.docker.io/inst ### Pre-compiled binaries -You can dowload binary releases at https://github.com/boot2docker/boot2docker-cli/releases +You can download binary releases at https://github.com/boot2docker/boot2docker-cli/releases ### Docker container build @@ -122,7 +122,7 @@ The `boot2docker` binary reads configuration from `$BOOT2DOCKER_PROFILE` if set, `$BOOT2DOCKER_DIR/profile` or `$HOME/.boot2docker/profile` or (on Windows) `%USERPROFILE%/.boot2docker/profile`. `boot2docker config` will tell you where it is looking for the file, and will also output the settings that -are in use, so you can initialise a default file to customise using +are in use, so you can initialise a default file to customize using `boot2docker config > /home/sven/.boot2docker/profile`. Currently you can configure the following options (undefined options take From 6437b11992b62f4c9798f761ec74ed708070ae12 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Mon, 15 Sep 2014 11:10:41 +1000 Subject: [PATCH 075/167] Add 'upgrade' and remove the duplicate 'destroy' --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 99db276..fcd0d0e 100644 --- a/config.go +++ b/config.go @@ -161,7 +161,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|socket|shellinit|delete|destroy|download|version} []\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|socket|shellinit|delete|download|upgrade|version} []\n", os.Args[0]) } func usageLong(flags *flag.FlagSet) { From b161571c698b2f34203faa56cb7465b893650129 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 17 Sep 2014 16:12:33 -0600 Subject: [PATCH 076/167] Add VirtualBox shared folders creation This includes a new commandline flag to control this behavior, for those who don't want the default (which is currently automount `/Users` for OS X, and automount `C:\Users` for Windows, but will change to automount `homeDir()` at some point in the future). The commandline flag (`--vbox-share=shareDirectory[=shareLabel]`) defines a series of essentially key-value pairs for VirtualBox shared folders in the format `shareDirectory[=shareLabel]`, where `shareLabel` becomes the in-guest mount location (and it defaults to the value of `shareDirectory`). It also supports `--vbox-share=disable` in order to explicitly disable any automatic sharing. --- virtualbox/machine.go | 83 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index c69f5a6..ff5b8d4 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -42,8 +42,14 @@ const ( type DriverCfg struct { VBM string // Path to VBoxManage utility. VMDK string // base VMDK to use as persistent disk. + + shares shareSlice + + // see also func ConfigFlags later in this file } +var shareDefault string // set in ConfigFlags - this is what gets filled in for "shares" if it's empty + var ( verbose bool // Verbose mode (Local copy of B2D.Verbose). cfg DriverCfg @@ -71,6 +77,37 @@ func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { return m, err } +type shareSlice map[string]string + +const shareSliceSep = "=" + +func (s shareSlice) String() string { + var ret []string + for name, dir := range s { + ret = append(ret, fmt.Sprintf("%s%s%s", dir, shareSliceSep, name)) + } + return fmt.Sprintf("[%s]", strings.Join(ret, " ")) +} + +func (s *shareSlice) Set(shareDir string) error { + var shareName string + if i := strings.Index(shareDir, shareSliceSep); i >= 0 { + shareName = shareDir[i+1:] + shareDir = shareDir[:i] + } + if shareName == "" { + // parts of the VBox internal code are buggy with share names that start with "/" + shareName = strings.TrimLeft(shareDir, "/") + // TODO do some basic Windows -> MSYS path conversion + // ie, s!^([a-z]+):[/\\]+!\1/!; s!\\!/!g + } + if *s == nil { + *s = shareSlice{} + } + (*s)[shareName] = shareDir + return nil +} + // Add cmdline params for this driver func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { //B2D.DriverCfg["virtualbox"] = cfg @@ -89,6 +126,21 @@ func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { } flags.StringVar(&cfg.VBM, "vbm", cfg.VBM, "path to VirtualBox management utility.") + // TODO once boot2docker improves, replace this all with homeDir() from config.go so we only share the current user's HOME by default + shareDefault = "disable" + switch runtime.GOOS { + case "darwin": + shareDefault = "/Users" + shareSliceSep + "Users" + case "windows": + shareDefault = "C:\\Users" + shareSliceSep + "c/Users" + } + + var defaultText string + if shareDefault != "disable" { + defaultText = "(defaults to '" + shareDefault + "' if no shares are specified; use 'disable' to explicitly prevent any shares from being created) " + } + flags.Var(&cfg.shares, "vbox-share", fmt.Sprintf("%sList of directories to share during 'init' via VirtualBox Guest Additions, with optional labels", defaultText)) + return nil } @@ -525,6 +577,37 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { return m, err } + // let VBoxService do nice magic automounting (when it's used) + if err := vbm("guestproperty", "set", mc.VM, "/VirtualBox/GuestAdd/SharedFolders/MountPrefix", "/"); err != nil { + return nil, err + } + if err := vbm("guestproperty", "set", mc.VM, "/VirtualBox/GuestAdd/SharedFolders/MountDir", "/"); err != nil { + return nil, err + } + + // set up some shared folders as appropriate + if len(cfg.shares) == 0 { + cfg.shares.Set(shareDefault) + } + for shareName, shareDir := range cfg.shares { + if shareDir == "disable" { + continue + } + if _, err := os.Stat(shareDir); err != nil { + return nil, err + } + + // woo, shareDir exists! let's carry on! + if err := vbm("sharedfolder", "add", mc.VM, "--name", shareName, "--hostpath", shareDir, "--automount"); err != nil { + return nil, err + } + + // enable symlinks + if err := vbm("setextradata", mc.VM, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/"+shareName, "1"); err != nil { + return nil, err + } + } + return m, nil } From 364fedeb5e5cf2f0ce1669b4185a9460b81cedf6 Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Wed, 24 Sep 2014 14:48:34 -0700 Subject: [PATCH 077/167] Output location line in profile as a comment --- cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index d0a4675..f82c979 100644 --- a/cmds.go +++ b/cmds.go @@ -199,7 +199,7 @@ func cmdConfig() error { return fmt.Errorf("Error working out Profile file location: %s\n", err) } filename := cfgFilename(dir) - fmt.Printf("boot2docker profile filename: %s\n", filename) + fmt.Printf("# boot2docker profile filename: %s\n", filename) fmt.Println(printConfig()) return nil } From 6cc72c4c5343ac7cab310a0ceee8fae126d8b938 Mon Sep 17 00:00:00 2001 From: Brice Jaglin Date: Mon, 6 Oct 2014 19:59:07 +0200 Subject: [PATCH 078/167] Make the source URL for the b2d ISO customizable --- README.md | 7 +++++++ cmds.go | 21 ++++++++++++++------- config.go | 1 + driver/config.go | 1 + 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dc15748..5d7048a 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,13 @@ SSHKey = "/Users/sven/.ssh/id_boot2docker" # name of boot2docker virtual machine VM = "boot2docker-vm" +# URL pointing either to a Github "/releases" API endpoint to automatically +# retrieve the `boot2docker.iso` asset from the latest released version of a +# repo, or directly to an ISO image +ISOURL = "https://api.github.com/repos/boot2docker/boot2docker/releases" +#ISOURL = "https://github.com/boot2docker/boot2docker/releases/download/v1.0.0/boot2docker.iso" +#ISOURL = "https://internal.corp.org/b2d.iso" + # path to boot2docker ISO image ISO = "/Users/sven/.boot2docker/boot2docker.iso" diff --git a/cmds.go b/cmds.go index f82c979..fb0bac9 100644 --- a/cmds.go +++ b/cmds.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "os/exec" + "regexp" "runtime" "strings" "time" @@ -406,15 +407,21 @@ func cmdIP() error { // Download the boot2docker ISO image. func cmdDownload() error { - fmt.Println("Downloading boot2docker ISO image...") - url := "https://api.github.com/repos/boot2docker/boot2docker/releases" - tag, err := getLatestReleaseName(url) - if err != nil { - return fmt.Errorf("Failed to get latest release: %s", err) + url := B2D.ISOURL + + re := regexp.MustCompile("https://api.github.com/repos/([^/]+)/([^/]+)/releases") + if matches := re.FindStringSubmatch(url); len(matches) == 3 { + tag, err := getLatestReleaseName(url) + if err != nil { + return fmt.Errorf("Failed to get latest release: %s", err) + } + org := matches[1] + repo := matches[2] + fmt.Printf("Latest release for %s/%s is %s\n", org, repo, tag) + url = fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/boot2docker.iso", org, repo, tag) } - fmt.Printf("Latest release is %s\n", tag) - url = fmt.Sprintf("https://github.com/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", tag) + fmt.Println("Downloading boot2docker ISO image...") if err := download(B2D.ISO, url); err != nil { return fmt.Errorf("Failed to download ISO image: %s", err) } diff --git a/config.go b/config.go index 99db276..2a3e90e 100644 --- a/config.go +++ b/config.go @@ -91,6 +91,7 @@ func config() (*flag.FlagSet, error) { // removed for now, requires re-parsing a new config file which is too messy //flags.StringVarP(&B2D.Dir, "dir", "d", dir, "boot2docker config directory.") B2D.Dir = dir + flags.StringVar(&B2D.ISOURL, "iso-url", "https://api.github.com/repos/boot2docker/boot2docker/releases", "source URL to provision the boot2docker ISO image.") flags.StringVar(&B2D.ISO, "iso", filepath.Join(dir, "boot2docker.iso"), "path to boot2docker ISO image.") // Sven disabled this, as it is broken - if I user with a fresh computer downloads diff --git a/driver/config.go b/driver/config.go index 5d11167..5133485 100644 --- a/driver/config.go +++ b/driver/config.go @@ -19,6 +19,7 @@ type MachineConfig struct { SSHKey string // SSH key to send to the vm VM string // virtual machine name Dir string // boot2docker directory + ISOURL string // Source URL to retrieve the ISO from ISO string // boot2docker ISO image path DiskSize uint // VM disk image size (MB) Memory uint // VM memory size (MB) From 98dac35da505dc5052461f172a8497c0dc740811 Mon Sep 17 00:00:00 2001 From: Shaun Donnelly Date: Fri, 10 Oct 2014 15:10:18 +0100 Subject: [PATCH 079/167] Corrected a spelling mistake. --- cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index ca813d6..9d191cd 100644 --- a/cmds.go +++ b/cmds.go @@ -402,7 +402,7 @@ func cmdIP() error { fmt.Fprintf(os.Stderr, "\n\n") } else { fmt.Fprintf(os.Stderr, "\nFailed to get VM Host only IP address.\n") - fmt.Fprintf(os.Stderr, "\tWas the VM initilized using boot2docker?\n") + fmt.Fprintf(os.Stderr, "\tWas the VM initialized using boot2docker?\n") } return nil } From af5ee8a9566cee2b1c960daf77be1faad15b588a Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Fri, 10 Oct 2014 20:57:57 +0100 Subject: [PATCH 080/167] Instruct user to set DOCKER_TLS_VERIFY Signed-off-by: Aanand Prasad --- cmds.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmds.go b/cmds.go index 9d191cd..628d4c8 100644 --- a/cmds.go +++ b/cmds.go @@ -190,6 +190,7 @@ func printExport(socket, certPath string) { } else { // Assume Docker 1.2.0 with TLS on... fmt.Printf(" export DOCKER_CERT_PATH=%s\n", certPath) + fmt.Printf(" export DOCKER_TLS_VERIFY=1\n") } } From 6059db4799096c3838f0ac1b2ccd28e7822dea6c Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Mon, 13 Oct 2014 11:14:06 +0100 Subject: [PATCH 081/167] Wait a bit longer for VM to boot because we're generating certs. Signed-off-by: Ben Firshman --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index 9d191cd..633bed3 100644 --- a/cmds.go +++ b/cmds.go @@ -103,7 +103,7 @@ func cmdUp() error { fmt.Printf("\nWaiting for Docker daemon to start...\n") } - time.Sleep(300 * time.Millisecond) + time.Sleep(600 * time.Millisecond) socket := "" for i := 1; i < 30; i++ { print(".") @@ -113,7 +113,7 @@ func cmdUp() error { if B2D.Verbose { fmt.Printf("Error requesting socket: %s\n", err) } - time.Sleep(300 * time.Millisecond) + time.Sleep(600 * time.Millisecond) } fmt.Printf("\nStarted.\n") From c6c5382ae5ac0b82c035ccb60f930849e0b78c78 Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Mon, 13 Oct 2014 11:14:52 +0100 Subject: [PATCH 082/167] Print errors when copying certs fails Signed-off-by: Ben Firshman --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index 633bed3..dafbb33 100644 --- a/cmds.go +++ b/cmds.go @@ -128,7 +128,7 @@ func cmdUp() error { } // Copying the certs here - someone might have have written a Windows API client. certPath, err := RequestCertsUsingSSH(m) - if err != nil && B2D.Verbose { + if err != nil { // These errors are not fatal fmt.Fprintf(os.Stderr, "Error copying Certificates: %s\n", err) } @@ -172,7 +172,7 @@ func cmdShellInit() error { } certPath, err := RequestCertsUsingSSH(m) - if err != nil && B2D.Verbose { + if err != nil { // These errors are not fatal fmt.Fprintf(os.Stderr, "Error copying Certificates: %s\n", err) } From a992801cf88c430cd3845f786b95ab1578074e7f Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Mon, 13 Oct 2014 11:42:05 +0100 Subject: [PATCH 083/167] Store certs in ~/.boot2docker/certs We don't want to clutter up ~/.docker. Signed-off-by: Ben Firshman --- util.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/util.go b/util.go index 19f245f..817757a 100644 --- a/util.go +++ b/util.go @@ -310,11 +310,13 @@ func RequestCertsUsingSSH(m driver.Machine) (string, error) { b, err := cmd.Output() if err == nil { - dir, err := cfgDir(".docker") + dir, err := cfgDir(".boot2docker") if err != nil { return "", err } + certDir = filepath.Join(dir, "certs", m.GetName()) + // Open the tar archive for reading. r := bytes.NewReader(b) tr := tar.NewReader(r) @@ -330,7 +332,6 @@ func RequestCertsUsingSSH(m driver.Machine) (string, error) { return "", err } filename := filepath.Base(hdr.Name) - certDir = filepath.Join(dir, m.GetName()) if err := os.MkdirAll(certDir, 0755); err != nil { return "", err } From fc4f7d36b66379875d266eecce35e46cf37823d6 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Mon, 13 Oct 2014 15:28:10 +0100 Subject: [PATCH 084/167] Send debug output to stderr when copying certs --- util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.go b/util.go index 19f245f..d5169d6 100644 --- a/util.go +++ b/util.go @@ -335,7 +335,7 @@ func RequestCertsUsingSSH(m driver.Machine) (string, error) { return "", err } certFile := filepath.Join(certDir, filename) - fmt.Printf("Writing %s:\n", certFile) + fmt.Fprintf(os.Stderr, "Writing %s\n", certFile) f, err := os.Create(certFile) if err != nil { return "", err From 75e6af82a933dafa990c653effa10adf498207a3 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Mon, 13 Oct 2014 14:57:10 +0100 Subject: [PATCH 085/167] Check all necessary environment variables If any of DOCKER_HOST, DOCKER_CERT_PATH or DOCKER_TLS_VERIFY are incorrect, `boot2docker up` will inform the user, and `boot2docker shellinit` will output the correct commands to set/unset them. Signed-off-by: Aanand Prasad --- cmds.go | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/cmds.go b/cmds.go index 628d4c8..46cba1a 100644 --- a/cmds.go +++ b/cmds.go @@ -142,12 +142,12 @@ func cmdUp() error { fmt.Fprintf(os.Stderr, "Auto detection of the VM's Docker socket failed.\n") fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.\n") } else { - // Check if $DOCKER_HOST ENV var is properly configured. - if os.Getenv("DOCKER_HOST") != socket || os.Getenv("DOCKER_CERT_PATH") != certPath { + // Check if $DOCKER_* ENV vars are properly configured. + if !checkEnvironment(socket, certPath) { fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") printExport(socket, certPath) } else { - fmt.Printf("Your DOCKER_HOST env variable is already set correctly.\n") + fmt.Printf("Your environment variables are already set correctly.\n") } } } @@ -181,17 +181,41 @@ func cmdShellInit() error { return nil } +func checkEnvironment(socket, certPath string) bool { + for name, value := range exports(socket, certPath) { + if os.Getenv(name) != value { + return false + } + } + + return true +} + func printExport(socket, certPath string) { - fmt.Printf(" export DOCKER_HOST=%s\n", socket) - if certPath == "" { - if os.Getenv("DOCKER_CERT_PATH") != "" { - fmt.Println(" unset DOCKER_CERT_PATH") + for name, value := range exports(socket, certPath) { + if os.Getenv(name) != value { + if value == "" { + fmt.Printf(" unset %s\n", name) + } else { + fmt.Printf(" export %s=%s\n", name, value) + } } + } +} + +func exports(socket, certPath string) map[string]string { + out := make(map[string]string) + + out["DOCKER_HOST"] = socket + out["DOCKER_CERT_PATH"] = certPath + + if certPath == "" { + out["DOCKER_TLS_VERIFY"] = "" } else { - // Assume Docker 1.2.0 with TLS on... - fmt.Printf(" export DOCKER_CERT_PATH=%s\n", certPath) - fmt.Printf(" export DOCKER_TLS_VERIFY=1\n") + out["DOCKER_TLS_VERIFY"] = "1" } + + return out } // Tell the user the config (and later let them set it?) From 3f3dcebb5d7c5a997400cc62f2743f73af329b3e Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Mon, 13 Oct 2014 19:18:02 +0100 Subject: [PATCH 086/167] Set up virtualbox shares on start Previously they were set up on create, but this meant that they would not be created when boot2docker was upgraded. Signed-off-by: Ben Firshman --- virtualbox/machine.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index ff5b8d4..951d255 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -135,12 +135,6 @@ func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { shareDefault = "C:\\Users" + shareSliceSep + "c/Users" } - var defaultText string - if shareDefault != "disable" { - defaultText = "(defaults to '" + shareDefault + "' if no shares are specified; use 'disable' to explicitly prevent any shares from being created) " - } - flags.Var(&cfg.shares, "vbox-share", fmt.Sprintf("%sList of directories to share during 'init' via VirtualBox Guest Additions, with optional labels", defaultText)) - return nil } @@ -195,6 +189,9 @@ func (m *Machine) Start() error { case driver.Paused: return vbm("controlvm", m.Name, "resume") case driver.Poweroff, driver.Saved, driver.Aborted: + if err := m.setUpShares(); err != nil { + return err + } return vbm("startvm", m.Name, "--type", "headless") } if err := m.Refresh(); err == nil { @@ -577,12 +574,16 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { return m, err } + return m, nil +} + +func (m *Machine) setUpShares() error { // let VBoxService do nice magic automounting (when it's used) - if err := vbm("guestproperty", "set", mc.VM, "/VirtualBox/GuestAdd/SharedFolders/MountPrefix", "/"); err != nil { - return nil, err + if err := vbm("guestproperty", "set", m.Name, "/VirtualBox/GuestAdd/SharedFolders/MountPrefix", "/"); err != nil { + return err } - if err := vbm("guestproperty", "set", mc.VM, "/VirtualBox/GuestAdd/SharedFolders/MountDir", "/"); err != nil { - return nil, err + if err := vbm("guestproperty", "set", m.Name, "/VirtualBox/GuestAdd/SharedFolders/MountDir", "/"); err != nil { + return err } // set up some shared folders as appropriate @@ -594,21 +595,20 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { continue } if _, err := os.Stat(shareDir); err != nil { - return nil, err + return err } // woo, shareDir exists! let's carry on! - if err := vbm("sharedfolder", "add", mc.VM, "--name", shareName, "--hostpath", shareDir, "--automount"); err != nil { - return nil, err + if err := vbm("sharedfolder", "add", m.Name, "--name", shareName, "--hostpath", shareDir, "--automount"); err != nil { + return err } // enable symlinks - if err := vbm("setextradata", mc.VM, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/"+shareName, "1"); err != nil { - return nil, err + if err := vbm("setextradata", m.Name, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/"+shareName, "1"); err != nil { + return err } } - - return m, nil + return nil } // Modify changes the settings of the machine. From 4711cbbfbe97abaaccd355085658b563fa28dfda Mon Sep 17 00:00:00 2001 From: Cyrill Schumacher Date: Tue, 14 Oct 2014 14:00:53 +1100 Subject: [PATCH 087/167] [FIX] Description for --vbox-share. Instead of "during init" it is during "up" command. --- virtualbox/machine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 0037130..20bfcf3 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -139,7 +139,7 @@ func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { if shareDefault != "disable" { defaultText = "(defaults to '" + shareDefault + "' if no shares are specified; use 'disable' to explicitly prevent any shares from being created) " } - flags.Var(&cfg.shares, "vbox-share", fmt.Sprintf("%sList of directories to share during 'init' via VirtualBox Guest Additions, with optional labels", defaultText)) + flags.Var(&cfg.shares, "vbox-share", fmt.Sprintf("%sList of directories to share during 'up|start|boot' via VirtualBox Guest Additions, with optional labels", defaultText)) return nil } From 09ed623e918605ffe8d4166b8ce66358bac47971 Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Mon, 13 Oct 2014 11:47:17 +0100 Subject: [PATCH 088/167] Bump to version 1.3.0 Signed-off-by: Ben Firshman --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 79127d8..18fa8e7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.2.0 +v1.3.0 From ba304c999004f532e9b1cda501ac1c2390090636 Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Tue, 14 Oct 2014 12:49:36 +0100 Subject: [PATCH 089/167] Only create 4 ports on storage controller As noted in this comment: https://github.com/boot2docker/boot2docker-cli/commit/9935fda0d9ad944f8f5cabba23c21655a65cd298#commitcomment-8148801 This speeds up boot by ~10 seconds. Signed-off-by: Ben Firshman --- virtualbox/machine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 20bfcf3..1f753a3 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -506,7 +506,7 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { } // Set VM storage - if err := m.AddStorageCtl("SATA", driver.StorageController{SysBus: driver.SysBusSATA, HostIOCache: true, Bootable: true}); err != nil { + if err := m.AddStorageCtl("SATA", driver.StorageController{SysBus: driver.SysBusSATA, HostIOCache: true, Bootable: true, Ports: 4}); err != nil { return m, err } From 24240adda1246c5396a269e9100df9a72af9eab3 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 14 Oct 2014 13:16:02 -0600 Subject: [PATCH 090/167] Add error message copy edits from #270 --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index 1924a37..0215d73 100644 --- a/cmds.go +++ b/cmds.go @@ -130,7 +130,7 @@ func cmdUp() error { certPath, err := RequestCertsUsingSSH(m) if err != nil { // These errors are not fatal - fmt.Fprintf(os.Stderr, "Error copying Certificates: %s\n", err) + fmt.Fprintf(os.Stderr, "Warning: error copying certificates: %s\n", err) } switch runtime.GOOS { case "windows": @@ -174,7 +174,7 @@ func cmdShellInit() error { certPath, err := RequestCertsUsingSSH(m) if err != nil { // These errors are not fatal - fmt.Fprintf(os.Stderr, "Error copying Certificates: %s\n", err) + fmt.Fprintf(os.Stderr, "Warning: error copying certificates: %s\n", err) } printExport(socket, certPath) From fa47d2c2c28cacd72f0eacd4096fdbe245e9056c Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 14 Oct 2014 14:41:01 -0600 Subject: [PATCH 091/167] Add max-tries logic to Stop() --- virtualbox/machine.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 1f753a3..2009d01 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -241,7 +241,8 @@ func (m *Machine) Stop() error { } } - for m.State != driver.Poweroff { // busy wait until the machine is stopped + // busy wait until the machine is stopped + for i := 0; i < 10; i++ { if err := vbm("controlvm", m.Name, "acpipowerbutton"); err != nil { return err } @@ -249,8 +250,12 @@ func (m *Machine) Stop() error { if err := m.Refresh(); err != nil { return err } + if m.State == driver.Poweroff { + return nil + } } - return nil + + return fmt.Errorf("timed out waiting for VM to stop") } // Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. From aebab75b6b091b87c2481ded02a14171ac07b18e Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 15 Oct 2014 15:54:05 +1000 Subject: [PATCH 092/167] roll back first attempt to deal with cert generation taking too long, replace with extra retries and add cmdline flag in case someone has a much slower system --- cmds.go | 14 +++++++------- config.go | 3 +++ driver/config.go | 4 ++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/cmds.go b/cmds.go index 0215d73..c13312b 100644 --- a/cmds.go +++ b/cmds.go @@ -82,17 +82,17 @@ func cmdUp() error { fmt.Println("Waiting for VM and Docker daemon to start...") //give the VM a little time to start, so we don't kill the Serial Pipe/Socket - time.Sleep(600 * time.Millisecond) + time.Sleep(time.Duration(B2D.Waittime) * time.Millisecond) natSSH := fmt.Sprintf("localhost:%d", m.GetSSHPort()) IP := "" - for i := 1; i < 30; i++ { + for i := 1; i < B2D.Retries; i++ { print(".") if B2D.Serial && runtime.GOOS != "windows" { if IP, err = RequestIPFromSerialPort(m.GetSerialFile()); err == nil { break } } - if err := read(natSSH, 1, 300*time.Millisecond); err == nil { + if err := read(natSSH, 1, time.Duration(B2D.Waittime)*time.Millisecond); err == nil { if IP, err = RequestIPFromSSH(m); err == nil { break } @@ -103,10 +103,10 @@ func cmdUp() error { fmt.Printf("\nWaiting for Docker daemon to start...\n") } - time.Sleep(600 * time.Millisecond) + time.Sleep(time.Duration(B2D.Waittime) * time.Millisecond) socket := "" - for i := 1; i < 30; i++ { - print(".") + for i := 1; i < B2D.Retries; i++ { + print("o") if socket, err = RequestSocketFromSSH(m); err == nil { break } @@ -119,7 +119,7 @@ func cmdUp() error { if socket == "" { // lets try one more time - time.Sleep(600 * time.Millisecond) + time.Sleep(time.Duration(B2D.Waittime) * time.Millisecond) fmt.Printf(" Trying to get Docker socket one more time\n") if socket, err = RequestSocketFromSSH(m); err != nil { diff --git a/config.go b/config.go index 94cbe9d..3e9b97f 100644 --- a/config.go +++ b/config.go @@ -118,6 +118,9 @@ func config() (*flag.FlagSet, error) { flags.IPVar(&B2D.LowerIP, "lowerip", net.ParseIP("192.168.59.103"), "VirtualBox host-only network DHCP lower bound.") flags.IPVar(&B2D.UpperIP, "upperip", net.ParseIP("192.168.59.254"), "VirtualBox host-only network DHCP upper bound.") + flags.IntVar(&B2D.Waittime, "waittime", 300, "Time in milliseconds to wait between port knocking retries during 'start'") + flags.IntVar(&B2D.Retries, "retries", 40, "number of port knocking retries during 'start'") + if runtime.GOOS != "windows" { //SerialFile ~~ filepath.Join(dir, B2D.vm+".sock") flags.StringVar(&B2D.SerialFile, "serialfile", "", "path to the serial socket/pipe.") diff --git a/driver/config.go b/driver/config.go index 5133485..eeeed4a 100644 --- a/driver/config.go +++ b/driver/config.go @@ -40,6 +40,10 @@ type MachineConfig struct { Serial bool SerialFile string + // boot2docker init retry settings + Waittime int + Retries int + DriverCfg map[string]interface{} } From 7a29dc17030cfc1de21191b396aff3a3a1e3684e Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 15 Oct 2014 11:53:22 -0600 Subject: [PATCH 093/167] Update port references everywhere to the new SSL port --- README.md | 6 +++--- config.go | 2 +- driver/config.go | 2 +- driver/driver.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5d7048a..693a13e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ login via SSH. On Windows, [MSYS SSH](http://www.mingw.org/) provides a first class way to connect to the boot2docker VM using `boot2docker.exe ssh`. -> **Note:** Docker now has an [IANA registered IP Port: 2375]( http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=docker) +> **Note:** Docker now has an [IANA registered IP Port: 2376]( http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=docker) > , so the use of port 4243 is deprecated. This also means that new Boot2Docker > ISO releases and management tool are not compatible. @@ -161,8 +161,8 @@ Memory = 2048 # host port forwarding to port 22 in the VM SSHPort = 2022 -# host port forwarding to port 2375 in the VM -DockerPort = 2375 +# host port forwarding to port 2376 in the VM +DockerPort = 2376 # host-only network host IP HostIP = "192.168.59.3" diff --git a/config.go b/config.go index 94cbe9d..77c7a7f 100644 --- a/config.go +++ b/config.go @@ -110,7 +110,7 @@ func config() (*flag.FlagSet, error) { flags.UintVarP(&B2D.DiskSize, "disksize", "s", 20000, "boot2docker disk image size (in MB).") flags.UintVarP(&B2D.Memory, "memory", "m", 2048, "virtual machine memory size (in MB).") flags.Uint16Var(&B2D.SSHPort, "sshport", 2022, "host SSH port (forward to port 22 in VM).") - flags.Uint16Var(&B2D.DockerPort, "dockerport", 0, "host Docker port (forward to port 2375 in VM). (deprecated - use with care)") + flags.Uint16Var(&B2D.DockerPort, "dockerport", 0, "host Docker port (forward to port 2376 in VM). (deprecated - use with care)") flags.IPVar(&B2D.HostIP, "hostip", net.ParseIP("192.168.59.3"), "VirtualBox host-only network IP address.") flags.IPMaskVar(&B2D.NetMask, "netmask", flag.ParseIPv4Mask("255.255.255.0"), "VirtualBox host-only network mask.") flags.BoolVar(&B2D.DHCPEnabled, "dhcp", true, "enable VirtualBox host-only network DHCP.") diff --git a/driver/config.go b/driver/config.go index 5133485..e37b10d 100644 --- a/driver/config.go +++ b/driver/config.go @@ -26,7 +26,7 @@ type MachineConfig struct { // NAT network: port forwarding SSHPort uint16 // host SSH port (forward to port 22 in VM) - DockerPort uint16 // host Docker port (forward to port 2375 in VM) + DockerPort uint16 // host Docker port (forward to port 2376 in VM) // host-only network HostIP net.IP diff --git a/driver/driver.go b/driver/driver.go index 1111fc9..9b5524a 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -12,7 +12,7 @@ type MachineState string const ( // Known ports SSHPort = 22 - DockerPort = 2375 + DockerPort = 2376 // VM states Poweroff = MachineState("poweroff") From dd4e58ac22d5ff7c7dcef749f16cb17876f95d2b Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 15 Oct 2014 12:03:14 -0600 Subject: [PATCH 094/167] Bump retries up to 75 for extra insanity See https://github.com/boot2docker/boot2docker-cli/pull/281#issuecomment-59186440 --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 3e9b97f..fd5f861 100644 --- a/config.go +++ b/config.go @@ -119,7 +119,7 @@ func config() (*flag.FlagSet, error) { flags.IPVar(&B2D.UpperIP, "upperip", net.ParseIP("192.168.59.254"), "VirtualBox host-only network DHCP upper bound.") flags.IntVar(&B2D.Waittime, "waittime", 300, "Time in milliseconds to wait between port knocking retries during 'start'") - flags.IntVar(&B2D.Retries, "retries", 40, "number of port knocking retries during 'start'") + flags.IntVar(&B2D.Retries, "retries", 75, "number of port knocking retries during 'start'") if runtime.GOOS != "windows" { //SerialFile ~~ filepath.Join(dir, B2D.vm+".sock") From 62208228f88fd899ad134ec21637e8364ae7aecd Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 15 Oct 2014 09:59:25 -0600 Subject: [PATCH 095/167] Update default ISO path to prefer an ISO that's next to the boot2docker CLI binary This is especially important for places like the Windows installer, where we want people to be able to install boot2docker 1.3 from an installer, and it includes the right ISO, so when they boot their VM, it should also be boot2docker 1.3, without any extra work or extra downloading. --- config.go | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/config.go b/config.go index 94cbe9d..8ec7363 100644 --- a/config.go +++ b/config.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "os" + "os/exec" "path/filepath" "regexp" "runtime" @@ -61,6 +62,36 @@ func cfgFilename(dir string) string { return filename } +func defaultIsoPath(dir string) string { + var err error + + iso := filepath.Join(dir, "boot2docker.iso") + + exe := os.Args[0] + if filepath.Base(exe) == exe { + // this logic borrowed from reexec/reexec.go in Docker itself :) + if lp, err := exec.LookPath(exe); err == nil { + exe = lp + } + } + + if exe, err = filepath.Abs(exe); err != nil { + return iso + } + + if exe, err = filepath.EvalSymlinks(exe); err != nil { + return iso + } + + // if there's a "boot2docker.iso" next to our boot2docker-cli executable, let's prefer that one by default + exeIso := filepath.Join(filepath.Dir(exe), "boot2docker.iso") + if _, err = os.Stat(exeIso); err == nil { + return exeIso + } + + return iso +} + // Write configuration set by the combination of profile and flags // Should result in a format that can be piped into a profile file func printConfig() string { @@ -92,7 +123,7 @@ func config() (*flag.FlagSet, error) { //flags.StringVarP(&B2D.Dir, "dir", "d", dir, "boot2docker config directory.") B2D.Dir = dir flags.StringVar(&B2D.ISOURL, "iso-url", "https://api.github.com/repos/boot2docker/boot2docker/releases", "source URL to provision the boot2docker ISO image.") - flags.StringVar(&B2D.ISO, "iso", filepath.Join(dir, "boot2docker.iso"), "path to boot2docker ISO image.") + flags.StringVar(&B2D.ISO, "iso", defaultIsoPath(dir), "path to boot2docker ISO image.") // Sven disabled this, as it is broken - if I user with a fresh computer downloads // just the boot2docker-cli, and then runs `boot2docker --init ip`, we create a vm From 233e4075dbe62e9953d25607f6831db0c626926c Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Tue, 30 Sep 2014 23:14:06 -0700 Subject: [PATCH 096/167] Add Fusion driver and vmx template --- cmds.go | 1 + vmware/machine.go | 234 ++++++++++++++++++++++++++++++++++++++++++++++ vmware/vmrun.go | 30 ++++++ vmware/vmx.go | 43 +++++++++ 4 files changed, 308 insertions(+) create mode 100644 vmware/machine.go create mode 100644 vmware/vmrun.go create mode 100644 vmware/vmx.go diff --git a/cmds.go b/cmds.go index c13312b..5fc0812 100644 --- a/cmds.go +++ b/cmds.go @@ -12,6 +12,7 @@ import ( _ "github.com/boot2docker/boot2docker-cli/dummy" _ "github.com/boot2docker/boot2docker-cli/virtualbox" + _ "github.com/boot2docker/boot2docker-cli/vmware" "github.com/boot2docker/boot2docker-cli/driver" ) diff --git a/vmware/machine.go b/vmware/machine.go new file mode 100644 index 0000000..adff36c --- /dev/null +++ b/vmware/machine.go @@ -0,0 +1,234 @@ +package vmware + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "text/template" + + "github.com/boot2docker/boot2docker-cli/driver" + "github.com/ogier/pflag" +) + +var ( + verbose bool // Verbose mode (Local copy of B2D.Verbose). + cfg DriverCfg +) + +type DriverCfg struct { + VMRUN string // Path to VBoxManage utility. + VMDK string // base VMDK to use as persistent disk. +} + +func init() { + if err := driver.Register("fusion", InitFunc); err != nil { + fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) + os.Exit(1) + } + if err := driver.RegisterConfig("fusion", ConfigFlags); err != nil { + fmt.Fprintf(os.Stderr, "Failed to initialize driver config. Error : %s", err.Error()) + os.Exit(1) + } +} + +// Initialize the Machine. +func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { + verbose = mc.Verbose + + m, err := GetMachine(getVMX(mc)) + if err != nil && mc.Init == true { + return CreateMachine(mc) + } + return m, err +} + +// Add cmdline params for this driver +func ConfigFlags(mc *driver.MachineConfig, flags *pflag.FlagSet) error { + cfg.VMRUN = "/Applications/VMware Fusion.app/Contents/Library/vmrun" + flags.StringVar(&cfg.VMRUN, "vmrun", cfg.VMRUN, "path to vmrun management utility.") + + return nil +} + +// Machine information. +type Machine struct { + Name string + State driver.MachineState + CPUs uint + Memory uint // main memory (in MB) + VRAM uint // video memory (in MB) + VMX string + OSType string + BootOrder []string // max 4 slots, each in {none|floppy|dvd|disk|net} + DockerPort uint + SSHPort uint +} + +// Refresh reloads the machine information. +func (m *Machine) Refresh() error { + mm, err := GetMachine(m.Name) + mm.State = driver.Running + if err != nil { + return err + } + *m = *mm + return nil +} + +// Start starts the machine. +func (m *Machine) Start() error { + m.State = driver.Running + vmrun("start", m.VMX, "nogui") + return nil +} + +// Suspend suspends the machine and saves its state to disk. +func (m *Machine) Save() error { + m.State = driver.Saved + fmt.Printf("Save %s: %s\n", m.Name, m.State) + return nil +} + +// Pause pauses the execution of the machine. +func (m *Machine) Pause() error { + m.State = driver.Paused + fmt.Printf("Pause %s: %s\n", m.Name, m.State) + return nil +} + +// Stop gracefully stops the machine. +func (m *Machine) Stop() error { + m.State = driver.Poweroff + vmrun("stop", m.VMX, "nogui") + return nil +} + +// Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. +func (m *Machine) Poweroff() error { + m.State = driver.Poweroff + fmt.Printf("Poweroff %s: %s\n", m.Name, m.State) + return nil +} + +// Restart gracefully restarts the machine. +func (m *Machine) Restart() error { + m.State = driver.Running + fmt.Printf("Restart %s: %s\n", m.Name, m.State) + return nil +} + +// Reset forcefully restarts the machine. State is lost and might corrupt the disk image. +func (m *Machine) Reset() error { + m.State = driver.Running + fmt.Printf("Reset %s: %s\n", m.Name, m.State) + return nil +} + +// Get vm name +func (m *Machine) GetName() string { + return m.Name +} + +// Get current state +func (m *Machine) GetState() driver.MachineState { + return m.State +} + +// Get serial file +func (m *Machine) GetSerialFile() string { + return "" +} + +// Get Docker port +func (m *Machine) GetDockerPort() uint { + return m.DockerPort +} + +// Get SSH port +func (m *Machine) GetSSHPort() uint { + return m.SSHPort +} + +// Delete deletes the machine and associated disk images. +func (m *Machine) Delete() error { + fmt.Printf("Delete %s: %s\n", m.Name, m.State) + return nil +} + +// Modify changes the settings of the machine. +func (m *Machine) Modify() error { + fmt.Printf("Modify %s: %s\n", m.Name, m.State) + return m.Refresh() +} + +// AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. +func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { + fmt.Println("Add NAT PF") + return nil +} + +// DelNATPF deletes the NAT port forwarding rule with the given name from the n-th NIC. +func (m *Machine) DelNATPF(n int, name string) error { + fmt.Println("Del NAT PF") + return nil +} + +// SetNIC set the n-th NIC. +func (m *Machine) SetNIC(n int, nic driver.NIC) error { + fmt.Println("Set NIC") + return nil +} + +// AddStorageCtl adds a storage controller with the given name. +func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { + fmt.Println("Add storage ctl") + return nil +} + +// DelStorageCtl deletes the storage controller with the given name. +func (m *Machine) DelStorageCtl(name string) error { + fmt.Println("Del storage ctl") + return nil +} + +// AttachStorage attaches a storage medium to the named storage controller. +func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { + fmt.Println("Attach storage") + return nil +} + +// GetMachine finds a machine. +func GetMachine(vmx string) (*Machine, error) { + if _, err := os.Stat(vmx); os.IsNotExist(err) { + return nil, ErrMachineNotExist + } + m := &Machine{VMX: vmx} + return m, nil +} + +// CreateMachine creates a new virtual machine. +func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { + if err := os.MkdirAll(getBaseFolder(mc), 0755); err != nil { + return nil, err + } + + if _, err := os.Stat(getVMX(mc)); err == nil { + return nil, ErrMachineExist + } + + vmxt := template.Must(template.New("vmx").Parse(vmx)) + vmxfile, err := os.Create(getVMX(mc)) + if err != nil { + return nil, err + } + vmxt.Execute(vmxfile, mc) + return nil, nil +} + +func getBaseFolder(mc *driver.MachineConfig) string { + return filepath.Join(mc.Dir, mc.VM) +} +func getVMX(mc *driver.MachineConfig) string { + return filepath.Join(getBaseFolder(mc), strings.Join([]string{mc.VM, "vmx"}, ".")) +} diff --git a/vmware/vmrun.go b/vmware/vmrun.go new file mode 100644 index 0000000..5742cc8 --- /dev/null +++ b/vmware/vmrun.go @@ -0,0 +1,30 @@ +package vmware + +import ( + "errors" + "log" + "os" + "os/exec" + "strings" +) + +var ( + ErrMachineExist = errors.New("machine already exists") + ErrMachineNotExist = errors.New("machine does not exist") + ErrVMRUNNotFound = errors.New("VMRUN not found") +) + +func vmrun(args ...string) error { + cmd := exec.Command(cfg.VMRUN, args...) + if verbose { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Printf("executing: %v %v", cfg.VMRUN, strings.Join(args, " ")) + } + if stdout := cmd.Run(); stdout != nil { + if ee, ok := stdout.(*exec.Error); ok && ee == exec.ErrNotFound { + return ErrVMRUNNotFound + } + } + return nil +} diff --git a/vmware/vmx.go b/vmware/vmx.go new file mode 100644 index 0000000..37ffcb1 --- /dev/null +++ b/vmware/vmx.go @@ -0,0 +1,43 @@ +package vmware + +const vmx = ` +.encoding = "UTF-8" +bios.bootOrder = "CDROM" +config.version = "8" +displayName = "{{.VM}}" +ethernet0.addressType = "static" +ethernet0.connectionType = "nat" +ethernet0.address = "00:0c:29:2c:fe:e5" +ethernet0.linkStatePropagation.enable = "FALSE" +ethernet0.pciSlotNumber = "33" +ethernet0.present = "TRUE" +ethernet0.virtualDev = "e1000" +ethernet0.wakeOnPcktRcv = "FALSE" +ethernet1.addressType = "static" +ethernet1.connectionType = "hostonly" +ethernet1.address = "00:0c:29:2c:fe:ef" +ethernet1.pciSlotNumber = "34" +ethernet1.present = "TRUE" +ethernet1.virtualDev = "e1000" +ethernet1.wakeOnPcktRcv = "FALSE" +floppy0.present = "FALSE" +guestOS = "other26xlinux-64" +hpet0.present = "TRUE" +ide1:0.deviceType = "cdrom-image" +ide1:0.fileName = "{{.ISO}}" +ide1:0.present = "TRUE" +mem.hotadd = "TRUE" +memsize = "1024" +powerType.powerOff = "soft" +powerType.powerOn = "soft" +powerType.reset = "soft" +powerType.suspend = "soft" +sata0.present = "TRUE" +sata0:0.fileName = "{{.VMDK}}" +sata0:0.present = "TRUE" +scsi0.pciSlotNumber = "16" +scsi0.present = "FALSE" +scsi0.virtualDev = "lsilogic" +scsi0:0.present = "FALSE" +virtualHW.version = "10" +` From 1dfab34b9835add0b445183dc4ef9fd1751c2c55 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Thu, 2 Oct 2014 15:43:56 -0700 Subject: [PATCH 097/167] Add vmdk diskman; first successful Fusion boot --- vmware/machine.go | 30 +++++++++++++++++++++++------- vmware/vmrun.go | 13 +++++++++++++ vmware/vmx.go | 26 +++++++------------------- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/vmware/machine.go b/vmware/machine.go index adff36c..3095fb7 100644 --- a/vmware/machine.go +++ b/vmware/machine.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "path/filepath" - "strings" "text/template" "github.com/boot2docker/boot2docker-cli/driver" @@ -12,13 +11,13 @@ import ( ) var ( - verbose bool // Verbose mode (Local copy of B2D.Verbose). + verbose bool // Verbose mode. cfg DriverCfg ) type DriverCfg struct { - VMRUN string // Path to VBoxManage utility. - VMDK string // base VMDK to use as persistent disk. + VMRUN string // Path to vmrun utility. + VDISKMAN string // Path to vdiskmanager utility. } func init() { @@ -46,7 +45,10 @@ func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { // Add cmdline params for this driver func ConfigFlags(mc *driver.MachineConfig, flags *pflag.FlagSet) error { cfg.VMRUN = "/Applications/VMware Fusion.app/Contents/Library/vmrun" - flags.StringVar(&cfg.VMRUN, "vmrun", cfg.VMRUN, "path to vmrun management utility.") + flags.StringVar(&cfg.VMRUN, "vmrun", cfg.VMRUN, "path to vmrun utility.") + + cfg.VDISKMAN = "/Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager" + flags.StringVar(&cfg.VDISKMAN, "vmdiskman", cfg.VDISKMAN, "path to vdiskmanager utility.") return nil } @@ -67,7 +69,7 @@ type Machine struct { // Refresh reloads the machine information. func (m *Machine) Refresh() error { - mm, err := GetMachine(m.Name) + mm, err := GetMachine(m.VMX) mm.State = driver.Running if err != nil { return err @@ -217,12 +219,26 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { return nil, ErrMachineExist } + // Generate vmx config file from template vmxt := template.Must(template.New("vmx").Parse(vmx)) vmxfile, err := os.Create(getVMX(mc)) if err != nil { return nil, err } vmxt.Execute(vmxfile, mc) + + // Generate vmdk file + diskImg := filepath.Join(getBaseFolder(mc), fmt.Sprintf("%s.vmdk", mc.VM)) + if _, err := os.Stat(diskImg); err != nil { + if !os.IsNotExist(err) { + return nil, err + } + + if err := vdiskmanager(diskImg, mc.DiskSize); err != nil { + return nil, err + } + } + return nil, nil } @@ -230,5 +246,5 @@ func getBaseFolder(mc *driver.MachineConfig) string { return filepath.Join(mc.Dir, mc.VM) } func getVMX(mc *driver.MachineConfig) string { - return filepath.Join(getBaseFolder(mc), strings.Join([]string{mc.VM, "vmx"}, ".")) + return filepath.Join(getBaseFolder(mc), fmt.Sprintf("%s.vmx", mc.VM)) } diff --git a/vmware/vmrun.go b/vmware/vmrun.go index 5742cc8..dc0fe27 100644 --- a/vmware/vmrun.go +++ b/vmware/vmrun.go @@ -2,6 +2,7 @@ package vmware import ( "errors" + "fmt" "log" "os" "os/exec" @@ -28,3 +29,15 @@ func vmrun(args ...string) error { } return nil } + +// Make a vmdk disk image with the given size (in MB). +func vdiskmanager(dest string, size uint) error { + cmd := exec.Command(cfg.VDISKMAN, "-c", "-t", "0", "-s", fmt.Sprintf("%dMB", size), "-a", "lsilogic", dest) + + if stdout := cmd.Run(); stdout != nil { + if ee, ok := stdout.(*exec.Error); ok && ee == exec.ErrNotFound { + return ErrVMRUNNotFound + } + } + return nil +} diff --git a/vmware/vmx.go b/vmware/vmx.go index 37ffcb1..7b64523 100644 --- a/vmware/vmx.go +++ b/vmware/vmx.go @@ -2,24 +2,14 @@ package vmware const vmx = ` .encoding = "UTF-8" -bios.bootOrder = "CDROM" config.version = "8" displayName = "{{.VM}}" -ethernet0.addressType = "static" +ethernet0.addressType = "generated" ethernet0.connectionType = "nat" -ethernet0.address = "00:0c:29:2c:fe:e5" -ethernet0.linkStatePropagation.enable = "FALSE" -ethernet0.pciSlotNumber = "33" +ethernet0.linkStatePropagation.enable = "TRUE" ethernet0.present = "TRUE" ethernet0.virtualDev = "e1000" ethernet0.wakeOnPcktRcv = "FALSE" -ethernet1.addressType = "static" -ethernet1.connectionType = "hostonly" -ethernet1.address = "00:0c:29:2c:fe:ef" -ethernet1.pciSlotNumber = "34" -ethernet1.present = "TRUE" -ethernet1.virtualDev = "e1000" -ethernet1.wakeOnPcktRcv = "FALSE" floppy0.present = "FALSE" guestOS = "other26xlinux-64" hpet0.present = "TRUE" @@ -27,17 +17,15 @@ ide1:0.deviceType = "cdrom-image" ide1:0.fileName = "{{.ISO}}" ide1:0.present = "TRUE" mem.hotadd = "TRUE" -memsize = "1024" +memsize = "{{.Memory}}" powerType.powerOff = "soft" powerType.powerOn = "soft" powerType.reset = "soft" powerType.suspend = "soft" -sata0.present = "TRUE" -sata0:0.fileName = "{{.VMDK}}" -sata0:0.present = "TRUE" -scsi0.pciSlotNumber = "16" -scsi0.present = "FALSE" +scsi0.present = "TRUE" scsi0.virtualDev = "lsilogic" -scsi0:0.present = "FALSE" +scsi0:0.fileName = "{{.VM}}.vmdk" +scsi0:0.present = "TRUE" +virtualHW.productCompatibility = "hosted" virtualHW.version = "10" ` From 7fb5cbd78db12b164a5f47c4e1838b11d8c23f22 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Wed, 8 Oct 2014 16:51:32 -0700 Subject: [PATCH 098/167] Add vm control commands and get hostname --- cmds.go | 2 +- driver/driver.go | 1 + dummy/machine.go | 8 +++- {vmware => fusion}/machine.go | 86 +++++++++++++++++++++++------------ {vmware => fusion}/vmrun.go | 23 ++++++---- {vmware => fusion}/vmx.go | 2 +- util.go | 3 +- virtualbox/machine.go | 5 ++ 8 files changed, 87 insertions(+), 43 deletions(-) rename {vmware => fusion}/machine.go (78%) rename {vmware => fusion}/vmrun.go (68%) rename {vmware => fusion}/vmx.go (98%) diff --git a/cmds.go b/cmds.go index 5fc0812..510b9d5 100644 --- a/cmds.go +++ b/cmds.go @@ -11,8 +11,8 @@ import ( "time" _ "github.com/boot2docker/boot2docker-cli/dummy" + _ "github.com/boot2docker/boot2docker-cli/fusion" _ "github.com/boot2docker/boot2docker-cli/virtualbox" - _ "github.com/boot2docker/boot2docker-cli/vmware" "github.com/boot2docker/boot2docker-cli/driver" ) diff --git a/driver/driver.go b/driver/driver.go index 9b5524a..b27d140 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -42,6 +42,7 @@ type Machine interface { AttachStorage(ctlName string, medium StorageMedium) error GetState() MachineState GetName() string + GetHostname() string GetSerialFile() string GetDockerPort() uint GetSSHPort() uint diff --git a/dummy/machine.go b/dummy/machine.go index cfc3f1d..ce34b35 100644 --- a/dummy/machine.go +++ b/dummy/machine.go @@ -47,8 +47,9 @@ func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { // Machine information. type Machine struct { - Name string UUID string + Name string + Hostname string State driver.MachineState CPUs uint Memory uint // main memory (in MB) @@ -122,6 +123,11 @@ func (m *Machine) GetName() string { return m.Name } +// Get machine hostname +func (m *Machine) GetHostname() string { + return m.Hostname +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State diff --git a/vmware/machine.go b/fusion/machine.go similarity index 78% rename from vmware/machine.go rename to fusion/machine.go index 3095fb7..69e3257 100644 --- a/vmware/machine.go +++ b/fusion/machine.go @@ -1,9 +1,12 @@ -package vmware +package fusion import ( + "bufio" "fmt" "os" "path/filepath" + "strconv" + "strings" "text/template" "github.com/boot2docker/boot2docker-cli/driver" @@ -55,22 +58,17 @@ func ConfigFlags(mc *driver.MachineConfig, flags *pflag.FlagSet) error { // Machine information. type Machine struct { - Name string - State driver.MachineState - CPUs uint - Memory uint // main memory (in MB) - VRAM uint // video memory (in MB) - VMX string - OSType string - BootOrder []string // max 4 slots, each in {none|floppy|dvd|disk|net} - DockerPort uint - SSHPort uint + Name string + State driver.MachineState + CPUs uint64 + Memory uint64 // main memory (in MB) + VMX string + OSType string } // Refresh reloads the machine information. func (m *Machine) Refresh() error { mm, err := GetMachine(m.VMX) - mm.State = driver.Running if err != nil { return err } @@ -80,50 +78,43 @@ func (m *Machine) Refresh() error { // Start starts the machine. func (m *Machine) Start() error { - m.State = driver.Running vmrun("start", m.VMX, "nogui") return nil } // Suspend suspends the machine and saves its state to disk. func (m *Machine) Save() error { - m.State = driver.Saved - fmt.Printf("Save %s: %s\n", m.Name, m.State) + vmrun("suspend", m.VMX, "nogui") return nil } // Pause pauses the execution of the machine. func (m *Machine) Pause() error { - m.State = driver.Paused - fmt.Printf("Pause %s: %s\n", m.Name, m.State) + vmrun("pause", m.VMX, "nogui") return nil } // Stop gracefully stops the machine. func (m *Machine) Stop() error { - m.State = driver.Poweroff vmrun("stop", m.VMX, "nogui") return nil } // Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. func (m *Machine) Poweroff() error { - m.State = driver.Poweroff - fmt.Printf("Poweroff %s: %s\n", m.Name, m.State) + vmrun("stop", m.VMX, "nogui") return nil } // Restart gracefully restarts the machine. func (m *Machine) Restart() error { - m.State = driver.Running - fmt.Printf("Restart %s: %s\n", m.Name, m.State) + vmrun("reset", m.VMX, "nogui") return nil } // Reset forcefully restarts the machine. State is lost and might corrupt the disk image. func (m *Machine) Reset() error { - m.State = driver.Running - fmt.Printf("Reset %s: %s\n", m.Name, m.State) + vmrun("reset", m.VMX, "nogui") return nil } @@ -132,6 +123,12 @@ func (m *Machine) GetName() string { return m.Name } +// Get vm hostname +func (m *Machine) GetHostname() string { + stdout, _, _ := vmrun("getGuestIPAddress", m.VMX) + return strings.TrimSpace(stdout) +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State @@ -144,23 +141,23 @@ func (m *Machine) GetSerialFile() string { // Get Docker port func (m *Machine) GetDockerPort() uint { - return m.DockerPort + return 2375 } // Get SSH port func (m *Machine) GetSSHPort() uint { - return m.SSHPort + return 22 } // Delete deletes the machine and associated disk images. func (m *Machine) Delete() error { - fmt.Printf("Delete %s: %s\n", m.Name, m.State) + vmrun("deleteVM", m.VMX, "nogui") return nil } // Modify changes the settings of the machine. func (m *Machine) Modify() error { - fmt.Printf("Modify %s: %s\n", m.Name, m.State) + fmt.Printf("Hot modify not supported") return m.Refresh() } @@ -205,7 +202,38 @@ func GetMachine(vmx string) (*Machine, error) { if _, err := os.Stat(vmx); os.IsNotExist(err) { return nil, ErrMachineNotExist } - m := &Machine{VMX: vmx} + + m := &Machine{VMX: vmx, State: driver.Poweroff} + + // VMRUN only tells use if the vm is running or not + if stdout, _, _ := vmrun("list"); strings.Contains(stdout, m.VMX) { + m.State = driver.Running + } + + // Parse the vmx file + vmxfile, err := os.Open(vmx) + if err != nil { + return m, err + } + defer vmxfile.Close() + + vmxscan := bufio.NewScanner(vmxfile) + for vmxscan.Scan() { + if vmxtokens := strings.Split(vmxscan.Text(), " = "); len(vmxtokens) > 1 { + vmxkey := strings.TrimSpace(vmxtokens[0]) + vmxvalue, _ := strconv.Unquote(vmxtokens[1]) + switch vmxkey { + case "displayName": + m.Name = vmxvalue + case "guestOS": + m.OSType = vmxvalue + case "memsize": + m.Memory, _ = strconv.ParseUint(vmxvalue, 10, 0) + case "numvcpus": + m.CPUs, _ = strconv.ParseUint(vmxvalue, 10, 0) + } + } + } return m, nil } diff --git a/vmware/vmrun.go b/fusion/vmrun.go similarity index 68% rename from vmware/vmrun.go rename to fusion/vmrun.go index dc0fe27..ba36419 100644 --- a/vmware/vmrun.go +++ b/fusion/vmrun.go @@ -1,10 +1,10 @@ -package vmware +package fusion import ( + "bytes" "errors" "fmt" "log" - "os" "os/exec" "strings" ) @@ -15,19 +15,24 @@ var ( ErrVMRUNNotFound = errors.New("VMRUN not found") ) -func vmrun(args ...string) error { +func vmrun(args ...string) (string, string, error) { cmd := exec.Command(cfg.VMRUN, args...) if verbose { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr log.Printf("executing: %v %v", cfg.VMRUN, strings.Join(args, " ")) } - if stdout := cmd.Run(); stdout != nil { - if ee, ok := stdout.(*exec.Error); ok && ee == exec.ErrNotFound { - return ErrVMRUNNotFound + + var stdout bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout, cmd.Stderr = &stdout, &stderr + + err := cmd.Run() + if err != nil { + if ee, ok := err.(*exec.Error); ok && ee == exec.ErrNotFound { + err = ErrVMRUNNotFound } } - return nil + + return stdout.String(), stderr.String(), err } // Make a vmdk disk image with the given size (in MB). diff --git a/vmware/vmx.go b/fusion/vmx.go similarity index 98% rename from vmware/vmx.go rename to fusion/vmx.go index 7b64523..2b467ba 100644 --- a/vmware/vmx.go +++ b/fusion/vmx.go @@ -1,4 +1,4 @@ -package vmware +package fusion const vmx = ` .encoding = "UTF-8" diff --git a/util.go b/util.go index fa072aa..7809835 100644 --- a/util.go +++ b/util.go @@ -168,7 +168,6 @@ func reader(r io.Reader) { } func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { - DefaultSSHArgs := []string{ "-o", "IdentitiesOnly=yes", "-o", "StrictHostKeyChecking=no", @@ -176,7 +175,7 @@ func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." "-p", fmt.Sprintf("%d", m.GetSSHPort()), "-i", B2D.SSHKey, - "docker@localhost", + fmt.Sprintf("docker@%s", m.GetHostname()), } sshArgs := append(DefaultSSHArgs, args...) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 2009d01..6523073 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -305,6 +305,11 @@ func (m *Machine) GetName() string { return m.Name } +// Get machine hostname +func (m *Machine) GetHostname() string { + return "localhost" +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State From 71c52c6a3ff512760fb559625e51011a66885747 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Wed, 15 Oct 2014 23:51:09 -0400 Subject: [PATCH 099/167] Report the iso path used by the vm to help debug possible support issues --- cmds.go | 6 +++++- virtualbox/machine.go | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index c13312b..3ea5875 100644 --- a/cmds.go +++ b/cmds.go @@ -329,9 +329,13 @@ func cmdInfo() error { if err != nil { return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) } - if err := json.NewEncoder(os.Stdout).Encode(m); err != nil { + b, err := json.MarshalIndent(m, "", "\t") + if err != nil { return fmt.Errorf("Failed to encode machine %q info: %s", B2D.VM, err) } + + os.Stdout.Write(b) + return nil } diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 2009d01..5b30295 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -161,6 +161,7 @@ func (f Flag) Get(o Flag) string { type Machine struct { Name string UUID string + Iso string State driver.MachineState CPUs uint Memory uint // main memory (in MB) @@ -355,6 +356,8 @@ func GetMachine(id string) (*Machine, error) { m.Name = val case "UUID": m.UUID = val + case "SATA-0-0": + m.Iso = val case "VMState": m.State = driver.MachineState(val) case "memory": From a8ca6ecf73d0dd309d30083d62b0b25c44b2ba76 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 16 Oct 2014 04:23:27 -0600 Subject: [PATCH 100/167] Revert "Update default ISO path to prefer an ISO that's next to the boot2docker CLI binary" --- config.go | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/config.go b/config.go index a06851d..48436bb 100644 --- a/config.go +++ b/config.go @@ -5,7 +5,6 @@ import ( "fmt" "net" "os" - "os/exec" "path/filepath" "regexp" "runtime" @@ -62,36 +61,6 @@ func cfgFilename(dir string) string { return filename } -func defaultIsoPath(dir string) string { - var err error - - iso := filepath.Join(dir, "boot2docker.iso") - - exe := os.Args[0] - if filepath.Base(exe) == exe { - // this logic borrowed from reexec/reexec.go in Docker itself :) - if lp, err := exec.LookPath(exe); err == nil { - exe = lp - } - } - - if exe, err = filepath.Abs(exe); err != nil { - return iso - } - - if exe, err = filepath.EvalSymlinks(exe); err != nil { - return iso - } - - // if there's a "boot2docker.iso" next to our boot2docker-cli executable, let's prefer that one by default - exeIso := filepath.Join(filepath.Dir(exe), "boot2docker.iso") - if _, err = os.Stat(exeIso); err == nil { - return exeIso - } - - return iso -} - // Write configuration set by the combination of profile and flags // Should result in a format that can be piped into a profile file func printConfig() string { @@ -123,7 +92,7 @@ func config() (*flag.FlagSet, error) { //flags.StringVarP(&B2D.Dir, "dir", "d", dir, "boot2docker config directory.") B2D.Dir = dir flags.StringVar(&B2D.ISOURL, "iso-url", "https://api.github.com/repos/boot2docker/boot2docker/releases", "source URL to provision the boot2docker ISO image.") - flags.StringVar(&B2D.ISO, "iso", defaultIsoPath(dir), "path to boot2docker ISO image.") + flags.StringVar(&B2D.ISO, "iso", filepath.Join(dir, "boot2docker.iso"), "path to boot2docker ISO image.") // Sven disabled this, as it is broken - if I user with a fresh computer downloads // just the boot2docker-cli, and then runs `boot2docker --init ip`, we create a vm From 4a1bd39cda5de28c93fc96cff8af5af1818759a5 Mon Sep 17 00:00:00 2001 From: lalyos Date: Thu, 16 Oct 2014 16:45:17 +0200 Subject: [PATCH 101/167] Fixing name collision of driver.ErrMachineNotExist and virtualbox.ErrMachineNotExist --- virtualbox/machine.go | 2 +- virtualbox/vbm.go | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 2009d01..f61646c 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -330,7 +330,7 @@ func GetMachine(id string) (*Machine, error) { stdout, stderr, err := vbmOutErr("showvminfo", id, "--machinereadable") if err != nil { if reMachineNotFound.FindString(stderr) != "" { - return nil, ErrMachineNotExist + return nil, driver.ErrMachineNotExist } return nil, err } diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index 641c071..bc36d91 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -25,9 +25,8 @@ var ( ) var ( - ErrMachineExist = errors.New("machine already exists") - ErrMachineNotExist = errors.New("machine does not exist") - ErrVBMNotFound = errors.New("VBoxManage not found") + ErrMachineExist = errors.New("machine already exists") + ErrVBMNotFound = errors.New("VBoxManage not found") ) func vbm(args ...string) error { From 78bc9cc7ba7a39d09ab6360d51f674331b84f220 Mon Sep 17 00:00:00 2001 From: lalyos Date: Thu, 16 Oct 2014 16:49:07 +0200 Subject: [PATCH 102/167] Moving ErrMachineExist to driver package "machine already exists" is not virtualbox specific --- driver/driver.go | 1 + virtualbox/machine.go | 2 +- virtualbox/vbm.go | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver/driver.go b/driver/driver.go index 9b5524a..2fbb8ab 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -53,6 +53,7 @@ var ( ErrNotSupported = errors.New("machine not supported") ErrMachineNotExist = errors.New("machine not exist") + ErrMachineExist = errors.New("machine already exists") ErrPrerequisites = errors.New("prerequisites for machine not satisfied (hypervisor installed?)") ) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index f61646c..54d3059 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -443,7 +443,7 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { } for _, m := range machineNames { if m == mc.VM { - return nil, ErrMachineExist + return nil, driver.ErrMachineExist } } diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index bc36d91..a4f534f 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -25,8 +25,7 @@ var ( ) var ( - ErrMachineExist = errors.New("machine already exists") - ErrVBMNotFound = errors.New("VBoxManage not found") + ErrVBMNotFound = errors.New("VBoxManage not found") ) func vbm(args ...string) error { From 013d5ccf8b07ba2d4b634308206ac9173c324d55 Mon Sep 17 00:00:00 2001 From: lalyos Date: Thu, 16 Oct 2014 16:54:25 +0200 Subject: [PATCH 103/167] Fixing error message when no suitable driver found Right now The error message is misleading in case of a non existing driver: "boot2docker-vm": machine not supported Its not the machine which is not supported, but the driver $ boot2docker --driver=nosuchdriver info Boot2Docker-cli version: v1.3.0 Git commit: 1d0b71b error in run: Failed to get machine "boot2docker-vm": machine not supported --- driver/driver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/driver.go b/driver/driver.go index 2fbb8ab..525ee9b 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -51,7 +51,7 @@ var ( // All registred machines machines map[string]InitFunc - ErrNotSupported = errors.New("machine not supported") + ErrNotSupported = errors.New("driver not supported") ErrMachineNotExist = errors.New("machine not exist") ErrMachineExist = errors.New("machine already exists") ErrPrerequisites = errors.New("prerequisites for machine not satisfied (hypervisor installed?)") From 5d389e875766fb760badf9a9c41f9e58cea697b4 Mon Sep 17 00:00:00 2001 From: lalyos Date: Thu, 16 Oct 2014 21:20:49 +0200 Subject: [PATCH 104/167] Starting from saved state skips setUpShares Fixes #292 --- virtualbox/machine.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 5b30295..c6c4ed9 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -195,11 +195,14 @@ func (m *Machine) Start() error { switch m.State { case driver.Paused: return vbm("controlvm", m.Name, "resume") - case driver.Poweroff, driver.Saved, driver.Aborted: + case driver.Poweroff, driver.Aborted: if err := m.setUpShares(); err != nil { return err } + fallthrough + case driver.Saved: return vbm("startvm", m.Name, "--type", "headless") + } if err := m.Refresh(); err == nil { if m.State != driver.Running { From 1a3d05e8e7c7354f5499a68e3e9a35d910888164 Mon Sep 17 00:00:00 2001 From: Douglas Camata Date: Fri, 17 Oct 2014 15:04:10 -0300 Subject: [PATCH 105/167] printExport support for fish-shell (based on boot2docker/boot2docker-cli#260) --- cmds.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index 3ea5875..14c60c3 100644 --- a/cmds.go +++ b/cmds.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "os/exec" + "path/filepath" "regexp" "runtime" "strings" @@ -195,9 +196,17 @@ func printExport(socket, certPath string) { for name, value := range exports(socket, certPath) { if os.Getenv(name) != value { if value == "" { - fmt.Printf(" unset %s\n", name) + if filepath.Base(os.Getenv("SHELL")) == "fish" { + fmt.Printf(" set -e %s\n", name) + } else { + fmt.Printf(" unset %s\n", name) + } } else { - fmt.Printf(" export %s=%s\n", name, value) + if filepath.Base(os.Getenv("SHELL")) == "fish" { + fmt.Printf(" set x %s\n", name) + } else { + fmt.Printf(" export %s=%s\n", name, value) + } } } } From ce2bc314e2ad49e46e422fdf8ef66d5b4275f461 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 23 Oct 2014 10:16:05 -0600 Subject: [PATCH 106/167] Make "socket" an alias of "shellinit" and hide it from usage --- cmds.go | 23 ----------------------- config.go | 5 ++--- main.go | 4 +--- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/cmds.go b/cmds.go index 3ea5875..03f9ed0 100644 --- a/cmds.go +++ b/cmds.go @@ -349,29 +349,6 @@ func cmdStatus() error { return nil } -// tell the User the Docker socket to connect to -func cmdSocket() error { - m, err := driver.GetMachine(&B2D) - if err != nil { - return fmt.Errorf("Failed to get machine %q: %s", B2D.VM, err) - } - - if m.GetState() != driver.Running { - return fmt.Errorf("VM %q is not running.", B2D.VM) - } - - socket, err := RequestSocketFromSSH(m) - if err != nil { - return fmt.Errorf("Error requesting socket: %s\n", err) - } - - fmt.Fprintf(os.Stderr, "\n\t export DOCKER_HOST=") - fmt.Printf("%s", socket) - fmt.Fprintf(os.Stderr, "\n\n") - - return nil -} - // Call the external SSH command to login into boot2docker VM. func cmdSSH() error { m, err := driver.GetMachine(&B2D) diff --git a/config.go b/config.go index 48436bb..b9b96a8 100644 --- a/config.go +++ b/config.go @@ -171,7 +171,7 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|socket|shellinit|delete|download|upgrade|version} []\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|shellinit|delete|download|upgrade|version} []\n", os.Args[0]) } func usageLong(flags *flag.FlagSet) { @@ -193,8 +193,7 @@ Commands: config|cfg Show selected profile file settings. info Display detailed information of VM. ip Display the IP address of the VM's Host-only network. - socket Display the DOCKER_HOST socket to connect to. - shellinit Display the shell command to set up the Docker client. + shellinit Display the shell commands to set up the Docker client. status Display current state of VM. download Download Boot2Docker ISO image. upgrade Upgrade the Boot2Docker ISO image (restart if running). diff --git a/main.go b/main.go index d062da2..a4f90dd 100644 --- a/main.go +++ b/main.go @@ -65,9 +65,7 @@ func run() error { return cmdDelete() case "info": return cmdInfo() - case "socket": - return cmdSocket() - case "shellinit": + case "shellinit", "socket": return cmdShellInit() case "status": return cmdStatus() From 66eb47103445eb26f99690f7d8b778c07172bbc5 Mon Sep 17 00:00:00 2001 From: Douglas Camata Date: Thu, 23 Oct 2014 14:32:35 -0200 Subject: [PATCH 107/167] printExport always showing the export/unset commands --- cmds.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cmds.go b/cmds.go index 14c60c3..b1d4608 100644 --- a/cmds.go +++ b/cmds.go @@ -193,20 +193,21 @@ func checkEnvironment(socket, certPath string) bool { } func printExport(socket, certPath string) { + shell = filepath.Base(os.Getenv("SHELL")) for name, value := range exports(socket, certPath) { - if os.Getenv(name) != value { - if value == "" { - if filepath.Base(os.Getenv("SHELL")) == "fish" { - fmt.Printf(" set -e %s\n", name) - } else { - fmt.Printf(" unset %s\n", name) - } - } else { - if filepath.Base(os.Getenv("SHELL")) == "fish" { - fmt.Printf(" set x %s\n", name) - } else { - fmt.Printf(" export %s=%s\n", name, value) - } + if value = "" { // unsetting vars + switch shell { + case "fish": + fmt.Printf(" set -e %s\n", name) + case "bash": // default command to export variables POSIX shells, like bash, zsh, etc. + fmt.Printf(" unset %s\n", name) + } + } else { // setting vars + switch shell { + case "fish": + fmt.Printf(" set -x %s\n", name) + case "bash": // default command to export variables POSIX shells, like bash, zsh, etc. + fmt.Printf(" export %s=%s\n", name, value) } } } From 7784a0934f69ae221c9fc1e7d18dfdf233c9e364 Mon Sep 17 00:00:00 2001 From: Douglas Camata Date: Thu, 23 Oct 2014 14:33:40 -0200 Subject: [PATCH 108/167] bash's behavior is default in printExport --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index b1d4608..32f5fb1 100644 --- a/cmds.go +++ b/cmds.go @@ -199,14 +199,14 @@ func printExport(socket, certPath string) { switch shell { case "fish": fmt.Printf(" set -e %s\n", name) - case "bash": // default command to export variables POSIX shells, like bash, zsh, etc. + default: // default command to export variables POSIX shells, like bash, zsh, etc. fmt.Printf(" unset %s\n", name) } } else { // setting vars switch shell { case "fish": fmt.Printf(" set -x %s\n", name) - case "bash": // default command to export variables POSIX shells, like bash, zsh, etc. + default: // default command to export variables POSIX shells, like bash, zsh, etc. fmt.Printf(" export %s=%s\n", name, value) } } From 8287ae83fd7808ebf7ded9a0c67a510e02372c3e Mon Sep 17 00:00:00 2001 From: Douglas Camata Date: Thu, 23 Oct 2014 14:36:37 -0200 Subject: [PATCH 109/167] refactoring printExport again --- cmds.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/cmds.go b/cmds.go index 32f5fb1..df73e55 100644 --- a/cmds.go +++ b/cmds.go @@ -195,20 +195,19 @@ func checkEnvironment(socket, certPath string) bool { func printExport(socket, certPath string) { shell = filepath.Base(os.Getenv("SHELL")) for name, value := range exports(socket, certPath) { - if value = "" { // unsetting vars - switch shell { - case "fish": + switch shell { + case "fish": + if value = "" { fmt.Printf(" set -e %s\n", name) - default: // default command to export variables POSIX shells, like bash, zsh, etc. - fmt.Printf(" unset %s\n", name) - } - } else { // setting vars - switch shell { - case "fish": + } else { fmt.Printf(" set -x %s\n", name) - default: // default command to export variables POSIX shells, like bash, zsh, etc. - fmt.Printf(" export %s=%s\n", name, value) } + default: // default command to export variables POSIX shells, like bash, zsh, etc. + if value = "" { + fmt.Printf(" unset %s\n", name) + } else { + fmt.Printf(" export %s=%s\n", name, value) + } } } } From 5e8d8c9b87f0992aace0069718be707fd8d48c2f Mon Sep 17 00:00:00 2001 From: Douglas Camata Date: Thu, 23 Oct 2014 14:37:36 -0200 Subject: [PATCH 110/167] type fixed in printExport --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index df73e55..65f1915 100644 --- a/cmds.go +++ b/cmds.go @@ -197,13 +197,13 @@ func printExport(socket, certPath string) { for name, value := range exports(socket, certPath) { switch shell { case "fish": - if value = "" { + if value == "" { fmt.Printf(" set -e %s\n", name) } else { fmt.Printf(" set -x %s\n", name) } default: // default command to export variables POSIX shells, like bash, zsh, etc. - if value = "" { + if value == "" { fmt.Printf(" unset %s\n", name) } else { fmt.Printf(" export %s=%s\n", name, value) From c7e7beb16dd232800e74d1ccd98696c4ed71f799 Mon Sep 17 00:00:00 2001 From: Douglas Camata Date: Thu, 23 Oct 2014 14:38:24 -0200 Subject: [PATCH 111/167] getting rid of unnecessary variable attribution --- cmds.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index 65f1915..c6b9dc4 100644 --- a/cmds.go +++ b/cmds.go @@ -193,9 +193,8 @@ func checkEnvironment(socket, certPath string) bool { } func printExport(socket, certPath string) { - shell = filepath.Base(os.Getenv("SHELL")) for name, value := range exports(socket, certPath) { - switch shell { + switch filepath.Base(os.Getenv("SHELL")) { case "fish": if value == "" { fmt.Printf(" set -e %s\n", name) From 8c9238e12b91dbfee6c5c5f45ffe068271727ffe Mon Sep 17 00:00:00 2001 From: Douglas Camata Date: Thu, 23 Oct 2014 14:57:55 -0200 Subject: [PATCH 112/167] forgot to add value in the fish variable export, sorry --- cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index c6b9dc4..ff508e5 100644 --- a/cmds.go +++ b/cmds.go @@ -199,7 +199,7 @@ func printExport(socket, certPath string) { if value == "" { fmt.Printf(" set -e %s\n", name) } else { - fmt.Printf(" set -x %s\n", name) + fmt.Printf(" set -x %s %s\n", name, value) } default: // default command to export variables POSIX shells, like bash, zsh, etc. if value == "" { From 1481459554fef1d2a7559b38822b9b908ca74304 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 23 Oct 2014 16:13:32 -0600 Subject: [PATCH 113/167] Fix some minor whitespace/gofmt issues --- cmds.go | 8 ++++---- virtualbox/machine.go | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cmds.go b/cmds.go index b6f6609..2ba13f9 100644 --- a/cmds.go +++ b/cmds.go @@ -203,10 +203,10 @@ func printExport(socket, certPath string) { } default: // default command to export variables POSIX shells, like bash, zsh, etc. if value == "" { - fmt.Printf(" unset %s\n", name) - } else { - fmt.Printf(" export %s=%s\n", name, value) - } + fmt.Printf(" unset %s\n", name) + } else { + fmt.Printf(" export %s=%s\n", name, value) + } } } } diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 3e23f1f..e275abb 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -202,7 +202,6 @@ func (m *Machine) Start() error { fallthrough case driver.Saved: return vbm("startvm", m.Name, "--type", "headless") - } if err := m.Refresh(); err == nil { if m.State != driver.Running { From 570418c2c985ccaa8f8f7ff11dda867be65e8f4b Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 30 Oct 2014 21:23:06 -0600 Subject: [PATCH 114/167] Bump to v1.3.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 18fa8e7..7574079 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.3.0 +v1.3.1 From 22ee883e8c35c1eda369df07f218a7cebf8d2a4f Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Mon, 10 Nov 2014 14:37:30 +1000 Subject: [PATCH 115/167] remove the library path before we exec --- virtualbox/vbm.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index a4f534f..bbb5630 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -9,12 +9,18 @@ import ( "os/exec" "path/filepath" "regexp" + "runtime" "strings" "github.com/boot2docker/boot2docker-cli/driver" ) func init() { + if runtime.GOOS == "darwin" { + // remove DYLD_LIBRARY_PATH and LD_LIBRARY_PATH as they break VBoxManage on OSX + os.Setenv("DYLD_LIBRARY_PATH", "") + os.Setenv("LD_LIBRARY_PATH", "") + } } var ( From 169d48ff57077a96ddefa70420644499f6e138fb Mon Sep 17 00:00:00 2001 From: Joey Geiger Date: Wed, 12 Nov 2014 14:10:31 -0700 Subject: [PATCH 116/167] Update README to use ~ for the home directory Using ~ to specify the home directory should allow anyone to copy/paste the example. Also, this makes all the references the same. Previously there was a /home/sven and a /Users/sven. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 693a13e..283089c 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ The `boot2docker` binary reads configuration from `$BOOT2DOCKER_PROFILE` if set, `%USERPROFILE%/.boot2docker/profile`. `boot2docker config` will tell you where it is looking for the file, and will also output the settings that are in use, so you can initialise a default file to customize using -`boot2docker config > /home/sven/.boot2docker/profile`. +`boot2docker config > ~/.boot2docker/profile`. Currently you can configure the following options (undefined options take default values): @@ -137,7 +137,7 @@ VBM = "VBoxManage" # path to SSH client utility SSH = "ssh" SSHGen = "ssh-keygen" -SSHKey = "/Users/sven/.ssh/id_boot2docker" +SSHKey = "~/.ssh/id_boot2docker" # name of boot2docker virtual machine VM = "boot2docker-vm" @@ -150,7 +150,7 @@ ISOURL = "https://api.github.com/repos/boot2docker/boot2docker/releases" #ISOURL = "https://internal.corp.org/b2d.iso" # path to boot2docker ISO image -ISO = "/Users/sven/.boot2docker/boot2docker.iso" +ISO = "~/.boot2docker/boot2docker.iso" # VM disk image size in MB DiskSize = 20000 From 5bc8009bc970268c7c298e80c8b989b8fde72ccb Mon Sep 17 00:00:00 2001 From: Joey Geiger Date: Thu, 13 Nov 2014 08:34:15 -0700 Subject: [PATCH 117/167] Revert changes to "config" parameters Per comment on the pull request, I've reverted the changes to the example parameters. I still believe the create config section should be changed as anyone can then copy/paste the command to create their config file without having to edit the command. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 283089c..2455237 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ VBM = "VBoxManage" # path to SSH client utility SSH = "ssh" SSHGen = "ssh-keygen" -SSHKey = "~/.ssh/id_boot2docker" +SSHKey = "/Users/sven/.ssh/id_boot2docker" # name of boot2docker virtual machine VM = "boot2docker-vm" @@ -150,7 +150,7 @@ ISOURL = "https://api.github.com/repos/boot2docker/boot2docker/releases" #ISOURL = "https://internal.corp.org/b2d.iso" # path to boot2docker ISO image -ISO = "~/.boot2docker/boot2docker.iso" +ISO = "/Users/sven/.boot2docker/boot2docker.iso" # VM disk image size in MB DiskSize = 20000 From e41a9aea94fe6fc803ca70bc0a2f9e9c9f256aed Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Mon, 24 Nov 2014 10:16:15 -0700 Subject: [PATCH 118/167] Bump to v1.3.2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7574079..968e750 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.3.1 +v1.3.2 From d80b782668f15ab6799382ea11c333b63b9b8b1b Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Mon, 1 Dec 2014 10:40:44 -0700 Subject: [PATCH 119/167] Remove "boot2docker ip" stderr output It confuses folks far too often, so as pretty as it is, it ought to go so we stop having to answer the same question over and over. --- cmds.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmds.go b/cmds.go index 2ba13f9..743be1c 100644 --- a/cmds.go +++ b/cmds.go @@ -411,9 +411,7 @@ func cmdIP() error { } } if IP != "" { - fmt.Fprintf(os.Stderr, "\nThe VM's Host only interface IP address is: ") - fmt.Printf("%s", IP) - fmt.Fprintf(os.Stderr, "\n\n") + fmt.Println(IP) } else { fmt.Fprintf(os.Stderr, "\nFailed to get VM Host only IP address.\n") fmt.Fprintf(os.Stderr, "\tWas the VM initialized using boot2docker?\n") From 4c59138232ee7ded5ba4bda9bb2c79d171d29d68 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Mon, 1 Dec 2014 15:07:07 -0700 Subject: [PATCH 120/167] Explicitly use the VirtualBox NAT DNS Proxy --- virtualbox/machine.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index e275abb..76f0b7d 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -633,10 +633,14 @@ func (m *Machine) Modify() error { "--firmware", "bios", "--bioslogofadein", "off", "--bioslogofadeout", "off", - "--natdnshostresolver1", "on", "--bioslogodisplaytime", "0", "--biosbootmenu", "disabled", + // VirtualBox's DNS Host Resolver doesn't support SRV records + // direct DNS pass-through doesn't support roaming laptops well + // so we explicitly enable the DNS proxy + "--natdnsproxy1", "on", + "--ostype", m.OSType, "--cpus", fmt.Sprintf("%d", m.CPUs), "--memory", fmt.Sprintf("%d", m.Memory), From 81bd2efb357cf84edb928883c0df43b1334e2860 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 11 Dec 2014 13:40:33 -0700 Subject: [PATCH 121/167] Bump to v1.3.3 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 968e750..ea7786a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.3.2 +v1.3.3 From 1f5d37d677e151aef9377afed967dd310646cb80 Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Fri, 12 Dec 2014 20:26:56 -0800 Subject: [PATCH 122/167] Use efficient cache in Dockerfile It seems that this caches slightly better than `go get ./...`, since there are only two packages. Signed-off-by: Nathan LeClaire --- Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 71515cc..cef04d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,10 +2,12 @@ FROM golang:1.3-cross -ADD . /go/src/github.com/boot2docker/boot2docker-cli WORKDIR /go/src/github.com/boot2docker/boot2docker-cli # Download (but not install) dependencies -RUN go get -d -v ./... +RUN go get github.com/BurntSushi/toml +RUN go get github.com/ogier/pflag + +ADD . /go/src/github.com/boot2docker/boot2docker-cli CMD ["make", "all"] From 17fa97244ed031a4670f196c5c501afa83d10379 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 16 Dec 2014 10:42:21 -0700 Subject: [PATCH 123/167] Switch to direct DNS pass-through --- virtualbox/machine.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 76f0b7d..9711a35 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -636,10 +636,12 @@ func (m *Machine) Modify() error { "--bioslogodisplaytime", "0", "--biosbootmenu", "disabled", - // VirtualBox's DNS Host Resolver doesn't support SRV records + // the DNS Host Resolver doesn't support SRV records + // the DNS proxy has performance issues // direct DNS pass-through doesn't support roaming laptops well - // so we explicitly enable the DNS proxy - "--natdnsproxy1", "on", + // we can't win, so let's go direct and at least get performance + "--natdnshostresolver1", "off", + "--natdnsproxy1", "off", "--ostype", m.OSType, "--cpus", fmt.Sprintf("%d", m.CPUs), From 583f71414e6b1579bc1d435fdea47e2f6e8eeef4 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 16 Dec 2014 12:33:16 -0700 Subject: [PATCH 124/167] Bump to v1.4.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ea7786a..0d0c52f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.3.3 +v1.4.0 From 5d670822bab7c35b0e4238b23fa1ef446cc19d44 Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Tue, 26 Aug 2014 20:55:17 -0700 Subject: [PATCH 125/167] Add support for upgrading binaries `boot2docker upgrade` will support the Docker client binary, boot2docker-cli binary, and boot2docker ISO now. Signed-off-by: Nathan LeClaire --- cmds.go | 143 +++++++++++++++++++++++++++++++++++++++++++++++ config.go | 8 +++ driver/config.go | 23 ++++---- util.go | 28 +++++++++- 4 files changed, 191 insertions(+), 11 deletions(-) diff --git a/cmds.go b/cmds.go index 743be1c..31c98e2 100644 --- a/cmds.go +++ b/cmds.go @@ -3,6 +3,9 @@ package main import ( "encoding/json" "fmt" + "net/http" + + "io/ioutil" "os" "os/exec" "path/filepath" @@ -277,6 +280,19 @@ func cmdPoweroff() error { // Upgrade the boot2docker ISO - preserving server state func cmdUpgrade() error { + if runtime.GOOS == "darwin" || runtime.GOOS == "linux" { + if B2D.Clobber { + err := upgradeDockerClientBinary() + if err != nil { + return err + } + } else { + fmt.Println("Skipping client binary download, use --clobber=true to enable...") + } + } + if err := upgradeBoot2DockerBinary(); err != nil { + return fmt.Errorf("Error upgrading boot2docker binary: %s", err) + } m, err := driver.GetMachine(&B2D) if err == nil { if m.GetState() == driver.Running || m.GetState() == driver.Saved || m.GetState() == driver.Paused { @@ -292,6 +308,133 @@ func cmdUpgrade() error { return cmdDownload() } +func upgradeBoot2DockerBinary() error { + var ( + goos, arch, ext string + ) + latestVersion, err := getLatestReleaseName("https://api.github.com/repos/boot2docker/boot2docker-cli/releases") + if err != nil { + return fmt.Errorf("Error attempting to get the latest boot2docker-cli release: %s", err) + } + baseUrl := "https://github.com/boot2docker/boot2docker-cli/releases/download" + + ext = "" + + switch runtime.GOARCH { + case "amd64": + arch = "amd64" + default: + return fmt.Errorf("Architecture not supported") + } + + switch runtime.GOOS { + case "darwin", "linux": + goos = runtime.GOOS + case "windows": + goos = "windows" + arch = "windows" + ext = ".exe" + default: + return fmt.Errorf("Operating system not supported") + } + binaryUrl := fmt.Sprintf("%s/%s/boot2docker-%s-%s-%s%s", baseUrl, latestVersion, latestVersion, goos, arch, ext) + currentBoot2DockerVersion := Version + if err := attemptUpgrade(binaryUrl, "boot2docker", latestVersion, currentBoot2DockerVersion); err != nil { + return fmt.Errorf("Error attempting upgrade: %s", err) + } + return nil +} + +func upgradeDockerClientBinary() error { + var ( + clientOs, clientArch string + ) + resp, err := http.Get("https://get.docker.com/latest") + if err != nil { + return fmt.Errorf("Error checking the latest version of Docker: %s", err) + } + defer resp.Body.Close() + latestVersionBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("Error reading response body on latest version of Docker call: %s", err) + } + latestVersion := strings.TrimSpace(string(latestVersionBytes)) + localClientVersion, err := getLocalClientVersion() + if err != nil { + return fmt.Errorf("Error getting local Docker client version: %s", err) + } + switch runtime.GOARCH { + case "amd64": + clientArch = "x86_64" + default: + return fmt.Errorf("Architecture not supported") + } + + switch runtime.GOOS { + case "darwin": + clientOs = "Darwin" + case "linux": + clientOs = "Linux" + default: + return fmt.Errorf("Operating system not supported") + } + binaryUrl := fmt.Sprintf("https://get.docker.com/builds/%s/%s/docker-latest", clientOs, clientArch) + if err := attemptUpgrade(binaryUrl, "docker", latestVersion, localClientVersion); err != nil { + return fmt.Errorf("Error attempting upgrade: %s", err) + } + return nil +} + +func attemptUpgrade(binaryUrl, binaryName, latestVersion, localVersion string) error { + if (latestVersion != localVersion && !strings.Contains(latestVersion, "rc")) || B2D.ForceUpgradeDownload { + if err := backupAndDownload(binaryUrl, binaryName, localVersion); err != nil { + return fmt.Errorf("Error attempting backup and download of Docker client binary: %s", err) + } + } else { + fmt.Printf("%s is up to date (%s), skipping upgrade...\n", binaryName, localVersion) + } + return nil +} + +func backupAndDownload(binaryUrl, binaryName, localVersion string) error { + binaryPath, err := exec.LookPath(binaryName) + if err != nil { + return fmt.Errorf("Error attempting to locate local binary: %s", err) + } + path := strings.TrimSpace(string(binaryPath)) + + fmt.Println("Backing up existing", binaryName, "binary...") + if err := backupBinary(binaryName, localVersion, path); err != nil { + return fmt.Errorf("Error backing up docker client: %s", err) + } + + fmt.Println("Downloading new", binaryName, "client binary...") + if err := download(path, binaryUrl); err != nil { + return fmt.Errorf("Error attempting to download new client binary: %s", err) + } + if err := os.Chmod(path, 0755); err != nil { + return err + } + fmt.Printf("Success: downloaded %s\n\tto %s\n\tThe old version is backed up to ~/.boot2docker.\n", binaryUrl, path) + return nil +} + +func backupBinary(binaryName, localVersion, path string) error { + dir, err := cfgDir(".boot2docker") + if err != nil { + return fmt.Errorf("Error getting boot2docker config dir", err) + } + buf, err := ioutil.ReadFile(path) + if err != nil { + return fmt.Errorf("Error opening binary for reading at %s: %s", path, err) + } + backupName := fmt.Sprintf("%s-%s", binaryName, localVersion) + if err := ioutil.WriteFile(filepath.Join(dir, backupName), buf, 0755); err != nil { + return fmt.Errorf("Error creating backup file", err) + } + return nil +} + // Gracefully stop and then start the VM. func cmdRestart() error { m, err := driver.GetMachine(&B2D) diff --git a/config.go b/config.go index b9b96a8..d7bc1f0 100644 --- a/config.go +++ b/config.go @@ -93,6 +93,14 @@ func config() (*flag.FlagSet, error) { B2D.Dir = dir flags.StringVar(&B2D.ISOURL, "iso-url", "https://api.github.com/repos/boot2docker/boot2docker/releases", "source URL to provision the boot2docker ISO image.") flags.StringVar(&B2D.ISO, "iso", filepath.Join(dir, "boot2docker.iso"), "path to boot2docker ISO image.") + if runtime.GOOS == "darwin" { + // clobber by default + flags.BoolVar(&B2D.Clobber, "clobber", true, "overwrite Docker client binary on boot2docker upgrade") + } else { + flags.BoolVar(&B2D.Clobber, "clobber", false, "overwrite Docker client binary on boot2docker upgrade") + } + + flags.BoolVar(&B2D.ForceUpgradeDownload, "force-upgrade-download", false, "always download on boot2docker upgrade, never skip") // Sven disabled this, as it is broken - if I user with a fresh computer downloads // just the boot2docker-cli, and then runs `boot2docker --init ip`, we create a vm diff --git a/driver/config.go b/driver/config.go index 8cef0d7..a450ff6 100644 --- a/driver/config.go +++ b/driver/config.go @@ -2,8 +2,9 @@ package driver import ( "fmt" - flag "github.com/ogier/pflag" "net" + + flag "github.com/ogier/pflag" ) // Machine config. @@ -14,15 +15,17 @@ type MachineConfig struct { Driver string // basic config - SSH string // SSH client executable - SSHGen string // SSH keygen executable - SSHKey string // SSH key to send to the vm - VM string // virtual machine name - Dir string // boot2docker directory - ISOURL string // Source URL to retrieve the ISO from - ISO string // boot2docker ISO image path - DiskSize uint // VM disk image size (MB) - Memory uint // VM memory size (MB) + Clobber bool + ForceUpgradeDownload bool + SSH string // SSH client executable + SSHGen string // SSH keygen executable + SSHKey string // SSH key to send to the vm + VM string // virtual machine name + Dir string // boot2docker directory + ISOURL string // Source URL to retrieve the ISO from + ISO string // boot2docker ISO image path + DiskSize uint // VM disk image size (MB) + Memory uint // VM memory size (MB) // NAT network: port forwarding SSHPort uint16 // host SSH port (forward to port 22 in VM) diff --git a/util.go b/util.go index fa072aa..5c8cab5 100644 --- a/util.go +++ b/util.go @@ -21,6 +21,11 @@ import ( "github.com/boot2docker/boot2docker-cli/driver" ) +var ( + // We're looking to get e.g. "1.2.0" from "Docker version 1.2.0, build fa7b24f" + versionRe = regexp.MustCompile(`(\d+\.?){3}`) +) + // Try if addr tcp://addr is readable for n times at wait interval. func read(addr string, n int, wait time.Duration) error { var lastErr error @@ -105,6 +110,7 @@ func getLatestReleaseName(url string) (string, error) { defer rsp.Body.Close() var t []struct { + Name string `json:"name"` TagName string `json:"tag_name"` } body, err := ioutil.ReadAll(rsp.Body) @@ -125,7 +131,27 @@ func getLatestReleaseName(url string) (string, error) { if len(t) == 0 { return "", fmt.Errorf("no releases found") } - return t[0].TagName, nil + + // Looking up by tag instead of release. + // Github API call for docker releases yields nothing, + // so we use tags API call in this case. + name := "" + if strings.Contains(url, "tags") { + name = t[0].Name + } else { + name = t[0].TagName + } + return name, nil +} + +func getLocalClientVersion() (string, error) { + versionOutput, err := exec.Command("docker", "-v").Output() + if err != nil { + return "", err + } + versionNumber := versionRe.FindString(string(versionOutput)) + + return versionNumber, nil } func cmdInteractive(m driver.Machine, args ...string) error { From 4a02ecaef40012977786877edecea919b8eb2ec3 Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Tue, 16 Dec 2014 13:29:52 -0800 Subject: [PATCH 126/167] Add small doc section on upgrade Signed-off-by: Nathan LeClaire --- README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/README.md b/README.md index 2455237..98c8776 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,40 @@ You can override the configurations using matching command-line flags. Type `boot2docker -h` for more information. The configuration file options are the same as the command-line flags with long names. +## Upgrade + +You can use boot2docker-cli to upgrade: + +1. The ISO you are using in the VM (and consequently the Docker daemon version) +2. The Docker client binary on your host system +3. The boot2docker-cli binary itself + +To do so, run the `boot2docker upgrade` command. + +``` +$ boot2docker upgrade +Backing up existing docker binary... +Downloading new docker client binary... +Success: downloaded https://get.docker.com/builds/Darwin/x86_64/docker-latest + to /usr/local/bin/docker + The old version is backed up to ~/.boot2docker. +Backing up existing boot2docker binary... +Downloading new boot2docker client binary... +Success: downloaded https://github.com/boot2docker/boot2docker-cli/releases/download/v1.4.0/boot2docker-v1.4.0-darwin-amd64 + to /usr/local/bin/boot2docker + The old version is backed up to ~/.boot2docker. +Latest release for boot2docker/boot2docker is v1.4.0 +Downloading boot2docker ISO image... +Success: downloaded https://github.com/boot2docker/boot2docker/releases/download/v1.4.0/boot2docker.iso + to /Users/youruser/.boot2docker/boot2docker.iso +Waiting for VM and Docker daemon to start... +.................ooo +Started. +``` + +This will back up your current `docker` and `boot2docker` binaries to +`~/.boot2docker` and download the latest ISO, `docker` binary and `boot2docker` +binary in place of the old versions. ## Contribution From ed7e00b2b9bd4effb9f1e55213355b1dadfdfe60 Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Tue, 16 Dec 2014 13:43:07 -0800 Subject: [PATCH 127/167] Add -v to go get as requested by @tianon Signed-off-by: Nathan LeClaire --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cef04d4..89066ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,8 +5,8 @@ FROM golang:1.3-cross WORKDIR /go/src/github.com/boot2docker/boot2docker-cli # Download (but not install) dependencies -RUN go get github.com/BurntSushi/toml -RUN go get github.com/ogier/pflag +RUN go get -v github.com/BurntSushi/toml +RUN go get -v github.com/ogier/pflag ADD . /go/src/github.com/boot2docker/boot2docker-cli From b9313209fad160ef85dfd5110faf3c39c961dbee Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Tue, 16 Dec 2014 14:01:52 -0800 Subject: [PATCH 128/167] Implement a few things from code review feedback Signed-off-by: Nathan LeClaire --- README.md | 2 +- cmds.go | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 98c8776..a48cd6e 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ You can use boot2docker-cli to upgrade: To do so, run the `boot2docker upgrade` command. -``` +```console $ boot2docker upgrade Backing up existing docker binary... Downloading new docker client binary... diff --git a/cmds.go b/cmds.go index 31c98e2..ff69f16 100644 --- a/cmds.go +++ b/cmds.go @@ -3,9 +3,8 @@ package main import ( "encoding/json" "fmt" - "net/http" - "io/ioutil" + "net/http" "os" "os/exec" "path/filepath" @@ -14,10 +13,9 @@ import ( "strings" "time" + "github.com/boot2docker/boot2docker-cli/driver" _ "github.com/boot2docker/boot2docker-cli/dummy" _ "github.com/boot2docker/boot2docker-cli/virtualbox" - - "github.com/boot2docker/boot2docker-cli/driver" ) // Initialize the boot2docker VM from scratch. @@ -332,7 +330,7 @@ func upgradeBoot2DockerBinary() error { goos = runtime.GOOS case "windows": goos = "windows" - arch = "windows" + arch = "amd64" ext = ".exe" default: return fmt.Errorf("Operating system not supported") From 051d76630103b6cddf0bb54bb170d80a12b14ddc Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Tue, 16 Dec 2014 14:07:11 -0800 Subject: [PATCH 129/167] go vet Signed-off-by: Nathan LeClaire --- cmds.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds.go b/cmds.go index ff69f16..44c8e33 100644 --- a/cmds.go +++ b/cmds.go @@ -420,7 +420,7 @@ func backupAndDownload(binaryUrl, binaryName, localVersion string) error { func backupBinary(binaryName, localVersion, path string) error { dir, err := cfgDir(".boot2docker") if err != nil { - return fmt.Errorf("Error getting boot2docker config dir", err) + return fmt.Errorf("Error getting boot2docker config dir: %s", err) } buf, err := ioutil.ReadFile(path) if err != nil { @@ -428,7 +428,7 @@ func backupBinary(binaryName, localVersion, path string) error { } backupName := fmt.Sprintf("%s-%s", binaryName, localVersion) if err := ioutil.WriteFile(filepath.Join(dir, backupName), buf, 0755); err != nil { - return fmt.Errorf("Error creating backup file", err) + return fmt.Errorf("Error creating backup file: %s", err) } return nil } From 6b12c9bb6caa62cb63a4a8bd89bcc40227fe040f Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Tue, 16 Dec 2014 14:52:52 -0800 Subject: [PATCH 130/167] Revise clobber flag default code Signed-off-by: Nathan LeClaire --- config.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/config.go b/config.go index d7bc1f0..23f300c 100644 --- a/config.go +++ b/config.go @@ -93,12 +93,11 @@ func config() (*flag.FlagSet, error) { B2D.Dir = dir flags.StringVar(&B2D.ISOURL, "iso-url", "https://api.github.com/repos/boot2docker/boot2docker/releases", "source URL to provision the boot2docker ISO image.") flags.StringVar(&B2D.ISO, "iso", filepath.Join(dir, "boot2docker.iso"), "path to boot2docker ISO image.") - if runtime.GOOS == "darwin" { - // clobber by default - flags.BoolVar(&B2D.Clobber, "clobber", true, "overwrite Docker client binary on boot2docker upgrade") - } else { - flags.BoolVar(&B2D.Clobber, "clobber", false, "overwrite Docker client binary on boot2docker upgrade") - } + + // clobber (overwrite client binary) by default on OSX. it's more likely that + // users have installed through package manager on Linux, and if so, they should + // upgrade that way. + flags.BoolVar(&B2D.Clobber, "clobber", (runtime.GOOS == "darwin"), "overwrite Docker client binary on boot2docker upgrade") flags.BoolVar(&B2D.ForceUpgradeDownload, "force-upgrade-download", false, "always download on boot2docker upgrade, never skip") From 43241cbf042744b5587978badb46121ad9b0379b Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 16 Dec 2014 16:22:19 -0700 Subject: [PATCH 131/167] Bump to v1.4.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0d0c52f..66d62a8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.4.0 +v1.4.1 From 780245e1eda11428f62360f7019658ea0da28203 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 8 Jan 2015 09:26:11 -0700 Subject: [PATCH 132/167] Revert "Add Fusion driver and vmx template" --- cmds.go | 1 - driver/driver.go | 1 - dummy/machine.go | 8 +- fusion/machine.go | 278 ------------------------------------------ fusion/vmrun.go | 48 -------- fusion/vmx.go | 31 ----- util.go | 3 +- virtualbox/machine.go | 5 - 8 files changed, 3 insertions(+), 372 deletions(-) delete mode 100644 fusion/machine.go delete mode 100644 fusion/vmrun.go delete mode 100644 fusion/vmx.go diff --git a/cmds.go b/cmds.go index f91473e..44c8e33 100644 --- a/cmds.go +++ b/cmds.go @@ -15,7 +15,6 @@ import ( "github.com/boot2docker/boot2docker-cli/driver" _ "github.com/boot2docker/boot2docker-cli/dummy" - _ "github.com/boot2docker/boot2docker-cli/fusion" _ "github.com/boot2docker/boot2docker-cli/virtualbox" ) diff --git a/driver/driver.go b/driver/driver.go index a53c0bc..525ee9b 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -42,7 +42,6 @@ type Machine interface { AttachStorage(ctlName string, medium StorageMedium) error GetState() MachineState GetName() string - GetHostname() string GetSerialFile() string GetDockerPort() uint GetSSHPort() uint diff --git a/dummy/machine.go b/dummy/machine.go index ce34b35..cfc3f1d 100644 --- a/dummy/machine.go +++ b/dummy/machine.go @@ -47,9 +47,8 @@ func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { // Machine information. type Machine struct { - UUID string Name string - Hostname string + UUID string State driver.MachineState CPUs uint Memory uint // main memory (in MB) @@ -123,11 +122,6 @@ func (m *Machine) GetName() string { return m.Name } -// Get machine hostname -func (m *Machine) GetHostname() string { - return m.Hostname -} - // Get current state func (m *Machine) GetState() driver.MachineState { return m.State diff --git a/fusion/machine.go b/fusion/machine.go deleted file mode 100644 index 69e3257..0000000 --- a/fusion/machine.go +++ /dev/null @@ -1,278 +0,0 @@ -package fusion - -import ( - "bufio" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "text/template" - - "github.com/boot2docker/boot2docker-cli/driver" - "github.com/ogier/pflag" -) - -var ( - verbose bool // Verbose mode. - cfg DriverCfg -) - -type DriverCfg struct { - VMRUN string // Path to vmrun utility. - VDISKMAN string // Path to vdiskmanager utility. -} - -func init() { - if err := driver.Register("fusion", InitFunc); err != nil { - fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) - os.Exit(1) - } - if err := driver.RegisterConfig("fusion", ConfigFlags); err != nil { - fmt.Fprintf(os.Stderr, "Failed to initialize driver config. Error : %s", err.Error()) - os.Exit(1) - } -} - -// Initialize the Machine. -func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { - verbose = mc.Verbose - - m, err := GetMachine(getVMX(mc)) - if err != nil && mc.Init == true { - return CreateMachine(mc) - } - return m, err -} - -// Add cmdline params for this driver -func ConfigFlags(mc *driver.MachineConfig, flags *pflag.FlagSet) error { - cfg.VMRUN = "/Applications/VMware Fusion.app/Contents/Library/vmrun" - flags.StringVar(&cfg.VMRUN, "vmrun", cfg.VMRUN, "path to vmrun utility.") - - cfg.VDISKMAN = "/Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager" - flags.StringVar(&cfg.VDISKMAN, "vmdiskman", cfg.VDISKMAN, "path to vdiskmanager utility.") - - return nil -} - -// Machine information. -type Machine struct { - Name string - State driver.MachineState - CPUs uint64 - Memory uint64 // main memory (in MB) - VMX string - OSType string -} - -// Refresh reloads the machine information. -func (m *Machine) Refresh() error { - mm, err := GetMachine(m.VMX) - if err != nil { - return err - } - *m = *mm - return nil -} - -// Start starts the machine. -func (m *Machine) Start() error { - vmrun("start", m.VMX, "nogui") - return nil -} - -// Suspend suspends the machine and saves its state to disk. -func (m *Machine) Save() error { - vmrun("suspend", m.VMX, "nogui") - return nil -} - -// Pause pauses the execution of the machine. -func (m *Machine) Pause() error { - vmrun("pause", m.VMX, "nogui") - return nil -} - -// Stop gracefully stops the machine. -func (m *Machine) Stop() error { - vmrun("stop", m.VMX, "nogui") - return nil -} - -// Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. -func (m *Machine) Poweroff() error { - vmrun("stop", m.VMX, "nogui") - return nil -} - -// Restart gracefully restarts the machine. -func (m *Machine) Restart() error { - vmrun("reset", m.VMX, "nogui") - return nil -} - -// Reset forcefully restarts the machine. State is lost and might corrupt the disk image. -func (m *Machine) Reset() error { - vmrun("reset", m.VMX, "nogui") - return nil -} - -// Get vm name -func (m *Machine) GetName() string { - return m.Name -} - -// Get vm hostname -func (m *Machine) GetHostname() string { - stdout, _, _ := vmrun("getGuestIPAddress", m.VMX) - return strings.TrimSpace(stdout) -} - -// Get current state -func (m *Machine) GetState() driver.MachineState { - return m.State -} - -// Get serial file -func (m *Machine) GetSerialFile() string { - return "" -} - -// Get Docker port -func (m *Machine) GetDockerPort() uint { - return 2375 -} - -// Get SSH port -func (m *Machine) GetSSHPort() uint { - return 22 -} - -// Delete deletes the machine and associated disk images. -func (m *Machine) Delete() error { - vmrun("deleteVM", m.VMX, "nogui") - return nil -} - -// Modify changes the settings of the machine. -func (m *Machine) Modify() error { - fmt.Printf("Hot modify not supported") - return m.Refresh() -} - -// AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. -func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { - fmt.Println("Add NAT PF") - return nil -} - -// DelNATPF deletes the NAT port forwarding rule with the given name from the n-th NIC. -func (m *Machine) DelNATPF(n int, name string) error { - fmt.Println("Del NAT PF") - return nil -} - -// SetNIC set the n-th NIC. -func (m *Machine) SetNIC(n int, nic driver.NIC) error { - fmt.Println("Set NIC") - return nil -} - -// AddStorageCtl adds a storage controller with the given name. -func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { - fmt.Println("Add storage ctl") - return nil -} - -// DelStorageCtl deletes the storage controller with the given name. -func (m *Machine) DelStorageCtl(name string) error { - fmt.Println("Del storage ctl") - return nil -} - -// AttachStorage attaches a storage medium to the named storage controller. -func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { - fmt.Println("Attach storage") - return nil -} - -// GetMachine finds a machine. -func GetMachine(vmx string) (*Machine, error) { - if _, err := os.Stat(vmx); os.IsNotExist(err) { - return nil, ErrMachineNotExist - } - - m := &Machine{VMX: vmx, State: driver.Poweroff} - - // VMRUN only tells use if the vm is running or not - if stdout, _, _ := vmrun("list"); strings.Contains(stdout, m.VMX) { - m.State = driver.Running - } - - // Parse the vmx file - vmxfile, err := os.Open(vmx) - if err != nil { - return m, err - } - defer vmxfile.Close() - - vmxscan := bufio.NewScanner(vmxfile) - for vmxscan.Scan() { - if vmxtokens := strings.Split(vmxscan.Text(), " = "); len(vmxtokens) > 1 { - vmxkey := strings.TrimSpace(vmxtokens[0]) - vmxvalue, _ := strconv.Unquote(vmxtokens[1]) - switch vmxkey { - case "displayName": - m.Name = vmxvalue - case "guestOS": - m.OSType = vmxvalue - case "memsize": - m.Memory, _ = strconv.ParseUint(vmxvalue, 10, 0) - case "numvcpus": - m.CPUs, _ = strconv.ParseUint(vmxvalue, 10, 0) - } - } - } - return m, nil -} - -// CreateMachine creates a new virtual machine. -func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { - if err := os.MkdirAll(getBaseFolder(mc), 0755); err != nil { - return nil, err - } - - if _, err := os.Stat(getVMX(mc)); err == nil { - return nil, ErrMachineExist - } - - // Generate vmx config file from template - vmxt := template.Must(template.New("vmx").Parse(vmx)) - vmxfile, err := os.Create(getVMX(mc)) - if err != nil { - return nil, err - } - vmxt.Execute(vmxfile, mc) - - // Generate vmdk file - diskImg := filepath.Join(getBaseFolder(mc), fmt.Sprintf("%s.vmdk", mc.VM)) - if _, err := os.Stat(diskImg); err != nil { - if !os.IsNotExist(err) { - return nil, err - } - - if err := vdiskmanager(diskImg, mc.DiskSize); err != nil { - return nil, err - } - } - - return nil, nil -} - -func getBaseFolder(mc *driver.MachineConfig) string { - return filepath.Join(mc.Dir, mc.VM) -} -func getVMX(mc *driver.MachineConfig) string { - return filepath.Join(getBaseFolder(mc), fmt.Sprintf("%s.vmx", mc.VM)) -} diff --git a/fusion/vmrun.go b/fusion/vmrun.go deleted file mode 100644 index ba36419..0000000 --- a/fusion/vmrun.go +++ /dev/null @@ -1,48 +0,0 @@ -package fusion - -import ( - "bytes" - "errors" - "fmt" - "log" - "os/exec" - "strings" -) - -var ( - ErrMachineExist = errors.New("machine already exists") - ErrMachineNotExist = errors.New("machine does not exist") - ErrVMRUNNotFound = errors.New("VMRUN not found") -) - -func vmrun(args ...string) (string, string, error) { - cmd := exec.Command(cfg.VMRUN, args...) - if verbose { - log.Printf("executing: %v %v", cfg.VMRUN, strings.Join(args, " ")) - } - - var stdout bytes.Buffer - var stderr bytes.Buffer - cmd.Stdout, cmd.Stderr = &stdout, &stderr - - err := cmd.Run() - if err != nil { - if ee, ok := err.(*exec.Error); ok && ee == exec.ErrNotFound { - err = ErrVMRUNNotFound - } - } - - return stdout.String(), stderr.String(), err -} - -// Make a vmdk disk image with the given size (in MB). -func vdiskmanager(dest string, size uint) error { - cmd := exec.Command(cfg.VDISKMAN, "-c", "-t", "0", "-s", fmt.Sprintf("%dMB", size), "-a", "lsilogic", dest) - - if stdout := cmd.Run(); stdout != nil { - if ee, ok := stdout.(*exec.Error); ok && ee == exec.ErrNotFound { - return ErrVMRUNNotFound - } - } - return nil -} diff --git a/fusion/vmx.go b/fusion/vmx.go deleted file mode 100644 index 2b467ba..0000000 --- a/fusion/vmx.go +++ /dev/null @@ -1,31 +0,0 @@ -package fusion - -const vmx = ` -.encoding = "UTF-8" -config.version = "8" -displayName = "{{.VM}}" -ethernet0.addressType = "generated" -ethernet0.connectionType = "nat" -ethernet0.linkStatePropagation.enable = "TRUE" -ethernet0.present = "TRUE" -ethernet0.virtualDev = "e1000" -ethernet0.wakeOnPcktRcv = "FALSE" -floppy0.present = "FALSE" -guestOS = "other26xlinux-64" -hpet0.present = "TRUE" -ide1:0.deviceType = "cdrom-image" -ide1:0.fileName = "{{.ISO}}" -ide1:0.present = "TRUE" -mem.hotadd = "TRUE" -memsize = "{{.Memory}}" -powerType.powerOff = "soft" -powerType.powerOn = "soft" -powerType.reset = "soft" -powerType.suspend = "soft" -scsi0.present = "TRUE" -scsi0.virtualDev = "lsilogic" -scsi0:0.fileName = "{{.VM}}.vmdk" -scsi0:0.present = "TRUE" -virtualHW.productCompatibility = "hosted" -virtualHW.version = "10" -` diff --git a/util.go b/util.go index 6ace43b..5c8cab5 100644 --- a/util.go +++ b/util.go @@ -194,6 +194,7 @@ func reader(r io.Reader) { } func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { + DefaultSSHArgs := []string{ "-o", "IdentitiesOnly=yes", "-o", "StrictHostKeyChecking=no", @@ -201,7 +202,7 @@ func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." "-p", fmt.Sprintf("%d", m.GetSSHPort()), "-i", B2D.SSHKey, - fmt.Sprintf("docker@%s", m.GetHostname()), + "docker@localhost", } sshArgs := append(DefaultSSHArgs, args...) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index b9a5b00..9711a35 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -308,11 +308,6 @@ func (m *Machine) GetName() string { return m.Name } -// Get machine hostname -func (m *Machine) GetHostname() string { - return "localhost" -} - // Get current state func (m *Machine) GetState() driver.MachineState { return m.State From 61a5a04e789dc753aee7331eca15e24dd525c9dd Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 8 Jan 2015 09:49:46 -0700 Subject: [PATCH 133/167] Add "Pending Deprecation" notice to README --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a48cd6e..652e3a7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ +# Pending Deprecation + +This project is officially in bug fixing/maintenance mode in favor of all +concerted effort going towards [Docker +Machine](https://github.com/docker/machine) instead. Merging of complex +features will require some pretty strong convincing as to why they should exist +here, and not instead be proposed for Docker Machine. + # boot2docker command line management tool This tool downloads the boot2docker ISO image, creates a VirtualBox virtual From bbabbab0083b5722d442f5d6e2f704afb1ddf773 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 5 Feb 2015 13:47:20 -0700 Subject: [PATCH 134/167] Convert .travis.yml to use "gimme" and update to Go 1.4 --- .travis.yml | 14 ++++++-------- Dockerfile | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3391bd5..0fac609 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,19 @@ language: go -# this should be exactly the same as what's in the Dockerfile -go: 1.3 +go: + - 1.4.1 + - 1.3.3 # let us have pretty experimental Docker-based Travis workers sudo: false env: - - _GOOS=linux _GOARCH=amd64 - - _GOOS=darwin _GOARCH=amd64 - - _GOOS=windows _GOARCH=amd64 + - GIMME_OS=linux GIMME_ARCH=amd64 + - GIMME_OS=darwin GIMME_ARCH=amd64 + - GIMME_OS=windows GIMME_ARCH=amd64 install: - env | sort - - gvm cross "$_GOOS" "$_GOARCH" - - export GOOS="$_GOOS" GOARCH="$_GOARCH" - - go env - go get -d -v ./... script: diff --git a/Dockerfile b/Dockerfile index 89066ca..a5a19eb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,12 @@ # Dockerfile to cross compile boot2docker-cli -FROM golang:1.3-cross +FROM golang:1.4-cross WORKDIR /go/src/github.com/boot2docker/boot2docker-cli # Download (but not install) dependencies RUN go get -v github.com/BurntSushi/toml -RUN go get -v github.com/ogier/pflag +RUN go get -v github.com/ogier/pflag ADD . /go/src/github.com/boot2docker/boot2docker-cli From ccd9032caf251ca63edaf3a0808456fa5d5f9057 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 10 Feb 2015 16:31:39 -0700 Subject: [PATCH 135/167] Bump to v1.5.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 66d62a8..2e7bd91 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.4.1 +v1.5.0 From b454359f2e1d8289fac3b738426a76bece1b45ba Mon Sep 17 00:00:00 2001 From: Mohit Soni Date: Sat, 7 Feb 2015 10:55:50 -0800 Subject: [PATCH 136/167] Configure CPUs #209 --- README.md | 3 +++ config.go | 1 + driver/config.go | 1 + virtualbox/machine.go | 6 +++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 652e3a7..55f5628 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,9 @@ DiskSize = 20000 # VM memory size in MB Memory = 2048 +# Number of CPUs +CPUs = 1 + # host port forwarding to port 22 in the VM SSHPort = 2022 diff --git a/config.go b/config.go index 23f300c..31d2342 100644 --- a/config.go +++ b/config.go @@ -116,6 +116,7 @@ func config() (*flag.FlagSet, error) { flags.StringVar(&B2D.SSHKey, "sshkey", filepath.Join(sshdir, "id_boot2docker"), "path to SSH key to use.") flags.UintVarP(&B2D.DiskSize, "disksize", "s", 20000, "boot2docker disk image size (in MB).") flags.UintVarP(&B2D.Memory, "memory", "m", 2048, "virtual machine memory size (in MB).") + flags.UintVarP(&B2D.CPUs, "cpus", "c", uint(runtime.NumCPU()), "number of CPUs for boot2docker.") flags.Uint16Var(&B2D.SSHPort, "sshport", 2022, "host SSH port (forward to port 22 in VM).") flags.Uint16Var(&B2D.DockerPort, "dockerport", 0, "host Docker port (forward to port 2376 in VM). (deprecated - use with care)") flags.IPVar(&B2D.HostIP, "hostip", net.ParseIP("192.168.59.3"), "VirtualBox host-only network IP address.") diff --git a/driver/config.go b/driver/config.go index a450ff6..b3841e5 100644 --- a/driver/config.go +++ b/driver/config.go @@ -26,6 +26,7 @@ type MachineConfig struct { ISO string // boot2docker ISO image path DiskSize uint // VM disk image size (MB) Memory uint // VM memory size (MB) + CPUs uint // Number of CPUs // NAT network: port forwarding SSHPort uint16 // host SSH port (forward to port 22 in VM) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 9711a35..dca7ef6 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -466,7 +466,11 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { // Configure VM for Boot2docker SetExtra(mc.VM, "VBoxInternal/CPUM/EnableHVP", "1") m.OSType = "Linux26_64" - m.CPUs = uint(runtime.NumCPU()) + if mc.CPUs > 0 { + m.CPUs = mc.CPUs + } else { + m.CPUs = uint(runtime.NumCPU()) + } if m.CPUs > 32 { m.CPUs = 32 } From d970599fe6ce3a301e4c6a598bc15bfd357de026 Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Wed, 11 Feb 2015 17:53:10 -0800 Subject: [PATCH 137/167] ErrMachineNotExist msg: Fix grammar, more helpful This adds the word "does" to make it sound nicer and it also asks if the user ran `boot2docker init`. --- driver/driver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/driver.go b/driver/driver.go index 525ee9b..1efa0b9 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -52,7 +52,7 @@ var ( machines map[string]InitFunc ErrNotSupported = errors.New("driver not supported") - ErrMachineNotExist = errors.New("machine not exist") + ErrMachineNotExist = errors.New("machine does not exist (Did you run `boot2docker init`?)") ErrMachineExist = errors.New("machine already exists") ErrPrerequisites = errors.New("prerequisites for machine not satisfied (hypervisor installed?)") ) From 2fa8dc39bfabbd61f7b4bebb4b0540209d61e80d Mon Sep 17 00:00:00 2001 From: Marc Abramowitz Date: Wed, 11 Feb 2015 18:05:46 -0800 Subject: [PATCH 138/167] Extract vmNotRunningError and make the error message suggest possible action to take --- cmds.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cmds.go b/cmds.go index 44c8e33..1da9479 100644 --- a/cmds.go +++ b/cmds.go @@ -18,6 +18,10 @@ import ( _ "github.com/boot2docker/boot2docker-cli/virtualbox" ) +func vmNotRunningError(vmName string) error { + return fmt.Errorf("VM %q is not running. (Did you run `boot2docker up`?)", vmName) +} + // Initialize the boot2docker VM from scratch. func cmdInit() error { B2D.Init = false @@ -165,7 +169,7 @@ func cmdShellInit() error { } if m.GetState() != driver.Running { - return fmt.Errorf("VM %q is not running.", B2D.VM) + return vmNotRunningError(B2D.VM) } socket, err := RequestSocketFromSSH(m) @@ -506,7 +510,7 @@ func cmdSSH() error { } if m.GetState() != driver.Running { - return fmt.Errorf("VM %q is not running.", B2D.VM) + return vmNotRunningError(B2D.VM) } // find the ssh cmd string and then pass any remaining strings to ssh @@ -530,7 +534,7 @@ func cmdIP() error { } if m.GetState() != driver.Running { - return fmt.Errorf("VM %q is not running.", B2D.VM) + return vmNotRunningError(B2D.VM) } IP := "" From 866271327b8dada8f86137e88da8a09f49515866 Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Thu, 5 Feb 2015 21:03:07 +0100 Subject: [PATCH 139/167] Support github enterprise release urls for ISO --- cmds.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cmds.go b/cmds.go index 44c8e33..fad228c 100644 --- a/cmds.go +++ b/cmds.go @@ -564,16 +564,24 @@ func cmdIP() error { func cmdDownload() error { url := B2D.ISOURL - re := regexp.MustCompile("https://api.github.com/repos/([^/]+)/([^/]+)/releases") - if matches := re.FindStringSubmatch(url); len(matches) == 3 { + // match github (enterprise) release urls: + // https://api.github.com/repos/../../relases or + // https://some.github.enterprise/api/v3/repos/../../relases + re := regexp.MustCompile("https://([^/]+)(/api/v3)?/repos/([^/]+)/([^/]+)/releases") + if matches := re.FindStringSubmatch(url); len(matches) == 5 { tag, err := getLatestReleaseName(url) if err != nil { return fmt.Errorf("Failed to get latest release: %s", err) } - org := matches[1] - repo := matches[2] + host := matches[1] + org := matches[3] + repo := matches[4] fmt.Printf("Latest release for %s/%s is %s\n", org, repo, tag) - url = fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/boot2docker.iso", org, repo, tag) + if host == "api.github.com" { + url = fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/boot2docker.iso", org, repo, tag) + } else { + url = fmt.Sprintf("https://%s/%s/%s/releases/download/%s/boot2docker.iso", host, org, repo, tag) + } } fmt.Println("Downloading boot2docker ISO image...") From bdae52fada74fa4277ab4f8a880af973c021e747 Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Fri, 6 Feb 2015 09:26:14 +0100 Subject: [PATCH 140/167] Simplify download url generation --- cmds.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmds.go b/cmds.go index fad228c..1c6409c 100644 --- a/cmds.go +++ b/cmds.go @@ -576,12 +576,11 @@ func cmdDownload() error { host := matches[1] org := matches[3] repo := matches[4] - fmt.Printf("Latest release for %s/%s is %s\n", org, repo, tag) if host == "api.github.com" { - url = fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/boot2docker.iso", org, repo, tag) - } else { - url = fmt.Sprintf("https://%s/%s/%s/releases/download/%s/boot2docker.iso", host, org, repo, tag) + host = "github.com" } + fmt.Printf("Latest release for %s/%s/%s is %s\n", host, org, repo, tag) + url = fmt.Sprintf("https://%s/%s/%s/releases/download/%s/boot2docker.iso", host, org, repo, tag) } fmt.Println("Downloading boot2docker ISO image...") From c02693450195ec5b2f8e0ae5c580a148a9a424c9 Mon Sep 17 00:00:00 2001 From: waltari Date: Tue, 24 Feb 2015 17:02:39 +0900 Subject: [PATCH 141/167] Remove Go 1.3 support --- .travis.yml | 1 - README.md | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0fac609..f6e163f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: go go: - 1.4.1 - - 1.3.3 # let us have pretty experimental Docker-based Travis workers sudo: false diff --git a/README.md b/README.md index 652e3a7..cec6a98 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ and `make` installed. ### Install from source -You need to have the [Go compiler (v1.3 or higher)](http://golang.org) installed, and `$GOPATH` +You need to have the [Go compiler (v1.4 or higher)](http://golang.org) installed, and `$GOPATH` [properly setup](http://golang.org/doc/code.html#GOPATH). Then run go get github.com/boot2docker/boot2docker-cli @@ -77,7 +77,7 @@ You can cross compile to OS X, Windows, and Linux. For that you need to first [make your Go compiler ready for cross compiling to the target platforms](http://stackoverflow.com/questions/12168873/cross-compile-go-on-osx). -Please make sure you build with golang v1.3 or later - it is required for +Please make sure you build with golang v1.4 or later - it is required for `boot2docker download` to work on OS X. We provide a Makefile to make the process a bit easier. From 0be3cf75579e571d44febc0b3c18537ff3eff890 Mon Sep 17 00:00:00 2001 From: waltari Date: Wed, 24 Dec 2014 14:14:45 +0900 Subject: [PATCH 142/167] Improve removing the library path --- virtualbox/vbm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/virtualbox/vbm.go b/virtualbox/vbm.go index bbb5630..ed166dd 100644 --- a/virtualbox/vbm.go +++ b/virtualbox/vbm.go @@ -18,8 +18,8 @@ import ( func init() { if runtime.GOOS == "darwin" { // remove DYLD_LIBRARY_PATH and LD_LIBRARY_PATH as they break VBoxManage on OSX - os.Setenv("DYLD_LIBRARY_PATH", "") - os.Setenv("LD_LIBRARY_PATH", "") + os.Unsetenv("DYLD_LIBRARY_PATH") + os.Unsetenv("LD_LIBRARY_PATH") } } From 941c70cb0137acccd36c2f8ef9426a12ddc58ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Fut=C3=A1sz?= Date: Fri, 27 Feb 2015 10:42:22 +0100 Subject: [PATCH 143/167] fix IPV6NetworkMaskPrefixLength value parsing #347 --- virtualbox/hostonlynet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virtualbox/hostonlynet.go b/virtualbox/hostonlynet.go index 305c245..6e25699 100644 --- a/virtualbox/hostonlynet.go +++ b/virtualbox/hostonlynet.go @@ -100,7 +100,7 @@ func HostonlyNets() (map[string]*HostonlyNet, error) { case "IPV6Address": n.IPv6.IP = net.ParseIP(val) case "IPV6NetworkMaskPrefixLength": - l, err := strconv.ParseUint(val, 10, 7) + l, err := strconv.ParseUint(val, 10, 8) if err != nil { return nil, err } From 792d7eb3adabc22b609286507e93ffc4897de2ea Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Thu, 12 Feb 2015 23:21:00 +0100 Subject: [PATCH 144/167] add boot2docker ip to NO_PROXY list The docker client respects the HTTP_PROXY environment variable for api calls since version 1.5. This kind of breaks the boot2docker scenario because docker is running on a local VM which most most certainly won't be reachable by the proxy. This commit changes `boot2docker shellinit` to append the DOCKER_HOST to the NO_PROXY variable. --- cmds.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cmds.go b/cmds.go index fbe78ef..b294e9c 100644 --- a/cmds.go +++ b/cmds.go @@ -228,6 +228,34 @@ func exports(socket, certPath string) map[string]string { out["DOCKER_TLS_VERIFY"] = "1" } + //if a http_proxy is set, we need to make sure the boot2docker ip + //is added to the NO_PROXY environment variable + if os.Getenv("http_proxy") != "" || os.Getenv("HTTP_PROXY") != "" { + //get the ip from the docket/DOCKER_HOST + re := regexp.MustCompile("tcp://([^:]+):") + if matches := re.FindStringSubmatch(socket); len(matches) == 2 { + ip := matches[1] + + //first check for an existing lower case no_proxy var + no_proxy_var := "no_proxy" + no_proxy_value := os.Getenv("no_proxy") + //otherweise try allcaps HTTP_PROXY + if no_proxy_value == "" { + no_proxy_var = "NO_PROXY" + no_proxy_value = os.Getenv("NO_PROXY") + } + + switch { + case no_proxy_value == "": + out[no_proxy_var] = ip + case strings.Contains(no_proxy_value, ip): + out[no_proxy_var] = no_proxy_value + default: + out[no_proxy_var] = fmt.Sprintf("%s,%s", no_proxy_value, ip) + } + } + } + return out } From 3c74ca3a22b2a860041df72a3875c2293f324166 Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Thu, 12 Mar 2015 21:40:13 +0100 Subject: [PATCH 145/167] fix typo --- cmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index b294e9c..1063783 100644 --- a/cmds.go +++ b/cmds.go @@ -231,7 +231,7 @@ func exports(socket, certPath string) map[string]string { //if a http_proxy is set, we need to make sure the boot2docker ip //is added to the NO_PROXY environment variable if os.Getenv("http_proxy") != "" || os.Getenv("HTTP_PROXY") != "" { - //get the ip from the docket/DOCKER_HOST + //get the ip from socket/DOCKER_HOST re := regexp.MustCompile("tcp://([^:]+):") if matches := re.FindStringSubmatch(socket); len(matches) == 2 { ip := matches[1] From 81f11e1d78d3ecca9b4f2c2908ae4529fb099239 Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Thu, 12 Mar 2015 21:42:58 +0100 Subject: [PATCH 146/167] shorten local variable names no_proxy_var -> name no_proxy_value -> val --- cmds.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cmds.go b/cmds.go index 1063783..2a8e47b 100644 --- a/cmds.go +++ b/cmds.go @@ -237,21 +237,21 @@ func exports(socket, certPath string) map[string]string { ip := matches[1] //first check for an existing lower case no_proxy var - no_proxy_var := "no_proxy" - no_proxy_value := os.Getenv("no_proxy") //otherweise try allcaps HTTP_PROXY - if no_proxy_value == "" { - no_proxy_var = "NO_PROXY" - no_proxy_value = os.Getenv("NO_PROXY") + name := "no_proxy" + val := os.Getenv("no_proxy") + if val == "" { + name = "NO_PROXY" + val = os.Getenv("NO_PROXY") } switch { - case no_proxy_value == "": - out[no_proxy_var] = ip - case strings.Contains(no_proxy_value, ip): - out[no_proxy_var] = no_proxy_value + case val == "": + out[name] = ip + case strings.Contains(val, ip): + out[name] = val default: - out[no_proxy_var] = fmt.Sprintf("%s,%s", no_proxy_value, ip) + out[name] = fmt.Sprintf("%s,%s", val, ip) } } } From 59c644f36d70a853ae2da150618439fe02a1f752 Mon Sep 17 00:00:00 2001 From: Fabian Ruff Date: Thu, 12 Mar 2015 21:43:53 +0100 Subject: [PATCH 147/167] remove comments and empty lines --- cmds.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmds.go b/cmds.go index 2a8e47b..6cbdff5 100644 --- a/cmds.go +++ b/cmds.go @@ -235,9 +235,6 @@ func exports(socket, certPath string) map[string]string { re := regexp.MustCompile("tcp://([^:]+):") if matches := re.FindStringSubmatch(socket); len(matches) == 2 { ip := matches[1] - - //first check for an existing lower case no_proxy var - //otherweise try allcaps HTTP_PROXY name := "no_proxy" val := os.Getenv("no_proxy") if val == "" { @@ -255,7 +252,6 @@ func exports(socket, certPath string) map[string]string { } } } - return out } From 9b7526cfa18ec1414f7a03b1d338c402e732e3f5 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Wed, 25 Mar 2015 11:26:28 -0700 Subject: [PATCH 148/167] Correct way to find home directory on windows Signed-off-by: Ahmet Alp Balkan --- config.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/config.go b/config.go index 31d2342..fc82d40 100644 --- a/config.go +++ b/config.go @@ -22,11 +22,10 @@ var ( func homeDir() (string, error) { dir := "" - - // *nix and MSYS Windows - if dir = os.Getenv("HOME"); dir == "" { - // Windows (if not running under MSYS) + if runtime.GOOS == "windows" { dir = os.Getenv("USERPROFILE") + } else { + dir = os.Getenv("HOME") } if _, err := os.Stat(dir); err != nil { return "", err From b215553c1049ed5e3bb0b92dbbcc19e3647d69c4 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Wed, 25 Mar 2015 16:17:52 -0700 Subject: [PATCH 149/167] Fix shellinit output for cmd.exe/powershell Also fixes the issue with Windows paths with backslashes in the bash `export` statements. When shellinit/up executed on windows, prints instructions on how to set environment variables correctly for Windows Command Prompt (cmd.exe) and PowerShell. (only the powershell set path statements are printed to stdout; the rest goes to stderr). Signed-off-by: Ahmet Alp Balkan --- cmds.go | 76 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/cmds.go b/cmds.go index 6cbdff5..16be4c3 100644 --- a/cmds.go +++ b/cmds.go @@ -138,23 +138,17 @@ func cmdUp() error { // These errors are not fatal fmt.Fprintf(os.Stderr, "Warning: error copying certificates: %s\n", err) } - switch runtime.GOOS { - case "windows": - fmt.Printf("Docker client does not run on Windows for now. Please use\n") - fmt.Printf(" \"%s\" ssh\n", os.Args[0]) - fmt.Printf("to SSH into the VM instead.\n") - default: - if socket == "" { - fmt.Fprintf(os.Stderr, "Auto detection of the VM's Docker socket failed.\n") - fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.\n") + + if socket == "" { + fmt.Fprintf(os.Stderr, "Auto detection of the VM's Docker socket failed.\n") + fmt.Fprintf(os.Stderr, "Please run `boot2docker -v up` to diagnose.\n") + } else { + // Check if $DOCKER_* ENV vars are properly configured. + if !checkEnvironment(socket, certPath) { + fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") + printExport(socket, certPath) } else { - // Check if $DOCKER_* ENV vars are properly configured. - if !checkEnvironment(socket, certPath) { - fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") - printExport(socket, certPath) - } else { - fmt.Printf("Your environment variables are already set correctly.\n") - } + fmt.Printf("Your environment variables are already set correctly.\n") } } fmt.Printf("\n") @@ -189,6 +183,7 @@ func cmdShellInit() error { func checkEnvironment(socket, certPath string) bool { for name, value := range exports(socket, certPath) { + value = strings.Trim(value, `"'`) // remove surrounding quotes if os.Getenv(name) != value { return false } @@ -198,7 +193,20 @@ func checkEnvironment(socket, certPath string) bool { } func printExport(socket, certPath string) { - for name, value := range exports(socket, certPath) { + values := exports(socket, certPath) + if runtime.GOOS == "windows" && !isUnixShellOnWindows() { + printExportWindows(values) + } else { + printExportUnix(values) + } +} + +func isUnixShellOnWindows() bool { + return os.Getenv("TERM") != "" +} + +func printExportUnix(values map[string]string) { + for name, value := range values { switch filepath.Base(os.Getenv("SHELL")) { case "fish": if value == "" { @@ -216,12 +224,46 @@ func printExport(socket, certPath string) { } } +func printExportWindows(values map[string]string) { + // Print cmd.exe instructions to stderr + fmt.Fprintln(os.Stderr, "If you are running inside Windows Command Prompt (cmd.exe), copy and paste the") + fmt.Fprintln(os.Stderr, "following commands to your terminal to set the environment variables:") + for name, value := range values { + if value == "" { + fmt.Fprintf(os.Stderr, " set %s=\n", name) + } else { + fmt.Fprintf(os.Stderr, " set %s=%s\n", name, value) + } + } + fmt.Fprintln(os.Stderr, "") + // Print powershell instructions to stderr + fmt.Fprintln(os.Stderr, "If you are running inside PowerShell, copy or paste the following commands") + fmt.Fprintln(os.Stderr, `to your shell or run "boot2docker shellinit | Invoke-Expression" to set the`) + fmt.Fprintln(os.Stderr, "environment variables:") + + // Print powershell exports to stdout + for name, value := range values { + if value == "" { + fmt.Printf(" Remove-Item Env:\\%s\n", name) + } else { + fmt.Printf(" $Env:%s = \"%s\"\n", name, value) + } + } +} + func exports(socket, certPath string) map[string]string { out := make(map[string]string) out["DOCKER_HOST"] = socket out["DOCKER_CERT_PATH"] = certPath + if runtime.GOOS == "windows" && isUnixShellOnWindows() { + // Surround Windows-style paths with single quotes in exported path otherwise + // bash swallows the backslashes in export statements like: + // export DOCKER_CERT_PATH=C:\Users\ahmet\.boot2docker\certs\boot2docker-vm + out["DOCKER_CERT_PATH"] = fmt.Sprintf("'%s'", out["DOCKER_CERT_PATH"]) + } + if certPath == "" { out["DOCKER_TLS_VERIFY"] = "" } else { From 1a24269223af7b3ef0ca9b0cbfc46600ce156992 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Fri, 27 Mar 2015 14:11:37 -0700 Subject: [PATCH 150/167] Print only base binary name in usage string (win) When `boot2docker` is called from msys bash shell, usage string prints the full path of the binary (e.g. `c:\program file\boot2docker for windows\boot2docker.exe`) in the short usage string. This change fixes that without breaking the behavior on unix systems or cmd.exe/powershell on windows which already print the short binary name Signed-off-by: Ahmet Alp Balkan --- config.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.go b/config.go index fc82d40..d29b324 100644 --- a/config.go +++ b/config.go @@ -178,7 +178,8 @@ func config() (*flag.FlagSet, error) { } func usageShort() { - fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|shellinit|delete|download|upgrade|version} []\n", os.Args[0]) + binName := filepath.Base(os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|shellinit|delete|download|upgrade|version} []\n", binName) } func usageLong(flags *flag.FlagSet) { From 9894ae9dbe350c5b96602ed8b9bddb827d9b322b Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 16 Apr 2015 14:33:06 -0600 Subject: [PATCH 151/167] Update to 1.6.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 2e7bd91..b7c0a9b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.5.0 +v1.6.0 From 076b58db9c502bb88827ffeb37c9d8f7d60b448e Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 7 May 2015 16:51:49 -0600 Subject: [PATCH 152/167] Bump to 1.6.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b7c0a9b..0236045 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.6.0 +v1.6.1 From cb2c3bcc890d8ee67bb76cc91ecf5b63927c97f9 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 13 May 2015 16:19:19 -0600 Subject: [PATCH 153/167] Update to 1.6.2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0236045..d4f6e2c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.6.1 +v1.6.2 From bcd1a9d3b16ce797a106fdc9ae122f6fb06e1d98 Mon Sep 17 00:00:00 2001 From: lalyos Date: Mon, 18 May 2015 21:32:42 +0200 Subject: [PATCH 154/167] Add checkEnvironment call into cmdHellInit before printExport. The same as cmdUp does: "Your environment variables are already set correctly." written to stderr in case no actions needed. This way env correctness can be checked by in script by: if [[ "$(boot2docker-cli shellinit 2>/dev/null)" == "" ]]; then # env is ok else # env isn't correct fi --- cmds.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmds.go b/cmds.go index 16be4c3..6e45f79 100644 --- a/cmds.go +++ b/cmds.go @@ -176,7 +176,13 @@ func cmdShellInit() error { // These errors are not fatal fmt.Fprintf(os.Stderr, "Warning: error copying certificates: %s\n", err) } - printExport(socket, certPath) + + // Check if $DOCKER_* ENV vars are properly configured. + if !checkEnvironment(socket, certPath) { + printExport(socket, certPath) + } else { + fmt.Fprintf(os.Stderr, "Your environment variables are already set correctly.\n") + } return nil } From 036a5afc1a4fc939c2a2d35987fc26adc9d6c93b Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Wed, 10 Jun 2015 15:23:51 +0100 Subject: [PATCH 155/167] Make |boot2docker up| mention `eval "$(boot2docker shellinit)"` Whilst the boot2docker docs have been updated with the improved shellinit pattern that uses eval (see boot2docker/boot2docker#786), many unofficial boot2docker articles/guides still use the old form. To increase awareness of the corrected version, it's now output at the end of |boot2docker up|. Fixes #369. --- cmds.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmds.go b/cmds.go index 6e45f79..9c8044c 100644 --- a/cmds.go +++ b/cmds.go @@ -147,6 +147,7 @@ func cmdUp() error { if !checkEnvironment(socket, certPath) { fmt.Printf("\nTo connect the Docker client to the Docker daemon, please set:\n") printExport(socket, certPath) + fmt.Printf("\nOr run: `eval \"$(boot2docker shellinit)\"`\n") } else { fmt.Printf("Your environment variables are already set correctly.\n") } From e576f5997af130ccaba918ff7b816244d2e78daa Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Wed, 10 Jun 2015 15:45:55 +0100 Subject: [PATCH 156/167] Give the user more feedback upon a successful |boot2docker init| Previously there was zero output to the console if init completed successfully, which gave the impression that nothing had occurred. Now we explain that the VM has been initialized, as well as how to start it. --- cmds.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmds.go b/cmds.go index 6e45f79..57a5276 100644 --- a/cmds.go +++ b/cmds.go @@ -66,6 +66,8 @@ func cmdInit() error { if err != nil { return fmt.Errorf("Failed to initialize machine %q: %s", B2D.VM, err) } + fmt.Printf("Initialization of virtual machine %q complete.\n", B2D.VM) + fmt.Printf("Use `boot2docker up` to start it.\n") return nil } From 7d89508118ffbf5f3313cfa8a10d563942e3a643 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 18 Jun 2015 11:45:29 -0700 Subject: [PATCH 157/167] Bump to 1.7.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d4f6e2c..a20e2d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.6.2 +v1.7.0 From 849a4d31343af5a788d0b3301644ed59181e547a Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Tue, 14 Jul 2015 16:37:19 -0700 Subject: [PATCH 158/167] Fix issues related to upgrading to Virtualbox 5 Signed-off-by: Nathan LeClaire --- virtualbox/machine.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index dca7ef6..acbd146 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -28,7 +28,6 @@ const ( F_cpuhotplug F_pae F_longmode - F_synthcpu F_hpet F_hwvirtex F_triplefaultreset @@ -658,7 +657,6 @@ func (m *Machine) Modify() error { "--cpuhotplug", m.Flag.Get(F_cpuhotplug), "--pae", m.Flag.Get(F_pae), "--longmode", m.Flag.Get(F_longmode), - "--synthcpu", m.Flag.Get(F_synthcpu), "--hpet", m.Flag.Get(F_hpet), "--hwvirtex", m.Flag.Get(F_hwvirtex), "--triplefaultreset", m.Flag.Get(F_triplefaultreset), @@ -690,7 +688,7 @@ func (m *Machine) Modify() error { // AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { - return vbm("controlvm", m.Name, fmt.Sprintf("natpf%d", n), + return vbm("modifyvm", m.Name, fmt.Sprintf("--natpf%d", n), fmt.Sprintf("%s,%s", name, rule.Format())) } From 8fdc6f573bf08149b6311681800d55fda6e19e71 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 14 Jul 2015 16:50:53 -0700 Subject: [PATCH 159/167] Bump to 1.7.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a20e2d8..a97fc44 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.7.0 +v1.7.1 From ed13438b1c8eca329af23687282a65b4145922bb Mon Sep 17 00:00:00 2001 From: Matt Robenolt Date: Sun, 9 Aug 2015 00:30:33 -0700 Subject: [PATCH 160/167] Remove old `|| true` hack in Makefile The issue was resolved back before docker 1.0. --- Makefile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 1d69821..6d66304 100644 --- a/Makefile +++ b/Makefile @@ -12,14 +12,13 @@ default: dockerbuild @true # stop from matching "%" later -# Build binaries in Docker container. The `|| true` hack is a temporary fix for -# https://github.com/dotcloud/docker/issues/3986 +# Build binaries in Docker container. dockerbuild: clean docker build -t "$(DOCKER_IMAGE)" . docker run --name "$(DOCKER_CONTAINER)" "$(DOCKER_IMAGE)" - docker cp "$(DOCKER_CONTAINER)":"$(DOCKER_SRC_PATH)"/$(PREFIX)-$(VERSION)-darwin-$(GOARCH) . || true - docker cp "$(DOCKER_CONTAINER)":"$(DOCKER_SRC_PATH)"/$(PREFIX)-$(VERSION)-linux-$(GOARCH) . || true - docker cp "$(DOCKER_CONTAINER)":"$(DOCKER_SRC_PATH)"/$(PREFIX)-$(VERSION)-windows-$(GOARCH).exe . || true + docker cp "$(DOCKER_CONTAINER)":"$(DOCKER_SRC_PATH)"/$(PREFIX)-$(VERSION)-darwin-$(GOARCH) . + docker cp "$(DOCKER_CONTAINER)":"$(DOCKER_SRC_PATH)"/$(PREFIX)-$(VERSION)-linux-$(GOARCH) . + docker cp "$(DOCKER_CONTAINER)":"$(DOCKER_SRC_PATH)"/$(PREFIX)-$(VERSION)-windows-$(GOARCH).exe . docker rm "$(DOCKER_CONTAINER)" From a7e24a86b06dce41a78ef76045d80ecb82527339 Mon Sep 17 00:00:00 2001 From: Matt Robenolt Date: Sun, 9 Aug 2015 00:37:53 -0700 Subject: [PATCH 161/167] util: add missing newline at end of debug message Without this, the output looks like: ``` Waiting for VM and Docker daemon to start... .Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0).Connecting to tcp://localhost:2022 (attempt #0)VM Host-only IP address: ``` --- util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.go b/util.go index 5c8cab5..6116d89 100644 --- a/util.go +++ b/util.go @@ -31,7 +31,7 @@ func read(addr string, n int, wait time.Duration) error { var lastErr error for i := 0; i < n; i++ { if B2D.Verbose { - fmt.Printf("Connecting to tcp://%v (attempt #%d)", addr, i) + fmt.Printf("Connecting to tcp://%v (attempt #%d)\n", addr, i) } conn, err := net.DialTimeout("tcp", addr, 1*time.Second) if err != nil { From 63a8d4b3921d36c2409f28f10a001abb720ef86d Mon Sep 17 00:00:00 2001 From: Mary Anthony Date: Mon, 10 Aug 2015 11:13:17 -0700 Subject: [PATCH 162/167] Moving old install into docs on b2b Signed-off-by: Mary Anthony --- docs/images/bad_host.png | Bin 0 -> 27367 bytes docs/images/cool_view.png | Bin 0 -> 24385 bytes docs/images/good_host.png | Bin 0 -> 103234 bytes docs/images/kitematic.png | Bin 0 -> 14191 bytes docs/images/newsite_view.png | Bin 0 -> 21403 bytes docs/images/windows-boot2docker-cmd.png | Bin 0 -> 37436 bytes .../images/windows-boot2docker-powershell.png | Bin 0 -> 37945 bytes docs/images/windows-boot2docker-start.png | Bin 0 -> 253995 bytes docs/images/windows-installer.png | Bin 0 -> 191913 bytes docs/mac.md | 358 ++++++++++++++++++ docs/windows.md | 172 +++++++++ 11 files changed, 530 insertions(+) create mode 100644 docs/images/bad_host.png create mode 100644 docs/images/cool_view.png create mode 100644 docs/images/good_host.png create mode 100644 docs/images/kitematic.png create mode 100644 docs/images/newsite_view.png create mode 100644 docs/images/windows-boot2docker-cmd.png create mode 100644 docs/images/windows-boot2docker-powershell.png create mode 100644 docs/images/windows-boot2docker-start.png create mode 100644 docs/images/windows-installer.png create mode 100644 docs/mac.md create mode 100644 docs/windows.md diff --git a/docs/images/bad_host.png b/docs/images/bad_host.png new file mode 100644 index 0000000000000000000000000000000000000000..cdc78defc551464b2e6a9cbe4cca772dca08c0d1 GIT binary patch literal 27367 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 Myt*7z_HEGr0f)>+{Qv*} literal 0 HcmV?d00001 diff --git a/docs/images/good_host.png b/docs/images/good_host.png new file mode 100644 index 0000000000000000000000000000000000000000..58b9783d3affb130ecb5681a6877992ad2866198 GIT binary patch literal 103234 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 literal 0 HcmV?d00001 diff --git a/docs/images/kitematic.png b/docs/images/kitematic.png new file mode 100644 index 0000000000000000000000000000000000000000..5bb221ccf7d6849b941dad105dc6a887430bed16 GIT binary patch literal 14191 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 literal 0 HcmV?d00001 diff --git a/docs/images/newsite_view.png b/docs/images/newsite_view.png new file mode 100644 index 0000000000000000000000000000000000000000..27b6b1a4dd63330e4f57883d75c7719ae6f3acf0 GIT binary patch literal 21403 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 zℜ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 a=tf^iKJiFReE_aL0h(%hs#VGsA^!uE&_J^Q literal 0 HcmV?d00001 diff --git a/docs/images/windows-boot2docker-cmd.png b/docs/images/windows-boot2docker-cmd.png new file mode 100644 index 0000000000000000000000000000000000000000..09e3206ef97ecef230a24e13e9b25e106f7b576e GIT binary patch literal 37436 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 literal 0 HcmV?d00001 diff --git a/docs/images/windows-boot2docker-powershell.png b/docs/images/windows-boot2docker-powershell.png new file mode 100644 index 0000000000000000000000000000000000000000..b1ef89672619b3dd7f4c1ee7d269f221bec3395d GIT binary patch literal 37945 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®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

%P{4>xD(SVWI?8XVKdzOBkj(gR$$Nf`C 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%0ATSnl0MRgz8Yk95xPJ5>!by5ocP3Xph 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 z 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%0AB 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 z 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 Xp`6&kJHUR=?z?&2?ppcPCsF?gwmnej literal 0 HcmV?d00001 diff --git a/docs/mac.md b/docs/mac.md new file mode 100644 index 0000000..ee5fcaa --- /dev/null +++ b/docs/mac.md @@ -0,0 +1,358 @@ + + +# Mac OS X + +You can install Docker using Boot2Docker to run `docker` commands at your command-line. +Choose this installation if you are familiar with the command-line or plan to +contribute to the Docker project on GitHub. + +[Download Kitematic](https://kitematic.com/download) + +Alternatively, you may want to try Kitematic, an application that lets you set up Docker and +run containers using a graphical user interface (GUI). + +## Command-line Docker with Boot2Docker + +Because the Docker daemon uses Linux-specific kernel features, you can't run +Docker natively in OS X. Instead, you must install the Boot2Docker application. +The application includes a VirtualBox Virtual Machine (VM), Docker itself, and the +Boot2Docker management tool. + +The Boot2Docker management tool is a lightweight Linux virtual machine made +specifically to run the Docker daemon on Mac OS X. The VirtualBox VM runs +completely from RAM, is a small ~24MB download, and boots in approximately 5s. + +**Requirements** + +Your Mac must be running OS X 10.6 "Snow Leopard" or newer to run Boot2Docker. + +### Learn the key concepts before installing + +In a Docker installation on Linux, your machine is both the localhost and the +Docker host. In networking, localhost means your computer. The Docker host is +the machine on which the containers run. + +On a typical Linux installation, the Docker client, the Docker daemon, and any +containers run directly on your localhost. This means you can address ports on a +Docker container using standard localhost addressing such as `localhost:8000` or +`0.0.0.0:8376`. + +![Linux Architecture Diagram](/installation/images/linux_docker_host.svg) + +In an OS X installation, the `docker` daemon is running inside a Linux virtual +machine provided by Boot2Docker. + +![OSX Architecture Diagram](/installation/images/mac_docker_host.svg) + +In OS X, the Docker host address is the address of the Linux VM. +When you start the `boot2docker` process, the VM is assigned an IP address. Under +`boot2docker` ports on a container map to ports on the VM. To see this in +practice, work through the exercises on this page. + + +### Installation + +1. Go to the [boot2docker/osx-installer ]( + https://github.com/boot2docker/osx-installer/releases/latest) release page. + +4. Download Boot2Docker by clicking `Boot2Docker-x.x.x.pkg` in the "Downloads" + section. + +3. Install Boot2Docker by double-clicking the package. + + The installer places Boot2Docker and VirtualBox in your "Applications" folder. + +The installation places the `docker` and `boot2docker` binaries in your +`/usr/local/bin` directory. + + +## Start the Boot2Docker Application + +To run a Docker container, you first start the `boot2docker` VM and then issue +`docker` commands to create, load, and manage containers. You can launch +`boot2docker` from your Applications folder or from the command line. + +> **NOTE**: Boot2Docker is designed as a development tool. You should not use +> it in production environments. + +### From the Applications folder + +When you launch the "Boot2Docker" application from your "Applications" folder, the +application: + +* opens a terminal window + +* creates a $HOME/.boot2docker directory + +* creates a VirtualBox ISO and certs + +* starts a VirtualBox VM running the `docker` daemon + +Once the launch completes, you can run `docker` commands. A good way to verify +your setup succeeded is to run the `hello-world` container. + + $ docker run hello-world + Unable to find image 'hello-world:latest' locally + 511136ea3c5a: Pull complete + 31cbccb51277: Pull complete + e45a5af57b00: Pull complete + hello-world:latest: The image you are pulling has been verified. + Important: image verification is a tech preview feature and should not be + relied on to provide security. + Status: Downloaded newer image for hello-world:latest + Hello from Docker. + This message shows that your installation appears to be working correctly. + + To generate this message, Docker took the following steps: + 1. The Docker client contacted the Docker daemon. + 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. + (Assuming it was not already locally available.) + 3. The Docker daemon created a new container from that image which runs the + executable that produces the output you are currently reading. + 4. The Docker daemon streamed that output to the Docker client, which sent it + to your terminal. + + To try something more ambitious, you can run an Ubuntu container with: + $ docker run -it ubuntu bash + + For more examples and ideas, visit: + http://docs.docker.com/userguide/ + + +A more typical way to start and stop `boot2docker` is using the command line. + +### From your command line + +Initialize and run `boot2docker` from the command line, do the following: + +1. Create a new Boot2Docker VM. + + $ boot2docker init + + This creates a new virtual machine. You only need to run this command once. + +2. Start the `boot2docker` VM. + + $ boot2docker start + +3. Display the environment variables for the Docker client. + + $ boot2docker shellinit + Writing /Users/mary/.boot2docker/certs/boot2docker-vm/ca.pem + Writing /Users/mary/.boot2docker/certs/boot2docker-vm/cert.pem + Writing /Users/mary/.boot2docker/certs/boot2docker-vm/key.pem + export DOCKER_HOST=tcp://192.168.59.103:2376 + export DOCKER_CERT_PATH=/Users/mary/.boot2docker/certs/boot2docker-vm + export DOCKER_TLS_VERIFY=1 + + The specific paths and address on your machine will be different. + +4. To set the environment variables in your shell do the following: + + $ eval "$(boot2docker shellinit)" + + You can also set them manually by using the `export` commands `boot2docker` + returns. + +5. Run the `hello-world` container to verify your setup. + + $ docker run hello-world + + +## Basic Boot2Docker exercises + +At this point, you should have `boot2docker` running and the `docker` client +environment initialized. To verify this, run the following commands: + + $ boot2docker status + $ docker version + +Work through this section to try some practical container tasks using `boot2docker` VM. + +### Access container ports + +1. Start an NGINX container on the DOCKER_HOST. + + $ docker run -d -P --name web nginx + + Normally, the `docker run` commands starts a container, runs it, and then + exits. The `-d` flag keeps the container running in the background + after the `docker run` command completes. The `-P` flag publishes exposed ports from the + container to your local host; this lets you access them from your Mac. + +2. Display your running container with `docker ps` command + + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + 5fb65ff765e9 nginx:latest "nginx -g 'daemon of 3 minutes ago Up 3 minutes 0.0.0.0:49156->443/tcp, 0.0.0.0:49157->80/tcp web + + At this point, you can see `nginx` is running as a daemon. + +3. View just the container's ports. + + $ docker port web + 443/tcp -> 0.0.0.0:49156 + 80/tcp -> 0.0.0.0:49157 + + This tells you that the `web` container's port `80` is mapped to port + `49157` on your Docker host. + +4. Enter the `http://localhost:49157` address (`localhost` is `0.0.0.0`) in your browser: + + ![Bad Address](/installation/images/bad_host.png) + + This didn't work. The reason it doesn't work is your `DOCKER_HOST` address is + not the localhost address (0.0.0.0) but is instead the address of the + `boot2docker` VM. + +5. Get the address of the `boot2docker` VM. + + $ boot2docker ip + 192.168.59.103 + +6. Enter the `http://192.168.59.103:49157` address in your browser: + + ![Correct Addressing](/installation/images/good_host.png) + + Success! + +7. To stop and then remove your running `nginx` container, do the following: + + $ docker stop web + $ docker rm web + +### Mount a volume on the container + +When you start `boot2docker`, it automatically shares your `/Users` directory +with the VM. You can use this share point to mount directories onto your container. +The next exercise demonstrates how to do this. + +1. Change to your user `$HOME` directory. + + $ cd $HOME + +2. Make a new `site` directory. + + $ mkdir site + +3. Change into the `site` directory. + + $ cd site + +4. Create a new `index.html` file. + + $ echo "my new site" > index.html + +5. Start a new `nginx` container and replace the `html` folder with your `site` directory. + + $ docker run -d -P -v $HOME/site:/usr/share/nginx/html --name mysite nginx + +6. Get the `mysite` container's port. + + $ docker port mysite + 80/tcp -> 0.0.0.0:49166 + 443/tcp -> 0.0.0.0:49165 + +7. Open the site in a browser: + + ![My site page](/installation/images/newsite_view.png) + +8. Try adding a page to your `$HOME/site` in real time. + + $ echo "This is cool" > cool.html + +9. Open the new page in the browser. + + ![Cool page](/installation/images/cool_view.png) + +9. Stop and then remove your running `mysite` container. + + $ docker stop mysite + $ docker rm mysite + +## Upgrade Boot2Docker + +If you running Boot2Docker 1.4.1 or greater, you can upgrade Boot2Docker from +the command line. If you are running an older version, you should use the +package provided by the `boot2docker` repository. + +### From the command line + +To upgrade from 1.4.1 or greater, you can do this: + +1. Open a terminal on your local machine. + +2. Stop the `boot2docker` application. + + $ boot2docker stop + +3. Run the upgrade command. + + $ boot2docker upgrade + + +### Use the installer + +To upgrade any version of Boot2Docker, do this: + +1. Open a terminal on your local machine. + +2. Stop the `boot2docker` application. + + $ boot2docker stop + +3. Go to the [boot2docker/osx-installer ]( + https://github.com/boot2docker/osx-installer/releases/latest) release page. + +4. Download Boot2Docker by clicking `Boot2Docker-x.x.x.pkg` in the "Downloads" + section. + +2. Install Boot2Docker by double-clicking the package. + + The installer places Boot2Docker in your "Applications" folder. + + +## Uninstallation + +1. Go to the [boot2docker/osx-installer ]( + https://github.com/boot2docker/osx-installer/releases/latest) release page. + +2. Download the source code by clicking `Source code (zip)` or + `Source code (tar.gz)` in the "Downloads" section. + +3. Extract the source code. + +4. Open a terminal on your local machine. + +5. Change to the directory where you extracted the source code: + + $ cd + +6. Make sure the uninstall.sh script is executable: + + $ chmod +x uninstall.sh + +7. Run the uninstall.sh script: + + $ ./uninstall.sh + + +## Learning more and acknowledgement + +Use `boot2docker help` to list the full command line reference. For more +information about using SSH or SCP to access the Boot2Docker VM, see the README +at [Boot2Docker repository](https://github.com/boot2docker/boot2docker). + +Thanks to Chris Jones whose [blog](http://viget.com/extend/how-to-use-docker-on-os-x-the-missing-guide) +inspired me to redo this page. + +Continue with the [Docker User Guide](/userguide). diff --git a/docs/windows.md b/docs/windows.md new file mode 100644 index 0000000..974e687 --- /dev/null +++ b/docs/windows.md @@ -0,0 +1,172 @@ + + +# Windows +> **Note:** +> Docker has been tested on Windows 7 and 8.1; it may also run on older versions. +> Your processor needs to support hardware virtualization. + +The Docker Engine uses Linux-specific kernel features, so to run it on Windows +we need to use a lightweight virtual machine (VM). You use the **Windows Docker +Client** to control the virtualized Docker Engine to build, run, and manage +Docker containers. + +To make this process easier, we've designed a helper application called +[Boot2Docker](https://github.com/boot2docker/boot2docker) creates a Linux virtual +machine on Windows to run Docker on a Linux operating system. + +Although you will be using Windows Docker client, the docker engine hosting the +containers will still be running on Linux. Until the Docker engine for Windows +is developed, you can launch only Linux containers from your Windows machine. + +![Windows Architecture Diagram](/installation/images/win_docker_host.svg) + +## Demonstration + + + +## Installation + +1. Download the latest release of the + [Docker for Windows Installer](https://github.com/boot2docker/windows-installer/releases/latest). +2. Run the installer, which will install Docker Client for Windows, VirtualBox, + Git for Windows (MSYS-git), the boot2docker Linux ISO, and the Boot2Docker + management tool. + ![](/installation/images/windows-installer.png) +3. Run the **Boot2Docker Start** shortcut from your Desktop or “Program Files → + Boot2Docker for Windows”. + The Start script will ask you to enter an ssh key passphrase - the simplest + (but least secure) is to just hit [Enter]. + +4. The **Boot2Docker Start** will start a unix shell already configured to manage + Docker running inside the virtual machine. Run `docker version` to see + if it is working correctly: + +![](/installation/images/windows-boot2docker-start.png) + +## Running Docker + +> **Note:** if you are using a remote Docker daemon, such as Boot2Docker, +> then _do not_ type the `sudo` before the `docker` commands shown in the +> documentation's examples. + +**Boot2Docker Start** will automatically start a shell with environment variables +correctly set so you can start using Docker right away: + +Let's try the `hello-world` example image. Run + + $ docker run hello-world + +This should download the very small `hello-world` image and print a +`Hello from Docker.` message. + +## Using Docker from Windows Command Line Prompt (cmd.exe) + +Launch a Windows Command Line Prompt (cmd.exe). + +Boot2Docker command requires `ssh.exe` to be in the PATH, therefore we need to +include `bin` folder of the Git installation (which has ssh.exe) to the `%PATH%` +environment variable by running: + + set PATH=%PATH%;"c:\Program Files (x86)\Git\bin" + +and then we can run the `boot2docker start` command to start the Boot2Docker VM. +(Run `boot2docker init` command if you get an error saying machine does not +exist.) Then copy the instructions for cmd.exe to set the environment variables +to your console window and you are ready to run docker commands such as +`docker ps`: + +![](/installation/images/windows-boot2docker-cmd.png) + +## Using Docker from PowerShell + +Launch a PowerShell window, then you need to add `ssh.exe` to your PATH: + + $Env:Path = "${Env:Path};c:\Program Files (x86)\Git\bin" + +and after running `boot2docker start` command it will print PowerShell commands +to set the environment variables to connect Docker running inside VM. Run these +commands and you are ready to run docker commands such as `docker ps`: + +![](/installation/images/windows-boot2docker-powershell.png) + +> NOTE: You can alternatively run `boot2docker shellinit | Invoke-Expression` +> command to set the environment variables instead of copying and pasting on +> PowerShell. + +# Further Details + +The Boot2Docker management tool provides several commands: + + $ boot2docker + Usage: boot2docker.exe [] {help|init|up|ssh|save|down|poweroff|reset|restart|config|status|info|ip|shellinit|delete|download|upgrade|version} [] + +## Upgrading + +1. Download the latest release of the [Docker for Windows Installer]( + https://github.com/boot2docker/windows-installer/releases/latest) + +2. Run the installer, which will update the Boot2Docker management tool. + +3. To upgrade your existing virtual machine, open a terminal and run: + + boot2docker stop + boot2docker download + boot2docker start + +## Container port redirection + +If you are curious, the username for the boot2docker default user is `docker` +and the password is `tcuser`. + +The latest version of `boot2docker` sets up a host only network adaptor which +provides access to the container's ports. + +If you run a container with an exposed port: + + docker run --rm -i -t -p 80:80 nginx + +Then you should be able to access that nginx server using the IP address reported +to you using: + + boot2docker ip + +Typically, it is 192.168.59.103, but it could get changed by Virtualbox's DHCP +implementation. + +For further information or to report issues, please see the [Boot2Docker site](http://boot2docker.io) + +## Login with PUTTY instead of using the CMD + +Boot2Docker generates and uses the public/private key pair in your `%USERPROFILE%\.ssh` +directory so to log in you need to use the private key from this same directory. + +The private key needs to be converted into the format PuTTY uses. + +You can do this with +[puttygen](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html): + +- Open `puttygen.exe` and load ("File"->"Load" menu) the private key from + `%USERPROFILE%\.ssh\id_boot2docker` +- then click: "Save Private Key". +- Then use the saved file to login with PuTTY using `docker@127.0.0.1:2022`. + +## Uninstallation + +You can uninstall Boot2Docker using Window's standard process for removing programs. +This process does not remove the `docker-install.exe` file. You must delete that file +yourself. + +## References + +If you have Docker hosts running and if you don't wish to do a +Boot2Docker installation, you can install the docker.exe using +unofficial Windows package manager Chocolately. For information +on how to do this, see [Docker package on Chocolatey](http://chocolatey.org/packages/docker). From 901b10c28de7a8cb1dbc22d0cc33b6b5528a5772 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 21 Jul 2015 13:36:09 -0700 Subject: [PATCH 163/167] Deprecate boot2docker-cli officially --- README.md | 8 ++------ cmds.go | 51 --------------------------------------------------- main.go | 3 +++ util.go | 26 ++++++++++++++++++-------- 4 files changed, 23 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index f2a9a9d..efb7e6b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ -# Pending Deprecation +# Deprecated -This project is officially in bug fixing/maintenance mode in favor of all -concerted effort going towards [Docker -Machine](https://github.com/docker/machine) instead. Merging of complex -features will require some pretty strong convincing as to why they should exist -here, and not instead be proposed for Docker Machine. +This project is officially deprecated in favor of [Docker Machine](https://docs.docker.com/machine/). The code and documentation here only exist as a reference for users who have not yet switched over (but please do soon). # boot2docker command line management tool diff --git a/cmds.go b/cmds.go index 2d60292..3cd391e 100644 --- a/cmds.go +++ b/cmds.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "net/http" "os" "os/exec" "path/filepath" @@ -357,16 +356,6 @@ func cmdPoweroff() error { // Upgrade the boot2docker ISO - preserving server state func cmdUpgrade() error { - if runtime.GOOS == "darwin" || runtime.GOOS == "linux" { - if B2D.Clobber { - err := upgradeDockerClientBinary() - if err != nil { - return err - } - } else { - fmt.Println("Skipping client binary download, use --clobber=true to enable...") - } - } if err := upgradeBoot2DockerBinary(); err != nil { return fmt.Errorf("Error upgrading boot2docker binary: %s", err) } @@ -422,46 +411,6 @@ func upgradeBoot2DockerBinary() error { return nil } -func upgradeDockerClientBinary() error { - var ( - clientOs, clientArch string - ) - resp, err := http.Get("https://get.docker.com/latest") - if err != nil { - return fmt.Errorf("Error checking the latest version of Docker: %s", err) - } - defer resp.Body.Close() - latestVersionBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return fmt.Errorf("Error reading response body on latest version of Docker call: %s", err) - } - latestVersion := strings.TrimSpace(string(latestVersionBytes)) - localClientVersion, err := getLocalClientVersion() - if err != nil { - return fmt.Errorf("Error getting local Docker client version: %s", err) - } - switch runtime.GOARCH { - case "amd64": - clientArch = "x86_64" - default: - return fmt.Errorf("Architecture not supported") - } - - switch runtime.GOOS { - case "darwin": - clientOs = "Darwin" - case "linux": - clientOs = "Linux" - default: - return fmt.Errorf("Operating system not supported") - } - binaryUrl := fmt.Sprintf("https://get.docker.com/builds/%s/%s/docker-latest", clientOs, clientArch) - if err := attemptUpgrade(binaryUrl, "docker", latestVersion, localClientVersion); err != nil { - return fmt.Errorf("Error attempting upgrade: %s", err) - } - return nil -} - func attemptUpgrade(binaryUrl, binaryName, latestVersion, localVersion string) error { if (latestVersion != localVersion && !strings.Contains(latestVersion, "rc")) || B2D.ForceUpgradeDownload { if err := backupAndDownload(binaryUrl, binaryName, localVersion); err != nil { diff --git a/main.go b/main.go index a4f90dd..47768a7 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "path/filepath" ) // The following vars will be injected during the build process. @@ -20,6 +21,8 @@ func (e unknownCommandError) Error() string { } func main() { + fmt.Fprintf(os.Stderr, "\n WARNING: the %q command is officially deprecated.\n Please switch to Docker Machine (https://docs.docker.com/machine/)\n as soon as possible.\n\n", filepath.Base(os.Args[0])) + // os.Exit will terminate the program at the place of call without running // any deferred cleanup statements. It might cause unintended effects. To // be safe, we wrap the program in run() and only os.Exit() outside the diff --git a/util.go b/util.go index 5c8cab5..f58be5f 100644 --- a/util.go +++ b/util.go @@ -110,8 +110,12 @@ func getLatestReleaseName(url string) (string, error) { defer rsp.Body.Close() var t []struct { - Name string `json:"name"` - TagName string `json:"tag_name"` + // ".../tags" endpoints + Name string `json:"name"` + + // ".../releases" endpoints + TagName string `json:"tag_name"` + Prerelease bool `json:"prerelease"` } body, err := ioutil.ReadAll(rsp.Body) if err != nil { @@ -129,19 +133,25 @@ func getLatestReleaseName(url string) (string, error) { return "", fmt.Errorf("Error getting releases: %s\n see %s", e.Message, e.DocumentationUrl) } if len(t) == 0 { - return "", fmt.Errorf("no releases found") + return "", fmt.Errorf("no releases found at %q", url) } // Looking up by tag instead of release. // Github API call for docker releases yields nothing, // so we use tags API call in this case. - name := "" if strings.Contains(url, "tags") { - name = t[0].Name - } else { - name = t[0].TagName + return t[0].Name, nil + } + + for _, rel := range t { + if rel.Prerelease { + // skip "pre-releases" (RCs, etc) entirely + continue + } + return rel.TagName, nil } - return name, nil + + return "", fmt.Errorf("no non-prerelease releases found at %q", url) } func getLocalClientVersion() (string, error) { From 35e2fc49f5212fdb4f49620d7c4847cfa3b40d68 Mon Sep 17 00:00:00 2001 From: Nathan LeClaire Date: Mon, 10 Aug 2015 14:50:14 -0700 Subject: [PATCH 164/167] Make error message configurable by HTTP call Signed-off-by: Nathan LeClaire --- README.md | 6 +++++- main.go | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index efb7e6b..f9b5c5d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # Deprecated -This project is officially deprecated in favor of [Docker Machine](https://docs.docker.com/machine/). The code and documentation here only exist as a reference for users who have not yet switched over (but please do soon). +This project is officially deprecated in favor of [Docker +Machine](https://docs.docker.com/machine/). The code and documentation here +only exist as a reference for users who have not yet switched over (but please +do soon). The recommended way to install Machine is with the [Docker +Toolbox](https://docker.com/toolbox). # boot2docker command line management tool diff --git a/main.go b/main.go index 47768a7..d8f7d4f 100644 --- a/main.go +++ b/main.go @@ -2,8 +2,9 @@ package main import ( "fmt" + "io/ioutil" + "net/http" "os" - "path/filepath" ) // The following vars will be injected during the build process. @@ -12,6 +13,16 @@ var ( GitSHA string ) +const ( + hardcodedWarning = ` + WARNING: The 'boot2docker' command line interface is being officially deprecated. + Users are expected to switch to Docker Machine (https://docs.docker.com/machine/) instead ASAP. + The Docker Toolbox is the recommended way to install it: https://docker.com/toolbox/ + +` + warningURL = "https://raw.githubusercontent.com/boot2docker/boot2docker-cli/master/DEPRECATION_WARNING" +) + type unknownCommandError struct { cmd string } @@ -21,8 +32,6 @@ func (e unknownCommandError) Error() string { } func main() { - fmt.Fprintf(os.Stderr, "\n WARNING: the %q command is officially deprecated.\n Please switch to Docker Machine (https://docs.docker.com/machine/)\n as soon as possible.\n\n", filepath.Base(os.Args[0])) - // os.Exit will terminate the program at the place of call without running // any deferred cleanup statements. It might cause unintended effects. To // be safe, we wrap the program in run() and only os.Exit() outside the @@ -51,8 +60,10 @@ func run() error { case "config", "cfg": return cmdConfig() case "init": + printDeprecationWarning() return cmdInit() case "up", "start", "boot", "resume": + printDeprecationWarning() return cmdUp() case "save", "suspend": return cmdSave() @@ -91,3 +102,27 @@ func run() error { return unknownCommandError{cmd: cmd} } } + +func printDeprecationWarning() { + var ( + warning string + ) + + // Try to get the warning from the Github raw URL. If there's any + // failure along the way, e.g. network, just fall back to the default + // warning hardcoded in the source. + resp, err := http.Get(warningURL) + if err != nil || resp.StatusCode != http.StatusOK { + warning = hardcodedWarning + } else { + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + warning = hardcodedWarning + } else { + warning = string(body) + } + } + + fmt.Fprintln(os.Stderr, warning) +} From 09542f35c85bb17c38363a196f74d3d235daa9f1 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 12 Aug 2015 11:14:22 -0700 Subject: [PATCH 165/167] Trim down our default message This adjusts the default message so that it fits comfortably in 80 columns: ```console $ ./boot2docker up WARNING: The 'boot2docker' command line interface is officially deprecated. Please switch to Docker Machine (https://docs.docker.com/machine/) ASAP. Docker Toolbox (https://docker.com/toolbox) is the recommended install method. ``` --- DEPRECATION_WARNING | 6 ++++++ main.go | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 DEPRECATION_WARNING diff --git a/DEPRECATION_WARNING b/DEPRECATION_WARNING new file mode 100644 index 0000000..1c8d2a8 --- /dev/null +++ b/DEPRECATION_WARNING @@ -0,0 +1,6 @@ + + WARNING: The 'boot2docker' command line interface is officially deprecated. + + Please switch to Docker Machine (https://docs.docker.com/machine/) ASAP. + + Docker Toolbox (https://docker.com/toolbox) is the recommended install method. diff --git a/main.go b/main.go index d8f7d4f..48416ca 100644 --- a/main.go +++ b/main.go @@ -15,10 +15,11 @@ var ( const ( hardcodedWarning = ` - WARNING: The 'boot2docker' command line interface is being officially deprecated. - Users are expected to switch to Docker Machine (https://docs.docker.com/machine/) instead ASAP. - The Docker Toolbox is the recommended way to install it: https://docker.com/toolbox/ + WARNING: The 'boot2docker' command line interface is officially deprecated. + Please switch to Docker Machine (https://docs.docker.com/machine/) ASAP. + + Docker Toolbox (https://docker.com/toolbox) is the recommended install method. ` warningURL = "https://raw.githubusercontent.com/boot2docker/boot2docker-cli/master/DEPRECATION_WARNING" ) From 9a2606673efcfa282fb64a5a5c9e1b2f89d86fb4 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 12 Aug 2015 14:04:44 -0700 Subject: [PATCH 166/167] Bump to 1.8.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a97fc44..804a616 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.7.1 +v1.8.0 From 06fd5c7d6cb0b724f1f0b4506f8c8c5c6128007c Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Mon, 5 Oct 2015 09:54:47 -0700 Subject: [PATCH 167/167] Update the DEPRECATION_WARNING to clarify cli vs OS deprecation --- DEPRECATION_WARNING | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DEPRECATION_WARNING b/DEPRECATION_WARNING index 1c8d2a8..32d7c87 100644 --- a/DEPRECATION_WARNING +++ b/DEPRECATION_WARNING @@ -1,5 +1,6 @@ - WARNING: The 'boot2docker' command line interface is officially deprecated. + WARNING: The 'boot2docker' command line interface (not to be confused with + 'boot2docker' the operating system) is officially deprecated. Please switch to Docker Machine (https://docs.docker.com/machine/) ASAP.