strange behaviour of template module

Hello,

I’m having a strange issue using template module.

First, here is my template file, ovz.j2:

ONBOOT="yes"
{# https://wiki.openvz.org/User_Guide/Managing_Resources #}

PHYSPAGES="0:{{ (ct_vram |int) * 1024 }}"
SWAPPAGES="0:{{ ct_swap }}M"
KMEMSIZE="1951399936:2147483648"
DCACHESIZE="975175680:1073741824"
LOCKEDPAGES="524288"
PRIVVMPAGES="unlimited"
SHMPAGES="unlimited"
NUMPROC="unlimited"
VMGUARPAGES="0:unlimited"
OOMGUARPAGES="0:unlimited"
NUMTCPSOCK="unlimited"
NUMFLOCK="unlimited"
NUMPTY="unlimited"
NUMSIGINFO="unlimited"
TCPSNDBUF="unlimited"
TCPRCVBUF="unlimited"
OTHERSOCKBUF="unlimited"
DGRAMRCVBUF="unlimited"
NUMOTHERSOCK="unlimited"
NUMFILE="unlimited"
NUMIPTENT="unlimited"

# Disk quota parameters (in form of softlimit:hardlimit)
DISKSPACE="{{ (ct_disk |int) * 1038576 }}:{{ (ct_disk |int) * 1153434 }}"
DISKINODES="{{ (ct_disk|int) * 20000 }}:{{ (ct_disk |int) * 220000 }}"
QUOTATIME="0"
QUOTAUGIDLIMIT="0"

# CPU fair scheduler parameter
CPUUNITS="1000"
CPUS="{{ ct_vcpu }}"
HOSTNAME="{{ my_name }}.{{ my_site }}"
SEARCHDOMAIN="our.tld"
NAMESERVER="172.16.0.XX"
IP_ADDRESS="{{ ct_ipv4 }}"
VE_ROOT="/var/lib/vz/root/$VEID"
VE_PRIVATE="/var/lib/vz/private/$VEID"
OSTEMPLATE="{{ ct_ostf }}.gz"

Second, here is my playbook to test in Ansible controller host, ovz.yml:

---
- hosts: localhost
  remote_user: mylogin
  become: yes
  gather_facts: no
  vars:
    ct_vmid: '10'
    ct_vram: '128'
    ct_swap: '128'
    ct_disk: '3'
    ct_vcpu: '1'
    ct_ipv4: '172.16.0.YY'
    ct_ostf: 'ubuntu-14.04-amd64-our.tar'
    my_name: 'a-name'
    my_site: 'a-site'
  tasks:
  - template:
      src: 'ovz.j2'
      dest: '/home/mylogin/ovz.conf-sample'

And the result is as expected, ovz.conf-sample:

ONBOOT="yes"

PHYSPAGES="0:131072"
SWAPPAGES="0:128M"
KMEMSIZE="1951399936:2147483648"
DCACHESIZE="975175680:1073741824"
LOCKEDPAGES="524288"
PRIVVMPAGES="unlimited"
SHMPAGES="unlimited"
NUMPROC="unlimited"
VMGUARPAGES="0:unlimited"
OOMGUARPAGES="0:unlimited"
NUMTCPSOCK="unlimited"
NUMFLOCK="unlimited"
NUMPTY="unlimited"
NUMSIGINFO="unlimited"
TCPSNDBUF="unlimited"
TCPRCVBUF="unlimited"
OTHERSOCKBUF="unlimited"
DGRAMRCVBUF="unlimited"
NUMOTHERSOCK="unlimited"
NUMFILE="unlimited"
NUMIPTENT="unlimited"

# Disk quota parameters (in form of softlimit:hardlimit)
DISKSPACE="3115728:3460302"
DISKINODES="60000:660000"
QUOTATIME="0"
QUOTAUGIDLIMIT="0"

# CPU fair scheduler parameter
CPUUNITS="1000"
CPUS="1"
HOSTNAME="a-name.a-site"
SEARCHDOMAIN="our.tld"
NAMESERVER="172.16.0.XX"
IP_ADDRESS="172.16.0.YY"
VE_ROOT="/var/lib/vz/root/$VEID"
VE_PRIVATE="/var/lib/vz/private/$VEID"
OSTEMPLATE="ubuntu-14.04-amd64-our.tar.gz"

Third, I ran the same playbook now with my target host (let’s say vz2.yml modified so):

---
- hosts: targethost
  remote_user: mylogin
  become: yes
  gather_facts: no
  vars:
    ct_vmid: '10'
    ct_vram: '128'
    ct_swap: '128'
    ct_disk: '3'
    ct_vcpu: '1'
    ct_ipv4: '172.16.0.YY'
    ct_ostf: 'ubuntu-14.04-amd64-our.tar'
    my_name: 'a-name'
    my_site: 'a-site'
  tasks:
  - template:
      src: 'ovz.j2'
      dest: '/etc/pve/openvz/ovz.conf-sample'

But it fails with the following messages:

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: OSError: [Errno 38] Function not implemented: '/etc/pve/openvz/.ansible_tmpGQkVGs0508.conf-sample'
fatal: [target]: FAILED! => {"changed": false, "checksum": "ce55188da5f9599a0bb22d4b34e86fce282ca693", "failed": true, "msg": "Failed to replace file: /home/mylogin/.ansible/tmp/ansible-tmp-1504974994.21-218229941602833/source to /etc/pve/openvz/0508.conf-sample: [Errno 38] Function not implemented: '/etc/pve/openvz/.ansible_tmpGQkVGs0508.conf-sample'"}

I can’t see why It cannot replace the file being root, and what may be that function not implemented.
I cannot either see a dependency I’m missing when reading the documentation page

Any hint? Am I facing a bug?

Regards.

It’s probably not a “real” file so it cannot be operated on safely. Try using the usage writes option

Hello,

Thanks for your answer Brian.
I have to admit that I didn’t understand your answer, about not being a “real” file…
On the target machine, I’m able to do a sudo touch /etc/pve/openvz/test1
I can also do a sudo vi /etc/pve/openvz/test2 and write the file with success.
Last, it’s possible to scp file to the target machine.

I finally went to the target and ls -ld /etc/pve/openvz showed a symlink.
In the playbook, setting the parameters unsafe_writes (as you’ve suggested) and follow to yes gives the same error…

I asked a collegua of mine if he can understand what real file means.
According to him, the issue may be related to the fact that /etc/pve here is a fuse mount point.
Strange… Anyway thanks for your kind reply.

Sorry i was not more explicit, but many things on the filesystem can
look like files but not be 'real files' .. either by device, mount
trickery (this last one seems to be the issue in your case) or others.
The 'not implemented' is probably the fuse device driver not allowing
a 'rename' operation with that file as a target, still 'unsafe writes'
should be able to bypass that.