tl;dr: Use a connection plugin to ensure the filesystem is writable.
Voyage Linux is, according to their website a:
Debian derived distribution that is best run on a x86 embedded platforms such as PC Engines ALIX/WRAP, Soekris 45xx/48xx/65xx and Atom-based boards.
So far so good. One of the features of Voyage is that it is designed to run on a CF card (further implementation details are available in the docs). In short, and in order to avoid wear, only a few directories are mounted read-write.
The idea is that if you wish to make changes to configuration or otherwise
write to the filesystem, you run the remountrw
command before making the changes,
and the remountro
command afterwards.
Obviously most of the tasks an IT Automation tool like Ansible will routinely do involve making changes to the state of the system. What we want to do is ensure that the filesystem is writable for the duration of any task that Ansible may be trying to do, and then attempt to put it back at the end.1
There are two obvious ways we can accomplish this:
Manually, with tasks
We can execute tasks at the beginning and end of our playbooks. For example:
- hosts: voyage-hosts
pre_tasks:
- shell: /usr/local/sbin/remountrw
roles:
# ...
post_tasks:
- shell: /usr/local/sbin/remountro
ignore_errors: yes
This is unwieldy. We have to do this in each playbook, it breaks ad-hoc
commands and tagging. In addition, if the play is aborted, the final
remountro
won’t be executed.
With a Connection Type Plugin
Ansible supports various connection methods (default: ssh) to allow for connecting to managed hosts in different ways. We can write a custom Connection Type Plugin which will do the setup and tear-down for us, which means that we never have to remember, and tagging and ad-hoc commands work as designed. Excellent.
The plugin I have come up with can be found in this gist, and all it
does is wrap the built-in ssh
connection plugin and attempt to call
remountrw
and remountro
in the appropriate places.
Simply place this file in your connection plugins directory and set the
ansible_connection
variable to voyage_ssh
on all relevant hosts.
A possible refinement would be to only run the commands if the connection plugin has not yet run them, but this works relatively efficiently and has not gotten in my way over the past several months of use.
-
Notice I said trying - if some other process has a file open for writing, we’ll get a
mount: / is busy
warning. I don’t want this to cause the Ansible run to fail. ↩