Repository: ansible-collections/community.vmware

Issue:
vmware_guest: add new NVDIMM device failed on standalone ESXi host
<!--- 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 -->
```MODULE FAILURE
See stdout/stderr for the exact error
Traceback (most recent call last):
  File "/tmp/ansible-tmp-1677045859.3063774-10008-266618381064444/AnsiballZ_vmware_guest.py", line 107, in <module>
    _ansiballz_main()
  File "/tmp/ansible-tmp-1677045859.3063774-10008-266618381064444/AnsiballZ_vmware_guest.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/tmp/ansible-tmp-1677045859.3063774-10008-266618381064444/AnsiballZ_vmware_guest.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.community.vmware.plugins.modules.vmware_guest', init_globals=dict(_module_fqn='ansible_collections.community.vmware.plugins.modules.vmware_guest', _modlib_path=modlib_path),
  File "/usr/lib/python3.10/runpy.py", line 209, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib/python3.10/runpy.py", line 96, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_community.vmware.vmware_guest_payload_t2d_8wpe/ansible_community.vmware.vmware_guest_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest.py", line 3563, in <module>
  File "/tmp/ansible_community.vmware.vmware_guest_payload_t2d_8wpe/ansible_community.vmware.vmware_guest_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest.py", line 3511, in main
  File "/tmp/ansible_community.vmware.vmware_guest_payload_t2d_8wpe/ansible_community.vmware.vmware_guest_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest.py", line 3148, in reconfigure_vm
  File "/tmp/ansible_community.vmware.vmware_guest_payload_t2d_8wpe/ansible_community.vmware.vmware_guest_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest.py", line 1784, in configure_nvdimm
  File "/tmp/ansible_community.vmware.vmware_guest_payload_t2d_8wpe/ansible_community.vmware.vmware_guest_payload.zip/ansible_collections/community/vmware/plugins/module_utils/vmware_spbm.py", line 48, in find_storage_profile_by_name
  File "/tmp/ansible_community.vmware.vmware_guest_payload_t2d_8wpe/ansible_community.vmware.vmware_guest_payload.zip/ansible_collections/community/vmware/plugins/module_utils/vmware_spbm.py", line 44, in get_spbm_connection
  File "/usr/lib/python3.10/site-packages/pyVmomi/VmomiSupport.py", line 598, in <lambda>
    self.f(*(self.args + (obj,) + args), **kwargs)
  File "/usr/lib/python3.10/site-packages/pyVmomi/VmomiSupport.py", line 388, in _InvokeMethod
    return self._stub.InvokeMethod(self, info, args)
  File "/usr/lib/python3.10/site-packages/pyVmomi/SoapAdapter.py", line 1578, in InvokeMethod
    raise six.moves.http_client.HTTPException(
http.client.HTTPException: 400 Bad Request
```

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
vmware_guest

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```
"ansible [core 2.14.1]",
        "  config file = /home/worker/workspace/Ansible_Cycle_Windows_Server_2022_64/ansible-vsphere-gos-validation/ansible.cfg",
        "  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']",
        "  ansible python module location = /usr/lib/python3.10/site-packages/ansible",
        "  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections",
        "  executable location = /usr/bin/ansible",
        "  python version = 3.10.0 (default, Nov 16 2022, 17:43:56) [GCC 10.2.0] (/usr/bin/python3.10)",
        "  jinja version = 3.1.2",
        "  libyaml = True"
```

