Rename Network Interface

Hi Community !
I’m getting failures msg for The task includes on this playbook…

- name: Rename network interfaces
  hosts: all
  become: true
  vars:
    src_prefix: "eth"
    dst_prefix: "em"
    osnet_conf: "/etc/os-net-config/config.json"
    src_interfaces: "{{ ansible_interfaces | select('match', src_prefix ~ '.*') | sort | list }}"
    undercloud_conf: "~/undercloud.conf"
  tasks:
    - debug:
        msg: "{{ src_interfaces }}"


    - name: Update udev rules
      tags:
        - udev
      lineinfile:
        line: >
          SUBSYSTEM=="net",
          ACTION=="add",
          DRIVERS=="?*",
          ATTR{address}=="{{ ansible_facts[item]['perm_macaddress'] | default(ansible_facts[item]['macaddress']) }}",
          NAME="{{ item | replace(src_prefix, dst_prefix) }}"
        path: /etc/udev/rules.d/70-rhosp-persistent-net.rules
        create: true
      with_items: "{{ src_interfaces | reject('match', '^.*\\..*$') | list }}"

Looks like ‘dict object’ has no attribute ‘macaddress’… and - name: Update udev rules no works…

Any Idea ?

I believe you missed to scape the scaping character itself on the latest line (with_items). This revised code works fine for me (I ran it on localhost, just change the host to whatever suits you):

- name: Rename network interfaces
  hosts: localhost
  become: true
  vars:
    src_prefix: "eth"
    dst_prefix: "em"
    osnet_conf: "~/os-net-config/config.json"
    src_interfaces: "{{ ansible_interfaces | select('match', src_prefix ~ '.*') | sort | list }}"
    undercloud_conf: "~/undercloud.conf"
  tasks:

    - name: Debug message
      ansible.builtin.debug:
        var: src_interfaces

    - name: Update udev rules
      ansible.builtin.lineinfile:
        line: >-
          SUBSYSTEM=="net",
          ACTION=="add",
          DRIVERS=="?",
          ATTR{address}=="{{ ansible_facts[item]['perm_macaddress'] | default(ansible_facts[item]['macaddress']) }}",
          NAME="{{ item | replace(src_prefix, dst_prefix) }}"
        path: /etc/udev/rules.d/70-rhosp-persistent-net.rules
        create: true
      tags: udev
      with_items: "{{ src_interfaces | reject('match', '^.\\...*$') | list }}"

Results log:

(ansible_ve) [10:24:09] jbericat@localhost:~/DEV/repos/test$ ansible-playbook -i localhost ansible_forum_test.yml --ask-become-pass
BECOME password: 
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Rename network interfaces] ***************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Debug message] ***************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "src_interfaces": [
        "eth0"
    ]
}

TASK [Update udev rules] ***********************************************************************************************************************************************************************************************
changed: [localhost] => (item=eth0)

PLAY RECAP *************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
$ cat /etc/udev/rules.d/70-rhosp-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?", ATTR{address}=="00:15:5d:c1:4d:80", NAME="em0"

Hope it helps :slight_smile:

Cheers!

PS:

On this forum, I suggest you to wrap yaml code with ctrl-e, it will be easier to help :wink:
Also, when coding Ansible is a good practice to use FQDN’s for modules -using ansible-linter helps A TON with this and other coding issues

4 Likes

Thanks jbericat

I’m missing something else ! Its not working to me :slightly_frowning_face:

So I got this results after playbook revision
FAILED! => {“msg”: “The last includes an option with an undefinied variable. The error was: ‘dict object’ has no attribute ‘macaddress’ \n\nThe error appears to be in (my yml file): line 16, column 7, but may\nbe alsewhere in the file… -name: Update udec rulws\n ^here\n”}

Hello Bruno,

Can you provide the "/etc/os-net-config/config.json” file?

mmm ! You got the point !

I didn’t see any reference for this path ! Should I create on the Ansible host or on the client… To be honest I supposed tha needs to be on some repository I see some examples in the github…

hmmm… Now I think I rushed a little bit to answer in my last post (my bad!). Actually, the issue shouldn’t have nothing to do with the osnet_conf var, since it’s not being used on the playbook.

Anyway, to provide you with the proper help I would require more data… More precisely, what this error tells me is that ansible’s does not find the dict element macaddress on the ansible_facts['eth0'] dictionary:

FAILED! => {“msg”: “The last includes an option with an undefinied variable. The error was: ‘dict object’ has no attribute ‘macaddress’ \n\nThe error appears to be in (my yml file): line 16, column 7, but may\nbe alsewhere in the file… -name: Update udec rulws\n ^here\n”}

Could it be that the interface you’re looking for is not included in the ansible_facts?

Try to add these tasks to your playbook in order to debug further:

    - name: Debug message
      ansible.builtin.debug:
        var: src_interfaces

    - name: Show interface facts
      ansible.builtin.debug:
        var: ansible_facts['eth0']

Also, it would be helpful if you give us the whole playbook’s execution log (not only the error) to see what the src_interfaces variable has.

PS: This is my ansible_facts['eth0'], see if it gives you more clues to workaround the issue.

TASK [Show interface facts] ***************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "ansible_facts['eth0']": {
        "active": true,
        "device": "eth0",
        "features": {
            ....
        },
        "hw_timestamp_filters": [],
        "ipv4": {
            "address": "x.x.x.x",
            "broadcast": "x.x.x.x",
            "netmask": "x.x.x.x",
            "network": "x.x.x.x",
            "prefix": "20"
        },
        "ipv6": [
            {
                "address": "fe80::215:5dff:fec1:4d80",
                "prefix": "64",
                "scope": "link"
            }
        ],
        "macaddress": "00:00:00:00:00:00",
        "module": "hv_netvsc",
        "mtu": 1500,
        "pciid": "xxxxxxxxxxxxxxxxxxxxxxxx",
        "promisc": false,
        "speed": 10000,
        "timestamping": [
            "tx_software",
            "rx_software",
            "software"
        ],
        "type": "ether"
    }
}

Lemme try it and back to you…

This is my target…
The playbook includes the following operations:

  • Adds a udev rules file with the new NIC name to MAC address assignments
  • Renames and updates all eth device files to the new NIC naming scheme
  • Renames and updates all eth route files to the new NIC naming scheme
  • Performs a final regex on all ifcfg-* files to convert any eth devices to the new naming scheme

Sorry for this edited print screen… So looks like same error and more debug lines !

1 Like

Hello Bruno, it’s becoming kind-of hard for me to debug your issue without having the whole picture of your environment (actually, I haven’t been able to replicate the same error locally). Maybe we could have a synchronous talk? That’s my id on Matrix @jbericat:matrix.org

Cheers!

Hi Jordi ! I got some progress… So I tried one node that’s worked fine ! And another is now partial failing… It means I need to run on some more hosts…

Thanks for for your help ! :slight_smile:

1 Like

Awesome! I’m very happy I was somewhat able to help :smiling_face:

Good luck with the remaining nodes!

Cheers

Hi @bspigari , welcome to the community forum! Let me share a couple of tips on using the forum:

I just edited your first message to include the code blocks for the playbook section, this makes it easier to read as it keeps the playbook format and spacing.

When composing your next messages, you can select the playbook you copy/pasted and use the </> button in the tool-bar right at the top of the message window where you are typing, this will automatically put it in the box you see in the messages above.

And if you get to a point where you consider a post by someone helped to solve the issue, please tick the checkbox below their message to mark it as the solution to help other users find the reply faster!

4 Likes

Hi !

We got the issues… but not clue yet…
We are stuck on sub-interfaces…
looping eth0, eth0_1, eth1. the task failure indicates that ansible_facts[‘eth0’][‘macaddress’] exists, but ansible_facts[‘eth0_1’][‘macaddress’] does not

1 Like

Can you dump ansible_facts[‘eth0’] and ansible_facts[‘eth0_1’] for us? That would go a long way toward us being able to reproduce your issue. Thanks.

1 Like

Hi Todd

Sure ! Looks like I have some limitation on this forum… So let me in case This part of dump of the job output is enough

TASK [Debug message] ***********************************************************
task path: /app/awxtmp/bwrap_2947532_b592cqna/awx_2947532_d0izo5ch/project/replace_nic_ethx.yml:12
ok: [10.132.78.192] => {
“src_interfaces”: [
“eth0”,
“eth0_1”,
“eth1”
]
}

TASK [Debug ansible_facts] *****************************************************
task path: /app/awxtmp/bwrap_2947532_b592cqna/awx_2947532_d0izo5ch/project/replace_nic_ethx.yml:15
ok: [10.132.78.192] => {
“ansible_facts[‘eth1’]”: {
“active”: true,
“device”: “eth1”,
“features”: {
“busy_poll”: “off [fixed]”,
“fcoe_mtu”: “off [fixed]”,
“generic_receive_offload”: “on”,
“generic_segmentation_offload”: “on”,
“highdma”: “on”,
“hw_tc_offload”: “off [fixed]”,
“l2_fwd_offload”: “off [fixed]”,
“large_receive_offload”: “on”,
“loopback”: “off [fixed]”,
“netns_local”: “off [fixed]”,
“ntuple_filters”: “off [fixed]”,
“receive_hashing”: “on”,
“rx_all”: “off [fixed]”,
“rx_checksumming”: “on”,
“rx_fcs”: “off [fixed]”,
“rx_gro_hw”: “off [fixed]”,
“rx_udp_tunnel_port_offload”: “off [fixed]”,
“rx_vlan_filter”: “on [fixed]”,
“rx_vlan_offload”: “on”,
“rx_vlan_stag_filter”: “off [fixed]”,
“rx_vlan_stag_hw_parse”: “off [fixed]”,
“scatter_gather”: “on”,
“tcp_segmentation_offload”: “on”,
“tx_checksum_fcoe_crc”: “off [fixed]”,
“tx_checksum_ip_generic”: “on”,
“tx_checksum_ipv4”: “off [fixed]”,
“tx_checksum_ipv6”: “off [fixed]”,
“tx_checksum_sctp”: “off [fixed]”,
“tx_checksumming”: “on”,
“tx_fcoe_segmentation”: “off [fixed]”,
“tx_gre_csum_segmentation”: “off [fixed]”,
“tx_gre_segmentation”: “off [fixed]”,
“tx_gso_partial”: “off [fixed]”,
“tx_gso_robust”: “off [fixed]”,
“tx_ipip_segmentation”: “off [fixed]”,
“tx_lockless”: “off [fixed]”,
“tx_nocache_copy”: “off”,
“tx_scatter_gather”: “on”,
“tx_scatter_gather_fraglist”: “off [fixed]”,
“tx_sctp_segmentation”: “off [fixed]”,
“tx_sit_segmentation”: “off [fixed]”,
“tx_tcp6_segmentation”: “on”,
“tx_tcp_ecn_segmentation”: “off [fixed]”,
“tx_tcp_mangleid_segmentation”: “off”,
“tx_tcp_segmentation”: “on”,
“tx_udp_tnl_csum_segmentation”: “off [fixed]”,
“tx_udp_tnl_segmentation”: “off [fixed]”,
“tx_vlan_offload”: “on”,
“tx_vlan_stag_hw_insert”: “off [fixed]”,
“udp_fragmentation_offload”: “off [fixed]”,
“vlan_challenged”: “off [fixed]”
},
“hw_timestamp_filters”: ,
“ipv4”: {
“address”: “10.132.196.252”,
“broadcast”: “10.132.197.255”,
“netmask”: “255.255.254.0”,
“network”: “10.132.196.0”
},
“macaddress”: “00:50:56:8d:05:97”,
“module”: “vmxnet3”,
“mtu”: 1500,
“pciid”: “0000:13:00.0”,
“promisc”: false,
“speed”: 10000,
“timestamping”: [
“rx_software”,
“software”
],
“type”: “ether”
}
}

