Repository: ansible-collections/community.vmware

Issue:
disk.controller_number and disk.unit_number set to 0 results in validation error because 0 == false in v1.8 
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
<!--- Explain the problem briefly below -->

Since v1.8 My playbook stopped working with the error

`disk.controller_type', 'disk.controller_number' and 'disk.unit_number' are mandatory parameters when configure multiple disk controllers and disks.
`

Checking my playbook it does have all the parameters


reverting to version 1.7 did fix the issue. I think this might be due to #640 but can"t pinpoint the issue 
 
##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
community.vmware/plugins/modules/vmware_guest.py 

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
ansible 2.10.3
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/var/lib/awx/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /data/awx/awx_venvs/vmware_community/lib64/python3.6/site-packages/ansible
  executable location = /data/awx/awx_venvs/vmware_community/bin/ansible
  python version = 3.6.8 (default, Apr 16 2020, 01:36:27) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]

```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
empty
```paste below

```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->


##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml

```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->
```yaml
- name: Alter VM template
  community.vmware.vmware_guest:
    validate_certs: False
    hostname: '{{ lookup("env", "VMWARE_HOST") }}'
    username: '{{ lookup("env", "VMWARE_USER") }}'
    password: '{{ lookup("env", "VMWARE_PASSWORD") }}'
    host: "{{ set_esxi_hostname | default(omit) }}"
    cluster: "{{ set_cluster | default(omit) }}"
    datacenter: "{{ datacenter }}"
    folder: "{{ folder }}"
    name: "{{ vmname }}"
    customization:
      existing_vm: True
      hostname: "{{ vm_hostname | default(omit)}}"
    disk:
    - size_gb: "{{ disk_size }}"
      type: "{{ disktype |lower }}"
      controller_type : 'paravirtual'
      datastore: "{{ datastore_recommended }}"
      controller_number: 0
      unit_number: 0
    hardware:
      hotadd_memory: True
      memory_mb: "{{ vm_memory  }}"
      num_cpus: "{{ cpu  }}"
      boot_firmware: "{{ boot_firmware  }}"
      scsi: "{{ scsi }}"
    networks:
    - name: "{{ port_grp }}"
      device_type: "vmxnet3"
      start_connected: True
      type: "{{ net_type }}"
      ip: "{{ server_ip }}"
      netmask: "{{ netmask }}"
      gateway: "{{ gateway }}"
      domain: "{{ searchdomain }}"
      dns_servers:
        - "{{ dns1 }}"
        - "{{ dns2 }}"
    state: present
```
output (some info censored)

```
"msg": "'disk.controller_type', 'disk.controller_number' and 'disk.unit_number' are mandatory parameters when configure multiple disk controllers and disks.",
    "invocation": {
        "module_args": {
            "validate_certs": false,
            "hostname": "censored",
            "username": "censored",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "cluster": "censored",
            "datacenter": "censored",
            "folder": "vm",
            "name": "censored",
            "customization": {
                "existing_vm": true,
                "autologon": null,
                "autologoncount": null,
                "dns_servers": null,
                "dns_suffix": null,
                "domain": null,
                "domainadmin": null,
                "domainadminpassword": null,
                "fullname": null,
                "hostname": null,
                "hwclockUTC": null,
                "joindomain": null,
                "joinworkgroup": null,
                "orgname": null,
                "password": null,
                "productid": null,
                "runonce": null,
                "timezone": null
            },
            "disk": [
                {
                    "size_gb": 45,
                    "type": "eagerzeroedthick",
                    "controller_type": "paravirtual",
                    "datastore": "censored",
                    "controller_number": 0,
                    "unit_number": 0,
                    "autoselect_datastore": null,
                    "disk_mode": null,
                    "filename": null,
                    "size": null,
                    "size_kb": null,
                    "size_mb": null,
                    "size_tb": null
                }
            ],
            "hardware": {
                "hotadd_memory": true,
                "memory_mb": 8096,
                "num_cpus": 2,
                "boot_firmware": "efi",
                "scsi": "paravirtual",
                "cpu_limit": null,
                "cpu_reservation": null,
                "hotadd_cpu": null,
                "hotremove_cpu": null,
                "max_connections": null,
                "mem_limit": null,
                "mem_reservation": null,
                "memory_reservation_lock": null,
                "nested_virt": null,
                "num_cpu_cores_per_socket": null,
                "version": null,
                "virt_based_security": null
            },
            "networks": [
                {
                    "name": "censored",
                    "device_type": "vmxnet3",
                    "start_connected": true,
                    "type": "static",
                    "ip": "censored",
                    "netmask": "censored",
                    "gateway": "censored",
                    "domain": "censored",
                    "dns_servers": [
                        "censored",
                        "censored"
                    ]
                }
            ],
            "state": "present",
            "port": 443,
            "is_template": false,
            "customvalues": [],
            "advanced_settings": [],
            "name_match": "first",
            "use_instance_uuid": false,
            "cdrom": [],
            "force": false,
            "wait_for_ip_address": false,
            "wait_for_ip_address_timeout": 300,
            "state_change_timeout": 0,
            "linked_clone": false,
            "wait_for_customization": false,
            "wait_for_customization_timeout": 3600,
            "vapp_properties": [],
            "delete_from_inventory": false,
            "proxy_host": null,
            "proxy_port": null,
            "template": null,
            "annotation": null,
            "uuid": null,
            "guest_id": null,
            "esxi_hostname": null,
            "snapshot_src": null,
            "resource_pool": null,
            "customization_spec": null,
            "datastore": null,
            "convert": null
        }
    },
    "_ansible_no_log": false,
    "changed": false

```


