Advertisement
Guest User

Untitled

a guest
Mar 22nd, 2020
358
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.58 KB | None | 0 0
  1. #!/usr/bin/python3.5
  2.  
  3. import subprocess, sys, re, argparse, stat, os
  4. from subprocess import DEVNULL, PIPE
  5.  
  6. # use a prefix to create snapshots
  7. SNAPSHOT_PREFIX="borg_snapshot"
  8.  
  9. def get_lv_details(target):
  10.     # fetch output of lvdisplay and return a tuple of (vg_name, lv_name, lv_size)
  11.     vg_name = lv_name = lv_size = None
  12.     process = subprocess.Popen(["lvdisplay", "--units", "K", target], stdout=PIPE, stderr=DEVNULL, universal_newlines=True)
  13.     if process == 0:
  14.         return (None, None, None)
  15.     output, errors = process.communicate(timeout=5)
  16.     for line in output.split("\n"):
  17.         result = re.search('\s+VG\sName\s+([^$]+)$', line)
  18.         if result is not None:
  19.             vg_name = result.group(1)
  20.             continue
  21.         result = re.search('\s+LV\sName\s+([^$]+)$', line)
  22.         if result is not None:
  23.             lv_name = result.group(1)
  24.             continue
  25.         result = re.search('\s+LV\sSize\s+([\d]+)[^\d]', line)
  26.         if result is not None:
  27.             lv_size = int(result.group(1))
  28.             continue
  29.  
  30.     if vg_name is not None and lv_name is not None and lv_size is not None:
  31.         return (vg_name, lv_name, lv_size)
  32.     else:
  33.         return (None, None, None)
  34.  
  35. def lv_exists(path):
  36.     # check if a block devices exists, return True or False
  37.     try:
  38.         return stat.S_ISBLK(os.stat(path).st_mode)
  39.     except:
  40.         return False
  41.  
  42. def cleanup(snapshot_list):
  43.     # cleanup all snapshots
  44.     for i in snapshot_list:
  45.         remove_snapshot(i)
  46.  
  47. def remove_snapshot(target):
  48.     # remove snapshot, check if it exists and if the snapshot prefix is included in the name
  49.     if lv_exists(target['snapshot']) and SNAPSHOT_PREFIX in target['snapshot']:
  50.         lvremove = ["lvremove", "-f", target['snapshot']]
  51.         result = subprocess.run(lvremove, stdout=DEVNULL, stderr=DEVNULL)
  52.         if result.returncode == 0:
  53.             print ("Snapshot removal succesful --", ' '.join(lvremove))
  54.         else:
  55.             print ("Snapshot removal failed --", ' '.join(lvremove))
  56.     else:
  57.         print ("Snapshot removal failed -- Snapshot", target['snapshot'], "not found")
  58.  
  59. def create_snapshot(target):
  60.     # create snapshot
  61.     lvcreate = ["lvcreate", "-s", "-L", str(target['snapshot_size']) + "K", "-n", target['snapshot_name'], target['target']]
  62.     result = subprocess.run(lvcreate, stdout=DEVNULL, stderr=DEVNULL)
  63.     if result.returncode == 0:
  64.         print ("Snapshot creation successful --" , ' '.join(lvcreate))
  65.         return target['snapshot_name']
  66.     else:
  67.         print ("Snapshot creation failed --" , ' '.join(lvcreate))
  68.         return None
  69.  
  70. def create_target_list(targets, snapshot_percentage):
  71.     # create a list of dicts containing all backup targets with relevant informations
  72.     target_list = []
  73.     for i in targets:
  74.         pv_name, lv_name, lv_size = get_lv_details(i)
  75.         # if lv does not exist stop the backup
  76.         if pv_name == None:
  77.             print ('Backup stopped, target', i, 'does not exist.')
  78.             sys.exit(75)
  79.         snapshot = '/'.join(i.split('/')[:-1] + [SNAPSHOT_PREFIX + '_' + lv_name])
  80.         snapshot_size = int(lv_size * (snapshot_percentage / 100))
  81.         target_list.append({'target': i,
  82.                             'pv_name': pv_name,
  83.                             'lv_name': lv_name,
  84.                             'snapshot': snapshot,
  85.                             'snapshot_size': snapshot_size,
  86.                             'snapshot_name': SNAPSHOT_PREFIX + '_' + lv_name})
  87.     return target_list
  88.  
  89. def main():
  90.     parser = argparse.ArgumentParser()
  91.     subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name')
  92.     parser_a = subparsers.add_parser('create', help='Create LV Snapshots')
  93.     parser_a.add_argument('--lv', required=True, action='append', dest='lv')
  94.     parser_a.add_argument('-s', action='append', dest='snapshot_percentage', default='10')
  95.     parser_b = subparsers.add_parser('remove', help='Remove LV Snapshots')
  96.     parser_b.add_argument('--lv', required=True, action='append', dest='lv')
  97.     args = parser.parse_args()
  98.  
  99.     if len(args.lv) > 0:
  100.         target_list = create_target_list(args.lv, int(args.snapshot_percentage) if hasattr(args, 'snapshot_percentage') else 0)
  101.  
  102.     if args.subparser_name == 'create':
  103.         # create snapshots
  104.         for i in target_list:
  105.             result = create_snapshot(i)
  106.             if result is None:
  107.                 cleanup(target_list)
  108.                 sys.exit(75)
  109.     elif args.subparser_name == 'remove':
  110.         cleanup(target_list)
  111.  
  112. if __name__ == "__main__":
  113.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement