Dear oVirt,

 

While deploying ovirt_infra , the role oivrt.networks fails on Setup Host Networks, with following error:

 

TypeError: '<' not supported between instances of 'dict' and 'dict'

 

Full output:

TASK [ovirt.infra/roles/ovirt.networks : Setup host networks] ******************************************************************************************************************

The full traceback is:

Traceback (most recent call last):

  File "/var/folders/40/w2c8fp151854mddz_4n3czwm0000gn/T/ansible_ovirt_host_network_payload_s0fx52mx/__main__.py", line 396, in main

    (nic is None or host_networks_module.has_update(nics_service.service(nic.id)))

  File "/var/folders/40/w2c8fp151854mddz_4n3czwm0000gn/T/ansible_ovirt_host_network_payload_s0fx52mx/__main__.py", line 289, in has_update

    update = self.__compare_options(get_bond_options(bond.get('mode'), bond.get('options')), getattr(nic.bonding, 'options', []))

  File "/var/folders/40/w2c8fp151854mddz_4n3czwm0000gn/T/ansible_ovirt_host_network_payload_s0fx52mx/__main__.py", line 247, in __compare_options

    return sorted(get_dict_of_struct(opt) for opt in new_options) != sorted(get_dict_of_struct(opt) for opt in old_options)

TypeError: '<' not supported between instances of 'dict' and 'dict'

 

failed: [localhost] (item={'name': 'ovirt-staging-hv-02.avinity.tv', 'check': True, 'save': True, 'bond': {'name': 'bond28', 'mode': 4, 'interfaces': ['p2p1', 'p2p2']}, 'networks': [{'name': 'backbone', 'boot_protocol': 'static', 'address': '172.17.28.212', 'netmask': '255.255.255.0', 'version': 'v4'}]}) => {

    "ansible_loop_var": "item",

    "changed": false,

    "invocation": {

        "module_args": {

            "bond": {

                "interfaces": [

                    "p2p1",

                    "p2p2"

                ],

                "mode": 4,

                "name": "bond28"

            },

            "check": true,

            "fetch_nested": false,

            "interface": null,

            "labels": null,

            "name": "ovirt-staging-hv-02.avinity.tv",

            "nested_attributes": [],

            "networks": [

                {

                    "address": "172.17.28.212",

                    "boot_protocol": "static",

                    "name": "backbone",

                    "netmask": "255.255.255.0",

                    "version": "v4"

                }

            ],

            "poll_interval": 3,

            "save": true,

            "state": "present",

            "sync_networks": false,

            "timeout": 180,

            "wait": true

        }

    },

    "item": {

        "bond": {

            "interfaces": [

                "p2p1",

                "p2p2"

            ],

            "mode": 4,

            "name": "bond28"

        },

        "check": true,

        "name": "ovirt-staging-hv-02.avinity.tv",

        "networks": [

            {

                "address": "172.17.28.212",

                "boot_protocol": "static",

                "name": "backbone",

                "netmask": "255.255.255.0",

                "version": "v4"

            }

        ],

        "save": true

    },

    "msg": "'<' not supported between instances of 'dict' and 'dict'"

}

Read vars_file 'vars/engine_vars.yml'

Read vars_file 'vars/secrets.yml'

Read vars_file 'vars/ovirt_infra_vars.yml'

 

Looking further into ovirt_host_network.py I found that issue is reported after following is executed:

return sorted(get_dict_of_struct(opt) for opt in new_options) != sorted(get_dict_of_struct(opt) for opt in old_options)

 

It seemed to be failing due to not getting the key value to sort the dicts, so I added sorting based on name, to test, and it worked in single test run:

return sorted((get_dict_of_struct(opt) for opt in new_options), key=lambda x: x["name"]) != sorted((get_dict_of_struct(opt) for opt in old_options), key=lambda x: x["name"])

 

After rerun of the play, with changes above:

TASK [ovirt.infra/roles/ovirt.networks : Setup host networks] ******************************************************************************************************************

task path: /Users/mvrgotic/Git/ovirt-engineering/roles/ovirt.infra/roles/ovirt.networks/tasks/main.yml:25

Using module file /Users/mvrgotic/.local/share/virtualenvs/ovirt-engineering-JaxzXThh/lib/python3.7/site-packages/ansible/modules/cloud/ovirt/ovirt_host_network.py

Pipelining is enabled.

<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: mvrgotic

<127.0.0.1> EXEC /bin/sh -c '/Users/mvrgotic/.local/share/virtualenvs/ovirt-engineering-JaxzXThh/bin/python3 && sleep 0'

