mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Merge pull request #4243 from kristinn/vsphere-cdrom-support
vSphere: Support mounting ISO images to virtual cdrom drives.
This commit is contained in:
commit
5b1b49e2b7
@ -53,6 +53,11 @@ type windowsOptConfig struct {
|
||||
domainUserPassword string
|
||||
}
|
||||
|
||||
type cdrom struct {
|
||||
datastore string
|
||||
path string
|
||||
}
|
||||
|
||||
type virtualMachine struct {
|
||||
name string
|
||||
folder string
|
||||
@ -65,6 +70,7 @@ type virtualMachine struct {
|
||||
template string
|
||||
networkInterfaces []networkInterface
|
||||
hardDisks []hardDisk
|
||||
cdroms []cdrom
|
||||
gateway string
|
||||
domain string
|
||||
timeZone string
|
||||
@ -328,6 +334,27 @@ func resourceVSphereVirtualMachine() *schema.Resource {
|
||||
},
|
||||
},
|
||||
|
||||
"cdrom": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"datastore": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"path": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"boot_delay": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
@ -492,6 +519,25 @@ func resourceVSphereVirtualMachineCreate(d *schema.ResourceData, meta interface{
|
||||
log.Printf("[DEBUG] disk init: %v", disks)
|
||||
}
|
||||
|
||||
if vL, ok := d.GetOk("cdrom"); ok {
|
||||
cdroms := make([]cdrom, len(vL.([]interface{})))
|
||||
for i, v := range vL.([]interface{}) {
|
||||
c := v.(map[string]interface{})
|
||||
if v, ok := c["datastore"].(string); ok && v != "" {
|
||||
cdroms[i].datastore = v
|
||||
} else {
|
||||
return fmt.Errorf("Datastore argument must be specified when attaching a cdrom image.")
|
||||
}
|
||||
if v, ok := c["path"].(string); ok && v != "" {
|
||||
cdroms[i].path = v
|
||||
} else {
|
||||
return fmt.Errorf("Path argument must be specified when attaching a cdrom image.")
|
||||
}
|
||||
}
|
||||
vm.cdroms = cdroms
|
||||
log.Printf("[DEBUG] cdrom init: %v", cdroms)
|
||||
}
|
||||
|
||||
if vm.template != "" {
|
||||
err := vm.deployVirtualMachine(client)
|
||||
if err != nil {
|
||||
@ -749,6 +795,31 @@ func addHardDisk(vm *object.VirtualMachine, size, iops int64, diskType string) e
|
||||
}
|
||||
}
|
||||
|
||||
// addCdrom adds a new virtual cdrom drive to the VirtualMachine and attaches an image (ISO) to it from a datastore path.
|
||||
func addCdrom(vm *object.VirtualMachine, datastore, path string) error {
|
||||
devices, err := vm.Device(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] vm devices: %#v", devices)
|
||||
|
||||
controller, err := devices.FindIDEController("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[DEBUG] ide controller: %#v", controller)
|
||||
|
||||
c, err := devices.CreateCdrom(controller)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c = devices.InsertIso(c, fmt.Sprintf("[%s] %s", datastore, path))
|
||||
log.Printf("[DEBUG] addCdrom: %#v", c)
|
||||
|
||||
return vm.AddDevice(context.TODO(), c)
|
||||
}
|
||||
|
||||
// buildNetworkDevice builds VirtualDeviceConfigSpec for Network Device.
|
||||
func buildNetworkDevice(f *find.Finder, label, adapterType string) (*types.VirtualDeviceConfigSpec, error) {
|
||||
network, err := f.Network(context.TODO(), "*"+label)
|
||||
@ -940,6 +1011,21 @@ func findDatastore(c *govmomi.Client, sps types.StoragePlacementSpec) (*object.D
|
||||
return datastore, nil
|
||||
}
|
||||
|
||||
// createCdroms is a helper function to attach virtual cdrom devices (and their attached disk images) to a virtual IDE controller.
|
||||
func createCdroms(vm *object.VirtualMachine, cdroms []cdrom) error {
|
||||
log.Printf("[DEBUG] add cdroms: %v", cdroms)
|
||||
for _, cd := range cdroms {
|
||||
log.Printf("[DEBUG] add cdrom (datastore): %v", cd.datastore)
|
||||
log.Printf("[DEBUG] add cdrom (cd path): %v", cd.path)
|
||||
err := addCdrom(vm, cd.datastore, cd.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createVirtualMachine creates a new VirtualMachine.
|
||||
func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
||||
dc, err := getDatacenter(c, vm.datacenter)
|
||||
@ -1077,6 +1163,7 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
||||
Operation: types.VirtualDeviceConfigSpecOperationAdd,
|
||||
Device: scsi,
|
||||
})
|
||||
|
||||
configSpec.Files = &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", mds.Name)}
|
||||
|
||||
task, err := folder.CreateVM(context.TODO(), configSpec, resourcePool, nil)
|
||||
@ -1104,6 +1191,12 @@ func (vm *virtualMachine) createVirtualMachine(c *govmomi.Client) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the cdroms if needed.
|
||||
if err := createCdroms(newVM, vm.cdroms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1255,6 +1348,7 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
|
||||
NumCoresPerSocket: 1,
|
||||
MemoryMB: vm.memoryMb,
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] virtual machine config spec: %v", configSpec)
|
||||
|
||||
log.Printf("[DEBUG] starting extra custom config spec: %v", vm.customConfigurations)
|
||||
@ -1407,6 +1501,11 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Create the cdroms if needed.
|
||||
if err := createCdroms(newVM, vm.cdroms); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
taskb, err := newVM.Customize(context.TODO(), customSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -1424,6 +1523,7 @@ func (vm *virtualMachine) deployVirtualMachine(c *govmomi.Client) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] virtual machine config spec: %v", configSpec)
|
||||
|
||||
newVM.PowerOn(context.TODO())
|
||||
|
@ -388,6 +388,71 @@ func TestAccVSphereVirtualMachine_createWithFolder(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccVSphereVirtualMachine_createWithCdrom(t *testing.T) {
|
||||
var vm virtualMachine
|
||||
var locationOpt string
|
||||
var datastoreOpt string
|
||||
|
||||
if v := os.Getenv("VSPHERE_DATACENTER"); v != "" {
|
||||
locationOpt += fmt.Sprintf(" datacenter = \"%s\"\n", v)
|
||||
}
|
||||
if v := os.Getenv("VSPHERE_CLUSTER"); v != "" {
|
||||
locationOpt += fmt.Sprintf(" cluster = \"%s\"\n", v)
|
||||
}
|
||||
if v := os.Getenv("VSPHERE_RESOURCE_POOL"); v != "" {
|
||||
locationOpt += fmt.Sprintf(" resource_pool = \"%s\"\n", v)
|
||||
}
|
||||
if v := os.Getenv("VSPHERE_DATASTORE"); v != "" {
|
||||
datastoreOpt = fmt.Sprintf(" datastore = \"%s\"\n", v)
|
||||
}
|
||||
template := os.Getenv("VSPHERE_TEMPLATE")
|
||||
label := os.Getenv("VSPHERE_NETWORK_LABEL_DHCP")
|
||||
cdromDatastore := os.Getenv("VSPHERE_CDROM_DATASTORE")
|
||||
cdromPath := os.Getenv("VSPHERE_CDROM_PATH")
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: fmt.Sprintf(
|
||||
testAccCheckVsphereVirtualMachineConfig_cdrom,
|
||||
locationOpt,
|
||||
label,
|
||||
datastoreOpt,
|
||||
template,
|
||||
cdromDatastore,
|
||||
cdromPath,
|
||||
),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckVSphereVirtualMachineExists("vsphere_virtual_machine.with_cdrom", &vm),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "name", "terraform-test-with-cdrom"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "vcpu", "2"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "memory", "4096"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "disk.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "disk.0.template", template),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "cdrom.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "cdrom.0.datastore", cdromDatastore),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "cdrom.0.path", cdromPath),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "network_interface.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"vsphere_virtual_machine.with_cdrom", "network_interface.0.label", label),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error {
|
||||
client := testAccProvider.Meta().(*govmomi.Client)
|
||||
finder := find.NewFinder(client.Client, true)
|
||||
@ -682,3 +747,24 @@ resource "vsphere_virtual_machine" "with_folder" {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccCheckVsphereVirtualMachineConfig_cdrom = `
|
||||
resource "vsphere_virtual_machine" "with_cdrom" {
|
||||
name = "terraform-test-with-cdrom"
|
||||
%s
|
||||
vcpu = 2
|
||||
memory = 4096
|
||||
network_interface {
|
||||
label = "%s"
|
||||
}
|
||||
disk {
|
||||
%s
|
||||
template = "%s"
|
||||
}
|
||||
|
||||
cdrom {
|
||||
datastore = "%s"
|
||||
path = "%s"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
@ -89,6 +89,11 @@ The following environment variables depend on your vSphere environment:
|
||||
* VSPHERE\_RESOURCE\_POOL
|
||||
* VSPHERE\_DATASTORE
|
||||
|
||||
The following additional environment variables are needed for running the "Mount ISO as CDROM media" acceptance tests.
|
||||
|
||||
* VSPHERE\_CDROM\_DATASTORE
|
||||
* VSPHERE\_CDROM\_PATH
|
||||
|
||||
|
||||
These are used to set and verify attributes on the `vsphere_virtual_machine`
|
||||
resource in tests.
|
||||
|
@ -46,6 +46,7 @@ The following arguments are supported:
|
||||
* `dns_servers` - (Optional) List of DNS servers for the virtual network adapter; defaults to 8.8.8.8, 8.8.4.4
|
||||
* `network_interface` - (Required) Configures virtual network interfaces; see [Network Interfaces](#network-interfaces) below for details.
|
||||
* `disk` - (Required) Configures virtual disks; see [Disks](#disks) below for details
|
||||
* `cdrom` - (Optional) Configures a CDROM device and mounts an image as its media; see [CDROM](#cdrom) below for more details.
|
||||
* `boot_delay` - (Optional) Time in seconds to wait for machine network to be ready.
|
||||
* `windows_opt_config` - (Optional) Extra options for clones of Windows machines.
|
||||
* `linked_clone` - (Optional) Specifies if the new machine is a [linked clone](https://www.vmware.com/support/ws5/doc/ws_clone_overview.html#wp1036396) of another machine or not.
|
||||
@ -71,6 +72,9 @@ The `windows_opt_config` block supports:
|
||||
* `domain_user` - (Optional) User that is a member of the specified domain.
|
||||
* `domain_user_password` - (Optional) Password for domain user, in plain text.
|
||||
|
||||
<a id="disks"></a>
|
||||
## Disks
|
||||
|
||||
The `disk` block supports:
|
||||
|
||||
* `template` - (Required if size not provided) Template for this disk.
|
||||
@ -79,6 +83,14 @@ The `disk` block supports:
|
||||
* `iops` - (Optional) Number of virtual iops to allocate for this disk.
|
||||
* `type` - (Optional) 'eager_zeroed' (the default), or 'thin' are supported options.
|
||||
|
||||
<a id="cdrom"></a>
|
||||
## CDROM
|
||||
|
||||
The `cdrom` block supports:
|
||||
|
||||
* `datastore` - (Required) The name of the datastore where the disk image is stored.
|
||||
* `path` - (Required) The absolute path to the image within the datastore.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
Loading…
Reference in New Issue
Block a user