Skip to content

Commit d65f66a

Browse files
committed
Merge pull request docker-archive-public#658 from frapposelli/fusion-driver-fixes
Fusion driver fixes
2 parents d28131e + 9410b5b commit d65f66a

File tree

2 files changed

+129
-44
lines changed

2 files changed

+129
-44
lines changed

drivers/vmwarefusion/fusion_darwin.go

Lines changed: 89 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package vmwarefusion
66

77
import (
8+
"archive/tar"
89
"fmt"
910
"io"
1011
"io/ioutil"
@@ -14,6 +15,7 @@ import (
1415
"path"
1516
"path/filepath"
1617
"regexp"
18+
"runtime"
1719
"strings"
1820
"text/template"
1921
"time"
@@ -24,14 +26,13 @@ import (
2426
"github.com/docker/machine/ssh"
2527
"github.com/docker/machine/state"
2628
"github.com/docker/machine/utils"
27-
cssh "golang.org/x/crypto/ssh"
2829
)
2930

3031
const (
3132
B2D_USER = "docker"
3233
B2D_PASS = "tcuser"
3334
dockerConfigDir = "/var/lib/boot2docker"
34-
isoFilename = "boot2docker-vmw.iso"
35+
isoFilename = "boot2docker-1.5.0-GH747.iso"
3536
)
3637

3738
// Driver for VMware Fusion
@@ -40,6 +41,7 @@ type Driver struct {
4041
IPAddress string
4142
Memory int
4243
DiskSize int
44+
CPUs int
4345
ISO string
4446
Boot2DockerURL string
4547
CaCertPath string
@@ -105,6 +107,13 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
105107
d.SwarmHost = flags.String("swarm-host")
106108
d.SwarmDiscovery = flags.String("swarm-discovery")
107109

110+
// We support a maximum of 16 cpu to be consistent with Virtual Hardware 10
111+
// specs.
112+
d.CPUs = int(runtime.NumCPU())
113+
if d.CPUs > 16 {
114+
d.CPUs = 16
115+
}
116+
108117
return nil
109118
}
110119

@@ -168,15 +177,16 @@ func (d *Driver) Create() error {
168177

169178
} else {
170179
// TODO: until vmw tools are merged into b2d master
171-
// we will use the iso from the vmware team
180+
// we will use the iso from the vmware team.
172181
//// todo: check latest release URL, download if it's new
173182
//// until then always use "latest"
174183
//isoURL, err = b2dutils.GetLatestBoot2DockerReleaseURL()
175184
//if err != nil {
176185
// log.Warnf("Unable to check for the latest release: %s", err)
177186
//}
178187

179-
isoURL := "https://github.com/cloudnativeapps/boot2docker/releases/download/v1.5.0-vmw/boot2docker-1.5.0-vmw.iso"
188+
// see https://github.com/boot2docker/boot2docker/pull/747
189+
isoURL := "https://github.com/cloudnativeapps/boot2docker/releases/download/1.5.0-GH747/boot2docker-1.5.0-GH747.iso"
180190

181191
if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) {
182192
log.Infof("Downloading boot2docker.iso to %s...", commonIsoPath)
@@ -255,34 +265,22 @@ func (d *Driver) Create() error {
255265
return fmt.Errorf("Machine didn't return an IP after 120 seconds, aborting")
256266
}
257267

268+
// we got an IP, let's copy ssh keys over
258269
d.IPAddress = ip
259270

260-
key, err := ioutil.ReadFile(d.publicSSHKeyPath())
261-
if err != nil {
271+
// Generate a tar keys bundle
272+
if err := d.generateKeyBundle(); err != nil {
262273
return err
263274
}
264275

265-
// so, vmrun above will not work without vmtools in b2d. since getting stuff into TCL
266-
// is much more painful, we simply use the b2d password to get the initial public key
267-
// onto the machine. from then on we use the pub key. meh.
268-
sshConfig := &cssh.ClientConfig{
269-
User: B2D_USER,
270-
Auth: []cssh.AuthMethod{
271-
cssh.Password(B2D_PASS),
272-
},
273-
}
274-
sshClient, err := cssh.Dial("tcp", fmt.Sprintf("%s:22", ip), sshConfig)
275-
if err != nil {
276-
return err
277-
}
278-
session, err := sshClient.NewSession()
279-
if err != nil {
280-
return err
281-
}
282-
if err := session.Run(fmt.Sprintf("mkdir /home/docker/.ssh && echo \"%s\" > /home/docker/.ssh/authorized_keys", string(key))); err != nil {
283-
return err
284-
}
285-
session.Close()
276+
// Test if /var/lib/boot2docker exists
277+
vmrun("-gu", B2D_USER, "-gp", B2D_PASS, "directoryExistsInGuest", d.vmxPath(), "/var/lib/boot2docker")
278+
279+
// Copy SSH keys bundle
280+
vmrun("-gu", B2D_USER, "-gp", B2D_PASS, "CopyFileFromHostToGuest", d.vmxPath(), path.Join(d.storePath, "userdata.tar"), "/home/docker/userdata.tar")
281+
282+
// Expand tar file.
283+
vmrun("-gu", B2D_USER, "-gp", B2D_PASS, "runScriptInGuest", d.vmxPath(), "/bin/sh", "sudo /bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar && sudo tar xf /var/lib/boot2docker/userdata.tar -C /home/docker/ > /var/log/userdata.log 2>&1 && sudo chown -R docker:staff /home/docker")
286284

287285
log.Debugf("Setting hostname: %s", d.MachineName)
288286
cmd, err := d.GetSSHCommand(fmt.Sprintf(
@@ -302,11 +300,13 @@ func (d *Driver) Create() error {
302300
}
303301

304302
func (d *Driver) Start() error {
303+
log.Infof("Starting %s...", d.MachineName)
305304
vmrun("start", d.vmxPath(), "nogui")
306305
return nil
307306
}
308307

309308
func (d *Driver) Stop() error {
309+
log.Infof("Gracefully shutting down %s...", d.MachineName)
310310
vmrun("stop", d.vmxPath(), "nogui")
311311
return nil
312312
}
@@ -319,18 +319,20 @@ func (d *Driver) Remove() error {
319319
return fmt.Errorf("Error stopping VM before deletion")
320320
}
321321
}
322-
322+
log.Infof("Deleting %s...", d.MachineName)
323323
vmrun("deleteVM", d.vmxPath(), "nogui")
324324
return nil
325325
}
326326

327327
func (d *Driver) Restart() error {
328+
log.Infof("Gracefully restarting %s...", d.MachineName)
328329
vmrun("reset", d.vmxPath(), "nogui")
329330
return nil
330331
}
331332

332333
func (d *Driver) Kill() error {
333-
vmrun("stop", d.vmxPath(), "nogui")
334+
log.Infof("Forcibly halting %s...", d.MachineName)
335+
vmrun("stop", d.vmxPath(), "hard nogui")
334336
return nil
335337
}
336338

@@ -351,7 +353,8 @@ func (d *Driver) StartDocker() error {
351353
func (d *Driver) StopDocker() error {
352354
log.Debug("Stopping Docker...")
353355

354-
cmd, err := d.GetSSHCommand("if [ -e /var/run/docker.pid ]; then sudo /etc/init.d/docker stop ; fi")
356+
// Check if pidfile exists, then if process exists, depending on that stop docker or remove pidfile
357+
cmd, err := d.GetSSHCommand("if [ -e /var/run/docker.pid ]; then if [ -f /proc/$(cat /var/run/docker.pid)/status ]; then sudo /etc/init.d/docker stop; else rm -f /var/run/docker.pid; fi fi")
355358
if err != nil {
356359
return err
357360
}
@@ -367,7 +370,7 @@ func (d *Driver) GetDockerConfigDir() string {
367370
}
368371

369372
func (d *Driver) Upgrade() error {
370-
return nil
373+
return fmt.Errorf("VMware Fusion does not currently support the upgrade operation.")
371374
}
372375

373376
func (d *Driver) GetSSHCommand(args ...string) (*exec.Cmd, error) {
@@ -502,3 +505,58 @@ func (d *Driver) sshKeyPath() string {
502505
func (d *Driver) publicSSHKeyPath() string {
503506
return d.sshKeyPath() + ".pub"
504507
}
508+
509+
// Make a boot2docker userdata.tar key bundle
510+
func (d *Driver) generateKeyBundle() error {
511+
log.Debugf("Creating Tar key bundle...")
512+
513+
magicString := "boot2docker, this is vmware speaking"
514+
515+
tf, err := os.Create(path.Join(d.storePath, "userdata.tar"))
516+
if err != nil {
517+
return err
518+
}
519+
defer tf.Close()
520+
var fileWriter io.WriteCloser = tf
521+
522+
tw := tar.NewWriter(fileWriter)
523+
defer tw.Close()
524+
525+
// magicString first so we can figure out who originally wrote the tar.
526+
file := &tar.Header{Name: magicString, Size: int64(len(magicString))}
527+
if err := tw.WriteHeader(file); err != nil {
528+
return err
529+
}
530+
if _, err := tw.Write([]byte(magicString)); err != nil {
531+
return err
532+
}
533+
// .ssh/key.pub => authorized_keys
534+
file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700}
535+
if err := tw.WriteHeader(file); err != nil {
536+
return err
537+
}
538+
pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
539+
if err != nil {
540+
return err
541+
}
542+
file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644}
543+
if err := tw.WriteHeader(file); err != nil {
544+
return err
545+
}
546+
if _, err := tw.Write([]byte(pubKey)); err != nil {
547+
return err
548+
}
549+
file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644}
550+
if err := tw.WriteHeader(file); err != nil {
551+
return err
552+
}
553+
if _, err := tw.Write([]byte(pubKey)); err != nil {
554+
return err
555+
}
556+
if err := tw.Close(); err != nil {
557+
return err
558+
}
559+
560+
return nil
561+
562+
}

drivers/vmwarefusion/vmx_darwin.go

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,57 @@ const vmx = `
88
.encoding = "UTF-8"
99
config.version = "8"
1010
displayName = "{{.MachineName}}"
11-
ethernet0.addressType = "generated"
12-
ethernet0.connectionType = "nat"
13-
ethernet0.linkStatePropagation.enable = "TRUE"
1411
ethernet0.present = "TRUE"
15-
ethernet0.virtualDev = "e1000"
12+
ethernet0.connectionType = "nat"
13+
ethernet0.virtualDev = "vmxnet3"
1614
ethernet0.wakeOnPcktRcv = "FALSE"
15+
ethernet0.addressType = "generated"
16+
ethernet0.linkStatePropagation.enable = "TRUE"
17+
pciBridge0.present = "TRUE"
18+
pciBridge4.present = "TRUE"
19+
pciBridge4.virtualDev = "pcieRootPort"
20+
pciBridge4.functions = "8"
21+
pciBridge5.present = "TRUE"
22+
pciBridge5.virtualDev = "pcieRootPort"
23+
pciBridge5.functions = "8"
24+
pciBridge6.present = "TRUE"
25+
pciBridge6.virtualDev = "pcieRootPort"
26+
pciBridge6.functions = "8"
27+
pciBridge7.present = "TRUE"
28+
pciBridge7.virtualDev = "pcieRootPort"
29+
pciBridge7.functions = "8"
30+
pciBridge0.pciSlotNumber = "17"
31+
pciBridge4.pciSlotNumber = "21"
32+
pciBridge5.pciSlotNumber = "22"
33+
pciBridge6.pciSlotNumber = "23"
34+
pciBridge7.pciSlotNumber = "24"
35+
scsi0.pciSlotNumber = "160"
36+
usb.pciSlotNumber = "32"
37+
ethernet0.pciSlotNumber = "192"
38+
sound.pciSlotNumber = "33"
39+
vmci0.pciSlotNumber = "35"
40+
sata0.pciSlotNumber = "36"
1741
floppy0.present = "FALSE"
18-
guestOS = "other26xlinux-64"
42+
guestOS = "other3xlinux-64"
1943
hpet0.present = "TRUE"
20-
ide1:0.deviceType = "cdrom-image"
21-
ide1:0.fileName = "{{.ISO}}"
22-
ide1:0.present = "TRUE"
44+
sata0.present = "TRUE"
45+
sata0:1.present = "TRUE"
46+
sata0:1.fileName = "{{.ISO}}"
47+
sata0:1.deviceType = "cdrom-image"
48+
vmci0.present = "TRUE"
2349
mem.hotadd = "TRUE"
2450
memsize = "{{.Memory}}"
25-
powerType.powerOff = "hard"
26-
powerType.powerOn = "hard"
27-
powerType.reset = "hard"
28-
powerType.suspend = "hard"
51+
powerType.powerOff = "soft"
52+
powerType.powerOn = "soft"
53+
powerType.reset = "soft"
54+
powerType.suspend = "soft"
2955
scsi0.present = "TRUE"
30-
scsi0.virtualDev = "lsilogic"
56+
scsi0.virtualDev = "pvscsi"
3157
scsi0:0.fileName = "{{.MachineName}}.vmdk"
3258
scsi0:0.present = "TRUE"
3359
virtualHW.productCompatibility = "hosted"
3460
virtualHW.version = "10"
3561
msg.autoanswer = "TRUE"
3662
uuid.action = "create"
63+
numvcpus = "{{.CPUs}}"
3764
`

0 commit comments

Comments
 (0)