{"id":1320,"date":"2019-03-13T18:59:14","date_gmt":"2019-03-13T23:59:14","guid":{"rendered":"http:\/\/blog.ls-al.com\/?p=1320"},"modified":"2019-03-19T15:37:25","modified_gmt":"2019-03-19T20:37:25","slug":"python-tar-backup-and-purge","status":"publish","type":"post","link":"https:\/\/blog.ls-al.com\/python-tar-backup-and-purge\/","title":{"rendered":"Python Tar Backup and Purge"},"content":{"rendered":"\n
While I was working on a related project to use python to write to cloud object storage and the logic around purging; I jotted down some quick and dirty code here for my reference to build on. Normally I would recommend using the excellent restic program but in this case I am forced to use native API's. <\/p>\n\n\n\n
This serves as a reminder for it is only a very elementary tar plus gzip daily backup and subsequent purging of old backups. Just a test.<\/p>\n\n\n
\n#!\/usr\/bin\/python\n#\n#: Script Name : tarBak.py\n#: Author : Riaan Rossouw\n#: Date Created : March 13, 2019\n#: Date Updated : March 13, 2019\n#: Description : Python Script to manage tar backups\n#: Examples : tarBak.py -t target -f 'folder1,folder2' -c -g GOLD\n#: : tarBak.py --target <backup folder> --folders <folders> --create\n\nimport optparse, os, glob, sys, re, datetime\nimport tarfile\nimport socket\n\n__version__ = '0.9.1'\noptdesc = 'This script is used to manage tar backups of files'\n\nparser = optparse.OptionParser(description=optdesc,version=os.path.basename(__file__) + ' ' + __version__)\nparser.formatter.max_help_position = 50\nparser.add_option('-t', '--target', help='Specify Target', dest='target', action='append')\nparser.add_option('-f', '--folders', help='Specify Folders', dest='folders', action='append')\nparser.add_option('-c', '--create', help='Create a new backup', dest='create', action='store_true',default=False)\nparser.add_option('-p', '--purge', help='Purge older backups per policy', dest='purge', action='store_true',default=False)\nparser.add_option('-g', '--group', help='Policy group', dest='group', action='append')\nparser.add_option('-l', '--list', help='List backups', dest='listall', action='store_true',default=False)\nopts, args = parser.parse_args()\n\ndef make_tarfile(output_filename, source_dirs):\n with tarfile.open(output_filename, "w:gz") as tar:\n for source_dir in source_dirs:\n tar.add(source_dir, arcname=os.path.basename(source_dir))\n\ndef getBackupType(backup_time_created):\n utc,mt = str(backup_time_created).split('.')\n d = datetime.datetime.strptime(utc, '%Y-%m-%d %H:%M:%S').date()\n dt = d.strftime('%a %d %B %Y')\n\n if d.weekday() == 6:\n backup_t = 'WEEKLY'\n elif d.day == 1:\n backup_t = 'MONTHLY'\n elif ( (d.day == 1) and (d.mon == 1) ):\n backup_t = 'YEARLY'\n else:\n backup_t = 'DAILY'\n\n return (backup_t,dt)\n\ndef listBackups(target):\n print ("Listing backup files..")\n\n files = glob.glob(target + "*DAILY*")\n files.sort(key=os.path.getmtime, reverse=True)\n\n for file in files:\n print file\n \ndef purgeBackups(target, group):\n print ("Purging backup files..this needs testing and more logic for SILVER and BRONZE policies?")\n\n files = glob.glob(target + "*.tgz*")\n files.sort(key=os.path.getmtime, reverse=True)\n daily = 0\n weekly = 0\n monthly = 0\n yearly = 0\n \n for file in files:\n comment = ""\n if ( ("DAILY" in file) or ("WEEKLY" in file) or ("MONTHLY" in file) or ("YEARLY" in file) ):\n #t = file.split("-")[0]\n sub = re.search('files-(.+?)-2019', file)\n #print sub\n t = sub.group(1)\n else:\n t = "MANUAL"\n\n if t == "DAILY":\n comment = "DAILY"\n daily = daily + 1\n if daily > 7:\n comment = comment + " this one is more than 7 deleting"\n os.remove(file)\n elif t == "WEEKLY":\n comment = "Sun"\n weekly = weekly + 1\n if weekly > 4:\n comment = comment + " this one is more than 4 deleting"\n os.remove(file)\n elif t == "MONTHLY":\n comment = "01"\n monthly = monthly + 1\n if monthly > 12:\n comment = comment + " this one is more than 12 deleting"\n os.remove(file)\n elif t == "YEARLY":\n comment = "01"\n yearly = yearly + 1\n if yearly > 5:\n comment = comment + " this one is more than 5 deleting"\n os.remove(file)\n else:\n comment = " manual snapshot not purging"\n \n if "this one " in comment:\n print ('DELETE: {:25}: {:25}'.format(file, comment) )\n\ndef createBackup(target, folders, group):\n print ("creating backup of " + str(folders))\n hostname = socket.gethostname()\n creationDate = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.0")\n t,ds = getBackupType(creationDate)\n BackupName = target + "\/" + hostname + '-files-' + t + "-" + datetime.datetime.now().strftime("%Y%m%d-%H%MCST") + '.tgz'\n\n proceed = "SNAPSHOT NOT NEEDED AT THIS TIME PER THE POLICY"\n if ( group == "BRONZE") and ( (t == "MONTHLY") or (t == "YEARLY") ):\n proceed = "CLEAR TO SNAP" \n elif ( group == "SILVER" and (t == "WEEKLY") or (t == "MONTHLY" ) or (t == "YEARLY") ):\n proceed = "CLEAR TO SNAP" \n elif group == "GOLD":\n proceed = "CLEAR TO SNAP" \n else:\n result = proceed\n \n make_tarfile(BackupName, folders)\n\ndef main():\n if opts.target:\n target = opts.target[0]\n else:\n print ("\\n\\n must specify target folder")\n exit(0)\n\n if opts.listall:\n listBackups(target)\n else:\n if opts.create:\n if opts.folders:\n folders = opts.folders[0].split(',')\n else:\n print ("\\n\\n must specify folders")\n exit(0)\n createBackup(target, folders, opts.group[0])\n\n if opts.purge:\n purgeBackups(target, opts.group[0])\n\nif __name__ == '__main__':\n main()\n<\/pre><\/div>\n\n\nAnd running it like this:<\/p>\n\n\n
\n$ python tarBak.py -t \/tmp\/MyBackups\/ -f '\/home\/rrosso,\/var\/log\/syslog' -g GOLD -c\ncreating backup of ['\/home\/rrosso', '\/var\/log\/syslog']\n\n$ python tarBak.py -t \/tmp\/MyBackups\/ -p -g GOLD\nPurging backup files..this needs testing and more logic for SILVER and BRONZE policies?\nDELETE: \/tmp\/MyBackups\/xubuntu32-files-DAILY-20190313-1420CST.tgz: DAILY this one is more than 7 deleting\n<\/pre><\/div>\n\n\n$ crontab -l | tail -1\n0 5 * * * cd \/Src\/tarBak\/ ; python tarBak.py -t \/MyBackups\/ -f '\/home\/rrosso,\/var\/spool\/syslog' -c -p -g GOLD 2>&1\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"While I was working on a related project to use python to write to cloud object storage and the logic<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1320","post","type-post","status-publish","format-standard","hentry","category-backups"],"_links":{"self":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/posts\/1320","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/comments?post=1320"}],"version-history":[{"count":0,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/posts\/1320\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/media?parent=1320"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/categories?post=1320"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ls-al.com\/wp-json\/wp\/v2\/tags?post=1320"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}