Search code examples
ansibleraspberry-pihostname

Ansible hostname module, set hostname based on IP address


I'm trying to use the ansible hostname module to change hostname of multiple Raspberry Pi Compute Module 4. Because they are all based from the same Raspberry Pi OS image, their hostname is raspberrypi for all of them, what I would like to change.

My inventory is roughly like this:

rpi-cm4-1:
  node_number: 1
  name: rpi-cm4-1
  ansible_host: 192.168.1.101

rpi-cm4-2:
  node_number: 2
  name: rpi-cm4-2
  ansible_host: 192.168.1.102

...

and my playbook is like this:

- name: Change hostname of managed nodes
  hosts: rpi_cm4-2
  tasks:
    - name: Change hostname of managed nodes
      ansible.builtin.hostname:
        name: "{{ hostvars[inventory_hostname].name }}"

When I run the playbook, the error I'm facing is this:

TASK [Gathering Facts] *****************************************************************************************************
ok: [rpi-cm4-2]

TASK [Change hostname of managed nodes] *****************************************************************************************************
fatal: [rpi-cm4-2]: FAILED! => changed=false
  msg: |-
    Command failed rc=1, out=, err=Could not set pretty hostname: Connection timed out

I guess that maybe Ansible is not using the ip address of the inventory (but it used it for gathering facts). What could I do to make him use the IP of the inventory ?

I could not manage to make Ansible use the IP address.

The -vvv actually shows this:

TASK [Change hostname of managed nodes] ****************************************************************************************************************************
task path: /home/ncasaux/home-lab/ansible/tpi2_rpi_cm4.tpi2_rpios.yml:75
<192.168.1.102> ESTABLISH SSH CONNECTION FOR USER: pi
<192.168.1.102> SSH: EXEC sshpass -d12 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o 'User="pi"' -o ConnectTimeout=10 -o 'ControlPath="/home/ncasaux/.ansible/cp/ed650a3305"' 192.168.1.102 '/bin/sh -c '"'"'echo ~pi && sleep 0'"'"''
<192.168.1.102> (0, b'/home/pi\n', b'')
<192.168.1.102> ESTABLISH SSH CONNECTION FOR USER: pi
<192.168.1.102> SSH: EXEC sshpass -d12 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o 'User="pi"' -o ConnectTimeout=10 -o 'ControlPath="/home/ncasaux/.ansible/cp/ed650a3305"' 192.168.1.102 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /home/pi/.ansible/tmp `"&& mkdir "` echo /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657 `" && echo ansible-tmp-1703118028.4996538-25006-160853801334657="` echo /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657 `" ) && sleep 0'"'"''
<192.168.1.102> (0, b'ansible-tmp-1703118028.4996538-25006-160853801334657=/home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657\n', b'')
Using module file /usr/lib/python3/dist-packages/ansible/modules/hostname.py
<192.168.1.102> PUT /home/ncasaux/.ansible/tmp/ansible-local-24823y1az1b7h/tmp3nxd67rj TO /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657/AnsiballZ_hostname.py
<192.168.1.102> SSH: EXEC sshpass -d12 sftp -o BatchMode=no -b - -C -o ControlMaster=auto -o ControlPersist=60s -o 'User="pi"' -o ConnectTimeout=10 -o 'ControlPath="/home/ncasaux/.ansible/cp/ed650a3305"' '[192.168.1.102]'
<192.168.1.102> (0, b'sftp> put /home/ncasaux/.ansible/tmp/ansible-local-24823y1az1b7h/tmp3nxd67rj /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657/AnsiballZ_hostname.py\n', b'')
<192.168.1.102> ESTABLISH SSH CONNECTION FOR USER: pi
<192.168.1.102> SSH: EXEC sshpass -d12 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o 'User="pi"' -o ConnectTimeout=10 -o 'ControlPath="/home/ncasaux/.ansible/cp/ed650a3305"' 192.168.1.102 '/bin/sh -c '"'"'chmod u+x /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657/ /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657/AnsiballZ_hostname.py && sleep 0'"'"''
<192.168.1.102> (0, b'', b'')
<192.168.1.102> ESTABLISH SSH CONNECTION FOR USER: pi
<192.168.1.102> SSH: EXEC sshpass -d12 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o 'User="pi"' -o ConnectTimeout=10 -o 'ControlPath="/home/ncasaux/.ansible/cp/ed650a3305"' -tt 192.168.1.102 '/bin/sh -c '"'"'/usr/bin/python3 /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657/AnsiballZ_hostname.py && sleep 0'"'"''
<192.168.1.102> (1, b'\x1b[1;31m==== AUTHENTICATING FOR org.freedesktop.hostname1.set-static-hostname ====\r\n\x1b[0mAuthentication is required to set the statically configured local hostname, as well as the pretty hostname.\r\nAuthenticating as: ,,, (pi)\r\nPassword: polkit-agent-helper-1: pam_authenticate failed: Authentication failure\r\n\r\n{"failed": true, "msg": "Command failed rc=1, out=, err=Could not set pretty hostname: Connection timed out\\n", "invocation": {"module_args": {"name": "192.168.1.102", "use": null}}}\r\n', b'Shared connection to 192.168.1.102 closed.\r\n')
<192.168.1.102> Failed to connect to the host via ssh: Shared connection to 192.168.1.102 closed.
<192.168.1.102> ESTABLISH SSH CONNECTION FOR USER: pi
<192.168.1.102> SSH: EXEC sshpass -d12 ssh -C -o ControlMaster=auto -o ControlPersist=60s -o 'User="pi"' -o ConnectTimeout=10 -o 'ControlPath="/home/ncasaux/.ansible/cp/ed650a3305"' 192.168.1.102 '/bin/sh -c '"'"'rm -f -r /home/pi/.ansible/tmp/ansible-tmp-1703118028.4996538-25006-160853801334657/ > /dev/null 2>&1 && sleep 0'"'"''
<192.168.1.102> (0, b'', b'')
fatal: [rpi-cm4-2]: FAILED! => changed=false
  invocation:
    module_args:
      name: 192.168.1.102
      use: null
  msg: |-
    Command failed rc=1, out=, err=Could not set pretty hostname: Connection timed out

So the IP seems to be used...


Solution

  • It's pretty clearly using the ip address, so that's not the problem. It looks like ansible is connecting successfully, but it receiving an error when it attempts to set the system hostname.

    From the error message, it looks like a permissions problem:

    ==== AUTHENTICATING FOR org.freedesktop.hostname1.set-static-hostname ====
    Authentication is required to set the statically configured local hostname, as well as the pretty hostname.
    Authenticating as: ,,, (pi)
    Password: polkit-agent-helper-1: pam_authenticate failed: Authentication failure
    

    You probably need to ensure that you're running the task as root on the remote host:

    - name: Change hostname of managed nodes
      hosts: rpi_cm4-2
      become: true
      tasks:
        - name: Change hostname of managed nodes
          ansible.builtin.hostname:
            name: "{{ hostvars[inventory_hostname].name }}"
    

    Note the addition of become: true, which will cause all tasks in this play to run as root.