Skip to content

Commit

Permalink
vmware_guest_disk: add IDE disk support (#1616)
Browse files Browse the repository at this point in the history
vmware_guest_disk: add IDE disk support

Signed-off-by: Diane Wang [email protected]
SUMMARY

We want to use vmware_guest_disk module to add or reconfigure IDE disk on VM.

Fixes #1428
Fixes #1617
ISSUE TYPE


Feature Pull Request

COMPONENT NAME

vmware_guest_disk
ADDITIONAL INFORMATION



- name: add new ide disk
   vmware_guest_disk:
        validate_certs: false
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        datacenter: "{{ datacenter_name }}"
        name: test_vm
        disk:
          - size_gb: 1
            type: thin
            datastore: Datastore1
            state: present
            controller_type: ide
            controller_number: 0
            unit_number: 1

Reviewed-by: Mario Lenz <[email protected]>
  • Loading branch information
Tomorrow9 authored Feb 6, 2023
1 parent 7541e32 commit df3ae15
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 190 deletions.
3 changes: 3 additions & 0 deletions changelogs/fragments/1616-vmware_guest_disk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- vmware_guest_disk - Add support for IDE disk add, remove or reconfigure, and change to gather same VM disk info as in vmware_guest_disk_info (https://github.com/ansible-collections/community.vmware/issues/1428).
- vmware_guest_disk_info - Move gather VM disk info function to vm_device_helper.py (https://github.com/ansible-collections/community.vmware/issues/1617)
109 changes: 109 additions & 0 deletions plugins/module_utils/vm_device_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ def __init__(self, module):
}
self.sata_device_type = vim.vm.device.VirtualAHCIController
self.nvme_device_type = vim.vm.device.VirtualNVMEController
self.ide_device_type = vim.vm.device.VirtualIDEController
self.disk_ctl_device_type = self.scsi_device_type.copy()
self.disk_ctl_device_type.update({
'sata': self.sata_device_type,
'nvme': self.nvme_device_type,
'ide': self.ide_device_type
})
self.usb_device_type = {
'usb2': vim.vm.device.VirtualUSBController,
'usb3': vim.vm.device.VirtualUSBXHCIController
Expand Down Expand Up @@ -404,3 +411,105 @@ def remove_tpm(self, vtpm_device):
vtpm_device_spec.device = vtpm_device

return vtpm_device_spec

def gather_disk_info(self, vm_obj):
"""
Gather information about VM's disks
Args:
vm_obj: Managed object of virtual machine
Returns: A list of dict containing disks information
"""
controller_info = dict()
disks_info = dict()
if vm_obj is None:
return disks_info

controller_index = 0
for controller in vm_obj.config.hardware.device:
for name, type in self.disk_ctl_device_type.items():
if isinstance(controller, type):
controller_info[controller_index] = dict(
key=controller.key,
controller_type=name,
bus_number=controller.busNumber,
devices=controller.device
)
controller_index += 1

disk_index = 0
for disk in vm_obj.config.hardware.device:
if isinstance(disk, vim.vm.device.VirtualDisk):
if disk.storageIOAllocation is None:
disk.storageIOAllocation = vim.StorageResourceManager.IOAllocationInfo()
disk.storageIOAllocation.shares = vim.SharesInfo()

if disk.shares is None:
disk.shares = vim.SharesInfo()

disks_info[disk_index] = dict(
key=disk.key,
label=disk.deviceInfo.label,
summary=disk.deviceInfo.summary,
backing_filename=disk.backing.fileName,
backing_datastore=disk.backing.datastore.name,
backing_sharing=disk.backing.sharing if hasattr(disk.backing, 'sharing') else None,
backing_uuid=disk.backing.uuid if hasattr(disk.backing, 'uuid') else None,
backing_writethrough=disk.backing.writeThrough if hasattr(disk.backing, 'writeThrough') else None,
backing_diskmode=disk.backing.diskMode if hasattr(disk.backing, 'diskMode') else None,
backing_disk_mode=disk.backing.diskMode if hasattr(disk.backing, 'diskMode') else None,
iolimit_limit=disk.storageIOAllocation.limit,
iolimit_shares_level=disk.storageIOAllocation.shares.level,
iolimit_shares_limit=disk.storageIOAllocation.shares.shares,
shares_level=disk.shares.level,
shares_limit=disk.shares.shares,
controller_key=disk.controllerKey,
unit_number=disk.unitNumber,
capacity_in_kb=disk.capacityInKB,
capacity_in_bytes=disk.capacityInBytes,
)
if isinstance(disk.backing, vim.vm.device.VirtualDisk.FlatVer1BackingInfo):
disks_info[disk_index]['backing_type'] = 'FlatVer1'

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.FlatVer2BackingInfo):
disks_info[disk_index]['backing_type'] = 'FlatVer2'
disks_info[disk_index]['backing_thinprovisioned'] = disk.backing.thinProvisioned
disks_info[disk_index]['backing_eagerlyscrub'] = disk.backing.eagerlyScrub

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.LocalPMemBackingInfo):
disks_info[disk_index]['backing_type'] = 'LocalPMem'
disks_info[disk_index]['backing_volumeuuid'] = disk.backing.volumeUUID

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.PartitionedRawDiskVer2BackingInfo):
disks_info[disk_index]['backing_type'] = 'PartitionedRawDiskVer2'
disks_info[disk_index]['backing_descriptorfilename'] = disk.backing.descriptorFileName

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo):
disks_info[disk_index]['backing_type'] = 'RawDiskMappingVer1'
disks_info[disk_index]['backing_devicename'] = disk.backing.deviceName
disks_info[disk_index]['backing_lunuuid'] = disk.backing.lunUuid
disks_info[disk_index]['backing_compatibility_mode'] = disk.backing.compatibilityMode

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.RawDiskVer2BackingInfo):
disks_info[disk_index]['backing_type'] = 'RawDiskVer2'
disks_info[disk_index]['backing_descriptorfilename'] = disk.backing.descriptorFileName

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SeSparseBackingInfo):
disks_info[disk_index]['backing_type'] = 'SeSparse'

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SparseVer1BackingInfo):
disks_info[disk_index]['backing_type'] = 'SparseVer1'
disks_info[disk_index]['backing_spaceusedinkb'] = disk.backing.spaceUsedInKB
disks_info[disk_index]['backing_split'] = disk.backing.split

elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SparseVer2BackingInfo):
disks_info[disk_index]['backing_type'] = 'SparseVer2'
disks_info[disk_index]['backing_spaceusedinkb'] = disk.backing.spaceUsedInKB
disks_info[disk_index]['backing_split'] = disk.backing.split

for controller_index in range(len(controller_info)):
if controller_info[controller_index]['key'] == disks_info[disk_index]['controller_key']:
disks_info[disk_index]['controller_bus_number'] = controller_info[controller_index]['bus_number']
disks_info[disk_index]['controller_type'] = controller_info[controller_index]['controller_type']

disk_index += 1
return disks_info
84 changes: 21 additions & 63 deletions plugins/modules/vmware_guest_disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,10 @@
description:
- Disk Unit Number.
- Valid value range from 0 to 15, except 7 for SCSI Controller.
- Valid value range from 0 to 64, except 7 for Paravirtual SCSI Controller on Virtual Hardware version 14 or higher
- Valid value range from 0 to 64, except 7 for Paravirtual SCSI Controller on Virtual Hardware version 14 or higher.
- Valid value range from 0 to 29 for SATA controller.
- Valid value range from 0 to 14 for NVME controller.
- Valid value range from 0 to 1 for IDE controller.
type: int
required: True
scsi_type:
Expand Down Expand Up @@ -189,9 +190,11 @@
- This parameter is added for managing disks attaching other types of controllers, e.g., SATA or NVMe.
- If either C(controller_type) or C(scsi_type) is not specified, then use C(paravirtual) type.
type: str
choices: ['buslogic', 'lsilogic', 'lsilogicsas', 'paravirtual', 'sata', 'nvme']
choices: ['buslogic', 'lsilogic', 'lsilogicsas', 'paravirtual', 'sata', 'nvme', 'ide']
controller_number:
description: This parameter is used with C(controller_type) for specifying controller bus number.
description:
- This parameter is used with C(controller_type) for specifying controller bus number.
- For C(ide) controller type, valid value is 0 or 1.
type: int
choices: [0, 1, 2, 3]
iolimit:
Expand Down Expand Up @@ -516,8 +519,6 @@ def __init__(self, module):
self.device_helper = PyVmomiDeviceHelper(self.module)
self.desired_disks = self.params['disk'] # Match with vmware_guest parameter
self.vm = None
self.ctl_device_type = self.device_helper.scsi_device_type.copy()
self.ctl_device_type.update({'sata': self.device_helper.sata_device_type, 'nvme': self.device_helper.nvme_device_type})
self.config_spec = vim.vm.ConfigSpec()
self.config_spec.deviceChange = []

