Skip to content

Commit

Permalink
feat: check ovftool version
Browse files Browse the repository at this point in the history
Checks the minimum required version of VMware Open Virtualization Format Tool ('ovftool').

Ref: #135

Signed-off-by: Ryan Johnson <[email protected]>
  • Loading branch information
tenthirtyam committed Jun 25, 2024
1 parent 25bbcd0 commit 843025f
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 134 deletions.
86 changes: 54 additions & 32 deletions .web-docs/components/builder/iso/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -814,43 +814,65 @@ provisioner](/packer/docs/provisioner/file).

<!-- Code generated from the comments of the ExportConfig struct in builder/vmware/common/export_config.go; DO NOT EDIT MANUALLY -->

- `format` (string) - Either "ovf", "ova" or "vmx", this specifies the output
format of the exported virtual machine. This defaults to "ovf" for
remote (esx) builds, and "vmx" for local builds.
Before using this option, you need to install ovftool.
Since ovftool is only capable of password based authentication
remote_password must be set when exporting the VM from a remote instance.
If you are building locally, Packer will create a vmx and then
export that vm to an ovf or ova. Packer will not delete the vmx and vmdk
files; this is left up to the user if you don't want to keep those
files.
- `format` (string) - The output format of the exported virtual machine. Allowed values are
`ova`, `ovf`, or `vmx`. The default value is `ovf` for remote builds on
an ESXi host, and `vmx` for local builds on a desktop hypervisor.

For builds on an ESXi host, `remote_password` must be set when exporting
the virtual machine

For builds on a desktop hypervisor, the plugin will create a `.vmx` and
export the virtual machine as an `.ovf` or `.ova` file. THe plugin will
not delete the `.vmx` and `.vmdk` files. You must manually delete these
files if they are no longer needed.

~> **Note:** Ensure VMware OVF Tool version 4.6.0 or later is installed.
For the latest version, visit [VMware OVF Tool](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest).

- `ovftool_options` ([]string) - Extra options to pass to ovftool during export. Each item in the array
is a new argument. The options `--noSSLVerify`, `--skipManifestCheck`,
and `--targetType` are used by Packer for remote exports, and should not
be passed to this argument. For ovf/ova exports from local builds, Packer
does not automatically set any ovftool options.

- `skip_export` (bool) - Defaults to `false`. When true, Packer will not export the VM. This can
be useful if the build output is not the resultant image, but created
inside the VM.

- `keep_registered` (bool) - Set this to true if you would like to keep a remotely-built
VM registered with the remote ESXi server. If you do not need to export
the vm, then also set `skip_export: true` in order to avoid unnecessarily
using ovftool to export the vm. Defaults to false.

- `skip_compaction` (bool) - VMware-created disks are defragmented and
compacted at the end of the build process using vmware-vdiskmanager or
vmkfstools in ESXi. In certain rare cases, this might actually end up
making the resulting disks slightly larger. If you find this to be the case,
you can disable compaction using this configuration value. Defaults to
false. Default to true for ESXi when disk_type_id is not explicitly
defined and false otherwise.
- `ovftool_options` ([]string) - allows for additional customization by specifying extra command-line
arguments to the VMware OVF Tool during the export process. Each string
in the array represents a separate command-line argument.

~> **Important:** The options `--noSSLVerify`, `--skipManifestCheck`, and
`--targetType` are automatically applied by the plugin for remote exports
and should not be included here. For local OVF/OVA exports, the plugin
does not preset any OVF Tool options by default.

~> **Note:** Ensure VMware OVF Tool version 4.6.0 or later is installed.
For the latest version, visit [VMware OVF Tool](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest).

- `skip_export` (bool) - Skips the export of the virtual machine. This is useful if the build
output is not the resultant image, but created inside the virtual
machine. This is useful for debugging purposes. Defaults to `false`.
Defaults to `false`.

- `keep_registered` (bool) - determines whether a virtual machine built on a an ESXi server should
remain registered after the build process. Setting this to `true` can be
useful if the virtual machine does not need to be exported. Defaults to
`false`.

- `skip_compaction` (bool) - At the end of the build process, the plugin defragments and compacts the
disks using `vmware-vdiskmanager` or `vmkfstools` for ESXi environments.
In some cases, this process may result in slightly larger disk sizes.
If this occurs, you can opt to skip the disk compaction step by using
this setting. Defaults to `false`. Defaults to `true` for ESXi when
`disk_type_id` is not explicitly defined and `false` otherwise.

<!-- End of code generated from the comments of the ExportConfig struct in builder/vmware/common/export_config.go; -->


HCL Example:

```hcl
source "vmware-iso" "example" {
# ... omitted for brevity ...
format = "ova"
ovftool_options = ["--compress=9", "--makeDeltaDisks"]
skip_export = false
keep_registered = false
skip_compaction = true
```

