Repository: ansible-collections/community.general

Issue:
proxmox_kvm: Create VM without providing vmid not idempotent
### Summary

When I try to run playbook that uses `community.general.proxmox_kvm` module to create a new VM without specifying its `vmid` and with the same `name` more than one time, new one with different `vmid` is always created.

Module behaviour changed with version `7.1.0` due to issue #6155.

Possible solution is to change the following:
https://github.com/ansible-collections/community.general/blob/2e0079cb3e683915d7421461839bd653f85334a4/plugins/modules/proxmox_kvm.py#L1265-L1273

to something like that:

```python
   if not vmid:
        if state == 'present' and not update and not clone and not delete and not revert and not migrate:
            existing_vmid = proxmox.get_vmid(name, ignore_missing=True)
            if existing_vmid:
                vmid = existing_vmid
            else:
                try:
                    vmid = proxmox.get_nextvmid()
                except Exception:
                    module.fail_json(msg="Can't get the next vmid for VM {0} automatically. Ensure your cluster state is good".format(name))
        else:
            clone_target = clone or name
            vmid = proxmox.get_vmid(clone_target, ignore_missing=True)
```

### Issue Type

Bug Report

### Component Name

proxmox_kvm

### Ansible Version

```console (paste below)
$ ansible --version
ansible [core 2.15.0]
...
    python version = 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0]
...
```


### Community.general Version

```console (paste below)
$ ansible-galaxy collection list community.general
Collection        Version
----------------- -------
community.general 7.1.0
```


### Configuration

```console (paste below)
$ ansible-config dump --only-changed

```


### OS / Environment

```console
$ lsb_release -a
Distributor ID:	Debian
Description:	Debian GNU/Linux 11 (bullseye)
Release:	11
Codename:	bullseye
```

```console
$ pip3 list | grep -iE "proxmoxer|requests"
proxmoxer          2.0.1
requests           2.31.0
```

### Steps to Reproduce

Run following playbook at least to times. With each run new VM named `test-vm` with different `vmid` is created.

In this test case fist playbook run creates a VM named `test-vm` with `vmid: 100`.

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
- hosts: localhost
  gather_facts: false
  vars_files:
    - api_credentials.yml
  tasks:
    - name: Deploy VM
      community.general.proxmox_kvm:
        api_host: "{{ api_host }}"
        api_user: "{{ api_user }}"
        api_token_id: "{{ api_token_id }}"
        api_token_secret: "{{ api_token_secret }}"
        node: pve
        name: test-vm
        state: present
```


### Expected Results

After discovering that VM with name `test-vm` already exists and no `vmid` was provided module shouldn't make any changes (`changed: false`, unless `update: true` or related flags are set) and return info about previously created one (as in `7.0.0`)

First run:
```console
$ ansible-playbook -v test.yml
changed: [127.0.0.1] => {
    "changed": true,
    "devices": {},
    "mac": {},
    "msg": "VM test-vm with vmid 100 deployed",
    "vmid": 100
}
```

Second run:
```console
$ ansible-playbook -v test.yml
ok: [127.0.0.1] => {
    "changed": false,
    "msg": "VM with name <test-vm> already exists",
    "vmid": 100
}
```

### Actual Results

Multiple VM instances with different `vmid` and the same `name` are created every playbook run.

First run:
```console
$ ansible-playbook -v test.yml
changed: [127.0.0.1] => {
    "changed": true,
    "devices": {},
    "mac": {},
    "msg": "VM test-vm with vmid 100 deployed",
    "vmid": 100
}
```
Second run:
```console (paste below)
$ ansible-playbook -v test.yml
changed: [127.0.0.1] => {
    "changed": true,
    "devices": {},
    "mac": {},
    "msg": "VM test-vm with vmid 101 deployed",
    "vmid": 101
}
```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* [`plugins/modules/proxmox_kvm.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/modules/proxmox_kvm.py)

If these files are incorrect, 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/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @Ajpantuso @Thulium-Drake @UnderGreen @helldorado @joshainglis @karmab @tleguern
[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: notify --->
@wozniaka I think the previous behavior was wrong. Proxmox API allows you to create/have multiple VMs with the same name. Previously the module didn't let that, but we shouldn't restrict something which is a feature by design in API.
@felixfontein or @russoz would like to hear your thoughts about that.
@UnderGreen I can understand that but can't module support this scenario by explicitly providing different pairs of `name` and `vmid` and keep the previous one if no `vmid` is provided? Module supports creating VM with `name` only, so i think in that case it could also be treated in unique manner.

However, I must admit that, in this case, getting `vmid` (as they would be needed to be defined explicitly) for mass created VM with the same `name` would be rather hard just by using `community.general.proxmox*` modules, as they're now. On the other side it's quite simple to get `vmid` of already deployed VM and provide playbook rather then task level idempotence.

Maybe module can provide some sort of switch between two use cases?

I hate to add more params to the module as it already contains about twenty of them, but we need some sort of `unique` param for the case if only a `name` is provided.
In any case notice of the changes for the user experience should be added to the module docs.

Resolving patch:
diff --git a/plugins/modules/proxmox_kvm.py b/plugins/modules/proxmox_kvm.py
--- a/plugins/modules/proxmox_kvm.py
+++ b/plugins/modules/proxmox_kvm.py
@@ -281,8 +281,9 @@
     type: int
   name:
     description:
-      - Specifies the VM name. Only used on the configuration web interface.
-      - Required only for C(state=present).
+      - Specifies the VM name. Name could be non-unique across the cluster.
+      - Required only for I(state=present).
+      - With I(state=present) if I(vmid) not provided and VM with name exists in the cluster then no changes will be made.
     type: str
   nameservers:
     description:
@@ -1210,10 +1211,14 @@ def main():
     # the cloned vm name or retrieve the next free VM id from ProxmoxAPI.
     if not vmid:
         if state == 'present' and not update and not clone and not delete and not revert:
-            try:
-                vmid = proxmox.get_nextvmid()
-            except Exception:
-                module.fail_json(msg="Can't get the next vmid for VM {0} automatically. Ensure your cluster state is good".format(name))
+            existing_vmid = proxmox.get_vmid(name, ignore_missing=True)
+            if existing_vmid:
+                vmid = existing_vmid
+            else:
+                try:
+                    vmid = proxmox.get_nextvmid()
+                except Exception:
+                    module.fail_json(msg="Can't get the next vmid for VM {0} automatically. Ensure your cluster state is good".format(name))
         else:
             clone_target = clone or name
             vmid = proxmox.get_vmid(clone_target, ignore_missing=True)


Test patch: