|
| 1 | +import os |
| 2 | +import subprocess |
| 3 | +from django.conf import settings |
| 4 | +from azure.storage.blob import BlockBlobService |
| 5 | + |
| 6 | + |
| 7 | +class BackupSystem: |
| 8 | + |
| 9 | + def __init__(self): |
| 10 | + self.blob_service_client: BlockBlobService |
| 11 | + default_config = settings.DATABASES.get('default') |
| 12 | + self.postgres_host = default_config.get('HOST') |
| 13 | + self.postgres_port = default_config.get('PORT') |
| 14 | + self.postgres_db = default_config.get('NAME') |
| 15 | + self.postgres_user = default_config.get('USER') |
| 16 | + self.postgres_password = default_config.get('PASSWORD') |
| 17 | + self.azure_credential = settings.AZURE_CREDENTIAL |
| 18 | + self.azure_container = settings.AZURE_CONTAINER |
| 19 | + self.azure_account_name = settings.AZURE_ACCOUNT_NAME |
| 20 | + self.azure_backup_folder_name = settings.AZURE_BACKUP_FOLDER_NAME |
| 21 | + self.blob_service_client = BlockBlobService(account_name=self.azure_account_name, |
| 22 | + account_key=self.azure_credential) |
| 23 | + |
| 24 | + def get_list_of_blobs(self): |
| 25 | + return self.blob_service_client.list_blobs(container_name=self.azure_container, |
| 26 | + prefix=self.azure_backup_folder_name + '/') |
| 27 | + |
| 28 | + def download_blob_file(self, name): |
| 29 | + return self.blob_service_client.get_blob_to_bytes(container_name=self.azure_container, |
| 30 | + blob_name=self.azure_backup_folder_name + "/" + name).content |
| 31 | + |
| 32 | + def upload_blob_file(self, name, data): |
| 33 | + self.blob_service_client.create_blob_from_bytes(container_name=self.azure_container, |
| 34 | + blob_name=self.azure_backup_folder_name + "/" + name, |
| 35 | + blob=data) |
| 36 | + |
| 37 | + def backup_postgres_db(self, verbose): |
| 38 | + """ |
| 39 | + Backup postgres db to a file. |
| 40 | + """ |
| 41 | + if verbose: |
| 42 | + try: |
| 43 | + process = subprocess.Popen( |
| 44 | + ['pg_dump', |
| 45 | + '-Fc', |
| 46 | + '-v'], |
| 47 | + shell=True, |
| 48 | + env={ |
| 49 | + 'PGUSER': self.postgres_user, |
| 50 | + 'PGPASSWORD': self.postgres_password, |
| 51 | + 'PGDATABASE': self.postgres_db, |
| 52 | + 'PGPORT': str(self.postgres_port), |
| 53 | + 'PGHOST': self.postgres_host |
| 54 | + }, |
| 55 | + stdout=subprocess.PIPE |
| 56 | + ) |
| 57 | + output = process.communicate()[0] |
| 58 | + if int(process.returncode) != 0: |
| 59 | + print('Command failed. Return code : {}'.format(process.returncode)) |
| 60 | + exit(1) |
| 61 | + return output |
| 62 | + except Exception as e: |
| 63 | + print(e) |
| 64 | + exit(1) |
| 65 | + else: |
| 66 | + print('{}:{}@{}:{}/{}'.format(self.postgres_user, |
| 67 | + self.postgres_password, |
| 68 | + self.postgres_host, |
| 69 | + self.postgres_port, |
| 70 | + self.postgres_db)) |
| 71 | + try: |
| 72 | + process = subprocess.Popen( |
| 73 | + ['pg_dump', |
| 74 | + '-Fc'], |
| 75 | + shell=True, |
| 76 | + env={ |
| 77 | + 'PGUSER': self.postgres_user, |
| 78 | + 'PGPASSWORD': self.postgres_password, |
| 79 | + 'PGDATABASE': self.postgres_db, |
| 80 | + 'PGPORT': str(self.postgres_port), |
| 81 | + 'PGHOST': self.postgres_host |
| 82 | + }, |
| 83 | + stdout=subprocess.PIPE |
| 84 | + ) |
| 85 | + output = process.communicate()[0] |
| 86 | + if process.returncode != 0: |
| 87 | + print('Command failed. Return code : {}'.format(process.returncode)) |
| 88 | + exit(1) |
| 89 | + return output |
| 90 | + except Exception as e: |
| 91 | + print(e) |
| 92 | + exit(1) |
| 93 | + |
| 94 | + def restore_postgres_db(self, filepath): |
| 95 | + """Restore postgres db from a file.""" |
| 96 | + try: |
| 97 | + d = dict(os.environ) |
| 98 | + d['PGPASSFILE'] = filepath |
| 99 | + d['PGPASSWORD'] = self.postgres_password |
| 100 | + host = self.postgres_host |
| 101 | + |
| 102 | + process = subprocess.Popen(['psql', |
| 103 | + "-f%s" % filepath, |
| 104 | + "-d%s" % self.postgres_db, |
| 105 | + "-h%s" % host, |
| 106 | + "-U%s" % self.postgres_user |
| 107 | + ], env=d, |
| 108 | + stdout=subprocess.PIPE, stderr=subprocess.DEVNULL |
| 109 | + ) |
| 110 | + process.wait() |
| 111 | + if process.returncode != 0: |
| 112 | + print('Command failed. Return code : {}'.format(process.returncode)) |
| 113 | + exit(1) |
| 114 | + return process.returncode |
| 115 | + except Exception as e: |
| 116 | + print("Issue with the db restore : {}".format(e)) |
0 commit comments