### Communicator configuration

#### Optional common fields:
Expand Down
84 changes: 52 additions & 32 deletions .web-docs/components/builder/vmx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,43 +373,63 @@ boot time.

<!-- Code generated from the comments of the ExportConfig struct in builder/vmware/common/export_config.go; DO NOT EDIT MANUALLY -->

- `format` (string) - Either "ovf", "ova" or "vmx", this specifies the output
format of the exported virtual machine. This defaults to "ovf" for
remote (esx) builds, and "vmx" for local builds.
Before using this option, you need to install ovftool.
Since ovftool is only capable of password based authentication
remote_password must be set when exporting the VM from a remote instance.
If you are building locally, Packer will create a vmx and then
export that vm to an ovf or ova. Packer will not delete the vmx and vmdk
files; this is left up to the user if you don't want to keep those
files.
- `format` (string) - The output format of the exported virtual machine. Allowed values are
`ova`, `ovf`, or `vmx`. The default value is `ovf` for remote builds on
an ESXi host, and `vmx` for local builds on a desktop hypervisor.

For builds on an ESXi host, `remote_password` must be set when exporting
the virtual machine

For builds on a desktop hypervisor, the plugin will create a `.vmx` and
export the virtual machine as an `.ovf` or `.ova` file. THe plugin will
not delete the `.vmx` and `.vmdk` files. You must manually delete these
files if they are no longer needed.

~> **Note:** Ensure VMware OVF Tool version 4.6.0 or later is installed.
For the latest version, visit [VMware OVF Tool](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest).

- `ovftool_options` ([]string) - Extra options to pass to ovftool during export. Each item in the array
is a new argument. The options `--noSSLVerify`, `--skipManifestCheck`,
and `--targetType` are used by Packer for remote exports, and should not
be passed to this argument. For ovf/ova exports from local builds, Packer
does not automatically set any ovftool options.

- `skip_export` (bool) - Defaults to `false`. When true, Packer will not export the VM. This can
be useful if the build output is not the resultant image, but created
inside the VM.

- `keep_registered` (bool) - Set this to true if you would like to keep a remotely-built
VM registered with the remote ESXi server. If you do not need to export
the vm, then also set `skip_export: true` in order to avoid unnecessarily
using ovftool to export the vm. Defaults to false.

- `skip_compaction` (bool) - VMware-created disks are defragmented and
compacted at the end of the build process using vmware-vdiskmanager or
vmkfstools in ESXi. In certain rare cases, this might actually end up
making the resulting disks slightly larger. If you find this to be the case,
you can disable compaction using this configuration value. Defaults to
false. Default to true for ESXi when disk_type_id is not explicitly
defined and false otherwise.
- `ovftool_options` ([]string) - allows for additional customization by specifying extra command-line
arguments to the VMware OVF Tool during the export process. Each string
in the array represents a separate command-line argument.

~> **Important:** The options `--noSSLVerify`, `--skipManifestCheck`, and
`--targetType` are automatically applied by the plugin for remote exports
and should not be included here. For local OVF/OVA exports, the plugin
does not preset any OVF Tool options by default.

~> **Note:** Ensure VMware OVF Tool version 4.6.0 or later is installed.
For the latest version, visit [VMware OVF Tool](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest).

- `skip_export` (bool) - Skips the export of the virtual machine. This is useful if the build
output is not the resultant image, but created inside the virtual
machine. This is useful for debugging purposes. Defaults to `false`.
Defaults to `false`.

- `keep_registered` (bool) - determines whether a virtual machine built on a an ESXi server should
remain registered after the build process. Setting this to `true` can be
useful if the virtual machine does not need to be exported. Defaults to
`false`.

- `skip_compaction` (bool) - At the end of the build process, the plugin defragments and compacts the
disks using `vmware-vdiskmanager` or `vmkfstools` for ESXi environments.
In some cases, this process may result in slightly larger disk sizes.
If this occurs, you can opt to skip the disk compaction step by using
this setting. Defaults to `false`. Defaults to `true` for ESXi when
`disk_type_id` is not explicitly defined and `false` otherwise.

<!-- End of code generated from the comments of the ExportConfig struct in builder/vmware/common/export_config.go; -->


HCL Example:

```hcl
format = "ova"
ovftool_options = ["--compress=9", "--makeDeltaDisks"]
skip_export = false
keep_registered = false
skip_compaction = true
```

### Output configuration

#### Optional:
Expand Down
51 changes: 41 additions & 10 deletions builder/vmware/common/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (
"github.com/hashicorp/packer-plugin-sdk/multistep"
)

// Sets the minimum required version of VMware Open Virtualization Format Tool
const minimumOvfToolVersion = "4.6.0"

// 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 +633,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 +645,34 @@ func GetOVFTool() string {
return ovftool
}

