Repository: ansible/ansible
Pull request: Ovirt vm state running wait false
##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
Now when you put vm wait=false and state running it will change the wait until the vm is runnnig and then resets the wait again to original val. 

<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
Fixes #49531
##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
- Bugfix Pull Request

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below -->
ovirt
##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->

<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below

```


Problem statement:
ovirt_vm fails to create a VM when running=true and wait=false on RHHI-V.
##### SUMMARY
ovirt_vm fails to create a VM when running=true and wait=false on RHHI-V.

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
ovirt_vm

##### ANSIBLE VERSION
```
[dieter@localhost test]$ ansible --version
ansible 2.7.2
  config file = /home/dieter/test/ansible.cfg
  configured module search path = ['/home/dieter/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.7.1 (default, Nov 23 2018, 10:01:49) [GCC 8.2.1 20181105 (Red Hat 8.2.1-5)]

```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```
[dieter@localhost test]$ ansible-config dump --only-changed
DEFAULT_HOST_LIST(/home/dieter/test/ansible.cfg) = ['/home/dieter/test/inventory']
DEFAULT_LOAD_CALLBACK_PLUGINS(/home/dieter/test/ansible.cfg) = True
DEFAULT_STDOUT_CALLBACK(/home/dieter/test/ansible.cfg) = yaml
HOST_KEY_CHECKING(/home/dieter/test/ansible.cfg) = False

```

##### OS / ENVIRONMENT
Workstation:
Ansible version 2.7.2 on Fedora 29
ovirt-engine-sdk-python==4.2.8 (from pip)

Red Hat Hyperconverged Infrastructure:
Red Hat Virtualization Host 4.2.7
GlusterFS glusterfs-3.12.2-25.el7rhgs

Red Hat Virtualization Manager: 
ovirt-engine 4.2.7.5


##### STEPS TO REPRODUCE
Run following playbook:

```
- hosts: localhost
  gather_facts: no
  tasks:
  - name: Obtain SSO token with using username/password credentials
    ovirt_auth:
      username: "{{ ovirt_username }}"
      password: "{{ ovirt_password }}"
      url: "{{ ovirt_url }}"
      insecure: "{{ ovirt_insecure }}"

  - name: Create virtual machine
    ovirt_vm:
      auth: "{{ ovirt_auth }}"
      cluster: Default
      cpu_cores: 2
      cpu_sockets: 1
      high_availability: no
      memory: 4GiB
      memory_guaranteed: 4GiB
      memory_max: 16GiB
      name: myvm
      state: running
      template: "{{ rhv_template }}"
      wait: false
```

##### EXPECTED RESULTS
The task to complete without errors.


##### ACTUAL RESULTS
ovirt_vm throws an error "Cannot run VM: VM is locked. Please try again in a few minutes."

<!--- Paste verbatim command output between quotes -->
```
[dieter@localhost test]$ ansible-playbook test.yml -vvvv
ansible-playbook 2.7.2
  config file = /home/dieter/test/ansible.cfg
  configured module search path = ['/home/dieter/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.7/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 3.7.1 (default, Nov 23 2018, 10:01:49) [GCC 8.2.1 20181105 (Red Hat 8.2.1-5)]
Using /home/dieter/test/ansible.cfg as config file
setting up inventory plugins
/home/dieter/test/inventory did not meet host_list requirements, check plugin documentation if this is unexpected
/home/dieter/test/inventory did not meet script requirements, check plugin documentation if this is unexpected
Set default localhost to localhost
Parsed /home/dieter/test/inventory inventory source with ini plugin
Loading callback plugin yaml of type stdout, v2.0 from /usr/lib/python3.7/site-packages/ansible/plugins/callback/yaml.py

PLAYBOOK: test.yml ************************************************************************************************************************************************************************************************
1 plays in test.yml

PLAY [localhost] **************************************************************************************************************************************************************************************************
META: ran handlers

TASK [Obtain SSO token with using username/password credentials] **************************************************************************************************************************************************
task path: /home/dieter/test/test.yml:4
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: dieter
<localhost> EXEC /bin/sh -c 'echo ~dieter && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/dieter/.ansible/tmp/ansible-tmp-1543997181.0548651-245440093272297 `" && echo ansible-tmp-1543997181.0548651-245440093272297="` echo /home/dieter/.ansible/tmp/ansible-tmp-1543997181.0548651-245440093272297 `" ) && sleep 0'
Using module file /usr/lib/python3.7/site-packages/ansible/modules/cloud/ovirt/ovirt_auth.py
<localhost> PUT /home/dieter/.ansible/tmp/ansible-local-13341d5brgvhh/tmpxqupj_mt TO /home/dieter/.ansible/tmp/ansible-tmp-1543997181.0548651-245440093272297/AnsiballZ_ovirt_auth.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/dieter/.ansible/tmp/ansible-tmp-1543997181.0548651-245440093272297/ /home/dieter/.ansible/tmp/ansible-tmp-1543997181.0548651-245440093272297/AnsiballZ_ovirt_auth.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /home/dieter/.ansible/tmp/ansible-tmp-1543997181.0548651-245440093272297/AnsiballZ_ovirt_auth.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /home/dieter/.ansible/tmp/ansible-tmp-1543997181.0548651-245440093272297/ > /dev/null 2>&1 && sleep 0'
ok: [localhost] => changed=false 
  ansible_facts:
    ovirt_auth:
      ca_file: null
      compress: true
      headers: null
      insecure: true
      kerberos: false
      timeout: 0
      token: Or3g1nm3gQGN2d2dq8PkDBKw15f1nSSDAOwZ94Pd35OFdYTqByIE_MRSe5R1KWYbhYhBXw7NxZyA7UCis1gj6w
      url: *****
  invocation:
    module_args:
      ca_file: null
      compress: true
      headers: null
      hostname: null
      insecure: true
      kerberos: false
      ovirt_auth: null
      password: VALUE_SPECIFIED_IN_NO_LOG_PARAMETER
      state: present
      timeout: 0
      token: null
      url: *****
      username: admin@internal

TASK [Create virtual machine] *************************************************************************************************************************************************************************************
task path: /home/dieter/test/test.yml:11
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: dieter
<localhost> EXEC /bin/sh -c 'echo ~dieter && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/dieter/.ansible/tmp/ansible-tmp-1543997181.4379315-226070906750108 `" && echo ansible-tmp-1543997181.4379315-226070906750108="` echo /home/dieter/.ansible/tmp/ansible-tmp-1543997181.4379315-226070906750108 `" ) && sleep 0'
Using module file /usr/lib/python3.7/site-packages/ansible/modules/cloud/ovirt/ovirt_vm.py
<localhost> PUT /home/dieter/.ansible/tmp/ansible-local-13341d5brgvhh/tmpihb56uyu TO /home/dieter/.ansible/tmp/ansible-tmp-1543997181.4379315-226070906750108/AnsiballZ_ovirt_vm.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/dieter/.ansible/tmp/ansible-tmp-1543997181.4379315-226070906750108/ /home/dieter/.ansible/tmp/ansible-tmp-1543997181.4379315-226070906750108/AnsiballZ_ovirt_vm.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /home/dieter/.ansible/tmp/ansible-tmp-1543997181.4379315-226070906750108/AnsiballZ_ovirt_vm.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /home/dieter/.ansible/tmp/ansible-tmp-1543997181.4379315-226070906750108/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_ovirt_vm_payload_1RD2Er/__main__.py", line 2071, in main
    ) else None,
  File "/tmp/ansible_ovirt_vm_payload_1RD2Er/ansible_ovirt_vm_payload.zip/ansible/module_utils/ovirt.py", line 738, in action
    getattr(entity_service, action)(**kwargs)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/services.py", line 30176, in start
    return self._internal_action(action, 'start', None, headers, query, wait)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 299, in _internal_action
    return future.wait() if wait else future
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 55, in wait
    return self._code(response)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 296, in callback
    self._check_fault(response)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 134, in _check_fault
    self._raise_error(response, body.fault)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 118, in _raise_error
    raise error
Error: Fault reason is "Operation Failed". Fault detail is "[Cannot run VM: VM is locked. Please try again in a few minutes.]". HTTP response code is 409.

fatal: [localhost]: FAILED! => changed=false 
  invocation:
    module_args:
      affinity_group_mappings: []
      affinity_label_mappings: []
      allow_partial_import: null
      ballooning_enabled: null
      boot_devices: null
      boot_menu: null
      cd_iso: null
      clone: false
      clone_permissions: false
      cloud_init: null
      cloud_init_nics: []
      cloud_init_persist: false
      cluster: Default
      cluster_mappings: []
      comment: null
      cpu_cores: 2
      cpu_mode: null
      cpu_pinning: null
      cpu_shares: null
      cpu_sockets: 1
      cpu_threads: null
      custom_compatibility_version: null
      custom_properties: null
      delete_protected: null
      description: null
      disk_format: cow
      disks: []
      domain_mappings: []
      fetch_nested: false
      force: false
      graphical_console: null
      high_availability: false
      high_availability_priority: null
      host: null
      host_devices: null
      id: null
      initrd_path: null
      instance_type: null
      io_threads: null
      kernel_params: null
      kernel_path: null
      kvm: null
      lease: null
      lun_mappings: []
      memory: 4GiB
      memory_guaranteed: 4GiB
      memory_max: 16GiB
      name: myvm
      nested_attributes: []
      nics: []
      numa_nodes: []
      numa_tune_mode: null
      operating_system: null
      placement_policy: null
      poll_interval: 3
      quota_id: null
      reassign_bad_macs: null
      rng_device: null
      role_mappings: []
      serial_console: null
      serial_policy: null
      serial_policy_value: null
      smartcard_enabled: null
      soundcard_enabled: null
      sso: null
      state: running
      stateless: null
      storage_domain: null
      sysprep: null
      template: rhel7.5-template_2
      template_version: null
      ticket: null
      timeout: 180
      timezone: null
      type: null
      usb_support: null
      use_latest_template_version: null
      vmware: null
      vnic_profile_mappings: []
      wait: false
      watchdog: null
      xen: null
  msg: 'Fault reason is "Operation Failed". Fault detail is "[Cannot run VM: VM is locked. Please try again in a few minutes.]". HTTP response code is 409.'
	to retry, use: --limit @/home/dieter/test/test.retry

PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1   
```

Hints from issue discussion:
Files identified in the description:
* [lib/ansible/modules/cloud/ovirt/ovirt_vm.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/cloud/ovirt/ovirt_vm.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 @machacekondra @mwperina
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Commit message: add seting vm wait before creating module

Patch to review:
diff --git a/lib/ansible/module_utils/ovirt.py b/lib/ansible/module_utils/ovirt.py
index 19653bbbee779e..cc74e92ce61742 100644
--- a/lib/ansible/module_utils/ovirt.py
+++ b/lib/ansible/module_utils/ovirt.py
@@ -741,7 +741,6 @@ def action(
             self.changed = True
 
         post_action(entity)
-
         wait(
             service=self._service.service(entity.id),
             condition=wait_condition,
diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_vm.py b/lib/ansible/modules/cloud/ovirt/ovirt_vm.py
index 3d04affacc0f20..46c651d6cf0854 100644
--- a/lib/ansible/modules/cloud/ovirt/ovirt_vm.py
+++ b/lib/ansible/modules/cloud/ovirt/ovirt_vm.py
@@ -2075,11 +2075,17 @@ def main():
         auth = module.params.pop('auth')
         connection = create_connection(auth)
         vms_service = connection.system_service().vms_service()
+
+        if not module.params['wait'] and state=='running':
+            original_wait = module.params['wait']
+            module.params['wait'] = True
+
         vms_module = VmsModule(
             connection=connection,
             module=module,
             service=vms_service,
         )
+
         vm = vms_module.search_entity(list_params={'all_content': True})
 
         control_state(vm, vms_service, module)
@@ -2143,7 +2149,6 @@ def kernel_persist_check():
                         and not module.params.get('cloud_init_persist')
                     ) else None,
                 )
-
                 if module.params['ticket']:
                     vm_service = vms_service.vm_service(ret['id'])
                     graphics_consoles_service = vm_service.graphics_consoles_service()
@@ -2152,7 +2157,8 @@ def kernel_persist_check():
                     ticket = console_service.remote_viewer_connection_file()
                     if ticket:
                         ret['vm']['remote_vv_file'] = ticket
-
+                if original_wait != None:
+                    vms_module._module.params['wait'] = original_wait
             if state == 'next_run':
                 # Apply next run configuration, if needed:
                 vm = vms_service.vm_service(ret['id']).get()


Code review comments:
diff_hunk: @@ -2075,11 +2075,17 @@ def main():
         auth = module.params.pop('auth')
         connection = create_connection(auth)
         vms_service = connection.system_service().vms_service()
+
+        if not module.params['wait'] and state=='running':
path: lib/ansible/modules/cloud/ovirt/ovirt_vm.py
text: @user1:
If I understand correctly now it will wait always, but we want only to wait to be created , not for running.

@user1:
please add spaces around '=='

diff_hunk: @@ -2152,7 +2157,8 @@ def kernel_persist_check():
                     ticket = console_service.remote_viewer_connection_file()
                     if ticket:
                         ret['vm']['remote_vv_file'] = ticket
-
+                if original_wait != None:
path: lib/ansible/modules/cloud/ovirt/ovirt_vm.py
text: @user1:
You should set `original_wait=None` at the beggingng