Skip to content
This repository was archived by the owner on Feb 27, 2018. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 47 additions & 21 deletions cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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: ")
Expand Down
79 changes: 40 additions & 39 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)(:.*)`)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future reference, it is a good habit to put regexp.MustCompile calls outside of all functions when they are static, as they can then be processed once at startup instead of upon each function call, since regexp compilation can be an expensive operation (not that this code is time-critical)... just FYI.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, thanks - good point. Its turning out to be hard to learn good go habits when learning go from a non-styled codebase :)

but you're helping immensely - thank you.

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))
Expand All @@ -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])
Expand Down Expand Up @@ -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
Expand Down