func CheckOvfToolVersion(ovftoolPath string) bool {
cmd := exec.Command(ovftoolPath, "--version")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return false
}

versionOutput := out.String()
versionRegex, err := regexp.Compile(`\d+\.\d+\.\d+`)
if err != nil {
log.Fatalf("failed to return version regex: %v", err)
}

fields := strings.Fields(versionOutput)
var version string
for _, field := range fields {
if versionRegex.MatchString(field) {
version = field
break
}
}

return version == minimumOvfToolVersion
}

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 +690,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 !CheckOvfToolVersion(ovftoolPath) {
return fmt.Errorf("ovftool does not meet the minimum version requirements: %s", minimumOvfToolVersion)
}

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
68 changes: 39 additions & 29 deletions builder/vmware/common/export_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,49 @@ import (
)

type ExportConfig struct {
// Either "ovf", "ova" or "vmx", this specifies the output
// format of the exported virtual machine. This defaults to "ovf" for
// remote (esx) builds, and "vmx" for local builds.
// Before using this option, you need to install ovftool.
// Since ovftool is only capable of password based authentication
// remote_password must be set when exporting the VM from a remote instance.
// If you are building locally, Packer will create a vmx and then
// export that vm to an ovf or ova. Packer will not delete the vmx and vmdk
// files; this is left up to the user if you don't want to keep those
// files.
// The output format of the exported virtual machine. Allowed values are
// `ova`, `ovf`, or `vmx`. The default value is `ovf` for remote builds on
// an ESXi host, and `vmx` for local builds on a desktop hypervisor.
//
// For builds on an ESXi host, `remote_password` must be set when exporting
// the virtual machine
//
// For builds on a desktop hypervisor, the plugin will create a `.vmx` and
// export the virtual machine as an `.ovf` or `.ova` file. THe plugin will
// not delete the `.vmx` and `.vmdk` files. You must manually delete these
// files if they are no longer needed.
//
// ~> **Note:** Ensure VMware OVF Tool version 4.6.0 or later is installed.
// For the latest version, visit [VMware OVF Tool](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest).
Format string `mapstructure:"format" required:"false"`
// Extra options to pass to ovftool during export. Each item in the array
// is a new argument. The options `--noSSLVerify`, `--skipManifestCheck`,
// and `--targetType` are used by Packer for remote exports, and should not
// be passed to this argument. For ovf/ova exports from local builds, Packer
// does not automatically set any ovftool options.
// allows for additional customization by specifying extra command-line
// arguments to the VMware OVF Tool during the export process. Each string
// in the array represents a separate command-line argument.
//
// ~> **Important:** The options `--noSSLVerify`, `--skipManifestCheck`, and
// `--targetType` are automatically applied by the plugin for remote exports
// and should not be included here. For local OVF/OVA exports, the plugin
// does not preset any OVF Tool options by default.
//
// ~> **Note:** Ensure VMware OVF Tool version 4.6.0 or later is installed.
// For the latest version, visit [VMware OVF Tool](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest).
OVFToolOptions []string `mapstructure:"ovftool_options" required:"false"`
// Defaults to `false`. When true, Packer will not export the VM. This can
// be useful if the build output is not the resultant image, but created
// inside the VM.
// Skips the export of the virtual machine. This is useful if the build
// output is not the resultant image, but created inside the virtual
// machine. This is useful for debugging purposes. Defaults to `false`.
// Defaults to `false`.
SkipExport bool `mapstructure:"skip_export" required:"false"`
// Set this to true if you would like to keep a remotely-built
// VM registered with the remote ESXi server. If you do not need to export
// the vm, then also set `skip_export: true` in order to avoid unnecessarily
// using ovftool to export the vm. Defaults to false.
// determines whether a virtual machine built on a an ESXi server should
// remain registered after the build process. Setting this to `true` can be
// useful if the virtual machine does not need to be exported. Defaults to
// `false`.
KeepRegistered bool `mapstructure:"keep_registered" required:"false"`
// VMware-created disks are defragmented and
// compacted at the end of the build process using vmware-vdiskmanager or
// vmkfstools in ESXi. In certain rare cases, this might actually end up
// making the resulting disks slightly larger. If you find this to be the case,
// you can disable compaction using this configuration value. Defaults to
// false. Default to true for ESXi when disk_type_id is not explicitly
// defined and false otherwise.
// At the end of the build process, the plugin defragments and compacts the
// disks using `vmware-vdiskmanager` or `vmkfstools` for ESXi environments.
// In some cases, this process may result in slightly larger disk sizes.
// If this occurs, you can opt to skip the disk compaction step by using
// this setting. Defaults to `false`. Defaults to `true` for ESXi when
// `disk_type_id` is not explicitly defined and `false` otherwise.
SkipCompaction bool `mapstructure:"skip_compaction" required:"false"`
}

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
Loading

0 comments on commit 843025f

Please sign in to comment.