share hardware customization step

This commit is contained in:
Michael Kuzmin 2018-05-06 00:41:14 +03:00
parent 0b4729c9e4
commit c44221a800
9 changed files with 146 additions and 159 deletions

View File

@ -39,8 +39,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&StepCloneVM{
config: &b.config.CloneConfig,
},
&StepConfigureHardware{
config: &b.config.HardwareConfig,
&common.StepConfigureHardware{
Config: &b.config.HardwareConfig,
},
&common.StepConfigParams{
Config: &b.config.ConfigParamsConfig,

View File

@ -10,9 +10,10 @@ import (
)
type CloneConfig struct {
Template string `mapstructure:"template"`
common.VMConfig `mapstructure:",squash"`
LinkedClone bool `mapstructure:"linked_clone"`
Template string `mapstructure:"template"`
common.VMConfig `mapstructure:",squash"`
LinkedClone bool `mapstructure:"linked_clone"`
DiskSize int64 `mapstructure:"disk_size"`
}
func (c *CloneConfig) Prepare() []error {
@ -44,7 +45,7 @@ func (s *StepCloneVM) Run(_ context.Context, state multistep.StateBag) multistep
vm, err := template.Clone(&driver.CloneConfig{
Name: s.config.VMName,
Folder: s.config.Folder,
Cluster: s.config.Cluster,
Cluster: s.config.Cluster,
Host: s.config.Host,
ResourcePool: s.config.ResourcePool,
Datastore: s.config.Datastore,
@ -54,8 +55,16 @@ func (s *StepCloneVM) Run(_ context.Context, state multistep.StateBag) multistep
state.Put("error", err)
return multistep.ActionHalt
}
state.Put("vm", vm)
if s.config.DiskSize > 0 {
err = vm.ResizeDisk(s.config.DiskSize)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}

View File

@ -1,43 +0,0 @@
package clone
import (
"github.com/hashicorp/packer/packer"
"github.com/jetbrains-infra/packer-builder-vsphere/common"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"context"
)
type StepConfigureHardware struct {
config *common.HardwareConfig
}
func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*driver.VirtualMachine)
if *s.config != (common.HardwareConfig{}) {
ui.Say("Customizing hardware parameters...")
err := vm.Configure(&driver.HardwareConfig{
CPUs: s.config.CPUs,
CPUReservation: s.config.CPUReservation,
CPULimit: s.config.CPULimit,
RAM: s.config.RAM,
RAMReservation: s.config.RAMReservation,
RAMReserveAll: s.config.RAMReserveAll,
DiskSize: s.config.DiskSize,
NestedHV: s.config.NestedHV,
CpuHotAddEnabled: s.config.CpuHotAddEnabled,
MemoryHotAddEnabled: s.config.MemoryHotAddEnabled,
})
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}
func (s *StepConfigureHardware) Cleanup(multistep.StateBag) {}

View File

@ -1,44 +0,0 @@
package common
import (
"fmt"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
)
type HardwareConfig struct {
CPUs int32 `mapstructure:"CPUs"`
CPUReservation int64 `mapstructure:"CPU_reservation"`
CPULimit int64 `mapstructure:"CPU_limit"`
RAM int64 `mapstructure:"RAM"`
RAMReservation int64 `mapstructure:"RAM_reservation"`
RAMReserveAll bool `mapstructure:"RAM_reserve_all"`
DiskSize int64 `mapstructure:"disk_size"`
NestedHV bool `mapstructure:"NestedHV"`
CpuHotAddEnabled bool `mapstructure:"CPU_hot_plug"`
MemoryHotAddEnabled bool `mapstructure:"RAM_hot_plug"`
}
func (c *HardwareConfig) Prepare() []error {
var errs []error
if c.RAMReservation > 0 && c.RAMReserveAll != false {
errs = append(errs, fmt.Errorf("'RAM_reservation' and 'RAM_reserve_all' cannot be used together"))
}
return errs
}
func (c *HardwareConfig) ToDriverHardwareConfig() driver.HardwareConfig {
return driver.HardwareConfig{
CPUs: c.CPUs,
CPUReservation: c.CPUReservation,
CPULimit: c.CPULimit,
RAM: c.RAM,
RAMReservation: c.RAMReservation,
RAMReserveAll: c.RAMReserveAll,
DiskSize: c.DiskSize,
NestedHV: c.NestedHV,
CpuHotAddEnabled: c.CpuHotAddEnabled,
MemoryHotAddEnabled: c.MemoryHotAddEnabled,
}
}

64
common/step_hardware.go Normal file
View File

@ -0,0 +1,64 @@
package common
import (
"github.com/hashicorp/packer/packer"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"context"
"fmt"
)
type HardwareConfig struct {
CPUs int32 `mapstructure:"CPUs"`
CPUReservation int64 `mapstructure:"CPU_reservation"`
CPULimit int64 `mapstructure:"CPU_limit"`
RAM int64 `mapstructure:"RAM"`
RAMReservation int64 `mapstructure:"RAM_reservation"`
RAMReserveAll bool `mapstructure:"RAM_reserve_all"`
NestedHV bool `mapstructure:"NestedHV"`
CpuHotAddEnabled bool `mapstructure:"CPU_hot_plug"`
MemoryHotAddEnabled bool `mapstructure:"RAM_hot_plug"`
}
func (c *HardwareConfig) Prepare() []error {
var errs []error
if c.RAMReservation > 0 && c.RAMReserveAll != false {
errs = append(errs, fmt.Errorf("'RAM_reservation' and 'RAM_reserve_all' cannot be used together"))
}
return errs
}
type StepConfigureHardware struct {
Config *HardwareConfig
}
func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*driver.VirtualMachine)
if *s.Config != (HardwareConfig{}) {
ui.Say("Customizing hardware parameters...")
err := vm.Configure(&driver.HardwareConfig{
CPUs: s.Config.CPUs,
CPUReservation: s.Config.CPUReservation,
CPULimit: s.Config.CPULimit,
RAM: s.Config.RAM,
RAMReservation: s.Config.RAMReservation,
RAMReserveAll: s.Config.RAMReserveAll,
NestedHV: s.Config.NestedHV,
CpuHotAddEnabled: s.Config.CpuHotAddEnabled,
MemoryHotAddEnabled: s.Config.MemoryHotAddEnabled,
})
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}
func (s *StepConfigureHardware) Cleanup(multistep.StateBag) {}

View File

@ -18,7 +18,7 @@ type VirtualMachine struct {
type CloneConfig struct {
Name string
Folder string
Cluster string
Cluster string
Host string
ResourcePool string
Datastore string
@ -32,22 +32,20 @@ type HardwareConfig struct {
RAM int64
RAMReservation int64
RAMReserveAll bool
DiskSize int64
NestedHV bool
CpuHotAddEnabled bool
MemoryHotAddEnabled bool
}
type CreateConfig struct {
HardwareConfig
DiskThinProvisioned bool
DiskControllerType string // example: "scsi", "pvscsi"
DiskSize int64
Annotation string
Name string
Folder string
Cluster string
Cluster string
Host string
ResourcePool string
Datastore string
@ -77,7 +75,14 @@ func (d *Driver) FindVM(name string) (*VirtualMachine, error) {
}
func (d *Driver) CreateVM(config *CreateConfig) (*VirtualMachine, error) {
createSpec := config.toConfigSpec()
createSpec := types.VirtualMachineConfigSpec{
Name: config.Name,
Annotation: config.Annotation,
GuestId: config.GuestOS,
}
if config.Version != 0 {
createSpec.Version = fmt.Sprintf("%s%d", "vmx-", config.Version)
}
folder, err := d.FindFolder(config.Folder)
if err != nil {
@ -238,27 +243,54 @@ func (vm *VirtualMachine) Destroy() error {
}
func (vm *VirtualMachine) Configure(config *HardwareConfig) error {
confSpec := config.toConfigSpec()
var confSpec types.VirtualMachineConfigSpec
confSpec.NumCPUs = config.CPUs
confSpec.MemoryMB = config.RAM
if config.DiskSize > 0 {
devices, err := vm.vm.Device(vm.driver.ctx)
if err != nil {
return err
}
var cpuSpec types.ResourceAllocationInfo
cpuSpec.Reservation = config.CPUReservation
cpuSpec.Limit = config.CPULimit
confSpec.CpuAllocation = &cpuSpec
disk, err := findDisk(devices)
if err != nil {
return err
}
var ramSpec types.ResourceAllocationInfo
ramSpec.Reservation = config.RAMReservation
confSpec.MemoryAllocation = &ramSpec
disk.CapacityInKB = config.DiskSize * 1024
confSpec.MemoryReservationLockedToMax = &config.RAMReserveAll
confSpec.NestedHVEnabled = &config.NestedHV
confSpec.DeviceChange = []types.BaseVirtualDeviceConfigSpec{
&types.VirtualDeviceConfigSpec{
Device: disk,
Operation: types.VirtualDeviceConfigSpecOperationEdit,
},
}
confSpec.CpuHotAddEnabled = &config.CpuHotAddEnabled
confSpec.MemoryHotAddEnabled = &config.MemoryHotAddEnabled
task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec)
if err != nil {
return err
}
_, err = task.WaitForResult(vm.driver.ctx, nil)
return err
}
func (vm *VirtualMachine) ResizeDisk(diskSize int64) error {
var confSpec types.VirtualMachineConfigSpec
devices, err := vm.vm.Device(vm.driver.ctx)
if err != nil {
return err
}
disk, err := findDisk(devices)
if err != nil {
return err
}
disk.CapacityInKB = diskSize * 1024
confSpec.DeviceChange = []types.BaseVirtualDeviceConfigSpec{
&types.VirtualDeviceConfigSpec{
Device: disk,
Operation: types.VirtualDeviceConfigSpecOperationEdit,
},
}
task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec)
@ -374,40 +406,6 @@ func (vm *VirtualMachine) GetDir() (string, error) {
return "", fmt.Errorf("cannot find '%s'", vmxName)
}
func (config HardwareConfig) toConfigSpec() types.VirtualMachineConfigSpec {
var confSpec types.VirtualMachineConfigSpec
confSpec.NumCPUs = config.CPUs
confSpec.MemoryMB = config.RAM
var cpuSpec types.ResourceAllocationInfo
cpuSpec.Reservation = config.CPUReservation
cpuSpec.Limit = config.CPULimit
confSpec.CpuAllocation = &cpuSpec
var ramSpec types.ResourceAllocationInfo
ramSpec.Reservation = config.RAMReservation
confSpec.MemoryAllocation = &ramSpec
confSpec.MemoryReservationLockedToMax = &config.RAMReserveAll
confSpec.NestedHVEnabled = &config.NestedHV
confSpec.CpuHotAddEnabled = &config.CpuHotAddEnabled
confSpec.MemoryHotAddEnabled = &config.MemoryHotAddEnabled
return confSpec
}
func (config CreateConfig) toConfigSpec() types.VirtualMachineConfigSpec {
confSpec := config.HardwareConfig.toConfigSpec()
confSpec.Name = config.Name
confSpec.Annotation = config.Annotation
confSpec.GuestId = config.GuestOS
if config.Version != 0 {
confSpec.Version = fmt.Sprintf("%s%d", "vmx-", config.Version)
}
return confSpec
}
func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
device, err := devices.CreateSCSIController(config.DiskControllerType)
if err != nil {

View File

@ -39,6 +39,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&StepCreateVM{
Config: &b.config.CreateConfig,
},
&common.StepConfigureHardware{
Config: &b.config.HardwareConfig,
},
&common.StepConfigParams{
Config: &b.config.ConfigParamsConfig,
},

View File

@ -6,7 +6,6 @@ import (
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"github.com/jetbrains-infra/packer-builder-vsphere/common"
"fmt"
)
type Config struct {
@ -20,6 +19,7 @@ type Config struct {
ConvertToTemplate bool `mapstructure:"convert_to_template"`
CreateConfig `mapstructure:",squash"`
common.HardwareConfig `mapstructure:",squash"`
CDRomConfig `mapstructure:",squash"`
FloppyConfig `mapstructure:",squash"`
common.ConfigParamsConfig `mapstructure:",squash"`
@ -38,9 +38,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare()...)
errs = packer.MultiErrorAppend(errs, c.ConnectConfig.Prepare()...)
errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
if c.DiskSize <= 0 {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("'disk_size' must be provided"))
}
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare()...)
errs = packer.MultiErrorAppend(errs, c.CreateConfig.Prepare()...)

View File

@ -11,10 +11,10 @@ import (
type CreateConfig struct {
common.VMConfig `mapstructure:",squash"`
common.HardwareConfig `mapstructure:",squash"`
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
DiskControllerType string `mapstructure:"disk_controller_type"`
DiskSize int64 `mapstructure:"disk_size"`
GuestOSType string `mapstructure:"guest_os_type"`
Network string `mapstructure:"network"`
@ -31,12 +31,16 @@ func (c *CreateConfig) Prepare() []error {
// do recursive calls
errs = append(errs, tmp.VMConfig.Prepare()...)
errs = append(errs, tmp.HardwareConfig.Prepare()...)
if tmp.Version < 0 {
errs = append(errs, fmt.Errorf("'vm_version' cannot be a negative number"))
}
if tmp.DiskSize == 0 {
errs = append(errs, fmt.Errorf("'disk_size' must be provided"))
}
if len(errs) > 0 {
return errs
}
@ -63,10 +67,9 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste
ui.Say("Creating VM...")
vm, err := d.CreateVM(&driver.CreateConfig{
HardwareConfig: s.Config.HardwareConfig.ToDriverHardwareConfig(),
DiskThinProvisioned: s.Config.DiskThinProvisioned,
DiskControllerType: s.Config.DiskControllerType,
DiskSize: s.Config.DiskSize,
Name: s.Config.VMName,
Folder: s.Config.Folder,
Cluster: s.Config.Cluster,