Expand Down Expand Up @@ -667,7 +668,7 @@ def ensure_disks(self, vm_obj=None):
# check if disk controller already exists
if not ctl_found:
for device in self.vm.config.hardware.device:
if isinstance(device, self.ctl_device_type[disk['controller_type']]):
if isinstance(device, self.device_helper.disk_ctl_device_type[disk['controller_type']]):
if device.busNumber == disk['controller_number']:
ctl_found = True
break
Expand Down Expand Up @@ -699,7 +700,7 @@ def ensure_disks(self, vm_obj=None):
disk_change = False
ctl_found = False
for device in self.vm.config.hardware.device:
if isinstance(device, self.ctl_device_type[disk['controller_type']]) and device.busNumber == disk['controller_number']:
if isinstance(device, self.device_helper.disk_ctl_device_type[disk['controller_type']]) and device.busNumber == disk['controller_number']:
for disk_key in device.device:
disk_device = self.find_disk_by_key(disk_key, disk['disk_unit_number'])
if disk_device is not None:
Expand Down Expand Up @@ -813,7 +814,7 @@ def ensure_disks(self, vm_obj=None):
self.config_spec.deviceChange = []
if any(disk_change_list):
results['changed'] = True
results['disk_data'] = self.gather_disk_facts(vm_obj=self.vm)
results['disk_data'] = self.device_helper.gather_disk_info(self.vm)
self.module.exit_json(**results)

def sanitize_disk_inputs(self):
Expand Down Expand Up @@ -870,6 +871,10 @@ def sanitize_disk_inputs(self):
else:
self.module.fail_json(msg="Please specify either 'scsi_type' or 'controller_type' for disk index [%s]."
% disk_index)
if current_disk['controller_type'] == 'ide':
if self.vm.runtime.powerState != vim.VirtualMachinePowerState.poweredOff:
self.module.fail_json(msg="Please make sure VM is in powered off state before doing IDE disk"
" reconfiguration.")

# Check controller bus number
if disk['scsi_controller'] is not None and disk['controller_number'] is None and disk['controller_type'] is None:
Expand All @@ -885,6 +890,10 @@ def sanitize_disk_inputs(self):
except ValueError:
self.module.fail_json(msg="Invalid controller bus number '%s' specified"
" for disk index [%s]" % (temp_disk_controller, disk_index))
if current_disk['controller_type'] == 'ide' and disk_controller not in [0, 1]:
self.module.fail_json(msg="Invalid controller bus number '%s' specified"
" for disk index [%s], valid value is 0 or 1" % (disk_controller, disk_index))

current_disk['controller_number'] = disk_controller

