123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import os
- import dropbox
- import docker
- from dropbox.files import WriteMode
- from dropbox.exceptions import ApiError, AuthError
- from docker.errors import NotFound, APIError
- from io import BytesIO
- from datetime import datetime, timedelta
- import time
- BACKUP_AGE = 30
- DOCKER_SOCK = 'unix://var/run/docker.sock'
- POSTGRES_CONTAINER = 'postgres'
- POSTGRES_USER = 'postgres'
- ODOO_IMAGE = 'odoo/robert:8.0'
- ODOO_PATH = '/opt/odoo'
- '''
- '''
- def get_dropbox_connection():
- token_file = open('token', 'r')
- token_str = token_file.read()
- token_file.close()
- dbx = dropbox.Dropbox(token_str)
- try:
- dbx.users_get_current_account()
- return dbx
- except AuthError:
- return None
- '''
- '''
- def delete_dropbox_old_folder(dbx=None):
- if dbx == None:
- return False
- try:
- result = dbx.files_list_folder('')
- date_now = datetime.now()
-
- for folder in result.entries:
- create_date = datetime.strptime(folder.name, '%Y_%m_%d')
- if create_date <= date_now - timedelta(BACKUP_AGE):
- # dbx.files_delete(folder.path_lower)
- dbx.files_permanently_delete(folder.path_lower)
- return True
- except ApiError:
- return False
-
- '''
- '''
- def create_folder_path():
- return '/' + time.strftime('%Y_%m_%d')
- '''
- '''
- def create_dropbox_folder(folder_path, dbx=None):
- if dbx == None:
- return False
- try:
- result = dbx.files_search('', folder_path)
-
- if len(result.matches) > 0:
- return False
- dbx.files_create_folder_v2(folder_path)
- return True
- except ApiError:
- return False
- '''
- '''
- def get_docker_client():
- return docker.DockerClient(base_url=DOCKER_SOCK)
- '''
- '''
- def get_pg_container(docker_client):
- try:
- pg_container = docker_client.containers.get(POSTGRES_CONTAINER)
- return pg_container
- except (NotFound, APIError):
- return None
- '''
- '''
- def list_postgres_databases(docker_client):
- pg_container = get_pg_container(docker_client)
- if pg_container is None or pg_container.status == 'exited':
- return []
-
- command = "psql -U %s -t -c 'SELECT datname FROM pg_database'" % POSTGRES_USER
- result = pg_container.exec_run(command)
- if result.exit_code == -1:
- return []
- output = result.output.split('\n')
- output = map(lambda x: x.strip(), output)
- output = filter(lambda x: x != '', output)
- BLACK_LIST = ['postgres', 'template1', 'template0']
- output = filter(lambda x: x not in BLACK_LIST, output)
- return output
- '''
- '''
- def filter_databases_by_active_containers(databases, docker_client):
- try:
- containers = docker_client.containers.list(filters={'status': 'running', 'ancestor': ODOO_IMAGE})
- containers_name = map(lambda x: x.name, containers)
- return filter(lambda x: x in containers_name, databases)
- except APIError:
- return []
- '''
- '''
- def create_postgres_backup(database, docker_client):
- pg_container = get_pg_container(docker_client)
- if pg_container is None or pg_container.status == 'exited':
- return (False, None)
- tmp_file = '%s_%s.tar' % (database, time.strftime('%Y-%m-%d_%H:%M:%S'))
- command = 'pg_dump -U %s -d %s -F tar -C -b -c -f %s' % (POSTGRES_USER, database, tmp_file)
-
- result = pg_container.exec_run(command)
- if result.exit_code == -1:
- (False, tmp_file)
-
- return (True, tmp_file)
- '''
- '''
- def create_odoo_filestore_backup():
- pass
- '''
- '''
- def upload_to_dropbox(backup_file_name, backup_path, docket_client, dbx):
- pg_container = get_pg_container(docket_client)
- if pg_container is None or pg_container.status == 'exited':
- return False
- try:
- (backup_file, _) = pg_container.get_archive('/%s' % backup_file_name)
- raw_data = BytesIO()
- for chunk in backup_file:
- raw_data.write(chunk)
- raw_data.seek(0)
- remote_path = ('%s/%s') % (backup_path, backup_file_name)
- dbx.files_upload(raw_data.read(), remote_path, mode=WriteMode('overwrite'))
- raw_data.close()
- return True
- except (APIError, ApiError):
- return False
- '''
- '''
- def delete_backup_file(backup_name, docker_client):
- pg_container = get_pg_container(docker_client)
- if pg_container is None or pg_container.status == 'exited':
- return False
-
- command = 'rm %s' % backup_name
- result = pg_container.exec_run(command)
- if result.exit_code == -1:
- return False
- return True
-
- '''
- '''
- def run_backup():
- # 1. get connection
- dbx = get_dropbox_connection()
- # 2. delete old folders
- delete_dropbox_old_folder(dbx)
- # 4. create folder name
- folder_path = create_folder_path()
- # 4. create dropbox folder
- create_dropbox_folder(folder_path, dbx)
- # 5. get docker client
- docker_client = get_docker_client()
- # 6. list database
- databases = list_postgres_databases(docker_client)
- # 7. filter databases by active containers
- databases = filter_databases_by_active_containers(databases, docker_client)
- # 8. backup databases
- for db in databases:
- (backup_ok, backup_name) = create_postgres_backup(db, docker_client)
- if not backup_ok:
- if backup_name:
- delete_backup_file(backup_name, docker_client)
- continue
-
- upload_to_dropbox(backup_name, folder_path, docker_client, dbx)
- delete_backup_file(backup_name, docker_client)
- time.sleep(1)
- docker_client.close()
- run_backup()
|