From c44221a800c10251112d7b3b7dacc7caa4f0e7fc Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Sun, 6 May 2018 00:41:14 +0300 Subject: [PATCH] share hardware customization step --- clone/builder.go | 4 +- clone/step_clone.go | 19 +++++-- clone/step_hardware.go | 43 --------------- common/hardware_config.go | 44 --------------- common/step_hardware.go | 64 ++++++++++++++++++++++ driver/vm.go | 112 +++++++++++++++++++------------------- iso/builder.go | 3 + iso/config.go | 5 +- iso/step_create.go | 11 ++-- 9 files changed, 146 insertions(+), 159 deletions(-) delete mode 100644 clone/step_hardware.go delete mode 100644 common/hardware_config.go create mode 100644 common/step_hardware.go diff --git a/clone/builder.go b/clone/builder.go index 343677c89..2ab34f99b 100644 --- a/clone/builder.go +++ b/clone/builder.go @@ -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, diff --git a/clone/step_clone.go b/clone/step_clone.go index 303ea93af..2f1e6adcb 100644 --- a/clone/step_clone.go +++ b/clone/step_clone.go @@ -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 } diff --git a/clone/step_hardware.go b/clone/step_hardware.go deleted file mode 100644 index 9283a6436..000000000 --- a/clone/step_hardware.go +++ /dev/null @@ -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) {} diff --git a/common/hardware_config.go b/common/hardware_config.go deleted file mode 100644 index 88531fcb4..000000000 --- a/common/hardware_config.go +++ /dev/null @@ -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, - } -} diff --git a/common/step_hardware.go b/common/step_hardware.go new file mode 100644 index 000000000..e96a4c96d --- /dev/null +++ b/common/step_hardware.go @@ -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) {} diff --git a/driver/vm.go b/driver/vm.go index e1f752dff..8c50c2daf 100644 --- a/driver/vm.go +++ b/driver/vm.go @@ -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 { diff --git a/iso/builder.go b/iso/builder.go index bb12aa4dd..086906b39 100644 --- a/iso/builder.go +++ b/iso/builder.go @@ -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, }, diff --git a/iso/config.go b/iso/config.go index d415aa527..31bdc7357 100644 --- a/iso/config.go +++ b/iso/config.go @@ -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()...) diff --git a/iso/step_create.go b/iso/step_create.go index 6c0eed5fa..87d8dfcd4 100644 --- a/iso/step_create.go +++ b/iso/step_create.go @@ -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,