2020-01-07 19:59:31 -05:00
//go:generate struct-markdown
2020-11-20 05:51:53 -05:00
//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig
2020-01-07 19:59:31 -05:00
2018-01-24 09:56:14 -05:00
package iso
import (
2018-10-31 17:42:24 -04:00
"context"
2018-01-24 09:56:14 -05:00
"fmt"
2020-04-23 08:07:07 -04:00
"path"
2020-01-08 18:28:26 -05:00
2020-01-07 19:59:31 -05:00
"github.com/hashicorp/packer/builder/vsphere/common"
"github.com/hashicorp/packer/builder/vsphere/driver"
2018-01-24 09:56:14 -05:00
"github.com/hashicorp/packer/packer"
2020-11-17 19:31:03 -05:00
"github.com/hashicorp/packer/packer-plugin-sdk/multistep"
2018-01-24 09:56:14 -05:00
)
2020-04-13 14:28:50 -04:00
// Defines a Network Adapter
//
// Example that creates two network adapters:
//
2020-08-05 13:23:52 -04:00
// In JSON:
2020-04-13 14:28:50 -04:00
// ```json
// "network_adapters": [
// {
// "network": "VM Network",
// "network_card": "vmxnet3"
// },
// {
// "network": "OtherNetwork",
// "network_card": "vmxnet3"
// }
// ],
// ```
2020-08-05 13:23:52 -04:00
// In HCL2:
// ```hcl
// network_adapters {
// network = "VM Network"
// network_card = "vmxnet3"
// }
// network_adapters {
// network = "OtherNetwork"
// network_card = "vmxnet3"
// }
// ```
2020-02-14 11:51:57 -05:00
type NIC struct {
2020-08-13 11:26:40 -04:00
// Set the network in which the VM will be connected to. If no network is
// specified, `host` must be specified to allow Packer to look for the
// available network. If the network is inside a network folder in vCenter,
// you need to provide the full path to the network.
2020-02-14 11:51:57 -05:00
Network string ` mapstructure:"network" `
// Set VM network card type. Example `vmxnet3`.
NetworkCard string ` mapstructure:"network_card" required:"true" `
// Set network card MAC address
MacAddress string ` mapstructure:"mac_address" `
// Enable DirectPath I/O passthrough
Passthrough * bool ` mapstructure:"passthrough" `
}
2018-01-24 09:56:14 -05:00
type CreateConfig struct {
2020-01-07 19:59:31 -05:00
// Set VM hardware version. Defaults to the most current VM hardware
// version supported by vCenter. See
// [VMWare article 1003746](https://kb.vmware.com/s/article/1003746) for
// the full list of supported VM hardware versions.
Version uint ` mapstructure:"vm_version" `
// Set VM OS type. Defaults to `otherGuest`. See [
2020-03-06 09:30:11 -05:00
// here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
2020-01-07 19:59:31 -05:00
// for a full list of possible values.
2020-11-20 05:51:53 -05:00
GuestOSType string ` mapstructure:"guest_os_type" `
StorageConfig common . StorageConfig ` mapstructure:",squash" `
2020-02-14 11:51:57 -05:00
// Network adapters
NICs [ ] NIC ` mapstructure:"network_adapters" `
2020-07-13 20:25:56 -04:00
// Create USB controllers for the virtual machine. "usb" for a usb 2.0 controller. "xhci" for a usb 3.0 controller. There can only be at most one of each.
USBController [ ] string ` mapstructure:"usb_controller" `
2020-01-07 19:59:31 -05:00
// VM notes.
2018-11-08 11:50:52 -05:00
Notes string ` mapstructure:"notes" `
2018-01-24 09:56:14 -05:00
}
func ( c * CreateConfig ) Prepare ( ) [ ] error {
var errs [ ] error
2020-11-20 05:51:53 -05:00
if len ( c . StorageConfig . DiskControllerType ) == 0 {
c . StorageConfig . DiskControllerType = append ( c . StorageConfig . DiskControllerType , "" )
2020-07-10 06:25:46 -04:00
}
2020-11-20 05:51:53 -05:00
// there should be at least one
if len ( c . StorageConfig . Storage ) == 0 {
errs = append ( errs , fmt . Errorf ( "no storage devices have been defined" ) )
2018-03-20 05:09:36 -04:00
}
2020-11-20 05:51:53 -05:00
errs = append ( errs , c . StorageConfig . Prepare ( ) ... )
2018-03-20 05:09:36 -04:00
2018-05-06 17:26:04 -04:00
if c . GuestOSType == "" {
c . GuestOSType = "otherGuest"
2018-05-05 17:41:14 -04:00
}
2020-07-13 20:25:56 -04:00
usbCount := 0
xhciCount := 0
for i , s := range c . USBController {
switch s {
// 1 and true for backwards compatibility
case "usb" , "1" , "true" :
usbCount ++
case "xhci" :
xhciCount ++
2020-07-14 12:11:24 -04:00
// 0 and false for backwards compatibility
case "false" , "0" :
continue
2020-07-13 20:25:56 -04:00
default :
errs = append ( errs , fmt . Errorf ( "usb_controller[%d] references an unknown usb controller" , i ) )
}
}
if usbCount > 1 || xhciCount > 1 {
errs = append ( errs , fmt . Errorf ( "there can only be one usb controller and one xhci controller" ) )
}
2018-05-06 17:26:04 -04:00
return errs
2018-01-24 09:56:14 -05:00
}
type StepCreateVM struct {
2018-05-06 17:26:04 -04:00
Config * CreateConfig
Location * common . LocationConfig
2018-11-16 10:37:54 -05:00
Force bool
2018-01-24 09:56:14 -05:00
}
2018-04-25 07:22:38 -04:00
func ( s * StepCreateVM ) Run ( _ context . Context , state multistep . StateBag ) multistep . StepAction {
2018-01-24 09:56:14 -05:00
ui := state . Get ( "ui" ) . ( packer . Ui )
2020-08-31 04:34:41 -04:00
d := state . Get ( "driver" ) . ( driver . Driver )
2020-04-23 08:07:07 -04:00
vmPath := path . Join ( s . Location . Folder , s . Location . VMName )
2018-01-24 09:56:14 -05:00
2020-04-23 08:07:07 -04:00
err := d . PreCleanVM ( ui , vmPath , s . Force )
if err != nil {
state . Put ( "error" , err )
2018-11-16 10:37:54 -05:00
return multistep . ActionHalt
}
2018-01-24 09:56:14 -05:00
ui . Say ( "Creating VM..." )
2020-02-14 11:51:57 -05:00
// add network/network card an the first nic for backwards compatibility in the type is defined
var networkCards [ ] driver . NIC
for _ , nic := range s . Config . NICs {
networkCards = append ( networkCards , driver . NIC {
Network : nic . Network ,
NetworkCard : nic . NetworkCard ,
MacAddress : nic . MacAddress ,
Passthrough : nic . Passthrough ,
} )
}
2020-02-21 10:47:46 -05:00
// add disk as the first drive for backwards compatibility if the type is defined
var disks [ ] driver . Disk
2020-11-20 05:51:53 -05:00
for _ , disk := range s . Config . StorageConfig . Storage {
2020-02-21 10:47:46 -05:00
disks = append ( disks , driver . Disk {
DiskSize : disk . DiskSize ,
DiskEagerlyScrub : disk . DiskEagerlyScrub ,
DiskThinProvisioned : disk . DiskThinProvisioned ,
2020-07-10 06:25:46 -04:00
ControllerIndex : disk . DiskControllerIndex ,
2020-02-21 10:47:46 -05:00
} )
}
2020-04-23 08:07:07 -04:00
vm , err := d . CreateVM ( & driver . CreateConfig {
2020-11-20 05:51:53 -05:00
StorageConfig : driver . StorageConfig {
DiskControllerType : s . Config . StorageConfig . DiskControllerType ,
Storage : disks ,
} ,
Annotation : s . Config . Notes ,
Name : s . Location . VMName ,
Folder : s . Location . Folder ,
Cluster : s . Location . Cluster ,
Host : s . Location . Host ,
ResourcePool : s . Location . ResourcePool ,
Datastore : s . Location . Datastore ,
GuestOS : s . Config . GuestOSType ,
NICs : networkCards ,
USBController : s . Config . USBController ,
Version : s . Config . Version ,
2018-01-24 09:56:14 -05:00
} )
if err != nil {
2018-02-01 06:47:09 -05:00
state . Put ( "error" , fmt . Errorf ( "error creating vm: %v" , err ) )
2018-01-24 09:56:14 -05:00
return multistep . ActionHalt
}
state . Put ( "vm" , vm )
2018-05-06 17:26:04 -04:00
2018-01-24 09:56:14 -05:00
return multistep . ActionContinue
}
func ( s * StepCreateVM ) Cleanup ( state multistep . StateBag ) {
2020-10-27 09:07:08 -04:00
common . CleanupVM ( state )
2018-01-24 09:56:14 -05:00
}