Files
linuxkit/src/cmd/linuxkit/run_vmware.go
Ian Campbell 97da92dc65 linuxkit: Bump to logrus 1.0.2 (with case change).
To enable this bump github.com/Azure/go-ansiterm and github.com/docker/docker
to their latest version which have switched to lower case.

This in turn requires bumping golang.org/x/sys since github.com/docker/docker/pkg/term
now uses `unix.IoctlGetTermios`. I picked the revision from docker/docker's vendor.conf.

Signed-off-by: Ian Campbell <ijc@docker.com>
2017-08-07 12:11:43 +01:00

246 lines
6.7 KiB
Go

package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
log "github.com/sirupsen/logrus"
)
//Version 12 relates to Fusion 8 and WS 12
//virtualHW.version = "12"
const vmxHW string = `config.version = "8"
virtualHW.version = "12"
vmci0.present = "TRUE"
floppy0.present = "FALSE"
displayName = "%s"
numvcpus = "%d"
memsize = "%d"
scsi0.present = "TRUE"
scsi0.sharedBus = "none"
scsi0.virtualDev = "lsilogic"
`
const vmxDisk string = `
scsi0:0.present = "TRUE"
scsi0:0.fileName = "%s"
scsi0:0.deviceType = "scsi-hardDisk"
`
const vmxDiskPersistent string = `scsi0:1.present = "TRUE"
scsi0:1.fileName = "%s"
scsi0:1.deviceType = "scsi-hardDisk"
`
const vmxCdrom string = `ide1:0.present = "TRUE"
ide1:0.fileName = "%s"
ide1:0.deviceType = "cdrom-image"
`
const vmxPCI string = `pciBridge0.present = "TRUE"
pciBridge4.present = "TRUE"
pciBridge4.virtualDev = "pcieRootPort"
pciBridge4.functions = "8"
pciBridge5.present = "TRUE"
pciBridge5.virtualDev = "pcieRootPort"
pciBridge5.functions = "8"
pciBridge6.present = "TRUE"
pciBridge6.virtualDev = "pcieRootPort"
pciBridge6.functions = "8"
pciBridge7.present = "TRUE"
pciBridge7.virtualDev = "pcieRootPort"
pciBridge7.functions = "8"
ethernet0.pciSlotNumber = "32"
ethernet0.present = "TRUE"
ethernet0.virtualDev = "e1000"
ethernet0.networkName = "Inside"
ethernet0.generatedAddressOffset = "0"
guestOS = "other3xlinux-64"
`
func runVMware(args []string) {
invoked := filepath.Base(os.Args[0])
flags := flag.NewFlagSet("vmware", flag.ExitOnError)
flags.Usage = func() {
fmt.Printf("USAGE: %s run vmware [options] prefix\n\n", invoked)
fmt.Printf("'prefix' specifies the path to the VM image.\n")
fmt.Printf("\n")
fmt.Printf("Options:\n")
flags.PrintDefaults()
}
cpus := flags.Int("cpus", 1, "Number of CPUs")
mem := flags.Int("mem", 1024, "Amount of memory in MB")
var disks Disks
flags.Var(&disks, "disk", "Disk config. [file=]path[,size=1G]")
state := flags.String("state", "", "Path to directory to keep VM state in")
if err := flags.Parse(args); err != nil {
log.Fatal("Unable to parse args")
}
remArgs := flags.Args()
if len(remArgs) == 0 {
fmt.Println("Please specify the prefix to the image to boot")
flags.Usage()
os.Exit(1)
}
prefix := remArgs[0]
if *state == "" {
*state = prefix + "-state"
}
if err := os.MkdirAll(*state, 0755); err != nil {
log.Fatalf("Could not create state directory: %v", err)
}
var vmrunPath, vmDiskManagerPath string
var vmrunArgs []string
switch runtime.GOOS {
case "windows":
vmrunPath = "C:\\Program\\ files\\VMware Workstation\\vmrun.exe"
vmDiskManagerPath = "C:\\Program\\ files\\VMware Workstation\\vmware-vdiskmanager.exe"
vmrunArgs = []string{"-T", "ws", "start"}
case "darwin":
vmrunPath = "/Applications/VMware Fusion.app/Contents/Library/vmrun"
vmDiskManagerPath = "/Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager"
vmrunArgs = []string{"-T", "fusion", "start"}
default:
vmrunPath = "vmrun"
vmDiskManagerPath = "vmware-vdiskmanager"
fullVMrunPath, err := exec.LookPath(vmrunPath)
if err != nil {
// Kept as separate error as people may manually change their environment vars
log.Fatalf("Unable to find %s within the $PATH", vmrunPath)
}
vmrunPath = fullVMrunPath
vmrunArgs = []string{"-T", "ws", "start"}
}
// Check vmrunPath exists before attempting to execute
if _, err := os.Stat(vmrunPath); os.IsNotExist(err) {
log.Fatalf("ERROR VMware executables can not be found, ensure software is installed")
}
for i, d := range disks {
id := ""
if i != 0 {
id = strconv.Itoa(i)
}
if d.Size != 0 && d.Path == "" {
d.Path = filepath.Join(*state, "disk"+id+".vmdk")
}
if d.Format != "" && d.Format != "vmdk" {
log.Fatalf("only vmdk supported for VMware driver")
}
if d.Path == "" {
log.Fatalf("disk specified with no size or name")
}
disks[i] = d
}
for _, d := range disks {
// Check vmDiskManagerPath exist before attempting to execute
if _, err := os.Stat(vmDiskManagerPath); os.IsNotExist(err) {
log.Fatalf("ERROR VMware Disk Manager executables can not be found, ensure software is installed")
}
// If disk doesn't exist then create one, error if disk is unreadable
if _, err := os.Stat(d.Path); err != nil {
if os.IsPermission(err) {
log.Fatalf("Unable to read file [%s], please check permissions", d.Path)
} else if os.IsNotExist(err) {
log.Infof("Creating new VMware disk [%s]", d.Path)
vmDiskCmd := exec.Command(vmDiskManagerPath, "-c", "-s", fmt.Sprintf("%dMB", d.Size), "-a", "lsilogic", "-t", "0", d.Path)
if err = vmDiskCmd.Run(); err != nil {
log.Fatalf("Error creating disk [%s]: %v", d.Path, err)
}
} else {
log.Fatalf("Unable to read file [%s]: %v", d.Path, err)
}
} else {
log.Infof("Using existing disk [%s]", d.Path)
}
}
if len(disks) > 1 {
log.Fatalf("VMware driver currently only supports a single disk")
}
disk := ""
if len(disks) == 1 {
disk = disks[0].Path
}
// Build the contents of the VMWare .vmx file
vmx := buildVMX(*cpus, *mem, disk, prefix)
if vmx == "" {
log.Fatalf("VMware .vmx file could not be generated, please confirm inputs")
}
// Create the .vmx file
vmxPath := filepath.Join(*state, "linuxkit.vmx")
err := ioutil.WriteFile(vmxPath, []byte(vmx), 0644)
if err != nil {
log.Fatalf("Error writing .vmx file: %v", err)
}
vmrunArgs = append(vmrunArgs, vmxPath)
cmd := exec.Command(vmrunPath, vmrunArgs...)
out, err := cmd.Output()
if err != nil {
log.Fatalf("Error starting vmrun: %v", err)
}
// check there is output to push to logging
if len(out) > 0 {
log.Info(out)
}
}
func buildVMX(cpus int, mem int, persistentDisk string, prefix string) string {
// CD-ROM can be added for use in a further release
cdromPath := ""
var returnString string
returnString += fmt.Sprintf(vmxHW, prefix, cpus, mem)
if cdromPath != "" {
returnString += fmt.Sprintf(vmxCdrom, cdromPath)
}
vmdkPath, err := filepath.Abs(prefix + ".vmdk")
if err != nil {
log.Fatalf("Unable get absolute path for boot vmdk: %v", err)
}
if _, err := os.Stat(vmdkPath); err != nil {
if os.IsPermission(err) {
log.Fatalf("Unable to read file [%s], please check permissions", vmdkPath)
}
if os.IsNotExist(err) {
log.Fatalf("File [%s] does not exist in current directory", vmdkPath)
}
} else {
returnString += fmt.Sprintf(vmxDisk, vmdkPath)
}
// Add persistentDisk to the vmx if it has been specified in the args.
if persistentDisk != "" {
persistentDisk, err = filepath.Abs(persistentDisk)
if err != nil {
log.Fatalf("Unable get absolute path for persistent disk: %v", err)
}
returnString += fmt.Sprintf(vmxDiskPersistent, persistentDisk)
}
returnString += vmxPCI
return returnString
}