ipspace / netlab

Making virtual networking labs suck less
https://netlab.tools
Other
445 stars 66 forks source link

[BUG] IOSXR - initial issue - domain ipv6 host <host> False #1465

Closed sdargoeuves closed 1 week ago

sdargoeuves commented 1 week ago

Describe the bug

I have an issue with the initialisation of my IOSXR devices, due to some ipv6 when configuring the domain ipv6 host <host> False The j2 fails to find the ipv6 address of the

To Reproduce

You will need to have ipv6 configured on some devices in your lab, and one iosxr device

Expected behavior

The initial configuration should complete

Lab topology

---
message: "Minitest in progress"
plugin: [ multilab ]
defaults.multilab.id: 3
defaults.addressing.mgmt.start: 10
provider: clab
defaults.device: eos
defaults.devices.eos.clab.image: "ceos:4.32.2F.1"

nodes:
  gw1:
    device: iosxr
    image: ios-xr/xrd-control-plane:7.11.1
    module: [ ospf ]
  gw2:
    module: [ ospf ]
  gw3:
    module: [ ospf ]

links:
  - gw2:
      ipv6: True
    gw3:
      ipv6: True
  - gw1:
    gw2:
  - gw1:
    gw3:

Output

TASK [iosxr_config: deploying initial from /home/sa/code/quick-netlab-lab/netlab/netsim/ansible/templates/initial/iosxr.j2] ******************************************************************************
[WARNING]: The value 'True' is not a valid IP address or network, passing this value to ipaddr filter might result in breaking change in future.
fatal: [gw1]: FAILED! => changed=false
  msg: |-
    domain ipv6 host gw2 False
                                                     ^
    % Invalid input detected at '^' marker.
    RP/0/RP0/CPU0:gw1(config)#

Version

Additional context

Output of the netlab initial -l <iosxr-device> -vvvv

The full traceback is:
  File "/home/sa/.ansible/collections/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py", line 467, in load_config
    response = conn.edit_config(
               ^^^^^^^^^^^^^^^^^
  File "/home/sa/code/netsim-main-lab/venv/lib/python3.11/site-packages/ansible/module_utils/connection.py", line 199, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [gw1]: FAILED! => changed=false
  invocation:
    module_args:
      admin: false
      after: null
      backup: false
      backup_options: null
      before: null
      comment: configured by iosxr_config
      config: null
      disable_default_comment: false
      exclusive: false
      force: false
      label: null
      lines: null
      match: line
      parents: null
      replace: line
      src: |-
        hostname gw1
        !
        domain lookup disable
        !
        lldp
         no management enable
        !
        domain ipv4 host gw2 10.0.0.2
        domain ipv4 host gw3 10.0.0.3
        domain ipv6 host gw2 False
        domain ipv6 host gw3 False
        !
        interface Loopback0
         ipv4 address 10.0.0.1 255.255.255.255
        !
        interface GigabitEthernet0/0/0/0
         no shutdown
         description gw1 -> gw2
         ipv4 address 10.1.0.5 255.255.255.252
        !
        interface GigabitEthernet0/0/0/1
         no shutdown
         description gw1 -> gw3
         ipv4 address 10.1.0.9 255.255.255.252
        !
  msg: |-
    domain ipv6 host gw2 False
                                                     ^
    % Invalid input detected at '^' marker.
    RP/0/RP0/CPU0:gw1(config)#

PLAY RECAP ***********************************************************************************************************************************************************************************************
gw1                        : ok=10   changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Error executing ansible-playbook /home/sa/code/quick-netlab-lab/netlab/netsim/ansible/initial-config.ansible -vvvv -l gw1:
  Command '['ansible-playbook', '/home/sa/code/quick-netlab-lab/netlab/netsim/ansible/initial-config.ansible', '-vvvv', '-l', 'gw1']' returned non-zero exit status 2.
[FATAL]   Executing Ansible playbook /home/sa/code/quick-netlab-lab/netlab/netsim/ansible/initial-config.ansible failed

The solution is hiding somewhere in here (netlab/netsim/ansible/templates/initial/iosxr.j2 between line 8 and 16)

{% for af in ['ipv4','ipv6'] %}
{%   for k,v in hostvars.items() if k != inventory_hostname and v.af[af]|default(False) %}
{%     if v.loopback[af] is defined %}
domain {{ af }} host {{ k }} {{ v.loopback[af]|ipaddr('address') }}
{%     elif v.interfaces|default([]) and v.interfaces[0][af] is defined %}
domain {{ af }} host {{ k }} {{ v.interfaces[0][af]|ipaddr('address') }}
{%     endif %}
{%   endfor %}
{% endfor %}
ipspace commented 1 week ago

The solution is hiding somewhere in here (netlab/netsim/ansible/templates/initial/iosxr.j2 between line 8 and 16)

That's absolutely correct and it's relatively easy to fix (we just have to check whether the address is a string, not whether it's defined), but I'd love to know how we got there. Could you please post a topology that triggers this error (as cleaned up as possible ;)


{% for af in ['ipv4','ipv6'] %}
{%   for k,v in hostvars.items() if k != inventory_hostname and v.af[af]|default(False) %}
{%     if v.loopback[af] is defined %}
domain {{ af }} host {{ k }} {{ v.loopback[af]|ipaddr('address') }}
{%     elif v.interfaces|default([]) and v.interfaces[0][af] is defined %}

This should be fixed (changing is defined into |default(False) is string), but as the device in question is probably a switch, it should have a loopback :(

sdargoeuves commented 1 week ago

I've updated the topology, in the original message. I am now looking at the output of v.interfaces and indeed, the ipv6 is a bool and not the value:

[
    {
        "clab": {
            "name": "et1"
        },
        "ifindex": 1,
        "ifname": "Ethernet1",
        "ipv4": "10.1.0.1/30",
        "ipv6": true,
        "linkindex": 1,
        "name": "gw2 -> gw3",
        "neighbors": [
            {
                "ifname": "Ethernet1",
                "ipv4": "10.1.0.2/30",
                "ipv6": true,
                "node": "gw3"
            }
        ],
        "ospf": {
            "area": "0.0.0.0",
            "network_type": "point-to-point",
            "passive": false
        },
        "type": "p2p"
    },
    {
        "clab": {
            "name": "et2"
        },
        "ifindex": 2,
        "ifname": "Ethernet2",
        "ipv4": "10.1.0.6/30",
        "linkindex": 2,
        "name": "gw2 -> gw1",
        "neighbors": [
            {
                "ifname": "GigabitEthernet0/0/0/0",
                "ipv4": "10.1.0.5/30",
                "node": "gw1"
            }
        ],
        "ospf": {
            "area": "0.0.0.0",
            "network_type": "point-to-point",
            "passive": false
        },
        "type": "p2p"
    }
]
ipspace commented 1 week ago

Ah, you set 'ipv6' to True without having IPv6 on the loopback. Fixing...

sdargoeuves commented 1 week ago

Ah, you set 'ipv6' to True without having IPv6 on the loopback. Fixing...

thank you!! And it's a good point, I didn't think about this... I reused a topology where we had some ipv6, and indeed no loopback are set to ipv6.