Move the remote_driver from iso to common.

This commit is contained in:
Alexander Laamanen 2017-01-27 16:11:55 +02:00 committed by Megan Marsh
parent 91c7089455
commit b5298464c5
10 changed files with 118 additions and 88 deletions

View File

@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"os"
@ -48,27 +47,23 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error {
linesToArray := func(lines string) []string { return strings.Split(strings.Trim(lines, "\n"), "\n") }
err := d.sh("test -r", src)
if err != nil {
return errors.New("Source VMX not found")
}
d.SetOutputDir(dst)
srcVmx := d.datastorePath(path.Dir(src))
dstVmx := d.datastorePath(dst)
srcDir := path.Dir(srcVmx)
dstDir := path.Dir(dstVmx)
vmName := strings.TrimSuffix(path.Base(src), ".vmx")
srcDir := path.Dir(src)
dstDir := path.Join(path.Dir(srcDir), path.Dir(dst))
dstVmx := path.Join(dstDir, path.Base(dst))
log.Printf("Source: %s\n", src)
log.Printf("Source: %s\n", srcVmx)
log.Printf("Dest: %s\n", dstVmx)
err = d.sh("mkdir", dstDir)
err := d.sh("mkdir", dstDir)
if err != nil {
return fmt.Errorf("Failed to create the destination directory %s: %s", dstDir, err)
}
err = d.sh("cp", src, dstVmx)
err = d.sh("cp", srcVmx, dstVmx)
if err != nil {
return fmt.Errorf("Failed to copy the vmx file %s: %s", src, err)
return fmt.Errorf("Failed to copy the vmx file %s: %s", srcVmx, err)
}
filesToClone, err := d.run(nil, "find", srcDir, "! -name '*.vmdk' ! -name '*.vmx' -type f")
@ -84,7 +79,7 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error {
}
}
disksToClone, err := d.run(nil, "sed -ne 's/.*file[Nn]ame = \"\\(.*vmdk\\)\"/\\1/p'", src)
disksToClone, err := d.run(nil, "sed -ne 's/.*file[Nn]ame = \"\\(.*vmdk\\)\"/\\1/p'", srcVmx)
if err != nil {
return fmt.Errorf("Failing to get the vmdk list to clone %s", err)
}
@ -94,37 +89,28 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error {
srcDisk = disk
}
destDisk := path.Join(dstDir, path.Base(disk))
err := d.sh("vmkfstools", "-d thin", "-i", srcDisk, destDisk)
err = d.sh("vmkfstools", "-d thin", "-i", srcDisk, destDisk)
if err != nil {
return fmt.Errorf("Failing to clone disk %s: %s", srcDisk, err)
}
}
vmxDir, err = ioutil.TempDir("", "packer-vmx")
if err != nil {
err := fmt.Errorf("Error preparing VMX template: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
// Set the tempDir so we clean it up
s.tempDir = vmxDir
// FIXME: VMName should be taken from the config.
vmxEdits := []string{
"s/\\(display[Nn]ame = \\).*/\\1\"" + vmName + "\"/",
"/ethernet..generated[aA]ddress =/d",
"/uuid.bios =/d",
"/uuid.location =/d",
"/vc.uuid =/d",
}
for _, edit := range vmxEdits {
err := d.sh("sed -i -e", "'", edit, "'", dstVmx)
if err != nil {
return fmt.Errorf("Failed to edit the destination file %s: %s", dstVmx, err)
}
}
//
// // FIXME: VMName should be taken from the config.
// vmxEdits := []string{
// "s/\\(display[Nn]ame = \\).*/\\1\"" + vmName + "\"/",
// "/ethernet..generated[aA]ddress =/d",
// "/uuid.bios =/d",
// "/uuid.location =/d",
// "/vc.uuid =/d",
// }
// for _, edit := range vmxEdits {
// err := d.sh("sed -i -e", "'", edit, "'", dstVmx)
// if err != nil {
// return fmt.Errorf("Failed to edit the destination file %s: %s", dstVmx, err)
// }
// }
log.Printf("Successfully cloned %s to %s\n", src, dst)
return nil
}
@ -150,6 +136,21 @@ func (d *ESX5Driver) ReloadVM() error {
return d.sh("vim-cmd", "vmsvc/reload", d.vmId)
}
func (d *ESX5Driver) ReadFile(name string) ([]byte, error) {
var b bytes.Buffer
writer := bufio.NewWriter(&b)
err := d.comm.Download(d.datastorePath(name), writer)
if err != nil {
return nil, fmt.Errorf("Cant read remote file %s: %s", name, err)
}
writer.Flush()
return b.Bytes(), nil
}
func (d *ESX5Driver) WriteFile(name string, content []byte) error {
return d.comm.Upload(d.datastorePath(name), bytes.NewReader(content), nil)
}
func (d *ESX5Driver) Start(vmxPathLocal string, headless bool) error {
for i := 0; i < 20; i++ {
//intentionally not checking for error since poweron may fail specially after initial VM registration
@ -172,7 +173,7 @@ func (d *ESX5Driver) Stop(vmxPathLocal string) error {
func (d *ESX5Driver) Register(vmxPathLocal string) error {
vmxPath := filepath.ToSlash(filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)))
if err := d.upload(vmxPath, vmxPathLocal); err != nil {
if err := d.Upload(vmxPath, vmxPathLocal); err != nil {
return err
}
r, err := d.run(nil, "vim-cmd", "solo/registervm", strconv.Quote(vmxPath))
@ -215,7 +216,7 @@ func (d *ESX5Driver) UploadISO(localPath string, checksum string, checksumType s
return finalPath, nil
}
if err := d.upload(finalPath, localPath); err != nil {
if err := d.Upload(finalPath, localPath); err != nil {
return "", err
}
@ -662,7 +663,7 @@ func (d *ESX5Driver) mkdir(path string) error {
return d.sh("mkdir", "-p", strconv.Quote(path))
}
func (d *ESX5Driver) upload(dst, src string) error {
func (d *ESX5Driver) Upload(dst, src string) error {
f, err := os.Open(src)
if err != nil {
return err
@ -671,15 +672,6 @@ func (d *ESX5Driver) upload(dst, src string) error {
return d.comm.Upload(dst, f, nil)
}
func (d *ESX5Driver) download(dst, src string) error {
f, err := os.Open(dst)
if err != nil {
return err
}
defer f.Close()
return d.comm.Download(dst, f, nil)
}
func (d *ESX5Driver) verifyChecksum(ctype string, hash string, file string) bool {
if ctype == "none" {
if err := d.sh("stat", strconv.Quote(file)); err != nil {

View File

@ -1,11 +1,7 @@
package iso
import (
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
)
package common
type RemoteDriver interface {
vmwcommon.Driver
Driver
// UploadISO uploads a local ISO to the remote side and returns the
// new path that should be used in the VMX along with an error if it
@ -28,8 +24,14 @@ type RemoteDriver interface {
IsDestroyed() (bool, error)
// Uploads a local file to remote side.
upload(dst, src string) error
Upload(dst, src string) error
// Reload VM on remote side.
ReloadVM() error
// Read bytes from of a remote file.
ReadFile(string) ([]byte, error)
// Write bytes to a remote file.
WriteFile(string, []byte) error
}

View File

@ -1,11 +1,7 @@
package iso
import (
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
)
package common
type RemoteDriverMock struct {
vmwcommon.DriverMock
DriverMock
UploadISOCalled bool
UploadISOPath string

View File

@ -0,0 +1,10 @@
package common
import (
"testing"
)
func TestRemoteDriverMock_impl(t *testing.T) {
var _ Driver = new(RemoteDriverMock)
var _ RemoteDriver = new(RemoteDriverMock)
}

View File

@ -1,6 +1,7 @@
package common
import (
"bytes"
"context"
"fmt"
"log"
@ -25,9 +26,14 @@ type StepConfigureVMX struct {
}
func (s *StepConfigureVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
vmxPath := state.Get("vmx_path").(string)
log.Printf("Configuring VMX...\n")
var vmxContents []byte
var err error
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
vmxPath := state.Get("vmx_path").(string)
vmxData, err := ReadVMX(vmxPath)
if err != nil {
err := fmt.Errorf("Error reading VMX file: %s", err)
@ -69,7 +75,15 @@ func (s *StepConfigureVMX) Run(_ context.Context, state multistep.StateBag) mult
}
}
if err := WriteVMX(vmxPath, vmxData); err != nil {
if remoteDriver, ok := driver.(RemoteDriver); ok {
var buf bytes.Buffer
buf.WriteString(EncodeVMX(vmxData))
err = remoteDriver.WriteFile(vmxPath, buf.Bytes())
} else {
err = WriteVMX(vmxPath, vmxData)
}
if err != nil {
err := fmt.Errorf("Error writing VMX file: %s", err)
state.Put("error", err)
ui.Error(err.Error())

View File

@ -1,12 +0,0 @@
package iso
import (
"testing"
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
)
func TestRemoteDriverMock_impl(t *testing.T) {
var _ vmwcommon.Driver = new(RemoteDriverMock)
var _ RemoteDriver = new(RemoteDriverMock)
}

View File

@ -20,7 +20,7 @@ func (s *StepRegister) Run(_ context.Context, state multistep.StateBag) multiste
ui := state.Get("ui").(packer.Ui)
vmxPath := state.Get("vmx_path").(string)
if remoteDriver, ok := driver.(RemoteDriver); ok {
if remoteDriver, ok := driver.(vmwcommon.RemoteDriver); ok {
ui.Say("Registering remote VM...")
if err := remoteDriver.Register(vmxPath); err != nil {
err := fmt.Errorf("Error registering VM: %s", err)
@ -51,7 +51,7 @@ func (s *StepRegister) Cleanup(state multistep.StateBag) {
return
}
if remoteDriver, ok := driver.(RemoteDriver); ok {
if remoteDriver, ok := driver.(vmwcommon.RemoteDriver); ok {
if s.Format == "" || config.SkipExport {
ui.Say("Unregistering virtual machine...")
if err := remoteDriver.Unregister(s.registeredPath); err != nil {

View File

@ -22,7 +22,7 @@ func (s *stepRemoteUpload) Run(_ context.Context, state multistep.StateBag) mult
driver := state.Get("driver").(vmwcommon.Driver)
ui := state.Get("ui").(packer.Ui)
remote, ok := driver.(RemoteDriver)
remote, ok := driver.(vmwcommon.RemoteDriver)
if !ok {
return multistep.ActionContinue
}

View File

@ -30,10 +30,10 @@ func (c *StepUploadVMX) Run(_ context.Context, state multistep.StateBag) multist
vmxPath := state.Get("vmx_path").(string)
if c.RemoteType == "esx5" {
remoteDriver, ok := driver.(RemoteDriver)
remoteDriver, ok := driver.(vmwcommon.RemoteDriver)
if ok {
remoteVmxPath := filepath.ToSlash(filepath.Join(fmt.Sprintf("%s", remoteDriver), filepath.Base(vmxPath)))
if err := remoteDriver.upload(remoteVmxPath, vmxPath); err != nil {
if err := remoteDriver.Upload(remoteVmxPath, vmxPath); err != nil {
state.Put("error", fmt.Errorf("Error writing VMX: %s", err))
return multistep.ActionHalt
}

View File

@ -3,7 +3,9 @@ package vmx
import (
"context"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
@ -18,9 +20,15 @@ type StepCloneVMX struct {
Path string
VMName string
Linked bool
tempDir string
}
func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
halt := func(err error) multistep.StepAction {
state.Put("error", err)
return multistep.ActionHalt
}
driver := state.Get("driver").(vmwcommon.Driver)
ui := state.Get("ui").(packer.Ui)
@ -29,6 +37,7 @@ func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multiste
ui.Say("Cloning source VM...")
log.Printf("Cloning from: %s", s.Path)
log.Printf("Cloning to: %s", vmxPath)
if err := driver.Clone(vmxPath, s.Path, s.Linked); err != nil {
state.Put("error", err)
return multistep.ActionHalt
@ -40,10 +49,26 @@ func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multiste
// network type so that it can work out things like IP's and MAC
// addresses
// * The disk compaction step needs the paths to all attached disks
if remoteDriver, ok := driver.(vmwcommon.RemoteDriver); ok {
tempDir, err := ioutil.TempDir("", "packer-vmx")
if err != nil {
return halt(err)
}
s.tempDir = tempDir
content, err := remoteDriver.ReadFile(vmxPath)
if err != nil {
return halt(err)
}
vmxPath = filepath.Join(tempDir, s.VMName+".vmx")
err = ioutil.WriteFile(vmxPath, content, 0600)
if err != nil {
return halt(err)
}
}
vmxData, err := vmwcommon.ReadVMX(vmxPath)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
return halt(err)
}
var diskFilenames []string
@ -104,4 +129,7 @@ func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multiste
}
func (s *StepCloneVMX) Cleanup(state multistep.StateBag) {
if s.tempDir != "" {
os.RemoveAll(s.tempDir)
}
}