From f89db2af9978e2acaa8c56ee6fb6dc9908119d1a Mon Sep 17 00:00:00 2001 From: Jiri Tyr Date: Tue, 10 Dec 2019 15:30:15 +0000 Subject: [PATCH] Adding filename and destroy options to vmware_guest_disk (#63740) Adding filename and destroy options to vmware_guest_disk --- ...40-vmware_guest_disk_filename_destroy.yaml | 5 ++ .../modules/cloud/vmware/vmware_guest_disk.py | 69 +++++++++++++++---- 2 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 changelogs/fragments/63740-vmware_guest_disk_filename_destroy.yaml diff --git a/changelogs/fragments/63740-vmware_guest_disk_filename_destroy.yaml b/changelogs/fragments/63740-vmware_guest_disk_filename_destroy.yaml new file mode 100644 index 00000000000..a14640444ca --- /dev/null +++ b/changelogs/fragments/63740-vmware_guest_disk_filename_destroy.yaml @@ -0,0 +1,5 @@ +--- + +minor_changes: + - vmware_guest_disk - Add `destroy` option which allows to remove a disk without deleting the VMDK file. + - vmware_guest_disk - Add `filename` option which allows to create a disk from an existing VMDK. diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py b/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py index a22809fca1a..bc070fbb1bf 100644 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py +++ b/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py @@ -104,6 +104,10 @@ options: - ' This value is ignored, if SCSI Controller is already present or C(state) is C(absent).' - ' Valid values are C(buslogic), C(lsilogic), C(lsilogicsas) and C(paravirtual).' - ' C(paravirtual) is default value for this parameter.' + - ' - C(destroy) (bool): If C(state) is C(absent), make sure the disk file is deleted from the datastore (default C(yes)).' + - ' Added in version 2.10.' + - ' - C(filename) (string): Existing disk image to be used. Filename must already exist on the datastore.' + - ' Specify filename string in C([datastore_name] path/to/file.vmdk) format. Added in version 2.10.' - ' - C(state) (string): State of disk. This is either "absent" or "present".' - ' If C(state) is set to C(absent), disk will be removed permanently from virtual machine configuration and from VMware storage.' - ' If C(state) is set to C(present), disk will be added if not present at given SCSI Controller and Unit Number.' @@ -148,10 +152,11 @@ EXAMPLES = ''' scsi_type: 'buslogic' unit_number: 1 disk_mode: 'independent_nonpersistent' + - filename: "[datastore1] path/to/existing/disk.vmdk" delegate_to: localhost register: disk_facts -- name: Remove disks from virtual machine using name +- name: Remove disk from virtual machine using name vmware_guest_disk: hostname: "{{ vcenter_hostname }}" username: "{{ vcenter_username }}" @@ -166,7 +171,7 @@ EXAMPLES = ''' delegate_to: localhost register: disk_facts -- name: Remove disks from virtual machine using moid +- name: Remove disk from virtual machine using moid vmware_guest_disk: hostname: "{{ vcenter_hostname }}" username: "{{ vcenter_username }}" @@ -180,6 +185,22 @@ EXAMPLES = ''' unit_number: 1 delegate_to: localhost register: disk_facts + +- name: Remove disk from virtual machine but keep the VMDK file on the datastore + vmware_guest_disk: + hostname: "{{ vcenter_hostname }}" + username: "{{ vcenter_username }}" + password: "{{ vcenter_password }}" + datacenter: "{{ datacenter_name }}" + validate_certs: no + name: VM_225 + disk: + - state: absent + scsi_controller: 1 + unit_number: 2 + destroy: no + delegate_to: localhost + register: disk_facts ''' RETURN = """ @@ -251,24 +272,31 @@ class PyVmomiHelper(PyVmomi): return scsi_ctl @staticmethod - def create_scsi_disk(scsi_ctl_key, disk_index, disk_mode): + def create_scsi_disk(scsi_ctl_key, disk_index, disk_mode, disk_filename): """ Create Virtual Device Spec for virtual disk Args: scsi_ctl_key: Unique SCSI Controller Key disk_index: Disk unit number at which disk needs to be attached + disk_mode: Disk mode + disk_filename: Path to the disk file on the datastore Returns: Virtual Device Spec for virtual disk """ disk_spec = vim.vm.device.VirtualDeviceSpec() disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - disk_spec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.create disk_spec.device = vim.vm.device.VirtualDisk() disk_spec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo() disk_spec.device.backing.diskMode = disk_mode disk_spec.device.controllerKey = scsi_ctl_key disk_spec.device.unitNumber = disk_index + + if disk_filename is not None: + disk_spec.device.backing.fileName = disk_filename + else: + disk_spec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.create + return disk_spec def reconfigure_vm(self, config_spec, device_type): @@ -347,16 +375,21 @@ class PyVmomiHelper(PyVmomi): scsi_controller = disk['scsi_controller'] + 1000 # VMware auto assign 1000 + SCSI Controller if disk['disk_unit_number'] not in current_scsi_info[scsi_controller]['disks'] and disk['state'] == 'present': # Add new disk - disk_spec = self.create_scsi_disk(scsi_controller, disk['disk_unit_number'], disk['disk_mode']) - disk_spec.device.capacityInKB = disk['size'] + disk_spec = self.create_scsi_disk(scsi_controller, disk['disk_unit_number'], disk['disk_mode'], disk['filename']) + if disk['filename'] is None: + disk_spec.device.capacityInKB = disk['size'] if disk['disk_type'] == 'thin': disk_spec.device.backing.thinProvisioned = True elif disk['disk_type'] == 'eagerzeroedthick': disk_spec.device.backing.eagerlyScrub = True - disk_spec.device.backing.fileName = "[%s] %s/%s_%s_%s.vmdk" % (disk['datastore'].name, - vm_name, vm_name, - str(scsi_controller), - str(disk['disk_unit_number'])) + if disk['filename'] is None: + disk_spec.device.backing.fileName = "[%s] %s/%s_%s_%s.vmdk" % ( + disk['datastore'].name, + vm_name, vm_name, + str(scsi_controller), + str(disk['disk_unit_number'])) + else: + disk_spec.device.backing.fileName = disk['filename'] disk_spec.device.backing.datastore = disk['datastore'] self.config_spec.deviceChange.append(disk_spec) disk_change = True @@ -386,7 +419,8 @@ class PyVmomiHelper(PyVmomi): # Disk already exists, deleting disk_spec = vim.vm.device.VirtualDeviceSpec() disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove - disk_spec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.destroy + if disk['destroy'] is True: + disk_spec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.destroy disk_spec.device = current_scsi_info[scsi_controller]['disks'][disk['disk_unit_number']] self.config_spec.deviceChange.append(disk_spec) disk_change = True @@ -420,6 +454,8 @@ class PyVmomiHelper(PyVmomi): # Initialize default value for disk current_disk = dict(disk_index=disk_index, state='present', + destroy=True, + filename=None, datastore=None, autoselect_datastore=True, disk_unit_number=0, @@ -434,7 +470,9 @@ class PyVmomiHelper(PyVmomi): else: current_disk['state'] = disk['state'] - if current_disk['state'] == 'present': + if current_disk['state'] == 'absent': + current_disk['destroy'] = disk['destroy'] + elif current_disk['state'] == 'present': # Select datastore or datastore cluster if 'datastore' in disk: if 'autoselect_datastore' in disk: @@ -469,11 +507,14 @@ class PyVmomiHelper(PyVmomi): datastore_freespace = ds.summary.freeSpace current_disk['datastore'] = datastore - if 'datastore' not in disk and 'autoselect_datastore' not in disk: + if 'datastore' not in disk and 'autoselect_datastore' not in disk and 'filename' not in disk: self.module.fail_json(msg="Either 'datastore' or 'autoselect_datastore' is" " required parameter while creating disk for " "disk index [%s]." % disk_index) + if 'filename' in disk: + current_disk['filename'] = disk['filename'] + if [x for x in disk.keys() if x.startswith('size_') or x == 'size']: # size, size_tb, size_gb, size_mb, size_kb disk_size_parse_failed = False @@ -529,7 +570,7 @@ class PyVmomiHelper(PyVmomi): disk_index, "', '".join(disk_units.keys()))) - else: + elif current_disk['filename'] is None: # No size found but disk, fail self.module.fail_json(msg="No size, size_kb, size_mb, size_gb or size_tb" " attribute found into disk index [%s] configuration." % disk_index)