vSphere StepHardware tests (#9866)
This commit is contained in:
parent
bddf3b03f7
commit
903deb9e6a
|
@ -0,0 +1,19 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
|
"github.com/hashicorp/packer/packer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func basicStateBag(errorBuffer *strings.Builder) *multistep.BasicStateBag {
|
||||||
|
state := new(multistep.BasicStateBag)
|
||||||
|
state.Put("ui", &packer.BasicUi{
|
||||||
|
Reader: new(bytes.Buffer),
|
||||||
|
Writer: new(bytes.Buffer),
|
||||||
|
ErrorWriter: errorBuffer,
|
||||||
|
})
|
||||||
|
return state
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ type StepConfigureHardware struct {
|
||||||
|
|
||||||
func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
vm := state.Get("vm").(driver.VirtualMachine)
|
||||||
|
|
||||||
if *s.Config != (HardwareConfig{}) {
|
if *s.Config != (HardwareConfig{}) {
|
||||||
ui.Say("Customizing hardware...")
|
ui.Say("Customizing hardware...")
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||||
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHardwareConfig_Prepare(t *testing.T) {
|
||||||
|
tc := []struct {
|
||||||
|
name string
|
||||||
|
config *HardwareConfig
|
||||||
|
fail bool
|
||||||
|
expectedErrMsg string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Validate empty config",
|
||||||
|
config: &HardwareConfig{},
|
||||||
|
fail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validate RAMReservation RAMReserveAll cannot be used together",
|
||||||
|
config: &HardwareConfig{
|
||||||
|
RAMReservation: 2,
|
||||||
|
RAMReserveAll: true,
|
||||||
|
},
|
||||||
|
fail: true,
|
||||||
|
expectedErrMsg: "'RAM_reservation' and 'RAM_reserve_all' cannot be used together",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid firmware",
|
||||||
|
config: &HardwareConfig{
|
||||||
|
Firmware: "invalid",
|
||||||
|
},
|
||||||
|
fail: true,
|
||||||
|
expectedErrMsg: "'firmware' must be '', 'bios', 'efi' or 'efi-secure'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validate 'bios' firmware",
|
||||||
|
config: &HardwareConfig{
|
||||||
|
Firmware: "bios",
|
||||||
|
},
|
||||||
|
fail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validate 'efi' firmware",
|
||||||
|
config: &HardwareConfig{
|
||||||
|
Firmware: "efi",
|
||||||
|
},
|
||||||
|
fail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Validate 'efi-secure' firmware",
|
||||||
|
config: &HardwareConfig{
|
||||||
|
Firmware: "efi-secure",
|
||||||
|
},
|
||||||
|
fail: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range tc {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
errs := c.config.Prepare()
|
||||||
|
if c.fail {
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatalf("Config preprare should fail")
|
||||||
|
}
|
||||||
|
if errs[0].Error() != c.expectedErrMsg {
|
||||||
|
t.Fatalf("Expected error message: %s but was '%s'", c.expectedErrMsg, errs[0].Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(errs) != 0 {
|
||||||
|
t.Fatalf("Config preprare should not fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStepConfigureHardware_Run(t *testing.T) {
|
||||||
|
tc := []struct {
|
||||||
|
name string
|
||||||
|
step *StepConfigureHardware
|
||||||
|
action multistep.StepAction
|
||||||
|
configureError error
|
||||||
|
configureCalled bool
|
||||||
|
hardwareConfig *driver.HardwareConfig
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Configure hardware",
|
||||||
|
step: basicStepConfigureHardware(),
|
||||||
|
action: multistep.ActionContinue,
|
||||||
|
configureError: nil,
|
||||||
|
configureCalled: true,
|
||||||
|
hardwareConfig: driverHardwareConfigFromConfig(basicStepConfigureHardware().Config),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Don't configure hardware when config is empty",
|
||||||
|
step: &StepConfigureHardware{Config: &HardwareConfig{}},
|
||||||
|
action: multistep.ActionContinue,
|
||||||
|
configureError: nil,
|
||||||
|
configureCalled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Halt when configure return error",
|
||||||
|
step: basicStepConfigureHardware(),
|
||||||
|
action: multistep.ActionHalt,
|
||||||
|
configureError: errors.New("failed to configure"),
|
||||||
|
configureCalled: true,
|
||||||
|
hardwareConfig: driverHardwareConfigFromConfig(basicStepConfigureHardware().Config),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range tc {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
state := basicStateBag(nil)
|
||||||
|
vmMock := new(driver.VirtualMachineMock)
|
||||||
|
vmMock.ConfigureError = c.configureError
|
||||||
|
state.Put("vm", vmMock)
|
||||||
|
|
||||||
|
action := c.step.Run(context.TODO(), state)
|
||||||
|
if action != c.action {
|
||||||
|
t.Fatalf("expected action '%v' but actual action was '%v'", c.action, action)
|
||||||
|
}
|
||||||
|
if vmMock.ConfigureCalled != c.configureCalled {
|
||||||
|
t.Fatalf("expecting vm.Configure called to %t but was %t", c.configureCalled, vmMock.ConfigureCalled)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(vmMock.ConfigureHardwareConfig, c.hardwareConfig); diff != "" {
|
||||||
|
t.Fatalf("wrong driver.HardwareConfig: %s", diff)
|
||||||
|
}
|
||||||
|
|
||||||
|
err, ok := state.GetOk("error")
|
||||||
|
containsError := c.configureError != nil
|
||||||
|
if containsError != ok {
|
||||||
|
t.Fatalf("Contain error - expecting %t but was %t", containsError, ok)
|
||||||
|
}
|
||||||
|
if containsError {
|
||||||
|
if !strings.Contains(err.(error).Error(), c.configureError.Error()) {
|
||||||
|
t.Fatalf("Destroy should fail with error message '%s' but failed with '%s'", c.configureError.Error(), err.(error).Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func basicStepConfigureHardware() *StepConfigureHardware {
|
||||||
|
return &StepConfigureHardware{
|
||||||
|
Config: &HardwareConfig{
|
||||||
|
CPUs: 1,
|
||||||
|
CpuCores: 1,
|
||||||
|
CPUReservation: 1,
|
||||||
|
CPULimit: 4000,
|
||||||
|
RAM: 1024,
|
||||||
|
RAMReserveAll: true,
|
||||||
|
Firmware: "efi-secure",
|
||||||
|
ForceBIOSSetup: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func driverHardwareConfigFromConfig(config *HardwareConfig) *driver.HardwareConfig {
|
||||||
|
return &driver.HardwareConfig{
|
||||||
|
CPUs: config.CPUs,
|
||||||
|
CpuCores: config.CpuCores,
|
||||||
|
CPUReservation: config.CPUReservation,
|
||||||
|
CPULimit: config.CPULimit,
|
||||||
|
RAM: config.RAM,
|
||||||
|
RAMReservation: config.RAMReservation,
|
||||||
|
RAMReserveAll: config.RAMReserveAll,
|
||||||
|
NestedHV: config.NestedHV,
|
||||||
|
CpuHotAddEnabled: config.CpuHotAddEnabled,
|
||||||
|
MemoryHotAddEnabled: config.MemoryHotAddEnabled,
|
||||||
|
VideoRAM: config.VideoRAM,
|
||||||
|
VGPUProfile: config.VGPUProfile,
|
||||||
|
Firmware: config.Firmware,
|
||||||
|
ForceBIOSSetup: config.ForceBIOSSetup,
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,7 +62,7 @@ func NewSimulatorServer(model *simulator.Model) (*simulator.Server, error) {
|
||||||
return model.Service.NewServer(), nil
|
return model.Service.NewServer(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSimulatorDriver(s *simulator.Server) (Driver, error) {
|
func NewSimulatorDriver(s *simulator.Server) (*VCenterDriver, error) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
user := &url.Userinfo{}
|
user := &url.Userinfo{}
|
||||||
s.URL.User = user
|
s.URL.User = user
|
||||||
|
|
|
@ -16,6 +16,10 @@ import (
|
||||||
type VirtualMachineMock struct {
|
type VirtualMachineMock struct {
|
||||||
DestroyError error
|
DestroyError error
|
||||||
DestroyCalled bool
|
DestroyCalled bool
|
||||||
|
|
||||||
|
ConfigureError error
|
||||||
|
ConfigureCalled bool
|
||||||
|
ConfigureHardwareConfig *HardwareConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VirtualMachineMock) Info(params ...string) (*mo.VirtualMachine, error) {
|
func (vm *VirtualMachineMock) Info(params ...string) (*mo.VirtualMachine, error) {
|
||||||
|
@ -51,6 +55,11 @@ func (vm *VirtualMachineMock) Destroy() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VirtualMachineMock) Configure(config *HardwareConfig) error {
|
func (vm *VirtualMachineMock) Configure(config *HardwareConfig) error {
|
||||||
|
vm.ConfigureCalled = true
|
||||||
|
vm.ConfigureHardwareConfig = config
|
||||||
|
if vm.ConfigureError != nil {
|
||||||
|
return vm.ConfigureError
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/vmware/govmomi/simulator"
|
||||||
|
"github.com/vmware/govmomi/vim25/methods"
|
||||||
|
"github.com/vmware/govmomi/vim25/soap"
|
||||||
|
"github.com/vmware/govmomi/vim25/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReconfigureFail changes the behavior of simulator.VirtualMachine
|
||||||
|
type ReconfigureFail struct {
|
||||||
|
*simulator.VirtualMachine
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override simulator.VirtualMachine.ReconfigVMTask to inject faults
|
||||||
|
func (vm *ReconfigureFail) ReconfigVMTask(req *types.ReconfigVM_Task) soap.HasFault {
|
||||||
|
task := simulator.CreateTask(req.This, "reconfigure", func(*simulator.Task) (types.AnyType, types.BaseMethodFault) {
|
||||||
|
return nil, &types.TaskInProgress{}
|
||||||
|
})
|
||||||
|
|
||||||
|
return &methods.ReconfigVM_TaskBody{
|
||||||
|
Res: &types.ReconfigVM_TaskResponse{
|
||||||
|
Returnval: task.Run(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVirtualMachineDriver_Configure(t *testing.T) {
|
||||||
|
model := simulator.VPX()
|
||||||
|
model.Machine = 1
|
||||||
|
defer model.Remove()
|
||||||
|
|
||||||
|
s, err := NewSimulatorServer(model)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not fail: %s", err.Error())
|
||||||
|
}
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
driverSim, err := NewSimulatorDriver(s)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not fail: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//Simulator shortcut to choose any pre created VM.
|
||||||
|
machine := simulator.Map.Any("VirtualMachine").(*simulator.VirtualMachine)
|
||||||
|
ref := machine.Reference()
|
||||||
|
vm := driverSim.NewVM(&ref)
|
||||||
|
|
||||||
|
// Happy test
|
||||||
|
hardwareConfig := &HardwareConfig{
|
||||||
|
CPUs: 1,
|
||||||
|
CpuCores: 1,
|
||||||
|
CPUReservation: 2500,
|
||||||
|
CPULimit: 1,
|
||||||
|
RAM: 1024,
|
||||||
|
RAMReserveAll: true,
|
||||||
|
VideoRAM: 512,
|
||||||
|
VGPUProfile: "grid_m10-8q",
|
||||||
|
Firmware: "efi-secure",
|
||||||
|
ForceBIOSSetup: true,
|
||||||
|
}
|
||||||
|
if err = vm.Configure(hardwareConfig); err != nil {
|
||||||
|
t.Fatalf("should not fail: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fail test
|
||||||
|
//Wrap the existing vm object with the mocked reconfigure task which will return a fault
|
||||||
|
simulator.Map.Put(&ReconfigureFail{machine})
|
||||||
|
if err = vm.Configure(&HardwareConfig{}); err == nil {
|
||||||
|
t.Fatalf("Configure should fail")
|
||||||
|
}
|
||||||
|
}
|
|
@ -160,7 +160,7 @@ func TestStepCreateVM_Run(t *testing.T) {
|
||||||
t.Fatalf("driver.CreateVM should be called.")
|
t.Fatalf("driver.CreateVM should be called.")
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(driverMock.CreateConfig, driverCreateConfig(step.Config, step.Location)); diff != "" {
|
if diff := cmp.Diff(driverMock.CreateConfig, driverCreateConfig(step.Config, step.Location)); diff != "" {
|
||||||
t.Fatalf("wrog driver.CreateConfig: %s", diff)
|
t.Fatalf("wrong driver.CreateConfig: %s", diff)
|
||||||
}
|
}
|
||||||
vm, ok := state.GetOk("vm")
|
vm, ok := state.GetOk("vm")
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
Loading…
Reference in New Issue