Delegated cronjobs with time vars per target host

157 views
Skip to first unread message

Martin Božič

unread,
Apr 2, 2014, 7:29:09 PM4/2/14
to ansible...@googlegroups.com
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
-----------------------------
- name: weekly rsnapshot cron
cron: name="rsnap {{ ansible_fqdn }} (upravlja Ansible)"
weekday={{ rsnap_weekly_day }} hour={{ rsnap_weekly_hour }}
minute={{ rsnap_weekly_min }} user="root"
job="rsnapshot -c /etc/rsnapshot.d/{{ ansible_fqdn }}.conf weekly"
cron_file="rsnap-{{ ansible_fqdn }}"
delegate_to: backuphost

FILE: host_vars/newhost
--------------------
rsnap_hourly_min: 12
rsnap_daily_min: 45
rsnap_daily_hour: 1
rsnap_weekly_min: 30
rsnap_weekly_hour: 21
rsnap_weekly_day: 3

What happens is that backuphost picks up the var of newhost and then cries
foul:

fatal: [backuphost] => One or more undefined variables: 'rsnap_daily_hour'
is undefined

I'm running out of ideas how I could do it. I've looked into several loops but
I'm still a beginner with Ansible and YAML syntax, so if anyone has any idea how
this delegation could work I'd really appreciate it!

Regards,
Martin

Brent Langston

unread,
Apr 3, 2014, 11:39:04 PM4/3/14
to ansible...@googlegroups.com
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

--------
Brent
--------




--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-project+unsubscribe@googlegroups.com.
To post to this group, send email to ansible-project@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/20140402232909.GA12514%40gmail.com.
For more options, visit https://groups.google.com/d/optout.

Brian Green

unread,
Apr 3, 2014, 11:49:27 PM4/3/14
to ansible...@googlegroups.com
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

Michael DeHaan

unread,
Apr 4, 2014, 11:08:13 AM4/4/14
to ansible...@googlegroups.com
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.







--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/a6e47e28-59ff-428c-9407-e8d38b1fb96e%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages