I got sick of having to cross-check amtape show against amadmin tape and the
list of tapes that we needed to take offsite, so I wrote the attached
program to do all the hard work for me.  It's probably not 100% perfect but
I tried to make it not rely on our own specific configuration as much as
possible.

Hope someone else finds it useful; if the amanda-hackers want to include it
they're more than welcome.
#!/usr/bin/python

"""looks at the amanda database, and the currently loaded set of tapes, and
decides which tape slots need to come out and what to replace them with.
"""

import sys, os, re, string
from email.MIMEText import MIMEText

debug = 0

def usage():
        print "usage: %s config" % sys.argv[0]

def dprint(s):
        if debug:
                print s

# get the config from the commmand line
try:
        config = sys.argv[1]
except IndexError:
        usage()
        print "please specify the config to print next tapes for"
        sys.exit(1)
        
# the list of tapes in the loader, from amtape $config show
current_tapes = [None] * 10 # retardo magic number
current_re = re.compile('^slot (\d+): date (\d+) label (.*)$')
for line in os.popen4("/usr/sbin/amtape %s show" % config)[1].readlines():
        stuff = current_re.match(line)
        if stuff:
                tape = stuff.group(3)
                slot = int(stuff.group(1))
                dprint("tape %s in slot %s" % (tape, slot))
                current_tapes[slot] = tape
dprint("current tapes: %s" % current_tapes)

# the latest tapes, required to do a complete restore of every DLE
latest_tapes = []
stats_re = re.compile('^stats:')
for line in os.popen4("/usr/sbin/amadmin %s export" % config)[1].readlines():
        if stats_re.match(line):
                tape = line.split(' ')[7][:-1]
                #print tape
                if tape not in latest_tapes:
                        latest_tapes.append(tape)
dprint("latest tapes: %s" % latest_tapes)

# the available tapes, which amanda expects tobe able to write to in the next
# $runtapes days
available_tapes = []
for line in open("/var/lib/amanda/%s/tapelist" % config, 'r').readlines():
        tape = line.split(' ')[1]
        available_tapes.append(tape)
# this file is in reverse order, i.e. the LRU tape is at the bottom
available_tapes.reverse()       
dprint("available_tapes = %s" % available_tapes)

# the next tapes, that amanda expects to use
next_tapes = []
next_re = re.compile("^The next Amanda run should go onto tape ([^ ]+) or a new 
tape.$")
for line in os.popen4("/usr/sbin/amadmin %s tape" % config)[1].readlines():
        tape = next_re.match(line)
        next_tapes.append(tape.group(1))

dprint("next tapes: %s" % next_tapes)

# work out which tapes need to come out
remove_tapes = []
for tape in current_tapes:
        if tape in latest_tapes and tape not in next_tapes:
                remove_tapes.append(tape)

if len(remove_tapes) > 0:
        dprint("these tapes need to come out: %s" % remove_tapes)

        slots = [str(current_tapes.index(tape)) for tape in remove_tapes]

        dprint("slots: %s" % slots)

        # work out which tapes to replace them with
        replace_tapes = []
        for tape in available_tapes:
                if tape not in current_tapes:
                        replace_tapes.append(tape)
                if len(replace_tapes) == len(remove_tapes):
                        break
        
        dprint("these tapes need to go in: %s" % replace_tapes)

        msg = """Hello!  Tape time!

Please remove the tapes in the following slots:

  %(slots)s
  
and replace them with the following tapes:

  %(tapes)s

Thanks!
"""
        filler = {'tapes': string.join(replace_tapes, ', '),
                          'slots': string.join(slots, ', '),
                          }
        
        mail = MIMEText(msg % filler)
        mail['Subject'] = "amanda tape helper for %s" % config
        mail['To'] = "root"
        mail['From'] = "amanda"

        dprint(mail.as_string())

        s = os.popen("/usr/sbin/sendmail -t", 'w')
        s.write(mail.as_string())
        s.close()

Reply via email to