wip: b2d import

Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
This commit is contained in:
Evan Hazlett 2015-04-08 09:49:52 -04:00
parent 5fc9b78b38
commit 576951e03a
4 changed files with 146 additions and 21 deletions

View File

@ -0,0 +1,46 @@
package virtualbox
import (
"bufio"
"io"
"strings"
)
type VirtualDisk struct {
UUID string
Path string
}
func parseDiskInfo(r io.Reader) (*VirtualDisk, error) {
s := bufio.NewScanner(r)
disk := &VirtualDisk{}
for s.Scan() {
line := s.Text()
if line == "" {
continue
}
res := reEqualLine.FindStringSubmatch(line)
if res == nil {
continue
}
switch key, val := res[1], res[2]; key {
case "SATA-1-0":
disk.Path = val
case "SATA-ImageUUID-1-0":
disk.UUID = val
}
}
if err := s.Err(); err != nil {
return nil, err
}
return disk, nil
}
func getVMDiskInfo(name string) (*VirtualDisk, error) {
out, err := vbmOut("showvminfo", name, "--machinereadable")
if err != nil {
return nil, err
}
r := strings.NewReader(out)
return parseDiskInfo(r)
}

View File

@ -0,0 +1,36 @@
package virtualbox
import (
"strings"
"testing"
)
var (
testDiskInfoText = `
storagecontrollerbootable0="on"
"SATA-0-0"="/home/ehazlett/.boot2docker/boot2docker.iso"
"SATA-IsEjected"="off"
"SATA-1-0"="/home/ehazlett/vm/test/disk.vmdk"
"SATA-ImageUUID-1-0"="12345-abcdefg"
"SATA-2-0"="none"
nic1="nat"
`
)
func TestVMDiskInfo(t *testing.T) {
r := strings.NewReader(testDiskInfoText)
disk, err := parseDiskInfo(r)
if err != nil {
t.Fatal(err)
}
diskPath := "/home/ehazlett/vm/test/disk.vmdk"
diskUUID := "12345-abcdefg"
if disk.Path != diskPath {
t.Fatalf("expected disk path %s", diskPath)
}
if disk.UUID != diskUUID {
t.Fatalf("expected disk uuid %s", diskUUID)
}
}

View File

@ -18,6 +18,7 @@ var (
reVMNameUUID = regexp.MustCompile(`"(.+)" {([0-9a-f-]+)}`) reVMNameUUID = regexp.MustCompile(`"(.+)" {([0-9a-f-]+)}`)
reVMInfoLine = regexp.MustCompile(`(?:"(.+)"|(.+))=(?:"(.*)"|(.*))`) reVMInfoLine = regexp.MustCompile(`(?:"(.+)"|(.+))=(?:"(.*)"|(.*))`)
reColonLine = regexp.MustCompile(`(.+):\s+(.*)`) reColonLine = regexp.MustCompile(`(.+):\s+(.*)`)
reEqualLine = regexp.MustCompile(`"(.+)"="(.*)"`)
reMachineNotFound = regexp.MustCompile(`Could not find a registered machine named '(.+)'`) reMachineNotFound = regexp.MustCompile(`Could not find a registered machine named '(.+)'`)
) )

View File

@ -30,19 +30,20 @@ const (
) )
type Driver struct { type Driver struct {
CPU int CPU int
MachineName string MachineName string
SSHUser string SSHUser string
SSHPort int SSHPort int
Memory int Memory int
DiskSize int DiskSize int
Boot2DockerURL string Boot2DockerURL string
CaCertPath string CaCertPath string
PrivateKeyPath string PrivateKeyPath string
SwarmMaster bool SwarmMaster bool
SwarmHost string SwarmHost string
SwarmDiscovery string SwarmDiscovery string
storePath string storePath string
Boot2DockerImportVM string
} }
func init() { func init() {
@ -80,6 +81,11 @@ func GetCreateFlags() []cli.Flag {
Usage: "The URL of the boot2docker image. Defaults to the latest available version", Usage: "The URL of the boot2docker image. Defaults to the latest available version",
Value: "", Value: "",
}, },
cli.StringFlag{
Name: "virtualbox-import-boot2docker-vm",
Usage: "The name of a Boot2Docker VM to import",
Value: "",
},
} }
} }
@ -147,6 +153,7 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
d.SwarmHost = flags.String("swarm-host") d.SwarmHost = flags.String("swarm-host")
d.SwarmDiscovery = flags.String("swarm-discovery") d.SwarmDiscovery = flags.String("swarm-discovery")
d.SSHUser = "docker" d.SSHUser = "docker"
d.Boot2DockerImportVM = flags.String("virtualbox-import-boot2docker-vm")
return nil return nil
} }
@ -170,21 +177,36 @@ func (d *Driver) Create() error {
return err return err
} }
log.Infof("Creating SSH key...")
b2dutils := utils.NewB2dUtils("", "") b2dutils := utils.NewB2dUtils("", "")
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
return err return err
} }
if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
return err
}
log.Infof("Creating VirtualBox VM...") log.Infof("Creating VirtualBox VM...")
if err := d.generateDiskImage(d.DiskSize); err != nil { // import b2d VM if requested
return err if d.Boot2DockerImportVM != "" {
log.Debugf("Importing disk image...")
if err := d.importB2DVM(d.Boot2DockerImportVM); err != nil {
return err
}
log.Debugf("Importing SSH key...")
keyPath := filepath.Join(utils.GetHomeDir(), ".ssh", "id_rsa")
if err := utils.CopyFile(keyPath, d.GetSSHKeyPath()); err != nil {
return err
}
} else {
log.Debugf("Creating disk image...")
if err := d.generateDiskImage(d.DiskSize); err != nil {
return err
}
log.Infof("Creating SSH key...")
if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
return err
}
} }
if err := vbm("createvm", if err := vbm("createvm",
@ -594,6 +616,26 @@ func zeroFill(w io.Writer, n int64) error {
return nil return nil
} }
func (d Driver) importB2DVM(name string) error {
// make sure vm is stopped
_ = vbm("controlvm", name, "poweroff")
diskInfo, err := getVMDiskInfo(name)
if err != nil {
return err
}
if _, err := os.Stat(diskInfo.Path); err != nil {
return err
}
if err := vbm("clonehd", diskInfo.Path, d.diskPath()); err != nil {
return err
}
return nil
}
func getAvailableTCPPort() (int, error) { func getAvailableTCPPort() (int, error) {
port := 0 port := 0
for i := 0; i <= 10; i++ { for i := 0; i <= 10; i++ {