##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```paste below

```



Discussion:
Files identified in the description:
None

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
Files identified in the description:
* [`plugins/modules/vmware_guest.py`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/plugins/modules/vmware_guest.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @Akasurde @Tomorrow9 @goneri @lparkes @nerzhul @pdellaert @pgbidkar @warthog9
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Hi

https://github.com/ansible-collections/community.vmware/blob/f913056612c776b6527aa3c373fe7cb7358d2762/plugins/modules/vmware_guest.py#L2480

should be changed to 
```
 if not disk_spec['controller_type'] or (not disk_spec['controller_number'] and disk_spec['controller_number'] != 0) or (not disk_spec['unit_number'] and disk_spec['controller_number'] != 0):
            
```

Because it errors if the number is 0 

Resolving patch:
diff --git a/plugins/modules/vmware_guest.py b/plugins/modules/vmware_guest.py
--- a/plugins/modules/vmware_guest.py
+++ b/plugins/modules/vmware_guest.py
@@ -2477,7 +2477,7 @@ def sanitize_disk_parameters(self, vm_obj):
         """
         controllers = []
         for disk_spec in self.params.get('disk'):
-            if not disk_spec['controller_type'] or not disk_spec['controller_number'] or not disk_spec['unit_number']:
+            if disk_spec['controller_type'] is None or disk_spec['controller_number'] is None or disk_spec['unit_number'] is None:
                 self.module.fail_json(msg="'disk.controller_type', 'disk.controller_number' and 'disk.unit_number' are"
                                           " mandatory parameters when configure multiple disk controllers and disks.")
 


Test patch:
diff --git a/tests/integration/targets/vmware_guest/defaults/main.yml b/tests/integration/targets/vmware_guest/defaults/main.yml
--- a/tests/integration/targets/vmware_guest/defaults/main.yml
+++ b/tests/integration/targets/vmware_guest/defaults/main.yml
@@ -19,6 +19,7 @@ vmware_guest_test_playbooks:
   - mac_address_d1_c1_f0.yml
   - max_connections.yml
   - mem_reservation.yml
+  - multiple_disk_controllers_d1_c1_f0.yml
   - network_negative_test.yml
   - network_with_device.yml
 # Currently, VCSIM doesn't support DVPG (as portkeys are not available) so commenting this test
diff --git a/tests/integration/targets/vmware_guest/tasks/multiple_disk_controllers_d1_c1_f0.yml b/tests/integration/targets/vmware_guest/tasks/multiple_disk_controllers_d1_c1_f0.yml
--- a/tests/integration/targets/vmware_guest/tasks/multiple_disk_controllers_d1_c1_f0.yml
+++ b/tests/integration/targets/vmware_guest/tasks/multiple_disk_controllers_d1_c1_f0.yml
@@ -1,215 +1,217 @@
 # Test code for the vmware_guest module.
 # Copyright: (c) 2020, Diane Wang <dianew@vmware.com>
 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-- name: create a new VM with multiple scsi controllers
-  vmware_guest:
-    validate_certs: false
-    hostname: "{{ vcenter_hostname }}"
-    username: "{{ vcenter_username }}"
-    password: "{{ vcenter_password }}"
-    datacenter: "{{ dc1 }}"
-    folder: vm
-    cluster: "{{ ccr1 }}"
-    resource_pool: Resources
-    name: test_vm1
-    guest_id: centos64Guest
-    datastore: "{{ rw_datastore }}"
-    hardware:
-      memory_mb: 512
-      num_cpus: 1
-    disk:
-    - controller_type: lsilogicsas
-      controller_number: 0
-      unit_number: 0
-      size_mb: 512
-      type: thin
-    - controller_type: paravirtual
-      controller_number: 1
-      unit_number: 0
-      size_mb: 256
-      type: eagerzeroedthick
-  register: multi_scsi_disk_vm
-
-- debug: var=multi_scsi_disk_vm
-
-- name: assert that VM was deployed
-  assert:
-    that:
-      - "multi_scsi_disk_vm.changed == true"
-
-- name: reconfigure created VM with multiple scsi controllers
-  vmware_guest:
-    validate_certs: false
-    hostname: "{{ vcenter_hostname }}"
-    username: "{{ vcenter_username }}"
-    password: "{{ vcenter_password }}"
-    datacenter: "{{ dc1 }}"
-    folder: vm
-    cluster: "{{ ccr1 }}"
-    resource_pool: Resources
-    name: test_vm1
-    datastore: "{{ rw_datastore }}"
-    state: present
-    disk:
-    - controller_type: lsilogicsas
-      controller_number: 0
-      unit_number: 0
-      disk_mode: independent_persistent
-    - controller_type: paravirtual
-      controller_number: 1
-      unit_number: 0
-      size_mb: 512
-  register: multi_scsi_disk_vm
-
-- debug: var=multi_scsi_disk_vm
-
-- name: assert that VM was configured
-  assert:
-    that:
-      - "multi_scsi_disk_vm.changed == true"
-
-- name: create a new VM with multiple sata controllers
-  vmware_guest:
-    validate_certs: false
-    hostname: "{{ vcenter_hostname }}"
-    username: "{{ vcenter_username }}"
-    password: "{{ vcenter_password }}"
-    folder: vm
-    datacenter: "{{ dc1 }}"
-    cluster: "{{ ccr1 }}"
-    resource_pool: Resources
-    name: test_vm2
-    guest_id: centos64Guest
-    datastore: "{{ rw_datastore }}"
-    hardware:
-      memory_mb: 512
-      num_cpus: 1
-    disk:
-    - controller_type: sata
-      controller_number: 0
-      unit_number: 0
-      size_mb: 512
-      disk_mode: independent_persistent
-    - controller_type: sata
-      controller_number: 1
-      unit_number: 0
-      size_mb: 256
-    - controller_type: sata
-      controller_number: 2
-      unit_number: 0
-      size_mb: 256
-  register: multi_sata_disk_vm
-
-- debug: var=multi_sata_disk_vm
-
-- name: assert that VM was deployed
-  assert:
-    that:
-      - "multi_sata_disk_vm.changed == true"
-
-- name: reconfigure created new VM with multiple sata controllers
-  vmware_guest:
-    validate_certs: false
-    hostname: "{{ vcenter_hostname }}"
-    username: "{{ vcenter_username }}"
-    password: "{{ vcenter_password }}"
-    folder: vm
-    datacenter: "{{ dc1 }}"
-    cluster: "{{ ccr1 }}"
-    resource_pool: Resources
-    name: test_vm2
-    state: present
-    datastore: "{{ rw_datastore }}"
-    disk:
-    - controller_type: sata
-      controller_number: 0
-      unit_number: 0
-      size_mb: 512
-      disk_mode: persistent
-    - controller_type: sata
-      controller_number: 1
-      unit_number: 0
-      size_mb: 512
-  register: multi_sata_disk_vm
-
-- debug: var=multi_sata_disk_vm
-
-- name: assert that VM was deployed
-  assert:
-    that:
-      - "multi_sata_disk_vm.changed == true"
-
-- name: create a new VM with multiple nvme controllers
-  vmware_guest:
-    validate_certs: false
-    hostname: "{{ vcenter_hostname }}"
-    username: "{{ vcenter_username }}"
-    password: "{{ vcenter_password }}"
-    folder: vm
-    datacenter: "{{ dc1 }}"
-    cluster: "{{ ccr1 }}"
-    resource_pool: Resources
-    name: test_vm3
-    guest_id: centos64Guest
-    datastore: "{{ rw_datastore }}"
-    hardware:
-      memory_mb: 512
-      num_cpus: 1
-      version: 14
-    disk:
-    - controller_type: nvme
-      controller_number: 0
-      unit_number: 0
-      size_mb: 512
-    - controller_type: nvme
-      controller_number: 1
-      unit_number: 0
-      size_mb: 256
-      type: thin
-    - controller_type: nvme
-      controller_number: 2
-      unit_number: 0
-      size_mb: 256
-  register: multi_nvme_disk_vm
-
-- debug: var=multi_nvme_disk_vm
-
-- name: assert that VM was deployed
-  assert:
-    that:
-      - "multi_nvme_disk_vm.changed == true"
-
-- name: reconfigure created new VM with multiple types of controllers
-  vmware_guest:
-    validate_certs: false
-    hostname: "{{ vcenter_hostname }}"
-    username: "{{ vcenter_username }}"
-    password: "{{ vcenter_password }}"
-    folder: vm
-    datacenter: "{{ dc1 }}"
-    cluster: "{{ ccr1 }}"
-    resource_pool: Resources
-    name: test_vm3
-    state: present
-    datastore: "{{ rw_datastore }}"
-    disk:
-    - controller_type: nvme
-      controller_number: 0
-      unit_number: 1
-      size_mb: 512
-    - controller_type: sata
-      controller_number: 1
-      unit_number: 0
-      size_mb: 256
-    - controller_type: paravirtual
-      controller_number: 0
-      unit_number: 0
-      size_mb: 256
-  register: multi_nvme_disk_vm
-
-- debug: var=multi_nvme_disk_vm
-
-- name: assert that VM was deployed
-  assert:
-    that:
-      - "multi_nvme_disk_vm.changed == true"
+- when: vcsim is not defined
+  block:
+    - name: create a new VM with multiple scsi controllers
+      vmware_guest:
+        validate_certs: false
+        hostname: "{{ vcenter_hostname }}"
+        username: "{{ vcenter_username }}"
+        password: "{{ vcenter_password }}"
+        datacenter: "{{ dc1 }}"
+        folder: vm
+        cluster: "{{ ccr1 }}"
+        resource_pool: Resources
+        name: test_vm1
+        guest_id: centos64Guest
+        datastore: "{{ rw_datastore }}"
+        hardware:
+          memory_mb: 512
+          num_cpus: 1
+        disk:
+        - controller_type: lsilogicsas
+          controller_number: 0
+          unit_number: 0
+          size_mb: 512
+          type: thin
+        - controller_type: paravirtual
+          controller_number: 1
+          unit_number: 0
+          size_mb: 256
+          type: eagerzeroedthick
+      register: multi_scsi_disk_vm
+
+    - debug: var=multi_scsi_disk_vm
+
+    - name: assert that VM was deployed
+      assert:
+        that:
+          - "multi_scsi_disk_vm.changed == true"
+
+    - name: reconfigure created VM with multiple scsi controllers
+      vmware_guest:
+        validate_certs: false
+        hostname: "{{ vcenter_hostname }}"
+        username: "{{ vcenter_username }}"
+        password: "{{ vcenter_password }}"
+        datacenter: "{{ dc1 }}"
+        folder: vm
+        cluster: "{{ ccr1 }}"
+        resource_pool: Resources
+        name: test_vm1
+        datastore: "{{ rw_datastore }}"
+        state: present
+        disk:
+        - controller_type: lsilogicsas
+          controller_number: 0
+          unit_number: 0
+          disk_mode: independent_persistent
+        - controller_type: paravirtual
+          controller_number: 1
+          unit_number: 0
+          size_mb: 512
+      register: multi_scsi_disk_vm
+
+    - debug: var=multi_scsi_disk_vm
+
+    - name: assert that VM was configured
+      assert:
+        that:
+          - "multi_scsi_disk_vm.changed == true"
+
+    - name: create a new VM with multiple sata controllers
+      vmware_guest:
+        validate_certs: false
+        hostname: "{{ vcenter_hostname }}"
+        username: "{{ vcenter_username }}"
+        password: "{{ vcenter_password }}"
+        folder: vm
+        datacenter: "{{ dc1 }}"
+        cluster: "{{ ccr1 }}"
+        resource_pool: Resources
+        name: test_vm2
+        guest_id: centos64Guest
+        datastore: "{{ rw_datastore }}"
+        hardware:
+          memory_mb: 512
+          num_cpus: 1
+        disk:
+        - controller_type: sata
+          controller_number: 0
+          unit_number: 0
+          size_mb: 512
+          disk_mode: independent_persistent
+        - controller_type: sata
+          controller_number: 1
+          unit_number: 0
+          size_mb: 256
+        - controller_type: sata
+          controller_number: 2
+          unit_number: 0
+          size_mb: 256
+      register: multi_sata_disk_vm
+
+    - debug: var=multi_sata_disk_vm
+
+    - name: assert that VM was deployed
+      assert:
+        that:
+          - "multi_sata_disk_vm.changed == true"
+
+    - name: reconfigure created new VM with multiple sata controllers
+      vmware_guest:
+        validate_certs: false
+        hostname: "{{ vcenter_hostname }}"
+        username: "{{ vcenter_username }}"
+        password: "{{ vcenter_password }}"
+        folder: vm
+        datacenter: "{{ dc1 }}"
+        cluster: "{{ ccr1 }}"
+        resource_pool: Resources
+        name: test_vm2
+        state: present
+        datastore: "{{ rw_datastore }}"
+        disk:
+        - controller_type: sata
+          controller_number: 0
+          unit_number: 0
+          size_mb: 512
+          disk_mode: persistent
+        - controller_type: sata
+          controller_number: 1
+          unit_number: 0
+          size_mb: 512
+      register: multi_sata_disk_vm
+
+    - debug: var=multi_sata_disk_vm
+
+    - name: assert that VM was deployed
+      assert:
+        that:
+          - "multi_sata_disk_vm.changed == true"
+
+    - name: create a new VM with multiple nvme controllers
+      vmware_guest:
+        validate_certs: false
+        hostname: "{{ vcenter_hostname }}"
+        username: "{{ vcenter_username }}"
+        password: "{{ vcenter_password }}"
+        folder: vm
+        datacenter: "{{ dc1 }}"
+        cluster: "{{ ccr1 }}"
+        resource_pool: Resources
+        name: test_vm3
+        guest_id: centos64Guest
+        datastore: "{{ rw_datastore }}"
+        hardware:
+          memory_mb: 512
+          num_cpus: 1
+          version: 14
+        disk:
+        - controller_type: nvme
+          controller_number: 0
+          unit_number: 0
+          size_mb: 512
+        - controller_type: nvme
+          controller_number: 1
+          unit_number: 0
+          size_mb: 256
+          type: thin
+        - controller_type: nvme
+          controller_number: 2
+          unit_number: 0
+          size_mb: 256
+      register: multi_nvme_disk_vm
+
+    - debug: var=multi_nvme_disk_vm
+
+    - name: assert that VM was deployed
+      assert:
+        that:
+          - "multi_nvme_disk_vm.changed == true"
+
+    - name: reconfigure created new VM with multiple types of controllers
+      vmware_guest:
+        validate_certs: false
+        hostname: "{{ vcenter_hostname }}"
+        username: "{{ vcenter_username }}"
+        password: "{{ vcenter_password }}"
+        folder: vm
+        datacenter: "{{ dc1 }}"
+        cluster: "{{ ccr1 }}"
+        resource_pool: Resources
+        name: test_vm3
+        state: present
+        datastore: "{{ rw_datastore }}"
+        disk:
+        - controller_type: nvme
+          controller_number: 0
+          unit_number: 1
+          size_mb: 512
+        - controller_type: sata
+          controller_number: 1
+          unit_number: 0
+          size_mb: 256
+        - controller_type: paravirtual
+          controller_number: 0
+          unit_number: 0
+          size_mb: 256
+      register: multi_nvme_disk_vm
+
+    - debug: var=multi_nvme_disk_vm
+
+    - name: assert that VM was deployed
+      assert:
+        that:
+          - "multi_nvme_disk_vm.changed == true"