try:
Expand Down Expand Up @@ -921,6 +930,9 @@ def sanitize_disk_inputs(self):
elif current_disk['controller_type'] == 'nvme' and temp_disk_unit_number not in range(0, 15):
self.module.fail_json(msg="Invalid Disk unit number ID specified for NVMe disk [%s] at index [%s],"
" please specify value between 0 to 14" % (temp_disk_unit_number, disk_index))
elif current_disk['controller_type'] == 'ide' and temp_disk_unit_number not in [0, 1]:
self.module.fail_json(msg="Invalid Disk unit number ID specified for IDE disk [%s] at index [%s],"
" please specify value 0 or 1" % (temp_disk_unit_number, disk_index))
current_disk['disk_unit_number'] = temp_disk_unit_number

# By default destroy file from datastore if 'destroy' parameter is not provided
Expand Down Expand Up @@ -1124,60 +1136,6 @@ def get_recommended_datastore(self, datastore_cluster_obj, disk_spec_obj):
return datastore.name
return None

@staticmethod
def gather_disk_facts(vm_obj):
"""
Gather facts about VM's disks
Args:
vm_obj: Managed object of virtual machine
Returns: A list of dict containing disks information
"""
disks_facts = dict()
if vm_obj is None:
return disks_facts

disk_index = 0
for disk in vm_obj.config.hardware.device:
if isinstance(disk, vim.vm.device.VirtualDisk):
if disk.storageIOAllocation is None:
disk.storageIOAllocation = vim.StorageResourceManager.IOAllocationInfo()
disk.storageIOAllocation.shares = vim.SharesInfo()

if disk.shares is None:
disk.shares = vim.SharesInfo()

disks_facts[disk_index] = dict(
key=disk.key,
label=disk.deviceInfo.label,
summary=disk.deviceInfo.summary,
backing_filename=disk.backing.fileName,
backing_datastore=disk.backing.datastore.name,
backing_disk_mode=disk.backing.diskMode,
backing_sharing=disk.backing.sharing if hasattr(disk.backing, 'sharing') else None,
backing_uuid=disk.backing.uuid,
controller_key=disk.controllerKey,
unit_number=disk.unitNumber,
iolimit_limit=disk.storageIOAllocation.limit,
iolimit_shares_level=disk.storageIOAllocation.shares.level,
iolimit_shares_limit=disk.storageIOAllocation.shares.shares,
shares_level=disk.shares.level,
shares_limit=disk.shares.shares,
capacity_in_kb=disk.capacityInKB,
capacity_in_bytes=disk.capacityInBytes,
)
if isinstance(disk.backing, vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo):
disks_facts[disk_index].update(backing_devicename=disk.backing.deviceName,
backing_compatibility_mode=disk.backing.compatibilityMode)

elif not isinstance(disk.backing, vim.vm.device.VirtualDisk.LocalPMemBackingInfo):
disks_facts[disk_index].update(backing_writethrough=disk.backing.writeThrough,
backing_thinprovisioned=disk.backing.thinProvisioned,
backing_eagerlyscrub=bool(disk.backing.eagerlyScrub))
disk_index += 1
return disks_facts


def main():
argument_spec = vmware_argument_spec()
Expand Down Expand Up @@ -1211,7 +1169,7 @@ def main():
destroy=dict(type='bool', default=True),
filename=dict(type='str'),
state=dict(type='str', default='present', choices=['present', 'absent']),
controller_type=dict(type='str', choices=['buslogic', 'lsilogic', 'paravirtual', 'lsilogicsas', 'sata', 'nvme']),
controller_type=dict(type='str', choices=['buslogic', 'lsilogic', 'paravirtual', 'lsilogicsas', 'sata', 'nvme', 'ide']),
controller_number=dict(type='int', choices=[0, 1, 2, 3]),
bus_sharing=dict(type='str', choices=['noSharing', 'physicalSharing', 'virtualSharing'], default='noSharing'),
cluster_disk=dict(type='bool', default=False),
Expand Down
Loading

0 comments on commit df3ae15

Please sign in to comment.