community.libvirt
community.libvirt copied to clipboard
Problem with file paths when using ansible.builtin.copy module
SUMMARY
Almost all Ansible operations appear to use the unresolved path to the Ansible temp directory '~/.ansible/tmp'. However, the ansible.builtin.copy module appears to resolve this path to '/root/.ansible/tmp' when looking for the source file. The underlying problem is that when I examined the filesystem on the VM, it appears that the community.libvirt.libvirt_qemu connection plugin is copying all files in the temp directory to '/~/.ansible/tmp'. The tilde is not being resolved to the homedir of the user and instead ends up in a '/~' directory at the root of the filesystem.
ISSUE TYPE
- Bug Report
COMPONENT NAME
community.libvirt.libvirt_qemu connection plugin
ANSIBLE VERSION
ansible [core 2.15.4]
config file = /home/user/ansible-dir/ansible.cfg
configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/user/ansible-dir/.venv/lib/python3.11/site-packages/ansible
ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
executable location = /home/user/ansible-dir/.venv/bin/ansible
python version = 3.11.5 (main, Aug 25 2023, 13:19:50) [GCC 11.4.0] (/home/user/ansible-dir/.venv/bin/python)
jinja version = 3.1.2
libyaml = True
COLLECTION VERSION
# /home/user/ansible-dir/.venv/lib/python3.11/site-packages/ansible_collections
Collection Version
----------------- -------
community.libvirt 1.2.0
CONFIGURATION
CONFIG_FILE() = /home/user/ansible-dir/ansible.cfg
DEFAULT_HOST_LIST(/home/user/ansible-dir/ansible.cfg) = ['/home/user/ansible-dir/inventory.yml']
DEFAULT_KEEP_REMOTE_FILES(env: ANSIBLE_KEEP_REMOTE_FILES) = False
EDITOR(env: EDITOR) = /home/user/bin/vim
OS / ENVIRONMENT
Target OS: Ubuntu 22.04 Server
STEPS TO REPRODUCE
ansible -i local-libvirt-inventory.yml --become all -m copy -a 'src=srcfile dest=/path/to/dest/file'
EXPECTED RESULTS
The local file is copied to the libvirt host.
ACTUAL RESULTS
The file is not copied. When examining the filesystem in the libvirt VM, I found that the directory '/root/.ansible/tmp' doesn't exist. It is located at '/~/.ansible/tmp' instead.
libvirt-host | FAILED! => {
"changed": false,
"checksum": "fac0b7e52fc298c5c5feb6b7673f74e2306aba6e",
"msg": "Source /root/.ansible/tmp/ansible-tmp-1695394376.1436307-368511-193439908275987/source not found"
}
@antonc42 hi, thanks for posting this issue. I've been trying to replicate it and didn't have luck with various versions of ansible and python on Fedora and CentOS. I spun up an Ubuntu 22.05 host and was able to replicate the issue.
After some digging, I think this is related to Ubuntu's use of dash as the default for /bin/sh on the guest. Are you able to try with bash and see if you have any different result?
Should be able to just set Use dash as the default system shell to no and retry without your patch.
sudo dpkg-reconfigure dash
Let me know how you go!
Sorry for the late reply. I kinda lost track of this.
I just tried your suggestion on a Ubuntu 24.04 guest and it didn't fix the problem. I still saw the same weird /~ directory being created.
Apparently the dpkg-reconfigure method no longer works starting with Ubuntu 22.10 and Debian 12.
I think this is a safe method to change the /bin/sh symlink on the guest VM to bash (taken from here):
sudo su -c 'pushd /bin && ln -s bash sh.bash && mv sh.bash sh && popd'
Another way to solve this would be to set the default executable to /bin/bash in the Ansible config or env var. That would not require changing anything on the guest VM.
Once the shell was set properly, then everything worked as expected.
I don't think automatically changing the default shell system-wide is an acceptable solution to the problem. This can have system-wide side effects and easily can break people's machines.
@leegarrett
You could try the second solution of changing the Ansible default executable setting. That doesn't change the default shell on the Ansible controller or on the remote. It just sets Ansible to use /bin/bash instead of /bin/sh when executing commands on the remote machine. That should probably be the default if Ansible is going to use bash-specific features like tilde expansion.
In ansible.cfg:
[defaults]
executable = /bin/bash