Repository: ansible/ansible

Issue:
ovirt_host_networks.py: netmask incorrectly converted to prefix causing ValueError
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report
 
##### COMPONENT NAME
<!---
Name of the module/plugin/task/feature
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
ovirt_host_networks.py

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.4.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/djasa/.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.14 (default, Nov  3 2017, 10:55:25) [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste 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 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.
-->
Fedora 27 / N/A

##### SUMMARY
<!--- Explain the problem briefly -->
ovirt_host_networks.py: netmask incorrectly converted to prefix causing ValueError

##### 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.
-->
1. run ovirt_host_networks against a host that has already networks up'n'running

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: setup host networks
  ovirt_host_networks:
    name: "{{ ovirt_host }}"
    interface: "{{ secondary_interface }}"
    networks:
    - name: display
      bootproto: dhcp
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
No change (or just a "display" designation addition) as the interface is already configured to use DHCP and no further changes are needed

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
ValueError

<!--- Paste verbatim command output between quotes below -->
```
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_tuJApk/ansible_module_ovirt_host_networks.py", line 292, in main
    (nic is None or host_networks_module.has_update(nics_service.service(nic.id)))
  File "/tmp/ansible_tuJApk/ansible_module_ovirt_host_networks.py", line 238, in has_update
    self.update_address(attachments_service, attachment, network)
  File "/tmp/ansible_tuJApk/ansible_module_ovirt_host_networks.py", line 183, in update_address
    if not equal(network.get('prefix'), int(ip.ip.netmask) if ip.ip.netmask else None):
ValueError: invalid literal for int() with base 10: '255.255.255.224'
```
FWIW the `int(netmask)` construct doesn't work for me either in 2.7 or 3.6:
```
$ cat netmask.py
#!/usr/bin/env python

netmask = "255.255.255.192"
prefix = int(netmask)
print("%s" % prefix)
$ python2.7 netmask.py
Traceback (most recent call last):
  File "netmask.py", line 4, in <module>
    prefix = int(netmask)
ValueError: invalid literal for int() with base 10: '255.255.255.192'
$ python3.6 netmask.py
Traceback (most recent call last):
  File "netmask.py", line 4, in <module>
    prefix = int(netmask)
ValueError: invalid literal for int() with base 10: '255.255.255.192'
```
What works for me is lambda function in place of int() as described at SO: https://stackoverflow.com/a/38085892


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 --->

Resolving patch:
diff --git a/lib/ansible/modules/cloud/ovirt/ovirt_host_networks.py b/lib/ansible/modules/cloud/ovirt/ovirt_host_networks.py
--- a/lib/ansible/modules/cloud/ovirt/ovirt_host_networks.py
+++ b/lib/ansible/modules/cloud/ovirt/ovirt_host_networks.py
@@ -180,7 +180,7 @@ def update_address(self, attachments_service, attachment, network):
                 if not equal(network.get('gateway'), ip.ip.gateway):
                     ip.ip.gateway = network.get('gateway')
                     changed = True
-                if not equal(network.get('prefix'), int(ip.ip.netmask) if ip.ip.netmask else None):
+                if not equal(network.get('prefix'), sum([bin(int(x)).count('1') for x in ip.ip.netmask.split('.')]) if ip.ip.netmask else None):
                     ip.ip.netmask = str(network.get('prefix'))
                     changed = True
 


Test patch: