Problem by setting up Network Interface (Newbie)

Hi All,

I’m new to Ansible and take over an existing Ansible setup from my co-worker.
Now the playbook worked on his configuration but now I made a modification with a new host and I receive an error message which doesn’t makes a whole lot of sense for me.

Ansible Version: 2.4.2.0-2.el7
Ansible OS: CentOS 7.5.1804
Receiving Server: CentOS 7.4.1708

ok: [server1.infra.sys] => (item={u’ipaddr’: u’1.1.1.2’, u’netmask’: u’255.255.255.0’, u’bootproto’: u’none’, u’device’: u’ens192’, u’type’: u’Ethernet’, u’gateway’: u’1.1.1.250’}) => {“changed”: false, “checksum”: “fdecaa26f260854783e24a79c166604488713c90”, “gid”: 0, “group”: “root”, “item”: {“bootproto”: “none”, “device”: “ens192”, “gateway”: “1.1.1.250”, “ipaddr”: “1.1.1.2”, “netmask”: “255.255.255.0”, “type”: “Ethernet”}, “mode”: “0644”, “owner”: “root”, “path”: “/etc/sysconfig/network-scripts/ifcfg-ens192”, “secontext”: “system_u:object_r:net_conf_t:s0”, “size”: 229, “state”: “file”, “uid”: 0}

fatal: [server1.infra.sys]: FAILED! => {“msg”: “The task includes an option with an undefined variable. The error was: ‘dict object’ has no attribute ‘device’\n\nThe error appears to have been in ‘/opt/ansible/playbooks/roles/basic/tasks/main.yml’: line 36, column 3, 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 primary interface IP information\n ^ here\n\nexception type: <class ‘ansible.errors.AnsibleUndefinedVariable’>\nexception: ‘dict object’ has no attribute ‘device’”}

The NIC got configured on the Server. the ifcfg-ens192 file looks like this now:

cat /etc/sysconfig/network-scripts/ifcfg-ens192

#######

Managed via Ansible

#######

NAME=ens192

TYPE=Ethernet

DEVICE=ens192

BOOTPROTO=none

ONBOOT=yes

NM_CONTROLLED=no

DEFROUTE=yes

IPV4_FAILURE_FATAL=no

IPV6INIT=no

IPADDR=1.1.1.2

PREFIX=255.255.255.0

GATEWAY=1.1.1.250

This is what I have written in to the host file in the inventory directory/./host_vars/server1.infra.sys:

HOST INTERFACES DEFINITIONS

interfaces:

  • device: ens192

type: Ethernet

bootproto: none

ipaddr: 1.1.1.2

netmask: 255.255.255.0

gateway: 1.1.1.250

As seen, there is device configured and in the error msg from Ansible it isn’t happy because the variable ‘device’ isn’t set.

This is a part of /opt/ansible/playbooks/roles/basic/tasks/main.yml

  • name: Update primary interface IP information

template:

src: roles/basic/templates/ifcfg.j2

dest: “/etc/sysconfig/network-scripts/ifcfg-{{item.device}}”

owner: root

group: root

mode: 0644

with_items: “{{ interfaces }}”

when: interfaces is defined

notify: restart network

So why should I get an error from Ansible when the changes have been made successfully?

I’m already very thankful for the time and help with my issue.

When I'm debugging Ansible Playbooks and I don't know if I can access a variable I usually have a debug block.

In your case this might look something like:

Hi Uwe,
Thank you for your help.

When I insert the - debug then I get this feedback of it:

TASK [basic : debug] ****************************************************
fatal: [server1.infra.sys]: FAILED! => {“msg”: “Unexpected failure in finding the lookup named ‘{{ interfaces }}’ in the available lookup plugins”}

ok: [server1.infra.sys] => (item={u'ipaddr': u'1.1.1.2', u'netmask':
u'255.255.255.0', u'bootproto': u'none', u'device': u'ens192', u'type':
u'Ethernet', u'gateway': u'1.1.1.250'}) => {"changed": false, "checksum":
"fdecaa26f260854783e24a79c166604488713c90", "gid": 0, "group": "root",
"item": {"bootproto": "none", "device": "ens192", "gateway": "1.1.1.250",
"ipaddr": "1.1.1.2", "netmask": "255.255.255.0", "type": "Ethernet"},
"mode": "0644", "owner": "root", "path":
"/etc/sysconfig/network-scripts/ifcfg-ens192", "secontext":
"system_u:object_r:net_conf_t:s0", "size": 229, "state": "file", "uid": 0}

fatal: [server1.infra.sys]: FAILED! => {"msg": "The task includes an option
with an undefined variable. The error was: 'dict object' has no attribute
'device'\n\nThe error appears to have been in
'/opt/ansible/playbooks/roles/basic/tasks/main.yml': line 36, column 3, 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 primary interface IP
information\n ^ here\n\nexception type: <class
'ansible.errors.AnsibleUndefinedVariable'>\nexception: 'dict object' has no
attribute 'device'"}

So you are running this task twice, so you with_items aka interfaces variable contain at least to list elements.

This is what I have written in to the host file in the inventory
directory/./host_vars/server1.infra.sys:

# HOST INTERFACES DEFINITIONS
interfaces:
- device: ens192
   type: Ethernet
   bootproto: none
   ipaddr: 1.1.1.2
   netmask: 255.255.255.0
   gateway: 1.1.1.250

My suspicion is that this is not the whole content of the file, because your output indicate that you have at least one more element in this list.

As seen, there is device configured and in the error msg from Ansible it
isn't happy because the variable 'device' isn't set.

This is a part of /opt/ansible/playbooks/roles/basic/tasks/main.yml

- name: Update primary interface IP information
  template:
   src: roles/basic/templates/ifcfg.j2
   dest: "/etc/sysconfig/network-scripts/ifcfg-{{item.device}}"
   owner: root
   group: root
   mode: 0644
  with_items: "{{ interfaces }}"
  when: interfaces is defined
  notify: restart network

So why should I get an error from Ansible when the changes have been made
successfully?

The first element in the list interfaces goes thru OK but not the second one.

If you before the task that fails add this

   - debug: var=interfaces

you can verify that you variable actually contain more than one list element.

Depending on the Ansible version it might be necessary to change

loop: '{{ interfaces }}'

to

with_items:
  - '{{ interfaces }}'

Yuo migth as well change the whole debug output as suggested by Kai Stian Olstad .

Hi Kai

Ok, with the new modification in main.yml with:

  • debug: var=interfaces

  • meta: end_play

does it works as designed.
Here the output of the debug:

ok: [server1.infra.sys] => {

“interfaces”: [

{

“bootproto”: “none”,

“device”: “ens192”,

“gateway”: “1.1.1.250”,

“ipaddr”: “1.1.1.2”,

“netmask”: “255.255.255.0”,

“type”: “Ethernet”

},

{

“aliases”: “ansible”,

“fqdn”: “ansible.infra.sys”,

“host”: “1.1.1.3”

}

]

}

This is the complete configuration of the interfaces and additional services:

fqdn: server1.infra.sys

HOST INTERFACES DEFINITIONS

interfaces:

  • device: ens192

type: Ethernet

bootproto: none

ipaddr: 1.1.1.2

netmask: 255.255.255.0

gateway: 1.1.1.250

/etc/hosts ENTRIES

  • host: 1.1.1.3

fqdn: ansible.infra.sys

aliases: “ansible”

ntp_servers:

  • server: 1.1.1.5

  • server: 1.1.1.6

ntp_interface: ens192

So when I understand the debug correct, device is set so it shouldn’t be any problem. Or do I need so specify anything else with device on an other part of the configuration?

I think you don't understand the structure of "interfaces"

Here the output of the debug:

    ok: [server1.infra.sys] => {
     "interfaces": [
     {
     "bootproto": "none",
     "device": "ens192",
     "gateway": "1.1.1.250",
     "ipaddr": "1.1.1.2",
     "netmask": "255.255.255.0",
     "type": "Ethernet"
     },
     {
     "aliases": "ansible",
     "fqdn": "ansible.infra.sys",
     "host": "1.1.1.3"
     }
     ]
    }

This tells us that "interfaces" is a list with two elements. Both are dictionaries but they have differing keys. As such you
cannot itterate over the elements of "interfaces" because in each iteration you are trying to access the key "device" for the
current element.

The second element has no such key. This is why your play fails.

That is correct. At the moment I do not have a wide understanding of Ansible because i got thrown in to the cold water and got told “just do it”. So I’m a little struggling.

Ok ok ok, I found the issue with your help and the exploration how Ansible is build up.
I missed out a line in the host_vars file for the server. The red marked line missed so Ansible thought, that the - host part should attache to interfaces. But it is a different function which should write a static entry to the /etc/hosts file.

So after the correction (marked in red) the error have been resolved.

HOST INTERFACES DEFINITIONS

interfaces:

  • device: ens192

type: Ethernet

bootproto: none

ipaddr: 1.1.1.2

netmask: 255.255.255.0

gateway: 1.1.1.250

/etc/hosts ENTRIES

etc_hosts:

  • host: 1.1.1.250

fqdn: ansible.infra.sys

aliases: “ansible”

Thank you a lot for your time and patience with me as a newbie on Ansible. :slight_smile: