#!/usr/bin/python import yaml import subprocess import StringIO import os import sys import difflib from optparse import OptionParser parser = OptionParser() parser.add_option('-d', '--debug', action='store_true', default=False, help="Debug output") parser.add_option('-y', '--yes', action='store_true', default=False, help="Always answer yes to questions (USE WITH CAUTION)") parser.add_option('-v', '--verbose', action='store_true', default=False, help="Show all checked backups") (options, args) = parser.parse_args() def print_debug(msg): if options.debug == True: print msg def run_command(cmd): print(cmd) if not options.debug == True: subprocess.call(cmd, shell=True) def print_verbose(msg): if options.verbose == True: print msg def question_yesno(question, print_current = False): if print_current: print('Host: %s.%s' % (host['host'], host['domain'])) print('Backup: %s' % backup['name']) if options.yes == True: print '%s' % question return True ans = raw_input('%s [y/N] ' % question) if ans == 'y': return True else: return False dirvish_conf_path = '/etc/dirvish' config_data = yaml.load(file('/etc/dirvish/dirvish.yaml', 'r')) list_banks = [] list_vaults = [] for host in config_data['hosts']: hostname = '%s.%s' % (host['host'], host['domain']) #hostname_filename = '%s_%s' % (host['host'], host['domain'].replace('.','_')) hostname_filename = hostname for backup in host['backups']: #lvmname = '%s-%s' % (hostname_filename, backup['name']) lvmname = '%s_%sLV' % (hostname_filename, backup['name']) backup_name = '%s_%s' % (host['host'], backup['name']) backup_path = '/backups/%s/%s' % (hostname_filename, backup_name) backup_device = '/dev/%s/%s' % (backup['volumegroup'], lvmname) # IWT # next 2 lines necessary since /dev/mapper is part of mount path mount_backup_device = '/dev/mapper/%s-%s' % (backup['volumegroup'], lvmname) print_debug('mount_backup_device=['+mount_backup_device+']') dirvish_config = StringIO.StringIO() print_verbose('Host: %s.%s' % (host['host'], host['domain'])) print_verbose('Backup: %s' % backup['name']) #print 'Mount: /dev/%s/%s -> %s' % (backup['volumegroup'], lvmname, backup_path) print_debug('checking if logical volume exists: %s' % lvmname) lvm,lvmerr = subprocess.Popen('find /dev/%s -name %s' % (backup['volumegroup'], lvmname), shell=True, stdout=subprocess.PIPE).communicate() print_debug('lvm=[%s]' % lvm) if lvm == "": print_debug("I don't think the logical volume exists!?") if question_yesno("Create the LV?", print_current = True): question_size = raw_input("Size of the LV? (In gigabytes, defaults to 5) [e.g. 5] ") if question_size == '': question_size = "5" run_command('lvcreate --size %sG --name %s %s' % (question_size, lvmname, backup['volumegroup'])) run_command('mkfs.ext3 %s' % backup_device) else: continue else: print_debug("I think the logical volume exists!?") print_debug('looking for entry in /etc/fstab') fstabs = open('/etc/fstab', 'r').readlines() found_fstab = False for fstab in fstabs: if fstab.split(' ')[0] == backup_device: print_debug('found it!') found_fstab = True print_debug(repr(fstab)) if fstab.split(' ')[1] != backup_path: print_debug('but its not right..') else: print_debug('and its correctly in fstab!') if found_fstab == False: print_debug('must not be fstabbed..') if question_yesno("Create the fstab entry?", print_current=True): run_command('echo "%s %s ext3 defaults 0 0 " >> /etc/fstab' % (backup_device, backup_path)) else: continue print_debug('looking for mount dev=[' + mount_backup_device +'] mnt=[' + backup_path + ']') mounts = open('/proc/mounts', 'r').readlines() found_mount = False print_debug('mount_backup_device = [' + mount_backup_device + ']') mnt_backup_device = mount_backup_device.replace('mapper/', '') mnt_backup_device = mnt_backup_device.replace('VG-', 'VG/') print_debug('mnt_backup_device = [' + mnt_backup_device + ']') for mount in mounts: print_debug('mount = ' + mount ) # print repr(mount.split(' ')[0]), repr('/dev/%s/%s' % (backup['volumegroup'], lvmname)) if (mount.split(' ')[0] == mnt_backup_device ) or (mount.split(' ')[0] == mount_backup_device): print_debug('found it! [' + mount + ']') found_mount = True print_debug(repr(mount)) if mount.split(' ')[1] != backup_path: print_debug('but its not right..') else: print_debug('and mounted correctly!') else: print_debug('mount not found look=[' + mnt_backup_device + '] fnd=[' + mount.split(' ')[0] + ']') if found_mount == False: print_debug('must not be mounted..') if question_yesno("Mount the filesystem?", print_current=True): run_command('mkdir -p %s' % backup_path) run_command('touch %s/fs.not.mounted' % backup_path) run_command('mount %s' % backup_path) else: continue print_debug('now looking for dirvish config at %s/dirvish' % backup_path) if os.path.exists('%s/dirvish' % backup_path): print_debug('there it is') else: print_debug('it appears the dirvish config path does not exist..') if question_yesno("Create dirvish configuration files?", print_current=True): run_command('mkdir %s/dirvish' % backup_path) if os.path.isfile('%s/dirvish/default.conf' % backup_path): print_debug('found the default.conf file') else: print_debug('nuts, cant find the file') print_debug('building what i think is the config file') #print >>dirvish_config, 'Config file: %s/dirvish/dirvish.conf' % (backup_path) print >>dirvish_config, 'client: root@%s\ntree: %s' % (hostname, backup['remotepath']) try: for host_k,host_v in host['extra'].items(): if type(host_v) is list: print >>dirvish_config, '%s: ' % (host_k) for val in host_v: print >>dirvish_config, ' %s' % val else: print >>dirvish_config, '%s: %s' % (host_k, host_v) except KeyError: pass try: for backup_k,backup_v in backup['extra'].items(): if type(backup_v) is list: print >>dirvish_config, '%s: ' % (backup_k) for val in backup_v: print >>dirvish_config, ' %s' % val else: print >>dirvish_config, '%s: %s' % (backup_k, backup_v) except KeyError: pass print_debug('looking for existing config file..') try: backup_conf = open('%s/dirvish/default.conf' % backup_path).readlines() except IOError: print_debug('config file not there!?!! okay using nothing') backup_conf = [] print_debug('diffing existing config with what I generated..') #print backup_conf #print dirvish_config.getvalue().splitlines(True) diff_lines = 0 diff = StringIO.StringIO() for line in difflib.unified_diff(backup_conf, dirvish_config.getvalue().splitlines(True),fromfile='%s/dirvish/default.conf' % backup_path,tofile='dconf.py'): diff.write(line) diff_lines = diff_lines + 1 if diff_lines > 0: sys.stdout.write(diff.getvalue()) if question_yesno("Replace existing config with generated one?", print_current=True): run_command('mv %s/dirvish/default.conf %s/dirvish/default.conf.bak 1>/dev/null 2>/dev/null' % (backup_path, backup_path)) print 'writing conf to %s/dirvish/default.conf' % backup_path write_conf = open('%s/dirvish/default.conf' % backup_path, 'w') write_conf.writelines(dirvish_config.getvalue()) write_conf.close() else: continue else: print_debug('config file looks good!') print_debug('okay, have we run dirvish befoer?') if os.path.isfile('%s/dirvish/default.hist' % backup_path): print_debug('wow this looks like a legit backup and everything..' ) else: print_debug('looks blank... prob need to run init..') print 'Run: dirvish --vault %s --init' % backup_name print ' ' print_verbose('This backup is configured correctly') bank = '/backups/%s' % (hostname_filename) if bank not in list_banks: list_banks.append('/backups/%s' % (hostname_filename)) list_vaults.append(backup_name) print_debug('add banks and vaults in') banks = StringIO.StringIO() vaults = StringIO.StringIO() print >>banks, 'bank:' for bank in list_banks: print >>banks, ' %s' % bank print >>vaults, 'Runall:' for vault in list_vaults: print >>vaults, ' %s' % vault write_banks = open('%s/bank.conf' % dirvish_conf_path, 'w') write_banks.writelines(banks.getvalue()) write_banks.close() write_vaults = open('%s/vault.conf' % dirvish_conf_path, 'w') write_vaults.writelines(vaults.getvalue()) write_vaults.close()