Repository: ansible/ansible
Pull request: ovirt add sync_networks
##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->

add ovirt synch networks
when you have unsynchronized network and you need to sync them
you can got this issue from changing VLAN or MTU...
https://www.ovirt.org/documentation/how-to/networking/setupnetworks-syncnetworks/

<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->

Fixes #39953

##### 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:
Synchronize hosts before modifying networks
<!---
Verify first that your issue/request is not already reported on GitHub.
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
Also test if the latest release, and devel branch are affected too.
ALWAYS add information AFTER (OUTSIDE) these html comments.
Otherwise it may end up being automatically closed by our bot. -->

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
<!--- Insert, BELOW THIS COMMENT, the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path-->
ovirt_host_networks

##### ANSIBLE VERSION
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
```
  config file = /root/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Feb 20 2018, 09:19:12) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]
```

##### CONFIGURATION
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).-->

##### OS / ENVIRONMENT
<!--- Mention, BELOW THIS COMMENT, the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.-->

##### SUMMARY
<!--- Explain the problem briefly -->
module fails when networks on host weren't synchronized. Module should deal with it
    "msg": "Fault reason is \"Operation Failed\". Fault detail is \"[Cannot setup Networks. The following Networks' definitions on the Network Interfaces are different than those on the Logical Networks. Please synchronize the Network Interfaces before editing the networks: ovirtmgmt.]\". HTTP response code is 409."

##### STEPS TO REPRODUCE
<!--- For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used. -->
make changes in network setting in webadmin (modify something and don't do synchronize)
try to make a change with module
<!--- Paste example playbooks or commands between quotes below -->
```yaml
    - name: set bond
      ovirt_host_networks:
        name: hostname
        bond:
          name: bond0
          mode: 1
          interfaces:
            - eth0
            - eth1
        networks:
          - name: ovirtmgmt
            boot_protocol: dhcp
        auth: "{{ ovirt_auth }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
synchronize and do changes specified by module
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
Using module file /usr/lib/python2.7/site-packages/ansible/modules/cloud/ovirt/ovirt_host_networks.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~ && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1525945608.99-276413151072310 `" && echo ansible-tmp-1525945608.99-276413151072310="` echo /root/.ansible/tmp/ansible-tmp-1525945608.99-276413151072310 `" ) && sleep 0'
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-35654kFxTqf/tmpYG_fFL TO /root/.ansible/tmp/ansible-tmp-1525945608.99-276413151072310/ovirt_host_networks.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1525945608.99-276413151072310/ /root/.ansible/tmp/ansible-tmp-1525945608.99-276413151072310/ovirt_host_networks.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python2 /root/.ansible/tmp/ansible-tmp-1525945608.99-276413151072310/ovirt_host_networks.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1525945608.99-276413151072310/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_fy5UB6/ansible_module_ovirt_host_networks.py", line 412, in main
    ] if networks else None,
  File "/tmp/ansible_fy5UB6/ansible_modlib.zip/ansible/module_utils/ovirt.py", line 729, in action
    getattr(entity_service, action)(**kwargs)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/services.py", line 37188, in setup_networks
    return self._internal_action(action, 'setupnetworks', 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 132, in _check_fault
    self._raise_error(response, body)
  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 setup Networks. The following Networks' definitions on the Network Interfaces are different than those on the Logical Networks. Please synchronize the Network Interfaces before editing the networks: ovirtmgmt.]". HTTP response code is 409.

fatal: [localhost]: FAILED! => {
    "changed": false, 
    "invocation": {
        "module_args": {
            "bond": {
                "interfaces": [
                    "eth0", 
                    "eth1"
                ], 
                "mode": 1, 
                "name": "bond0"
            }, 
            "check": null, 
            "fetch_nested": false, 
            "interface": null, 
            "labels": null, 
            "name": "hostname", 
            "nested_attributes": [], 
            "networks": [
                {
                    "boot_protocol": "dhcp", 
                    "id": "d938c2c3-696d-4db1-84b2-1b5f9997d90e", 
                    "name": "ovirtmgmt"
                }
            ], 
            "poll_interval": 3, 
            "save": null, 
            "state": "present", 
            "timeout": 180, 
            "wait": true
        }
    }, 
    "msg": "Fault reason is \"Operation Failed\". Fault detail is \"[Cannot setup Networks. The following Networks' definitions on the Network Interfaces are different than those on the Logical Networks. Please synchronize the Network Interfaces before editing the networks: ovirtmgmt.]\". HTTP response code is 409."
}
```

Hints from issue discussion:
Files identified in the description:
* [lib/ansible/modules/cloud/ovirt/ovirt_host_networks.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/cloud/ovirt/ovirt_host_networks.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 --->
Files identified in the description:
* [lib/ansible/modules/cloud/ovirt/_ovirt_host_networks.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/cloud/ovirt/_ovirt_host_networks.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 --->
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 --->

Commit message: ovirt sync networks update docs

Patch to review:
diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_host_network.py b/lib/ansible/modules/cloud/ovirt/ovirt_host_network.py
index 49681fcba47adf..007e140aaa50b2 100644
--- a/lib/ansible/modules/cloud/ovirt/ovirt_host_network.py
+++ b/lib/ansible/modules/cloud/ovirt/ovirt_host_network.py
@@ -76,6 +76,12 @@
         description:
             - "If I(true) network configuration will be persistent, by default they are temporarily."
         type: bool
+    sync_networks:
+        description:
+            - "If I(true) all networks will be synchronized before modification"
+        type: bool
+        default: false
+        version_added: 2.8
 extends_documentation_fragment: ovirt
 '''
 
@@ -320,6 +326,16 @@ def _action_save_configuration(self, entity):
             self.changed = True
 
 
+def needs_sync(nics_service):
+    nics = nics_service.list()
+    for nic in nics:
+        nic_service = nics_service.nic_service(nic.id)
+        for network_attachment_service in nic_service.network_attachments_service().list():
+            if not network_attachment_service.in_sync:
+                return True
+    return False
+
+
 def main():
     argument_spec = ovirt_full_argument_spec(
         state=dict(
@@ -333,6 +349,7 @@ def main():
         labels=dict(default=None, type='list'),
         check=dict(default=None, type='bool'),
         save=dict(default=None, type='bool'),
+        sync_networks=dict(default=False, type='bool'),
     )
     module = AnsibleModule(argument_spec=argument_spec)
 
@@ -362,8 +379,14 @@ def main():
         nics_service = host_service.nics_service()
         nic = search_by_name(nics_service, nic_name)
 
+        if module.params["sync_networks"] and not module.check_mode:
+            if needs_sync(nics_service):
+                host_service.sync_all_networks()
+                host_networks_module.changed = True
+
         network_names = [network['name'] for network in networks or []]
         state = module.params['state']
+
         if (
             state == 'present' and
             (nic is None or host_networks_module.has_update(nics_service.service(nic.id)))


Code review comments:
diff_hunk: @@ -362,8 +379,14 @@ def main():
         nics_service = host_service.nics_service()
         nic = search_by_name(nics_service, nic_name)
 
+        if module.params["sync_networks"] and not module.check_mode:
path: lib/ansible/modules/cloud/ovirt/ovirt_host_network.py
text: @user1:
```python
        if module.params["sync_networks"]:
            if needs_sync(nics_service):
                if not module.check_mode
                    host_service.sync_all_networks()
                host_networks_module.changed = True 
```