##### COLLECTION VERSION
<!--- Paste verbatim output from "ansible-galaxy collection list <namespace>.<collection>"  between the quotes
for example: ansible-galaxy collection list community.general
-->
```
"# /root/.ansible/collections/ansible_collections",
        "Collection        Version",
        "----------------- -------",
        "ansible.netcommon 4.1.0  ",
        "ansible.posix     1.4.0  ",
        "ansible.utils     2.8.0  ",
        "ansible.windows   1.13.0 ",
        "community.crypto  2.10.0 ",
        "community.general 6.2.0  ",
        "community.vmware  3.2.0  ",
        "community.windows 1.12.0 "
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```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 -->
`vsphere_host_name` is configured ESXi hostname.
```
- name: "Configure VM NVDIMM device"
  community.vmware.vmware_guest:
    hostname: "{{ vsphere_host_name }}"
    username: "{{ vsphere_host_user }}"
    password: "{{ vsphere_host_user_password }}"
    validate_certs: "{{ validate_certs | default(false) }}"
    datacenter: "{{ vsphere_host_datacenter }}"
    folder: "{{ vm_folder }}"
    name: "{{ vm_name }}"
    nvdimm:
      state: "{{ vm_nvdimm_state | default('present') }}"
      size_mb: "{{ vm_nvdimm_size_mb | default(1024) }}"
      label: "{{ vm_nvdimm_label | default(omit) }}"
  register: vm_config_nvdimm_result
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->
NVDIMM device can be added successfully on standalone ESXi host

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->
NVDIMM device failed to add on standalone ESXi host

<!--- Paste verbatim command output between quotes -->
```paste below

```



Discussion:

Resolving patch:
diff --git a/plugins/module_utils/vm_device_helper.py b/plugins/module_utils/vm_device_helper.py
--- a/plugins/module_utils/vm_device_helper.py
+++ b/plugins/module_utils/vm_device_helper.py
@@ -360,9 +360,10 @@ def create_nvdimm_device(self, nvdimm_ctl_dev_key, pmem_profile_id, nvdimm_dev_s
         nvdimm_dev_spec.device.capacityInMB = nvdimm_dev_size_mb
         nvdimm_dev_spec.device.deviceInfo = vim.Description()
         nvdimm_dev_spec.device.backing = vim.vm.device.VirtualNVDIMM.BackingInfo()
-        profile = vim.vm.DefinedProfileSpec()
-        profile.profileId = pmem_profile_id
-        nvdimm_dev_spec.profile = [profile]
+        if pmem_profile_id is not None:
+            profile = vim.vm.DefinedProfileSpec()
+            profile.profileId = pmem_profile_id
+            nvdimm_dev_spec.profile = [profile]
 
         return nvdimm_dev_spec
 
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
@@ -1787,12 +1787,16 @@ def configure_nvdimm(self, vm_obj):
             # New VM or existing VM without label specified, add new NVDIMM device
             if vm_obj is None or (vm_obj and not vm_obj.config.template and self.params['nvdimm']['label'] is None):
                 if self.params['nvdimm']['state'] == 'present':
-                    # Get host default PMem storage policy
-                    storage_profile_name = "Host-local PMem Default Storage Policy"
-                    spbm = SPBM(self.module)
-                    pmem_profile = spbm.find_storage_profile_by_name(profile_name=storage_profile_name)
-                    if pmem_profile is None:
-                        self.module.fail_json(msg="Can not find PMem storage policy with name '%s'." % storage_profile_name)
+                    vc_pmem_profile_id = None
+                    # Get default PMem storage policy when host is vCenter
+                    if self.is_vcenter():
+                        storage_profile_name = "Host-local PMem Default Storage Policy"
+                        spbm = SPBM(self.module)
+                        pmem_profile = spbm.find_storage_profile_by_name(profile_name=storage_profile_name)
+                        if pmem_profile is None:
+                            self.module.fail_json(msg="Can not find PMem storage policy with name '%s'." % storage_profile_name)
+                        vc_pmem_profile_id = pmem_profile.profileId.uniqueId
+
                     if not nvdimm_ctl_exists:
                         nvdimm_ctl_spec = self.device_helper.create_nvdimm_controller()
                         self.configspec.deviceChange.append(nvdimm_ctl_spec)
@@ -1800,7 +1804,7 @@ def configure_nvdimm(self, vm_obj):
 
                     nvdimm_dev_spec = self.device_helper.create_nvdimm_device(
                         nvdimm_ctl_dev_key=nvdimm_ctl_key,
-                        pmem_profile_id=pmem_profile.profileId.uniqueId,
+                        pmem_profile_id=vc_pmem_profile_id,
                         nvdimm_dev_size_mb=self.params['nvdimm']['size_mb']
                     )
                     self.change_detected = True


Test patch: