Random "'ansible_hostname' is undefined" errors

3,898 views
Skip to first unread message

Guy Knights

unread,
Apr 15, 2016, 7:21:05 PM4/15/16
to ansible...@googlegroups.com
I have a weird issue where occasionally when I run a playbook that has a task which uses the {{ ansible_hostname }} variable in it, I get an error "'ansible_hostname' is undefined". In most cases, if I re-run the playbook again right after I see the errors, it works fine and I don't see these errors.

Does anyone know why this might be happening?

Thanks,
Guy

Greg Chavez

unread,
Apr 16, 2016, 5:01:28 PM4/16/16
to ansible...@googlegroups.com
Guy, no, but the next time this happens to you, gather as much information you can before you run again when, presumably, the playbook with run without the error.  Present as much as the information as you can share here.

Thanks
--Greg Chavez

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/CANNH9msH0Qa79nirc9QHx1qhQp04ibh8h1%3DOMS4Cmz77jubKgA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.



--
\*..+.-
--Greg Chavez
+//..;};

Alex Leonhardt

unread,
Apr 16, 2016, 6:32:20 PM4/16/16
to ansible...@googlegroups.com

Only ever seen that when the play didn't gather facts... Which must be explicitly disabled with 'gather_facts: no' or similar.. Maybe that's somewhere in your playbooks?

Phonthip Namkaew

unread,
Apr 17, 2016, 6:56:03 AM4/17/16
to Ansible Project
I have a similar issue with a playbook which runs once a day using a cron job on the Ansible control host. Probably once a week, I get the follwoing error for a random server:

(..)

The following task failed for host ejpdxannnn-mgt.example.com:

 

template:  {"dest": "/tmp/fragments.d/SLES.frag", "src": "std-templates/std-playbook-make-inventory-by-os.j2", "group": "admin2", "mode": "0400", "owner": "admin2"}

 

with the following message:

 

AnsibleUndefinedVariable: 'dict object' has no attribute 'ansible_hostname'

 

A complete dump of the error:

 

{"changed": false, "failed": true, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'ansible_hostname'"}


(..)


Ansible version is 2.0.1.0. The playbook runs on 600 hosts with forks=20. The Ansible control host has 16 GB RAM and if I run the playbook manually there is no memory shortage (no swapping on Ansible control host) and I can not reproduce the error.
It seems that every now and then, Ansible does not gather the facts for all 600 hosts or the facts get lost on the Ansible control host due to some unknown resource constraints. As far as I understand the concept, Ansible
keeps all the facts in the control host's memory while the playbook is run. For 600 hosts that is a lot of data.


The playbook is:

admin2@xxxxx:/data/ansible/playbooks> cat std-playbook-make-inventory-by-os.yml
---

- hosts: all
  gather_facts: True
  tasks:

  - set_fact:
      path_to_fragments: /tmp/fragments.d
      file_inventory: /data/ansible/inventory/inventory.os


- hosts: all[0]
  gather_facts: False
  tasks:
  - name: Remove file ansible host:{{ file_inventory }}
    local_action: file path={{ file_inventory }} state=absent
    changed_when: False

  - name: Remove dir ansible host:{{ path_to_fragments }}
    local_action: file path={{ path_to_fragments }} state=absent
    changed_when: False

  - name: Make dir ansible host:{{ path_to_fragments }}
    local_action: file path={{ path_to_fragments }} state=directory mode=0700
    changed_when: False



- hosts: all
  gather_facts: False
  tasks: 

  ##
  ## SLES, Solaris
  ##

  - name: Group server by distribution
    group_by: key={{ ansible_distribution }}

  ##
  ## SLES-11, SLES-12
  ##

  - name: Group server by distribution, distribution_major_version
    group_by: key={{ ansible_distribution }}-{{ ansible_distribution_major_version }}

  ##
  ## SLES-11-4, SLES-12-0
  ##

  - name: Group server by distribution, distribution_major_version, ansible_distribution_release
    group_by: key={{ ansible_distribution }}-{{ ansible_distribution_major_version }}-{{ansible_distribution_release}}

  ## 
  ## Solaris-10, Solaris-11.2
  ## 
  - name: Group server by distribution, distribution_version
    group_by: key={{ ansible_distribution }}-{{ ansible_distribution_version }}


#
# For each following statement of type < - hosts: XXXX >, an Ansible group [ XXXX ]
# is generated in an single inventory file named inventory/{{file_inventory}}
#

- hosts: SLES
  gather_facts: False
  vars:
    fragment_file: "{{ ansible_distribution }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}]"
     run_once: true
     changed_when: False



- hosts: SLES-12
  gather_facts: False
  vars:
    fragment_file: "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}-{{ ansible_distribution_major_version }}]"
     run_once: true
     changed_when: False



- hosts: SLES-12-0
  gather_facts: False
  vars:
    fragment_file: "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}-{{ ansible_distribution_release }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}-{{ ansible_distribution_major_version }}-{{ansible_distribution_release }}]"
     run_once: true
     changed_when: False



- hosts: SLES-11
  gather_facts: False
  vars:
    fragment_file: "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}-{{ ansible_distribution_major_version }}]"
     run_once: true
     changed_when: False



- hosts: SLES-11-4
  gather_facts: False
  vars: 
    fragment_file: "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}-{{ ansible_distribution_release }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }} 
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}-{{ ansible_distribution_major_version }}-{{ ansible_distribution_release }}]"
     run_once: true   
     changed_when: False



- hosts: Solaris
  gather_facts: False
  vars:
    fragment_file: "{{ ansible_distribution }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}]"
     run_once: true
     changed_when: False



- hosts: Solaris-11.2
  gather_facts: False
  vars:
    fragment_file: "{{ ansible_distribution }}-{{ ansible_distribution_version }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}-{{ ansible_distribution_version }}]"
     run_once: true
     changed_when: False



- hosts: Solaris-10
  gather_facts: False
  vars:
    fragment_file: "{{ ansible_distribution }}-{{ ansible_distribution_version }}.frag"

  tasks:
   - name: Template file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: template src=std-templates/std-playbook-make-inventory-by-os.j2 dest={{ path_to_fragments }}/{{ fragment_file }} owner=admin2 group=admin2 mode=0400
     run_once: true
     changed_when: False

   - name: Lineinfile header to file {{ path_to_fragments }}/{{ fragment_file }}
     local_action: lineinfile dest={{ path_to_fragments }}/{{ fragment_file }} insertbefore=BOF line="[{{ ansible_distribution }}-{{ ansible_distribution_version }}]"
     run_once: true
     changed_when: False



- hosts: all[0]
  gather_facts: False

  tasks:
  - name: Assemble fragments to file {{ file_inventory }}
    local_action: assemble src={{ path_to_fragments }} dest={{ file_inventory }} owner=admin2 group=admin2 mode=0644
    changed_when: False

  - name: Add header block to file {{ file_inventory }}
    local_action:
      module: blockinfile
      dest: "{{ file_inventory }}"
      state: present
      block: |
       #
       #
       # This file is generated using a cron job and playbooks/std-playbook-make-inventory-by-os.yml
       #
       #
      insertbefore: BOF



Message has been deleted

J Hawkesworth

unread,
Apr 18, 2016, 7:09:25 AM4/18/16
to Ansible Project
I think ansible_hostname is a property of the ssh connection.  I'm pretty certain it is not present when you use, for example, wirnm connection.

This is a complete guess but I wonder if in your case sometimes it is failing to set up ssh connection and then falling back to another connection type (say paramiko) which perhaps doesn't have ansible_hostname defined.

Hope this helps,

Jon

Toshaan Bharvani | VanTosh

unread,
Apr 18, 2016, 9:31:03 AM4/18/16
to ansible...@googlegroups.com

On 17/04/16 12:56, Phonthip Namkaew wrote:
> I have a similar issue with a playbook which runs once a day using a
> cron job on the Ansible control host. Probably once a week, I get the
> follwoing error for a random server:
>
> (..)
>
> The following task failed for host ejpdxannnn-mgt.example.com:
>
> template:{"dest": "/tmp/fragments.d/SLES.frag", "src":
> "std-templates/std-playbook-make-inventory-by-os.j2", "group": "admin2",
> "mode": "0400", "owner": "admin2"}
>
> with the following message:
>
> AnsibleUndefinedVariable: 'dict object' has no attribute 'ansible_hostname'
>
> A complete dump of the error:
>
> {"changed": false, "failed": true, "msg": "AnsibleUndefinedVariable:
> 'dict object' has no attribute 'ansible_hostname'"}
Remenber that all variables staring with 'ansible_*' are gathered at the
beginning of a play section in a playbook.
Your playbook contains several plays, each play will initiate fact
gathering by using the setup module, unless the play section specifies
no fact gathering, as you do.
If memory serves me well, the default behaviour for fact gathering
between plays in one playbook changed a while ago.
I use the 'smart' gathering, so new hosts get facts gathered, while old
ones don't

[defaults]
gathering = smart

http://docs.ansible.com/ansible/intro_configuration.html#gathering

>
>
> (..)
>
>
> Ansible version is 2.0.1.0. The playbook runs on 600 hosts with
> forks=20. The Ansible control host has 16 GB RAM and if I run the
> playbook manually there is no memory shortage (no swapping on Ansible
> control host) and I can not reproduce the error.
> It seems that every now and then, Ansible does not gather the facts for
> all 600 hosts or the facts get lost on the Ansible control host due to
> some unknown resource constraints. As far as I understand the concept,
> Ansible
> keeps all the facts in the control host's memory while the playbook is
> run. For 600 hosts that is a lot of data.

I am guessing and presuming you are doing this for speed.
It might be worth looking at setting up your ansible host with fact
caching in redis

For a redis setup that would be as following
[defaults]
fact_caching = redis
fact_caching_timeout = 3600
fact_caching_connection = localhost:6379:0

I have used this in the case of a +/- 500 host setup with a mgmt host of
4GB works fine, and reduces ram, while speeding up most operations

If you want them on your disk you could setup file based caching,
however for 600 hosts that might be slow.
For a file setup that would be as following
[defaults]
fact_caching = jsonfile
fact_caching_timeout = 3600
fact_caching_connection = /tmp/ansible/facts/cache



>
>
> The playbook is:
>
> admin2@xxxxx:/data/ansible/playbooks> cat
> std-playbook-make-inventory-by-os.yml
> ---
>
> - hosts: all
> gather_facts: True
> tasks:
>
> - set_fact:
> path_to_fragments: /tmp/fragments.d
> file_inventory: /data/ansible/inventory/inventory.os
>
>
> - hosts: all[0]
> gather_facts: False
Here is you problem
> --
> You received this message because you are subscribed to the Google
> Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to ansible-proje...@googlegroups.com
> <mailto:ansible-proje...@googlegroups.com>.
> To post to this group, send email to ansible...@googlegroups.com
> <mailto:ansible...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ansible-project/eb312faf-e412-4bff-a462-374bda7a67f0%40googlegroups.com
> <https://groups.google.com/d/msgid/ansible-project/eb312faf-e412-4bff-a462-374bda7a67f0%40googlegroups.com?utm_medium=email&utm_source=footer>.
Reply all
Reply to author
Forward
0 new messages