I have a thing that needed to change this one time, and I don’t want to have to stick around to change it. Not having to be hands-on is the reason I use puppet, and I wanted a way to make puppet do it.

My boss, the president of Ed Wyse & Co, Inc, hasn’t taken a vacation in somewhere around 20 years, nor does he even take a single day completely off. Even on Sunday, he uses having to change the backup drive and getting some exercise in the process as an excuse to ride his bike 37 miles round-trip to the office to be in touch with the business. This week changes everything. This week, one of his children receives their master’s degree in New York. He’s taking a week and changing coasts. As a result, nobody’s going to be around to change the backup drive.

Our solution is simple. It’s USB. Just plug another drive into another port. By knowing in advance which port it’ll be plugged in to, I can use /dev/disk /by-path to select the other port for just Sunday’s backup. Simple.

Well, mostly simple. I use automount to allow us to easily manage changing the drive. Automount has a problem with the colons used in the device name in /dev/disk/by-path and wouldn’t work reliably. To solve this problem, I use puppet to create symlinks to the device, calling it /dev/backup/usb-disk and the partition is /dev/backup/usb-media. It’s been working for years. To solve this I saw two ways of handling it. I could either create two different symlinks and change my backup script to handle choosing which one, or I could just change the symlink on Sunday (technically Saturday night by 11pm). I chose the latter.

In order to accomplish this, I had to make my puppet backup module be able to change based on the day of the week. For that I used an inline template.

class backup::server {
    $day_of_week = inline_template("<%= Time.now.gmtime.wday %>")

This simply loads the variable $day_of_week with a number representing the day of the week, the week starting with Sunday = 0. I chose to use gmtime because I’m 8 hours behind GMT. Since my Sunday backup actually starts on Saturday at 11pm, this allows the links to be changed 7 hours before the backup starts. There are other ways of handling that, of course, but this seemed the simplest. Now I can just test if it’s Sunday.

    # create device links
    if $day_of_week == "0" {
        file { "/dev/backup/usb-disk":
            ensure => '/dev/disk/by-path/pci-0000:00:02.1-usb-0:3:1.0-scsi-0:0:0:0',
            force => true,
        }
        file { "/dev/backup/usb-media":
            ensure => '/dev/disk/by-path/pci-0000:00:02.1-usb-0:3:1.0-scsi-0:0:0:0-part1',
            force => true,
        }
    } else {
        file { "/dev/backup/usb-disk":
            ensure => '/dev/disk/by-path/pci-0000:00:02.1-usb-0:4:1.0-scsi-0:0:0:0',
            force => true,
        }
        file { "/dev/backup/usb-media":
            ensure => '/dev/disk/by-path/pci-0000:00:02.1-usb-0:4:1.0-scsi-0:0:0:0-part1',
            force => true,
        }
    }

There, if it’s Sunday, use the device on usb-0:3 and any other day use usb-0:4.

Now you may be asking, like my good friend Louis, “Why don’t you juse use the schedule type already built in?”

Two reasons. 1, Currently, schedules can only be used to stop a resource from being applied; they cannot cause a resource to be applied when it otherwise wouldn’t be, and they cannot accurately specify a time when a resource should run; and 2 because I couldn’t find that when I was looking for something to do this. Even the IRC channel didn’t offer that suggestion.

It turns out that schedule wouldn’t have worked for this anyway. You can specify a range within a 24 hour day, and a period in minutes, hours, days weeks… but you can’t specify which day. So you can’t tell it to schedule a resource only on Sunday.