| #!/usr/bin/python |
| |
| # ***************************************************************************** |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| # ****************************************************************************** |
| |
| from time import gmtime, strftime |
| from fabric.api import * |
| import argparse |
| import yaml |
| import json |
| import sys |
| import os |
| |
| parser = argparse.ArgumentParser(description="Backup script for DLab configs, keys, certs, jars, database & logs") |
| parser.add_argument('--user', type=str, default='dlab-user', help='System username') |
| parser.add_argument('--dlab_path', type=str, default='/opt/dlab/', help='Path to DLab. Default: /opt/dlab/') |
| parser.add_argument('--configs', type=str, default='skip', help='Comma separated names of config files, like "security.yml", etc. Default: skip. Also available: all') |
| parser.add_argument('--keys', type=str, default='skip', help='Comma separated names of keys, like "user_name.pub". Default: skip. Also available: all') |
| parser.add_argument('--certs', type=str, default='skip', help='Comma separated names of SSL certificates and keys, like "dlab.crt", etc. Default: skip. Also available: all') |
| parser.add_argument('--jars', type=str, default='skip', help='Comma separated names of jar application, like "self-service" (without .jar), etc. Default: skip. Also available: all') |
| parser.add_argument('--db', action='store_true', default=False, help='Mongo DB. Key without arguments. Default: disable') |
| parser.add_argument('--logs', action='store_true', default=False, help='All logs (include docker). Key without arguments. Default: disable') |
| parser.add_argument('--request_id', type=str, default='', help='Uniq request ID for response and backup') |
| parser.add_argument('--result_path', type=str, default='/opt/dlab/tmp/result', help='Path to store backup and response files') |
| args = parser.parse_args() |
| |
| |
| def backup_prepare(): |
| try: |
| local('mkdir {}'.format(temp_folder)) |
| if args.configs != 'skip': |
| local('mkdir -p {0}conf'.format(temp_folder)) |
| if args.keys != 'skip': |
| local('mkdir -p {}keys'.format(temp_folder)) |
| if args.certs != 'skip': |
| local('mkdir -p {}certs'.format(temp_folder)) |
| if args.jars != 'skip': |
| local('mkdir -p {}jars'.format(temp_folder)) |
| if args.logs: |
| local('mkdir -p {}logs'.format(temp_folder)) |
| local('mkdir -p {}logs/docker'.format(temp_folder)) |
| except Exception as err: |
| append_result(error='Failed to create temp folder. {}'.format(str(err))) |
| sys.exit(1) |
| |
| |
| def backup_configs(): |
| try: |
| print('Backup configs: {}'.format(args.configs)) |
| if args.configs == 'skip': |
| print('Skipped config backup.') |
| elif args.configs == 'all': |
| local("find {0}{2} -name '*yml' -exec cp {3} {1}{2} \;".format(args.dlab_path, temp_folder, conf_folder, "{}")) |
| else: |
| for conf_file in args.configs.split(','): |
| local('cp {0}{2}{3} {1}{2}'.format(args.dlab_path, temp_folder, conf_folder, conf_file)) |
| except: |
| append_result(error='Backup configs failed.') |
| sys.exit(1) |
| |
| |
| def backup_keys(): |
| try: |
| print('Backup keys: {}'.format(args.keys)) |
| if args.keys == 'skip': |
| print('Skipped keys backup.') |
| elif args.keys == 'all': |
| local('cp {0}* {1}keys'.format(keys_folder, temp_folder)) |
| else: |
| for key_file in args.keys.split(','): |
| local('cp {0}{1} {2}keys'.format(keys_folder, key_file, temp_folder)) |
| except: |
| append_result(error='Backup keys failed.') |
| sys.exit(1) |
| |
| |
| def backup_certs(): |
| try: |
| print('Backup certs: {}'.format(args.certs)) |
| if args.certs == 'skip': |
| print('Skipped certs backup.') |
| elif args.certs == 'all': |
| for cert in all_certs: |
| local('sudo cp {0}{1} {2}certs'.format(certs_folder, cert, temp_folder)) |
| local('sudo chown {0}:{0} {1}certs/{2} '.format(os_user, temp_folder, cert)) |
| else: |
| for cert in args.certs.split(','): |
| local('cp {0}{1} {2}certs'.format(certs_folder, cert, temp_folder)) |
| local('sudo chown {0}:{0} {1}certs/{2} '.format(os_user, temp_folder, cert)) |
| except: |
| append_result(error='Backup certs failed.') |
| sys.exit(1) |
| |
| |
| def backup_jars(): |
| try: |
| print('Backup jars: {}'.format(args.jars)) |
| if args.jars == 'skip': |
| print('Skipped jars backup.') |
| elif args.jars == 'all': |
| for root, dirs, files in os.walk('{0}{1}'.format(args.dlab_path, jars_folder)): |
| for service in dirs: |
| local('cp -RP {0}{1}{2}* {3}jars'.format(args.dlab_path, jars_folder, service, temp_folder)) |
| else: |
| for service in args.jars.split(','): |
| local('cp -RP {0}{1}{2}* {3}jars'.format(args.dlab_path, jars_folder, service, temp_folder)) |
| except: |
| append_result(error='Backup jars failed.') |
| sys.exit(1) |
| |
| |
| def backup_database(): |
| try: |
| print('Backup db: {}'.format(args.db)) |
| if args.db: |
| ssn_conf = open('{0}{1}ssn.yml'.format(args.dlab_path, conf_folder)).read() |
| data = yaml.load('mongo{}'.format(ssn_conf.split('mongo')[-1])) |
| with settings(hide('running')): |
| local("mongodump --host {0} --port {1} --username {2} --password '{3}' --db={4} --archive={5}mongo.db" \ |
| .format(data['mongo']['host'], data['mongo']['port'], data['mongo']['username'], |
| data['mongo']['password'], data['mongo']['database'], temp_folder)) |
| except: |
| append_result(error='Backup db failed.') |
| sys.exit(1) |
| |
| |
| def backup_logs(): |
| try: |
| print('Backup logs: {}'.format(args.logs)) |
| if args.logs: |
| print('Backup dlab logs') |
| local('cp -R {0}* {1}logs'.format(dlab_logs_folder, temp_folder)) |
| print('Backup docker logs') |
| local("sudo find {0} -name '*log' -exec cp {2} {1}logs/docker \;".format(docker_logs_folder, temp_folder, "{}")) |
| local('sudo chown -R {0}:{0} {1}logs/docker'.format(os_user, temp_folder)) |
| except: |
| append_result(error='Backup logs failed.') |
| print('Backup logs failed.') |
| sys.exit(1) |
| |
| |
| def backup_finalize(): |
| try: |
| print('Compressing all files to archive...') |
| local('cd {0} && tar -zcf {1} .'.format(temp_folder, dest_file)) |
| except Exception as err: |
| append_result(error='Compressing backup failed. {}'.format(str(err))) |
| sys.exit(1) |
| |
| try: |
| print('Clear temp folder...') |
| if temp_folder != '/': |
| local('rm -rf {}'.format(temp_folder)) |
| except Exception as err: |
| append_result(error='Clear temp folder failed. {}'.format(str(err))) |
| sys.exit(1) |
| |
| |
| def append_result(status='failed', error='', backup_file=''): |
| with open(dest_result, 'w') as result: |
| res = {"status": status, |
| "request_id": args.request_id} |
| if status == 'failed': |
| print(error) |
| res['error_message'] = error |
| elif status == 'created': |
| print('Successfully created backup file: {}'.format(backup_file)) |
| res['backup_file'] = backup_file |
| print(json.dumps(res)) |
| result.write(json.dumps(res)) |
| |
| |
| if __name__ == "__main__": |
| backup_time = strftime('%d_%b_%Y_%H-%M-%S', gmtime()) |
| os_user = args.user |
| temp_folder = '/tmp/dlab_backup-{}/'.format(backup_time) |
| conf_folder = 'conf/' |
| keys_folder = '/home/{}/keys/'.format(os_user) |
| certs_folder = '/etc/ssl/certs/' |
| all_certs = ['dhparam.pem', 'dlab.crt', 'dlab.key'] |
| jars_folder = 'webapp/lib/' |
| dlab_logs_folder = '/var/log/dlab/' |
| docker_logs_folder = '/var/lib/docker/containers/' |
| dest_result = '{0}/backup_{1}.json'.format(args.result_path, args.request_id) |
| dest_file = '{0}/backup_{1}.tar.gz'.format(args.result_path, args.request_id) |
| |
| # Backup file section |
| backup_prepare() |
| |
| # Backup section |
| backup_configs() |
| backup_keys() |
| backup_certs() |
| backup_jars() |
| backup_database() |
| backup_logs() |
| |
| # Compressing & cleaning tmp folder |
| backup_finalize() |
| |
| append_result(status='created', error='Backup keys failed.', backup_file=dest_file) |