Delegated cronjobs with time vars per target host

Hi,

I want to dynamically every new host to the backup server with rsnapshot. I have no problems putting SSH keys on backup target hosts and putting a template and exclude config for the target host into /etc/rsnapshot.d on backup host.

The problem is when I try to add the rsnapshot cronjob for the new host. And here's the trick - I'm trying to add different times for each host because I don't want them to all hit the backup disk at the same time. So I figured I could put several cron time vars for each host in host_vars/ directory. Here's an example of what I'm trying to pull-off with cron module:

FILE: roles/common/backup.yml

I did this a while back, thinking I’d replace it with something more elegant when I have time… honestly, it’s been working so well, I haven’t thought about it again, until you reminded me.

I have a script saved in my ansible git repo: $GIT/ansible/bin/cron_scheduler.sh

#!/bin/bash

PATH=/bin:/usr/bin

helptext() {
echo “Usage: $0 -i ip_address -f frequency” >&2
echo “Example: $0 -i 10.10.5.160 -f 15 # run once every 15 minutes” >&2
exit 1
}

if [ “$#” -ne 4 ] || [ “$1” = “-h” ] || [ “$1” = “–help” ]; then
helptext
fi

while getopts i:f: option
do
case “${option}”
in
i) ip_address=${OPTARG};;
f) frequency=${OPTARG};;
*) helptext;;
esac
done

decimal=$(echo $ip_address | sed ‘s/./+/g’ | bc)
ip_rand=$(expr $decimal % $frequency)

x=$ip_rand
declare -a minutes=$ip_rand

count=0
while [ $x -lt 60 ]
do
next=$(expr “${minutes[$count]}” + $frequency)
if [ $next -lt 60 ] ; then
minutes=(“${minutes[@]}” “$next”)
fi
(( count++ ))
x=$next
done

echo -n ${minutes[@]} | tr " " ,

So running this:

cron_scheduler.sh -i 10.10.5.160 -f 15

results in this output:
5,20,35,50
(every 15 minutes)

So just decide how frequently you want to schedule the task, and pass in the IP address. voila.

  • name: pick a minute to run example
    script: bin/cron_scheduler.sh -i {{ ansible_default_ipv4.address }} -f 10
    register: cron_minutes

  • name: configure example
    template: src=example/example.cron dest=/etc/cron.d/example.cron owner=root group=root mode=0644

and the template would have something like this:

{{cron_minutes.stdout}} * * * * root /usr/local/bin/example

Where are you using the rsnap_daily_hour variable? The task you pasted doesn’t have it included.

The vars file you included is host specific for ‘newhost’, if you are trying to use those variables in a play involving the backuphost (not a delegated_to task), you’ll either need to use hostvars or restructure your variables in a different manner.

So, using hostvars, accessing rsnap_daily_hour in a play on backuphost would be {{ hostvars[‘newhost’][‘rsnap_daily_hour’] }}.

If it was me, I’d use group_vars with separate groups for each time slot, and then make the backuphost a member of each time slot group. That may or may not scale well, but I try to avoid using hostvars if at all possible. I’d change my mind if I was in an environment absolutely destined to remain small & stable of course.

Brian

There have been pull requests for a random Jinja2 filter, but they were pretty complicated in terms of syntax (i.e. not pretty syntax wise) and I wanted to see them pared down.