changed: [localhost] => (item={'name': 'ovirt-staging-hv-02.avinity.tv', 'check': True, 'save': True, 'bond': {'name': 'bond28', 'mode': 4, 'interfaces': ['p2p1', 'p2p2']}, 'networks': [{'name': 'backbone', 'boot_protocol': 'static', 'address': '172.17.28.212', 'netmask': '255.255.255.0', 'version': 'v4'}]}) => {

    "ansible_loop_var": "item",

    "changed": true,

    "host_nic": {

        "ad_aggregator_id": 6,

        "bonding": {

            "ad_partner_mac": {

                "address": "44:31:92:7c:b3:11"

            },

            "options": [

                {

                    "name": "mode",

                    "type": "Dynamic link aggregation (802.3ad)",

                    "value": "4"

                },

                {

                    "name": "xmit_hash_policy",

                    "value": "2"

                }

            ],

            "slaves": [

                {

                    "href": "/ovirt-engine/api/hosts/aa1f7a65-a867-436a-9a7f-264068f4bdea/nics/01703220-570c-44f5-9729-6717ceead304",

                    "id": "01703220-570c-44f5-9729-6717ceead304"

                },

                {

                    "href": "/ovirt-engine/api/hosts/aa1f7a65-a867-436a-9a7f-264068f4bdea/nics/e879c1c6-065d-4742-b282-fcdb477f95a7",

                    "id": "e879c1c6-065d-4742-b282-fcdb477f95a7"

                }

            ]

        },

        "boot_protocol": "static",

        "bridged": false,

        "custom_configuration": false,

        "host": {

            "href": "/ovirt-engine/api/hosts/aa1f7a65-a867-436a-9a7f-264068f4bdea",

            "id": "aa1f7a65-a867-436a-9a7f-264068f4bdea"

        },

        "href": "/ovirt-engine/api/hosts/aa1f7a65-a867-436a-9a7f-264068f4bdea/nics/abce07fa-cb7f-46f2-b967-69d1feaa4075",

        "id": "abce07fa-cb7f-46f2-b967-69d1feaa4075",

        "ip": {

            "address": "172.17.28.212",

            "netmask": "255.255.255.0",

            "version": "v4"

        },

        "ipv6": {

            "gateway": "::",

            "version": "v6"

        },

        "ipv6_boot_protocol": "none",

        "mac": {

            "address": "b4:96:91:3f:47:1c"

        },

        "mtu": 9000,

        "name": "bond28",

        "network": {

            "href": "/ovirt-engine/api/networks/f3ef80cf-bf3a-4fa5-aed9-7d9e7455f804",

            "id": "f3ef80cf-bf3a-4fa5-aed9-7d9e7455f804"

        },

        "network_labels": [],

        "properties": [],

        "speed": 10000000000,

        "statistics": [],

        "status": "up"

    },

    "id": "abce07fa-cb7f-46f2-b967-69d1feaa4075",

    "invocation": {

        "module_args": {

            "bond": {

                "interfaces": [

                    "p2p1",

                    "p2p2"

                ],

                "mode": 4,

                "name": "bond28"

            },

            "check": true,

            "fetch_nested": false,

            "interface": null,

            "labels": null,

            "name": "ovirt-staging-hv-02.avinity.tv",

            "nested_attributes": [],

            "networks": [

                {

                    "address": "172.17.28.212",

                    "boot_protocol": "static",

                    "id": "3e40ff7d-5384-45f1-b036-13e6f91aff56",

                    "name": "backbone",

                    "netmask": "255.255.255.0",

                    "version": "v4"

                }

            ],

            "poll_interval": 3,

            "save": true,

            "state": "present",

            "sync_networks": false,

            "timeout": 180,

            "wait": true

        }

    },

    "item": {

        "bond": {

            "interfaces": [

                "p2p1",

                "p2p2"

            ],

            "mode": 4,

            "name": "bond28"

        },

        "check": true,

        "name": "ovirt-staging-hv-02.avinity.tv",

        "networks": [

            {

                "address": "172.17.28.212",

                "boot_protocol": "static",

                "name": "backbone",

                "netmask": "255.255.255.0",

                "version": "v4"

            }

        ],

        "save": true

    }

}

Read vars_file 'vars/engine_vars.yml'

Read vars_file 'vars/secrets.yml'

Read vars_file 'vars/ovirt_infra_vars.yml'

 

Changes resulted in applying configuration exactly as intended.

Not sure it this was the actual intention, but please let me know if the made change was as initially intended for sorted compare to work.

 

My pipenv setup:

Python 3.7

ansible==2.8.6

asn1crypto==1.1.0

bcrypt==3.1.7

cffi==1.13.1

cryptography==2.8

dnspython==1.16.0

ipaddress==1.0.23

Jinja2==2.10.3

jmespath==0.9.4

lxml==4.4.1

MarkupSafe==1.1.1

netaddr==0.7.19

ovirt-engine-sdk-python==4.3.3

paramiko==2.6.0

passlib==1.7.1

pyasn1==0.4.5

pycparser==2.19

pycurl==7.43.0.3

PyNaCl==1.3.0

PyYAML==5.1.2

six==1.12.0

 

Ansible vars and play:

=================================

host_networks:

 - name: ovirt-staging-hv-02.avinity.tv

    check: true

    save: true

    bond:

     name: bond28

      mode: 4

      interfaces:

        - p2p1

        - p2p2

    networks:

      - name: backbone

        boot_protocol: static

        address: 172.17.28.212

        netmask: 255.255.255.0

        version: v4

=================================

- name: Setup host networks

  ovirt_host_network:

    auth: "{{ ovirt_auth }}"

    name: "{{ item.name }}"

    state: "{{ item.state | default(omit) }}"

    check: "{{ item.check | default(omit) }}"

    save: "{{ item.save | default(omit) }}"

    bond: "{{ item.bond | default(omit) }}"

    networks: "{{ item.networks | default(omit) }}"

    labels: "{{ item.labels | default(omit) }}"

    interface: "{{ item.interface | default(omit) }}"

  with_items:

    - "{{ host_networks | default([]) }}"

  tags:

    - host_networks

    - networks

====================================