Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: check ovftool version #201

Merged
merged 1 commit into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 55 additions & 10 deletions builder/vmware/common/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,21 @@ import (
"strings"
"time"

"github.com/hashicorp/go-version"
"github.com/hashicorp/packer-plugin-sdk/multistep"
)

const (
ovfToolDownloadURL = "https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest"
ovfToolMinVersion = "4.6.0"
)

// The minimum recommended version of the VMware OVF Tool.
var ovfToolMinRecommended = version.Must(version.NewVersion(ovfToolMinVersion))

// A regex to match the version of the VMware OVF Tool.
var ovfToolVersionRegex = regexp.MustCompile(`\d+\.\d+\.\d+`)

// A driver is able to talk to VMware, control virtual machines, etc.
type Driver interface {
// Clone clones the VMX and the disk to the destination path. The
Expand Down Expand Up @@ -630,10 +642,10 @@ func (d *VmwareDriver) HostIP(state multistep.StateBag) (string, error) {
return "", fmt.Errorf("unable to find host IP from devices %v, last error: %s", devices, lastError)
}

func GetOVFTool() string {
func GetOvfTool() string {
ovftool := "ovftool"
if runtime.GOOS == "windows" {
ovftool = "ovftool.exe"
ovftool += ".exe"
}

if _, err := exec.LookPath(ovftool); err != nil {
Expand All @@ -642,8 +654,39 @@ func GetOVFTool() string {
return ovftool
}

// CheckOvfToolVersion checks the version of the VMware OVF Tool.
func CheckOvfToolVersion(ovftoolPath string) error {
output, err := exec.Command(ovftoolPath, "--version").CombinedOutput()
if err != nil {
log.Printf("[WARN] Error running 'ovftool --version': %v.", err)
log.Printf("[WARN] Returned: %s", string(output))
return errors.New("failed to execute ovftool")
}
versionOutput := string(output)
log.Printf("Returned ovftool version: %s.", versionOutput)

versionString := ovfToolVersionRegex.FindString(versionOutput)
if versionString == "" {
return errors.New("unable to determine the version of ovftool")
}

currentVersion, err := version.NewVersion(versionString)
if err != nil {
log.Printf("[WARN] Failed to parse version '%s': %v.", versionString, err)
return fmt.Errorf("failed to parse ovftool version: %v", err)
}

if currentVersion.LessThan(ovfToolMinRecommended) {
log.Printf("[WARN] The version of ovftool (%s) is below the minimum recommended version (%s). Please download the latest version from %s.", currentVersion, ovfToolMinRecommended, ovfToolDownloadURL)
// Log a warning; do not return an error.
// TODO: Transition this to an error in a future major release.
}

return nil
}

func (d *VmwareDriver) Export(args []string) error {
ovftool := GetOVFTool()
ovftool := GetOvfTool()
if ovftool == "" {
return fmt.Errorf("error finding ovftool in path")
}
Expand All @@ -661,13 +704,15 @@ func (d *VmwareDriver) VerifyOvfTool(SkipExport, _ bool) error {
}

log.Printf("Verifying that ovftool exists...")
// Validate that tool exists, but no need to validate credentials.
ovftool := GetOVFTool()
if ovftool != "" {
return nil
} else {
return fmt.Errorf("ovftool not found in path. either set " +
"'skip_export = true', remove 'format' option, or install ovftool")
ovftoolPath := GetOvfTool()
if ovftoolPath == "" {
return fmt.Errorf("ovftool not found; install and include it in your PATH")
}

log.Printf("Checking ovftool version...")
if err := CheckOvfToolVersion(ovftoolPath); err != nil {
return fmt.Errorf("%v", err)
}

return nil
}
2 changes: 1 addition & 1 deletion builder/vmware/common/driver_esx5.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ func (d *ESX5Driver) VerifyOvfTool(SkipExport, skipValidateCredentials bool) err
// check that password is valid by sending a dummy ovftool command
// now, so that we don't fail for a simple mistake after a long
// build
ovftool := GetOVFTool()
ovftool := GetOvfTool()

if d.Password == "" {
return fmt.Errorf("exporting the vm from esxi with ovftool requires " +
Expand Down
2 changes: 1 addition & 1 deletion builder/vmware/common/step_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multiste

var args, ui_args []string

ovftool := GetOVFTool()
ovftool := GetOvfTool()
if c.RemoteType == "esx5" {
// Generate arguments for the ovftool command, but obfuscating the
// password that we can log the command to the UI for debugging.
Expand Down