mirror of
https://github.com/docker/docs.git
synced 2026-04-12 06:19:22 +07:00
Merge pull request #674 from frapposelli/vsphere-driver-fixes
vSphere driver fixes
This commit is contained in:
@@ -114,7 +114,8 @@ func (conn VcConn) VmCreate(isoPath string) error {
|
||||
args = append(args, fmt.Sprintf("--m=%s", memory))
|
||||
cpu := strconv.Itoa(conn.driver.CPU)
|
||||
args = append(args, fmt.Sprintf("--c=%s", cpu))
|
||||
args = append(args, "--disk.controller=scsi")
|
||||
args = append(args, "--disk.controller=pvscsi")
|
||||
args = append(args, "--net.adapter=vmxnet3")
|
||||
args = append(args, "--on=false")
|
||||
if conn.driver.Pool != "" {
|
||||
args = append(args, fmt.Sprintf("--pool=%s", conn.driver.Pool))
|
||||
@@ -168,6 +169,24 @@ func (conn VcConn) VmPowerOff() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (conn VcConn) VmShutdown() error {
|
||||
log.Infof("Powering off virtual machine %s of vCenter %s... ",
|
||||
conn.driver.MachineName, conn.driver.IP)
|
||||
|
||||
args := []string{"vm.power"}
|
||||
args = conn.AppendConnectionString(args)
|
||||
args = append(args, fmt.Sprintf("--dc=%s", conn.driver.Datacenter))
|
||||
args = append(args, "-s")
|
||||
args = append(args, conn.driver.MachineName)
|
||||
_, stderr, err := govcOutErr(args...)
|
||||
|
||||
if stderr == "" && err == nil {
|
||||
return nil
|
||||
} else {
|
||||
return errors.NewVmError("power on", conn.driver.MachineName, stderr)
|
||||
}
|
||||
}
|
||||
|
||||
func (conn VcConn) VmDestroy() error {
|
||||
log.Infof("Deleting virtual machine %s of vCenter %s... ",
|
||||
conn.driver.MachineName, conn.driver.IP)
|
||||
@@ -268,6 +287,23 @@ func (conn VcConn) GuestUpload(guestUser, guestPass, localPath, remotePath strin
|
||||
}
|
||||
}
|
||||
|
||||
func (conn VcConn) GuestStart(guestUser, guestPass, remoteBin, remoteArguments string) error {
|
||||
args := []string{"guest.start"}
|
||||
args = conn.AppendConnectionString(args)
|
||||
args = append(args, fmt.Sprintf("--dc=%s", conn.driver.Datacenter))
|
||||
args = append(args, fmt.Sprintf("--l=%s:%s", guestUser, guestPass))
|
||||
args = append(args, fmt.Sprintf("--vm=%s", conn.driver.MachineName))
|
||||
args = append(args, remoteBin)
|
||||
args = append(args, remoteArguments)
|
||||
_, stderr, err := govcOutErr(args...)
|
||||
|
||||
if stderr == "" && err == nil {
|
||||
return nil
|
||||
} else {
|
||||
return errors.NewGuestError("start", conn.driver.MachineName, stderr)
|
||||
}
|
||||
}
|
||||
|
||||
func (conn VcConn) GuestDownload(guestUser, guestPass, remotePath, localPath string) error {
|
||||
args := []string{"guest.download"}
|
||||
args = conn.AppendConnectionString(args)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package vmwarevsphere
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
@@ -23,12 +25,12 @@ import (
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
cssh "golang.org/x/crypto/ssh"
|
||||
// cssh "golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
DATASTORE_DIR = "boot2docker-iso"
|
||||
isoFilename = "boot2docker-vmw.iso"
|
||||
isoFilename = "boot2docker-1.5.0-GH747.iso"
|
||||
B2D_ISO_NAME = isoFilename
|
||||
DEFAULT_CPU_NUMBER = 2
|
||||
dockerConfigDir = "/var/lib/boot2docker"
|
||||
@@ -231,7 +233,7 @@ func (d *Driver) PreCreateCheck() error {
|
||||
|
||||
// the current implementation does the following:
|
||||
// 1. check whether the docker directory contains the boot2docker ISO
|
||||
// 2. generate an SSH keypair
|
||||
// 2. generate an SSH keypair and bundle it in a tar.
|
||||
// 3. create a virtual machine with the boot2docker ISO mounted;
|
||||
// 4. reconfigure the virtual machine network and disk size;
|
||||
func (d *Driver) Create() error {
|
||||
@@ -275,7 +277,8 @@ func (d *Driver) Create() error {
|
||||
|
||||
//}
|
||||
|
||||
isoURL := "https://github.com/cloudnativeapps/boot2docker/releases/download/v1.5.0-vmw/boot2docker-1.5.0-vmw.iso"
|
||||
// see https://github.com/boot2docker/boot2docker/pull/747
|
||||
isoURL := "https://github.com/cloudnativeapps/boot2docker/releases/download/1.5.0-GH747/boot2docker-1.5.0-GH747.iso"
|
||||
|
||||
if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) {
|
||||
log.Infof("Downloading boot2docker.iso to %s...", commonIsoPath)
|
||||
@@ -339,6 +342,21 @@ func (d *Driver) Create() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate a tar keys bundle
|
||||
if err := d.generateKeyBundle(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy SSH keys bundle
|
||||
if err := vcConn.GuestUpload(B2D_USER, B2D_PASS, path.Join(d.storePath, "userdata.tar"), "/home/docker/userdata.tar"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Expand tar file.
|
||||
if err := vcConn.GuestStart(B2D_USER, B2D_PASS, "/usr/bin/sudo", "/bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar && /usr/bin/sudo tar xf /var/lib/boot2docker/userdata.tar -C /home/docker/ > /var/log/userdata.log 2>&1 && /usr/bin/sudo chown -R docker:staff /home/docker"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Setting hostname: %s", d.MachineName)
|
||||
cmd, err := d.GetSSHCommand(fmt.Sprintf(
|
||||
"echo \"127.0.0.1 %s\" | sudo tee -a /etc/hosts && sudo hostname %s && echo \"%s\" | sudo tee /etc/hostname",
|
||||
@@ -380,41 +398,6 @@ func (d *Driver) Start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Configuring virtual machine %s... ", d.MachineName)
|
||||
|
||||
key, err := ioutil.ReadFile(d.publicSSHKeyPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// so, vmrun above will not work without vmtools in b2d. since getting stuff into TCL
|
||||
// is much more painful, we simply use the b2d password to get the initial public key
|
||||
// onto the machine. from then on we use the pub key. meh.
|
||||
sshConfig := &cssh.ClientConfig{
|
||||
User: B2D_USER,
|
||||
Auth: []cssh.AuthMethod{
|
||||
cssh.Password(B2D_PASS),
|
||||
},
|
||||
}
|
||||
|
||||
ip, err := d.GetIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sshClient, err := cssh.Dial("tcp", fmt.Sprintf("%s:22", ip), sshConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
session, err := sshClient.NewSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := session.Run(fmt.Sprintf("mkdir /home/docker/.ssh && echo \"%s\" > /home/docker/.ssh/authorized_keys", string(key))); err != nil {
|
||||
return err
|
||||
}
|
||||
session.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
return errors.NewInvalidStateError(d.MachineName)
|
||||
@@ -422,11 +405,11 @@ func (d *Driver) Start() error {
|
||||
|
||||
func (d *Driver) Stop() error {
|
||||
vcConn := NewVcConn(d)
|
||||
err := vcConn.VmPowerOff()
|
||||
if err != nil {
|
||||
if err := vcConn.VmShutdown(); err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Remove() error {
|
||||
@@ -435,13 +418,12 @@ func (d *Driver) Remove() error {
|
||||
return err
|
||||
}
|
||||
if machineState == state.Running {
|
||||
if err = d.Stop(); err != nil {
|
||||
if err = d.Kill(); err != nil {
|
||||
return fmt.Errorf("can't stop VM: %s", err)
|
||||
}
|
||||
}
|
||||
vcConn := NewVcConn(d)
|
||||
err = vcConn.VmDestroy()
|
||||
if err != nil {
|
||||
if err = vcConn.VmDestroy(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -451,11 +433,40 @@ func (d *Driver) Restart() error {
|
||||
if err := d.Stop(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Check for 120 seconds for the machine to stop
|
||||
for i := 1; i <= 60; i++ {
|
||||
machineState, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if machineState == state.Running {
|
||||
log.Debugf("Not there yet %d/%d", i, 60)
|
||||
time.Sleep(2 * time.Second)
|
||||
continue
|
||||
}
|
||||
if machineState == state.Stopped {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
machineState, err := d.GetState()
|
||||
// If the VM is still running after 120 seconds just kill it.
|
||||
if machineState == state.Running {
|
||||
if err = d.Kill(); err != nil {
|
||||
return fmt.Errorf("can't stop VM: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return d.Start()
|
||||
}
|
||||
|
||||
func (d *Driver) Kill() error {
|
||||
return d.Stop()
|
||||
vcConn := NewVcConn(d)
|
||||
if err := vcConn.VmPowerOff(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) StartDocker() error {
|
||||
@@ -503,7 +514,7 @@ func (d *Driver) GetSSHCommand(args ...string) (*exec.Cmd, error) {
|
||||
}
|
||||
|
||||
func (d *Driver) sshKeyPath() string {
|
||||
return filepath.Join(d.StorePath, "id_docker_host_vsphere")
|
||||
return path.Join(d.storePath, "id_rsa")
|
||||
}
|
||||
|
||||
func (d *Driver) publicSSHKeyPath() string {
|
||||
@@ -558,3 +569,58 @@ func downloadISO(dir, file, url string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Make a boot2docker userdata.tar key bundle
|
||||
func (d *Driver) generateKeyBundle() error {
|
||||
log.Debugf("Creating Tar key bundle...")
|
||||
|
||||
magicString := "boot2docker, this is vmware speaking"
|
||||
|
||||
tf, err := os.Create(path.Join(d.storePath, "userdata.tar"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tf.Close()
|
||||
var fileWriter io.WriteCloser = tf
|
||||
|
||||
tw := tar.NewWriter(fileWriter)
|
||||
defer tw.Close()
|
||||
|
||||
// magicString first so we can figure out who originally wrote the tar.
|
||||
file := &tar.Header{Name: magicString, Size: int64(len(magicString))}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write([]byte(magicString)); err != nil {
|
||||
return err
|
||||
}
|
||||
// .ssh/key.pub => authorized_keys
|
||||
file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user