TASK [Update udev rules] *******************************************************
.
.
.
},
“item”: “eth0”,
“msg”: “line added”
}
fatal: [10.132.78.192]: FAILED! => {
“msg”: “The task includes an option with an undefined variable. The error was: ‘dict object’ has no attribute ‘macaddress’\n\nThe error appears to have been in ‘/app/awxtmp/bwrap_2947532_b592cqna/awx_2947532_d0izo5ch/project/replace_nic_ethx.yml’: line 23, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Update udev rules\n ^ here\n”
}

PLAY RECAP *********************************************************************
10.132.78.192 : ok=3 changed=0 unreachable=0 failed=1

The eth0 case seems to be the “normal” one. Is my guess is correct that eth0_1 is a secondary IP defined on the same hardware/macaddress as eth0? I set up a secondary IP on my primary internet interface, but I’m on wireless and that device name is wlp82s0, so we’re already enough different — my udev rules are probably not like yours at all (what OS are you on, btw?) — that comparisons may get iffy. Unfortunately, that doesn’t give me an ansible_wlp82s0_1. It’s only listed as a "ipv4_secondaries" sub-dict under ansible_wlp82s0. Hmm.

There was another thread the other day, get-the-name-of-an-interface-for-a-given-ip, where the same problem was dealt with albeit for a different purpose. The solution there was to loop over the ansible_<interfaces> data to add the benign defaults for otherwise missing data for the secondary addresses. The whole point was to avoid blowing up on missing data.

It looks like you’ve got 3 options: (1) use a technique similar to that in the linked thread above so you’ve got sufficiently fleshed out dicts for your secondary IPs, (2) skip the src_interfaces that don’t have macaddress defined (simplest by far, but has implications wrt why you’re renaming these interfaces), and finally (3) reconsider what’s driving the desire to rename these interfaces and attack that as the problem to solve rather than – to be blunt – tossing away the udev work done by your distro for questionable gain. Granted, why you’re trying to do this has not been discussed, it’s your business not mine, etc. But after the tiny bit of reading I’ve done over the last 48 hours on udev rules and device naming, I’d need to hear an extremely compelling argument before I’d go down that road. And maybe you have one. I just wanted to include #3 because, speaking for myself, sometimes I fixate on implementing a solution to a problem that shouldn’t be solved, but rather eliminated further upstream.

I would still like to see what your ansible_facts['eth0_1'] looks like (assuming that’s the one blowing up on you).

1 Like

Hey @bspigari, looks like you haven’t completed the new user tutorial, so you got a limited access to the forum. Look for a “Greetings!” notice from @discobot on your notifications, that will enable you to have a better user experience. It takes only 5 minutes :wink:

1 Like

Yes its a secondary IP under same eth0 interface.

1 Like

Ah. And what version of ansible? (ansible --version) I’m asking because in later versions, everything in ansible_facts got a ansible_ prefix. The code in that other thread I linked to would expect to see ansible_facts['ansible_{{ interface }}'] for example.

And what OS / distro?

2 Likes

So…
Tower 3.8.5 Ansible version 2.9.25 for QA
Tower 3.8.5 Ansible version 2.9.27 for PROD
And OS / distro > RHEL 7.9

Identity added: /app/awxtmp/bwrap_2947532_b592cqna/awx_2947532_d0izo5ch/artifacts/2947532/ssh_key_data (/app/awxtmp/bwrap_2947532_b592cqna/awx_2947532_d0izo5ch/artifacts/2947532/ssh_key_data)
ansible-playbook 2.7.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u’/var/lib/awx/.ansible/plugins/modules’, u’/usr/share/ansible/plugins/modules’]
ansible python module location = /app/awxvenv/ansible-2.7/lib/python2.7/site-packages/ansible
executable location = /app/awxvenv/ansible-2.7/bin/ansible-playbook
python version = 2.7.5 (default, Aug 13 2020, 02:51:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Using /etc/ansible/ansible.cfg as config file

1 Like