Implement the first version of the remote Clone().

This commit is contained in:
Alexander Laamanen 2017-01-24 10:24:53 +02:00 committed by Megan Marsh
parent 46cfb5a30c
commit 91c7089455
2 changed files with 90 additions and 9 deletions

View File

@ -7,9 +7,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log" "log"
"net" "net"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@ -43,20 +45,87 @@ type ESX5Driver struct {
} }
func (d *ESX5Driver) Clone(dst, src string, linked bool) error { func (d *ESX5Driver) Clone(dst, src string, linked bool) error {
ret, err := d.sh("test -r %s", src)
linesToArray := func(lines string) []string { return strings.Split(strings.Trim(lines, "\n"), "\n") }
err := d.sh("test -r", src)
if err != nil { if err != nil {
return errors.New("Source VMX not found") return errors.New("Source VMX not found")
} }
ret, err = d.run(nil, "ls") vmName := strings.TrimSuffix(path.Base(src), ".vmx")
files := strings.Split(ret, "\n") 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("Dest: %s\n", dstVmx)
err = d.sh("mkdir", dstDir)
if err != nil { if err != nil {
return errors.New("Error running cmd") return fmt.Errorf("Failed to create the destination directory %s: %s", dstDir, err)
} }
for _, f := range files {
log.Printf("One file is: %s", f) err = d.sh("cp", src, dstVmx)
if err != nil {
return fmt.Errorf("Failed to copy the vmx file %s: %s", src, err)
} }
log.Printf("Return was: %s", ret)
filesToClone, err := d.run(nil, "find", srcDir, "! -name '*.vmdk' ! -name '*.vmx' -type f")
if err != nil {
return fmt.Errorf("Failed to get the file list to copy: %s", err)
}
for _, f := range linesToArray(filesToClone) {
log.Printf("Copying file %s\n", f)
err := d.sh("cp", f, dstDir)
if err != nil {
return fmt.Errorf("Failing to copy %s to %s: %s", f, dstDir, err)
}
}
disksToClone, err := d.run(nil, "sed -ne 's/.*file[Nn]ame = \"\\(.*vmdk\\)\"/\\1/p'", src)
if err != nil {
return fmt.Errorf("Failing to get the vmdk list to clone %s", err)
}
for _, disk := range linesToArray(disksToClone) {
srcDisk := path.Join(srcDir, disk)
if path.IsAbs(disk) {
srcDisk = disk
}
destDisk := path.Join(dstDir, path.Base(disk))
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)
}
}
return nil
} }
func (d *ESX5Driver) CompactDisk(diskPathLocal string) error { func (d *ESX5Driver) CompactDisk(diskPathLocal string) error {
@ -602,6 +671,15 @@ func (d *ESX5Driver) upload(dst, src string) error {
return d.comm.Upload(dst, f, nil) 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 { func (d *ESX5Driver) verifyChecksum(ctype string, hash string, file string) bool {
if ctype == "none" { if ctype == "none" {
if err := d.sh("stat", strconv.Quote(file)); err != nil { if err := d.sh("stat", strconv.Quote(file)); err != nil {

View File

@ -2,6 +2,7 @@ package vmx
import ( import (
"fmt" "fmt"
"log"
"os" "os"
vmwcommon "github.com/hashicorp/packer/builder/vmware/common" vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
@ -74,8 +75,10 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is blank, but is required")) errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is blank, but is required"))
} else { } else {
if _, err := os.Stat(c.SourcePath); err != nil { if _, err := os.Stat(c.SourcePath); err != nil {
errs = packer.MultiErrorAppend(errs, // FIXME:
fmt.Errorf("source_path is invalid: %s", err)) log.Printf("source_path is invalid: %s", err)
// errs = packer.MultiErrorAppend(errs,
// fmt.Errorf("source_path is invalid: %s", err))
} }
} }