community.docker
community.docker copied to clipboard
ansible hostname task fails with nsenter connection plugin
SUMMARY
The hostname Ansible task fails when using the nsenter connection plugin.
ISSUE TYPE
- Bug Report
COMPONENT NAME
nsenter connection plugin https://docs.ansible.com/ansible/latest/collections/community/docker/nsenter_connection.html
ANSIBLE VERSION
# ansible --version
ansible [core 2.12.10]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.10/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.8 (main, Nov 14 2022, 00:00:00) [GCC 12.2.1 20220819 (Red Hat 12.2.1-2)]
jinja version = 3.0.3
libyaml = True
# rpm -q ansible
ansible-5.9.0-1.fc36.noarch
COLLECTION VERSION
# ansible-galaxy collection list community.docker
# /usr/lib/python3.10/site-packages/ansible_collections
Collection Version
---------------- -------
community.docker 2.6.0
# /root/.ansible/collections/ansible_collections
Collection Version
---------------- -------
community.docker 3.4.0
CONFIGURATION
# ansible-config dump --only-changed
OS / ENVIRONMENT
Ansible is running in a privileged podman container that is invoked like this:
sudo podman run --pull=newer --rm -it --pid=host --privileged registry.hub.docker.com/library/fedora:36
It uses nsenter to escape the container and execute the Ansible task on the host.
STEPS TO REPRODUCE
Start a container as described above.
Then dnf install ansible , put an example host name in your inventory and do
# ansible -c community.docker.nsenter -m hostname -a 'name="myhost.example.org"' --check myhost.example.org
[WARNING]: Platform linux on host myhost.example.org is using the discovered Python interpreter at /usr/libexec/platform-python, but future installation of another Python
interpreter could change the meaning of that path. See https://docs.ansible.com/ansible-core/2.12/reference_appendices/interpreter_discovery.html for more information.
myhost.example.org | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Command failed rc=1, out=, err=Could not get property: Connection timed out\n"
}
EXPECTED RESULTS
It should be possible to read or set the hostname. I would be very happy to even have read only access to the hostname, which should not require any special privileges?
ACTUAL RESULTS
Extra verbose output shows:
# ansible -vvv -c community.docker.nsenter -m hostname -a 'name="myhost.example.org"' --check myhost.example.org
ansible [core 2.12.10]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.10/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.8 (main, Nov 14 2022, 00:00:00) [GCC 12.2.1 20220819 (Red Hat 12.2.1-2)]
jinja version = 3.0.3
libyaml = True
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
META: ran handlers
<myhost.example.org> ESTABLISH NSENTER CONNECTION FOR USER: root
<myhost.example.org> EXEC nsenter --ipc --mount --net --pid --uts --preserve-credentials --target=1 -- /bin/sh -c 'echo ~ && sleep 0'
<myhost.example.org> EXEC nsenter --ipc --mount --net --pid --uts --preserve-credentials --target=1 -- /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491 `" && echo ansible-tmp-1674602671.8849206-718043-63878993635491="` echo /root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491 `" ) && sleep 0'
<myhost.example.org> Attempting python interpreter discovery
<myhost.example.org> EXEC nsenter --ipc --mount --net --pid --uts --preserve-credentials --target=1 -- /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'python3.10'"'"'; command -v '"'"'python3.9'"'"'; command -v '"'"'python3.8'"'"'; command -v '"'"'python3.7'"'"'; command -v '"'"'python3.6'"'"'; command -v '"'"'python3.5'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'/usr/libexec/platform-python'"'"'; command -v '"'"'python2.7'"'"'; command -v '"'"'python2.6'"'"'; command -v '"'"'/usr/bin/python'"'"'; command -v '"'"'python'"'"'; echo ENDFOUND && sleep 0'
<myhost.example.org> Python interpreter discovery fallback (pipelining support required for extended interpreter discovery)
Using module file /usr/lib/python3.10/site-packages/ansible/modules/hostname.py
<myhost.example.org> PUT /root/.ansible/tmp/ansible-local-718036pr2p_16a/tmpvdowh4c0 to /root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491/AnsiballZ_hostname.py
<myhost.example.org> EXEC [b'nsenter', b'--ipc', b'--mount', b'--net', b'--pid', b'--uts', b'--preserve-credentials', b'--target=1', b'--', b'tee', b'/root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491/AnsiballZ_hostname.py']
<myhost.example.org> EXEC nsenter --ipc --mount --net --pid --uts --preserve-credentials --target=1 -- /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491/ /root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491/AnsiballZ_hostname.py && sleep 0'
<myhost.example.org> EXEC nsenter --ipc --mount --net --pid --uts --preserve-credentials --target=1 -- /bin/sh -c '/usr/libexec/platform-python /root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491/AnsiballZ_hostname.py && sleep 0'
<myhost.example.org> EXEC nsenter --ipc --mount --net --pid --uts --preserve-credentials --target=1 -- /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1674602671.8849206-718043-63878993635491/ > /dev/null 2>&1 && sleep 0'
[WARNING]: Platform linux on host myhost.example.org is using the discovered Python interpreter at /usr/libexec/platform-python, but future installation of another Python
interpreter could change the meaning of that path. See https://docs.ansible.com/ansible-core/2.12/reference_appendices/interpreter_discovery.html for more information.
myhost.example.org | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"invocation": {
"module_args": {
"name": "myhost.example.org",
"use": null
}
},
"msg": "Command failed rc=1, out=, err=Could not get property: Connection timed out\n"
}
I can reproduce it with the same nsenter command, or even if I do:
[root@0b9e5c0ea9d4 /]# nsenter -a -t 1
[root@myhost /]# hostnamectl --static
Could not get property: Connection timed out
Of course hostnamectl works fine on the host itself when not run in a container or nsenter.
I also tried running the podman container with --network=host but the result was the same (even though in this case the podman container knows the hostname). In either case, nsenter and hostname -f works, but hostnamectl does not work.
Other Ansible tasks work, only hostname seems to be affected. Maybe something related to permissions in the namespace, but I don't see any other privileges or namespace access that I have not already granted to the podman container.
The default hostnamectl-based strategy being used by the hostname module is systemd: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/hostname_module.html
I also tried generic and redhat but they failed with different errors. The host is Almalinux 8 and the redhat strategy uses /etc/sysconfig/network which does not contain the hostname anymore.
The sles or solaris strategies might appear to work but I'm not sure if editing /etc/hostname or using /usr/bin/hostname to change hostname is supported on EL8.
I don't think this is a problem with the nsenter connection plugin, but with the hostname module (or maybe even the action of changing the hostname through nsenter in general). There is nothing the nsenter connection plugin can do to improve this situation.
@felixfontein As that may be, do you know what the cause of the issue is or how the issue could be worked around?
Seems to also affect the timezone task and timedatectl command. Not sure why but it seems these commands can't talk to systemd via the dbus socket when using nsenter.
https://unix.stackexchange.com/questions/639168/why-is-the-uts-namespace-isolation-not-working