Skip to content
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
22 changes: 22 additions & 0 deletions .web-docs/components/builder/vsphere-clone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,13 @@ wget http://{{ .HTTPIP }}:{{ .HTTPPort }}/foo/bar/preseed.cfg

- `vTPM` (bool) - Enable virtual trusted platform module (TPM) device for the virtual
machine. Defaults to `false`.

-> **Note:** A virtual machine with a vTPM cannot be exported as OVF/OVA
(`export`) or imported to a content library as an OVF template
(`content_library_destination` with `ovf` set to `true`). Set
[`remove_vtpm`](#remove_vtpm) to `true` to remove the device after
shutdown. A content library VM template (`ovf` unset or `false`) can keep
the vTPM.

- `precision_clock` (string) - The virtual precision clock device for the virtual machine.
Defaults to `none`.
Expand All @@ -1506,6 +1513,20 @@ wget http://{{ .HTTPIP }}:{{ .HTTPPort }}/foo/bar/preseed.cfg
<!-- End of code generated from the comments of the HardwareConfig struct in builder/vsphere/common/step_hardware.go; -->


<!-- Code generated from the comments of the RemoveVTPMConfig struct in builder/vsphere/common/step_remove_vtpm.go; DO NOT EDIT MANUALLY -->

- `remove_vtpm` (bool) - Remove the virtual trusted platform module (vTPM) device from the virtual
machine after shutdown. Defaults to `false`.

-> **Note:** A virtual machine with a vTPM cannot be exported as OVF/OVA
(`export`) or imported to a content library as an OVF template
(`content_library_destination` with `ovf` set to `true`). Set this option
to `true` to remove the device after shutdown. A content library VM
template (`ovf` unset or `false`) can keep the vTPM.

<!-- End of code generated from the comments of the RemoveVTPMConfig struct in builder/vsphere/common/step_remove_vtpm.go; -->


### Location Configuration

**Optional:**
Expand Down Expand Up @@ -2442,6 +2463,7 @@ Clone the default **Read-Only** vSphere role and add the following privileges:
| ... | Download files | `ContentLibrary.DownloadSession` |
| Cryptographic Operations | Direct access | `Cryptographer.Access` |
| ... | Encrypt | `Cryptographer.Encrypt` |
| ... | Decrypt | `Cryptographer.Decrypt` |
| Datastore | Allocate space | `Datastore.AllocateSpace` |
| ... | Browse datastore | `Datastore.Browse` |
| ... | Low level file operations | `Datastore.FileManagement` |
Expand Down
22 changes: 22 additions & 0 deletions .web-docs/components/builder/vsphere-iso/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ wget http://{{ .HTTPIP }}:{{ .HTTPPort }}/foo/bar/preseed.cfg

- `vTPM` (bool) - Enable virtual trusted platform module (TPM) device for the virtual
machine. Defaults to `false`.

-> **Note:** A virtual machine with a vTPM cannot be exported as OVF/OVA
(`export`) or imported to a content library as an OVF template
(`content_library_destination` with `ovf` set to `true`). Set
[`remove_vtpm`](#remove_vtpm) to `true` to remove the device after
shutdown. A content library VM template (`ovf` unset or `false`) can keep
the vTPM.

- `precision_clock` (string) - The virtual precision clock device for the virtual machine.
Defaults to `none`.
Expand All @@ -286,6 +293,20 @@ wget http://{{ .HTTPIP }}:{{ .HTTPPort }}/foo/bar/preseed.cfg
<!-- End of code generated from the comments of the HardwareConfig struct in builder/vsphere/common/step_hardware.go; -->


<!-- Code generated from the comments of the RemoveVTPMConfig struct in builder/vsphere/common/step_remove_vtpm.go; DO NOT EDIT MANUALLY -->

- `remove_vtpm` (bool) - Remove the virtual trusted platform module (vTPM) device from the virtual
machine after shutdown. Defaults to `false`.

-> **Note:** A virtual machine with a vTPM cannot be exported as OVF/OVA
(`export`) or imported to a content library as an OVF template
(`content_library_destination` with `ovf` set to `true`). Set this option
to `true` to remove the device after shutdown. A content library VM
template (`ovf` unset or `false`) can keep the vTPM.

<!-- End of code generated from the comments of the RemoveVTPMConfig struct in builder/vsphere/common/step_remove_vtpm.go; -->


### Create Configuration

**Optional**:
Expand Down Expand Up @@ -1973,6 +1994,7 @@ Clone the default **Read-Only** vSphere role and add the following privileges:
| ... | Update library Item | `ContentLibrary.UpdateLibraryItem` |
| Cryptographic Operations | Direct access | `Cryptographer.Access` |
| ... | Encrypt | `Cryptographer.Encrypt` |
| ... | Decrypt | `Cryptographer.Decrypt` |
| Datastore | Allocate space | `Datastore.AllocateSpace` |
| ... | Browse datastore | `Datastore.Browse` |
| ... | Low level file operations | `Datastore.FileManagement` |
Expand Down
3 changes: 3 additions & 0 deletions builder/vsphere/clone/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
Config: &b.config.ReattachCDRomConfig,
CDRomConfig: &b.config.CDRomConfig,
},
&common.StepRemoveVTPM{
Config: &b.config.RemoveVTPMConfig,
},
&common.StepCreateSnapshot{
CreateSnapshot: b.config.CreateSnapshot,
SnapshotName: b.config.SnapshotName,
Expand Down
74 changes: 74 additions & 0 deletions builder/vsphere/clone/builder_acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,21 @@ func teardownVM(vmName string) error {
return acceptance.CleanupVm(d, vmName)
}

func teardownContentLibraryItem(libraryName, itemName string) error {
d, err := acceptance.TestConn()
if err != nil {
return fmt.Errorf("cannot connect %v", err)
}
item, err := d.ResolveContentLibraryItem(libraryName, itemName)
if err != nil {
if strings.Contains(err.Error(), "not found") {
return nil
}
return err
}
return d.DeleteContentLibraryItem(item.ID)
}

// ---------------------------------------------------------------------------
// Matrix A — Template Source
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -692,3 +707,62 @@ func checkMatrixI(name string, acc env.AccConfig, policies []string) error {
}
return acceptance.CheckStoragePolicyDiskPlacements(d, vm, policies)
}

// ---------------------------------------------------------------------------
// Matrix J — vTPM add and remove with content library OVF
// ---------------------------------------------------------------------------

func TestAccCloneBuilder_MatrixJ(t *testing.T) {
acceptance.RequireAcceptance(t)
acceptance.RequireKeyProvider(t)
acc := env.AccFromEnv()
config := cloneExampleConfig()
config["firmware"] = "efi"
config["vTPM"] = true
config["remove_vtpm"] = true
vmName := config["vm_name"].(string)
clItemName := vmName + "-ovf-template"
config["content_library_destination"] = map[string]any{
"library": acc.ContentLibrary,
"name": clItemName,
"ovf": true,
}

testCase := &acctest.PluginTestCase{
Name: "vsphere-clone-matrix-j",
Template: acceptance.RenderConfig("vsphere-clone", config),
Teardown: func() error {
_ = teardownVM(vmName)
return teardownContentLibraryItem(acc.ContentLibrary, clItemName)
},
Check: func(buildCommand *exec.Cmd, logfile string) error {
if err := checkBuildSucceeded(buildCommand, logfile); err != nil {
return err
}
return checkMatrixJ(vmName, acc, acc.ContentLibrary, clItemName)
},
}
acctest.TestPlugin(t, testCase)
}

func checkMatrixJ(name string, acc env.AccConfig, libraryName, itemName string) error {
d, vm, parent, rp, err := findVM(name)
if err != nil {
return err
}
if err := checkFolderAndResourcePool(d, parent, rp, acc); err != nil {
return err
}
if err := acceptance.CheckNoVTPM(vm); err != nil {
return err
}

item, err := d.ResolveContentLibraryItem(libraryName, itemName)
if err != nil {
return fmt.Errorf("expected content library OVF item: %v", err)
}
if !strings.EqualFold(item.Type, "ovf") {
return fmt.Errorf("unexpected content library item type %q, want ovf", item.Type)
}
return nil
}
5 changes: 5 additions & 0 deletions builder/vsphere/clone/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Config struct {
common.RemoveCDRomConfig `mapstructure:",squash"`
common.ReattachCDRomConfig `mapstructure:",squash"`
common.RemoveNetworkAdapterConfig `mapstructure:",squash"`
common.RemoveVTPMConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
common.RunConfig `mapstructure:",squash"`
common.BootConfig `mapstructure:",squash"`
Expand Down Expand Up @@ -120,6 +121,10 @@ func (c *Config) Prepare(raws ...any) ([]string, error) {
warnings = append(warnings, customizeWarnings...)
}

exportOVF := c.Export != nil
contentLibraryOVF := c.ContentLibraryDestinationConfig != nil && c.ContentLibraryDestinationConfig.Ovf
warnings = append(warnings, c.RemoveVTPMConfig.Prepare(c.VTPMEnabled, exportOVF, contentLibraryOVF)...)

if len(errs.Errors) > 0 {
return nil, errs
}
Expand Down
2 changes: 2 additions & 0 deletions builder/vsphere/clone/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions builder/vsphere/common/step_hardware.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ type HardwareConfig struct {
BootDelay int64 `mapstructure:"boot_delay"`
// Enable virtual trusted platform module (TPM) device for the virtual
// machine. Defaults to `false`.
//
// -> **Note:** A virtual machine with a vTPM cannot be exported as OVF/OVA
// (`export`) or imported to a content library as an OVF template
// (`content_library_destination` with `ovf` set to `true`). Set
// [`remove_vtpm`](#remove_vtpm) to `true` to remove the device after
// shutdown. A content library VM template (`ovf` unset or `false`) can keep
// the vTPM.
VTPMEnabled bool `mapstructure:"vTPM"`
// The virtual precision clock device for the virtual machine.
// Defaults to `none`.
Expand Down
78 changes: 78 additions & 0 deletions builder/vsphere/common/step_remove_vtpm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// © Broadcom. All Rights Reserved.
// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
// SPDX-License-Identifier: MPL-2.0

//go:generate packer-sdc struct-markdown
//go:generate packer-sdc mapstructure-to-hcl2 -type RemoveVTPMConfig

package common

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/vmware/packer-plugin-vsphere/builder/vsphere/driver"
)

type RemoveVTPMConfig struct {
// Remove the virtual trusted platform module (vTPM) device from the virtual
// machine after shutdown. Defaults to `false`.
//
// -> **Note:** A virtual machine with a vTPM cannot be exported as OVF/OVA
// (`export`) or imported to a content library as an OVF template
// (`content_library_destination` with `ovf` set to `true`). Set this option
// to `true` to remove the device after shutdown. A content library VM
// template (`ovf` unset or `false`) can keep the vTPM.
RemoveVTPM bool `mapstructure:"remove_vtpm"`
}

// Prepare returns warnings when a vTPM would block OVF/OVA export or a
// content library OVF template import.
func (c *RemoveVTPMConfig) Prepare(vtpmEnabled, exportOVF, contentLibraryOVF bool) []string {
if !vtpmEnabled || c.RemoveVTPM {
return nil
}

var ops []string
if exportOVF {
ops = append(ops, "OVF/OVA export is configured")
}
if contentLibraryOVF {
ops = append(ops, "content library OVF template import is configured")
}
if len(ops) == 0 {
return nil
}

return []string{fmt.Sprintf("vTPM is enabled and %s; this will fail unless 'remove_vtpm' is true", strings.Join(ops, " and "))}
}

type StepRemoveVTPM struct {
Config *RemoveVTPMConfig
}

func (s *StepRemoveVTPM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
if !s.Config.RemoveVTPM {
return multistep.ActionContinue
}

ui := state.Get("ui").(packersdk.Ui)
vm := state.Get("vm").(driver.VirtualMachine)

ui.Say("Removing vTPM...")
err := vm.RemoveVTPM()

if err != nil {
state.Put("error", fmt.Errorf("error removing vTPM: %v", err))
return multistep.ActionHalt
}

return multistep.ActionContinue
}

func (s *StepRemoveVTPM) Cleanup(state multistep.StateBag) {
// no cleanup
}
31 changes: 31 additions & 0 deletions builder/vsphere/common/step_remove_vtpm.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading