def reset_slave(master_db_args, slave_db_args, master_cnf_dir, master_os_args, slave_os_args, slave_cnf_dir): rds_version = get_all(master_db_args, "show variables like 'rds_version';") if rds_version == []: check_mas_cnf_exsits = ssh_input_noprint( master_os_args, f"ls {master_cnf_dir}_ori.bak")[0] if " cannot access " not in check_mas_cnf_exsits: ssh_input(master_os_args, f"mv {master_cnf_dir}_ori.bak {master_cnf_dir}") else: pass check_sla_cnf_exsits = ssh_input_noprint(slave_os_args, f"ls {slave_cnf_dir}_ori.bak")[0] if " cannot access " not in check_sla_cnf_exsits: ssh_input(slave_os_args, f"mv {slave_cnf_dir}_ori.bak {slave_cnf_dir}") set_readonly_master(master_db_args, 'off', master_cnf_dir, master_os_args) set_readonly_master(slave_db_args, 'off', slave_cnf_dir, slave_os_args) select_drop_sql = '''select concat("drop user '",user,"'@'",host,"';") from mysql.user where user like 'mcbak_%' ;''' select_drop_res_m = get_all(master_db_args, select_drop_sql) for sql in select_drop_res_m: run_noprint(master_db_args, sql[0]) select_drop_res_s = get_all(slave_db_args, select_drop_sql) for sql_s in select_drop_res_s: run_noprint(slave_db_args, sql_s[0]) set_con_warn = "SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN;" set_con_off = "SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = OFF;" set_mode_off_p = "SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;" set_mode_on_p = "SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;" set_mode_off = "SET @@GLOBAL.GTID_MODE = OFF;" run_noprint(master_db_args, "set global rpl_semi_sync_master_enabled=off;") run_noprint(slave_db_args, "set global rpl_semi_sync_slave_enabled=off;") run_noprint(master_db_args, "reset master;") run_noprint(slave_db_args, "stop slave;") get_dict(master_db_args, set_mode_on_p) get_dict(master_db_args, set_mode_off_p) get_dict(master_db_args, set_mode_off) get_dict(master_db_args, set_con_warn) get_dict(master_db_args, set_con_off) get_dict(slave_db_args, set_mode_on_p) get_dict(slave_db_args, set_mode_off_p) get_dict(slave_db_args, set_mode_off) get_dict(slave_db_args, set_con_warn) get_dict(slave_db_args, set_con_off) run_noprint(slave_db_args, "reset slave all;") run_noprint(slave_db_args, "reset master;") rep_status(master_db_args, slave_db_args) print("===============INFO:RESET COMPLETE====================") return "reset complete"
def restore_db(slave_db_args, slave_os_args, slave_cnf_dir, xbakup_dir, data_dir, redo_dir, undo_dir, bin_dir): ssh_input_noprint(slave_os_args, f"sudo rm -rf {data_dir}") ssh_input_noprint(slave_os_args, f"sudo rm -rf {redo_dir}") ssh_input_noprint(slave_os_args, f"sudo rm -rf {undo_dir}") db_dir = '/'.join((data_dir + '/').replace('//', '/').split('/')[0:-2]) ssh_input_noprint( slave_os_args, f"sudo chmod -R 777 {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}" ) ssh_input_noprint( slave_os_args, f"sudo mv {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}/* {db_dir} " ) start_db(slave_os_args, slave_db_args, bin_dir, slave_cnf_dir) return 0
def get_pos(slave_os_args, slave_db_args): s_ip, s_db_user, s_db_port, s_db_pwd = slave_db_args dump_file_dir = ssh_input_noprint(slave_os_args, f'cat /tmp/{s_ip}_{s_db_port}.log')[0] if 'No such' not in dump_file_dir and '没有' not in dump_file_dir: if 'exp_' in dump_file_dir: change_pos_sql = ssh_input( slave_os_args, f'''grep "CHANGE MASTER TO MASTER_LOG_FILE='" {dump_file_dir}''' )[0] else: pos_info = dump_file_dir.replace('\n', '').split(' ') change_pos_sql = f"-- CHANGE MASTER TO MASTER_LOG_FILE='{pos_info[0]}', MASTER_LOG_POS={pos_info[-1]};" ssh_input_noprint(slave_os_args, f'rm -rf /tmp/{s_ip}_{s_db_port}.log') return change_pos_sql else: return "file not access"
def start_db(os_args, db_args, bin_dir, cnf_dir): ip, db_user, db_port, db_pwd = db_args start_sh = f'nohup {bin_dir}mysqld --defaults-file={cnf_dir} > /dev/null 2>&1 >>/tmp/startmysql{ip}{db_port}.log &' ssh_input_noprint(os_args, start_sh) time.sleep(3) start_res = ''.join( ssh_input_noprint(os_args, f'cat /tmp/startmysql{ip}{db_port}.log')) if 'ready for connections' in start_res or start_res == '': print(f"INFO:\ndatabase IP:{ip} PORT:{db_port} start complete.") ssh_input_noprint(os_args, f'rm -f /tmp/startmysql{ip}{db_port}.log') return 'start success' else: print(f"WARNING:\ndatabase IP:{ip} PORT:{db_port} start failed.") ssh_input_noprint(os_args, f'rm -f /tmp/startmysql{ip}{db_port}.log') return 'start failed'
def stop_db(os_args, db_args): base_dir = get_all(db_args, " show variables like 'basedir';")[0][1] socket_dir = get_all(db_args, "show global variables like 'socket'")[0][1] bin_dir = f"{base_dir}/bin/" ip, db_user, db_port, db_pwd = db_args db_pwd = db_pwd.replace('!', '\\!') stop_res = ''.join( ssh_input_noprint( os_args, f"{bin_dir}mysqladmin -u {db_user} -p{db_pwd} -P {db_port} -S {socket_dir} shutdown" )) if 'error' not in stop_res: print(f"INFO:\ndatabase IP:{ip} PORT:{db_port} shutdown complete.") return 'stop db s', bin_dir else: print(f"INFO:\ndatabase IP:{ip} PORT:{db_port} shutdown failed.") return 'stop db f', bin_dir
def innobackup(master_os_args, master_db_args, master_cnf_dir, xbakup_dir, slaves): mount_res = mount_nfs(xbakup_dir, slaves, master_os_args) if mount_res != 'nfs mount complete': os._exit(0) else: m_ip, m_db_user, m_db_port, m_db_pwd = master_db_args m_db_pwd = m_db_pwd.replace('!', '\\!') m_socket_dir = get_all(master_db_args, "show global variables like 'socket'")[0][1] master_bakup_cmd = f"{xbakup_dir}/percona-xtrabackup-2.4.13-Linux-x86_64/bin/innobackupex --defaults-file={master_cnf_dir} \ -u{m_db_user} -p{m_db_pwd} --socket={m_socket_dir} --slave-info {xbakup_dir}" ssh_input_noprint(master_os_args, f"sudo rm -rf {xbakup_dir}/20*") res = ''.join(ssh_input_noprint(master_os_args, master_bakup_cmd)) # ssh_input_noprint(master_os_args,f"chmod -R 777 {xbakup_dir}/20*") if ' completed OK!' in res: print("INFO:master db innobackup completed.\n") print( "===============INFO:INNOBACKUP MASTER COMPLETE====================" ) # for slave in slaves: # slave_db_args, slave_os_args, slave_cnf_dir = slave # check_dir_res = ssh_input_noprint(slave_os_args,f'cat {xbakup_dir}/{slave_db_args[0]}_{slave_db_args[2]}')[0] # if 'No such' not in check_dir_res and '没有' not in check_dir_res: # pass # else: # data_dir = get_all(slave_db_args,"show variables like 'datadir'")[0][1] # if data_dir != check_dir_res: # ssh_input_noprint(master_os_args,f"rm -rf {xbakup_dir}/{slave_db_args[0]}_{slave_db_args[2]}\necho '{data_dir}'>>{xbakup_dir}/{slave_db_args[0]}_{slave_db_args[2]}") apply_res = ''.join( ssh_input_noprint( master_os_args, f"{xbakup_dir}/percona-xtrabackup-2.4.13-Linux-x86_64/bin/innobackupex --apply-log {xbakup_dir}/20*" )) ssh_input_noprint(master_os_args, f"sudo chmod -R 777 {xbakup_dir}/20*") for slave in slaves: slave_db_args, slave_os_args, slave_cnf_dir = slave print( F"###INFO:IP:{slave_db_args[0]} PORT:{slave_db_args[2]} Innobackup start:\n" ) # data_dir = ''.join(ssh_input_noprint(slave_os_args,f"cat {xbakup_dir}/{slave_db_args[0]}_{slave_db_args[2]}")).replace('\n','') #base_dir = [i for i in ssh_input_noprint(slave_os_args,f"cat {slave_cnf_dir} |grep -i basedir") if '#' not in i][0].replace('\n','').replace(' ','').split('=')[-1] #data_dir = [i for i in ssh_input_noprint(slave_os_args,f"cat {slave_cnf_dir} |grep -i datadir") if '#' not in i][0].replace('\n','').replace(' ','').split('=')[-1] base_dir = get_all(slave_db_args, " show variables like 'basedir';")[0][1] data_dir = get_all(slave_db_args, " show variables like 'datadir';")[0][1] redo_dir = get_all( slave_db_args, " show variables like 'innodb_log_group_home_dir';")[0][1] undo_dir = get_all( slave_db_args, " show variables like 'innodb_undo_directory';")[0][1] db_dir = '/'.join( (data_dir + '/').replace('//', '/').split('/')[0:-2]) #ssh_input_noprint(slave_os_args,"ps -aux | grep mysqld| awk '{print $2}' | xargs kill") #ssh_input_noprint(slave_os_args,f"mysqladmin -u{slave_db_args[1]} -p{slave_db_args[3]} -h{slave_db_args[0]} -P{slave_db_args[2]} shutdown ") stop_res, bin_dir = stop_db(slave_os_args, slave_db_args) ssh_input_noprint( slave_os_args, f"sudo rm -rf {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}" ) ssh_input_noprint( slave_os_args, f"sudo mkdir -p {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}\n\ sudo chmod -R 777 {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}" ) ssh_input_noprint(slave_os_args, f"sudo chmod -R 777 {db_dir}") ssh_input_noprint( slave_os_args, f"sudo mv {data_dir} {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}" ) ssh_input_noprint( slave_os_args, f"sudo mv {redo_dir} {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}" ) ssh_input_noprint( slave_os_args, f"sudo mv {undo_dir} {xbakup_dir}/data_dir_{slave_db_args[0]}_{slave_db_args[2]}" ) print( "INFO:Shutdown mysqld server and run innobackupex --apply-log.\n" ) if ' completed OK!' in apply_res: print("INFO:Run innobackupex --apply-log complete\n") copy_res = ''.join( ssh_input_noprint( slave_os_args, f'''{xbakup_dir}/percona-xtrabackup-2.4.13-Linux-x86_64/bin/innobackupex --defaults-file={slave_cnf_dir} \ --copy-back {xbakup_dir}/20*''')) if ' completed OK!' in copy_res: print(f"INFO: copy back complete\n") ssh_input_noprint( slave_os_args, f'cp {xbakup_dir}/20*/xtrabackup_binlog_info /tmp/{slave_db_args[0]}_{slave_db_args[2]}.log' ) start_db(slave_os_args, slave_db_args, bin_dir, slave_cnf_dir) print( f"===============INFO:INNOBACKUP IP:{slave_db_args[0]} PORT:{slave_db_args[2]} COMPLETE====================" ) else: print("INFO:Run innobackupex copy back failed\n") restore_db(slave_db_args, slave_os_args, slave_cnf_dir, xbakup_dir, data_dir, redo_dir, undo_dir, bin_dir) print("INFO:Restore databse now\n") else: print("INFO:Run innobackupex --apply-log failed\n") restore_db(slave_db_args, slave_os_args, slave_cnf_dir, xbakup_dir, data_dir, redo_dir, undo_dir, bin_dir) print("INFO:Restore databse now\n") return 0 else: print("INFO:master db innobackup falied.\n") return "backup failed"
def mount_nfs(xbakup_dir, slaves, master_os_args): dir_counts = len(xbakup_dir.split('/')) if dir_counts > 2: print("INFO:The directory of backup are available.\n") ssh_input_noprint( master_os_args, f'sudo mkdir -p {xbakup_dir}\nsudo chmod 777 {xbakup_dir}') check_soft = ''.join(ssh_input(master_os_args, f"sudo ls {xbakup_dir}")) if 'percona-xtrabackup' in check_soft: print("INFO:There have xtrabackup software in directory.") else: ssh_ftp(master_os_args, f'{xbakup_dir}/percona-xtrabackup-2.4.13.tar.gz', 'percona-xtrabackup-2.4.13.tar.gz', 'put') ssh_input_noprint( master_os_args, f'sudo tar -zxvf {xbakup_dir}/percona-xtrabackup-2.4.13.tar.gz -C {xbakup_dir}' ) exports_text = ssh_input(master_os_args, 'sudo cat /etc/exports') for slave in slaves: slave_db_args, slave_os_args, slave_cnf_dir = slave if xbakup_dir not in ''.join( exports_text) and slave_os_args[0] != master_os_args[0]: exports_text.append( f'{xbakup_dir} {slave_db_args[0]}(rw,sync,all_squash)') ssh_input_noprint( slave_os_args, f'sudo mkdir -p {xbakup_dir}\nsudo chmod 777 {xbakup_dir}') ssh_input_noprint( master_os_args, f'''sudo mv /etc/exports /etc/exports.bak\nsudo sh -c "echo '{''.join(exports_text)}' >> /etc/exports"''' ) rhel_version = ssh_input(master_os_args, 'uname -r')[0] if 'el7' in rhel_version: ssh_input_noprint( master_os_args, 'sudo exportfs -r\nsudo systemctl stop nfs\nsudo rpcbind stop\nsudo rpcbind reload\nsudo systemctl start nfs' ) else: ssh_input_noprint( master_os_args, 'sudo exportfs -r\nsudo nfs stop\nsudo rpcbind stop\nsudo rpcbind reload\nsudo nfs start' ) check_nfs = ssh_input(master_os_args, 'sudo showmount -e localhost') for slave in slaves: slave_db_args, slave_os_args, slave_cnf_dir = slave if slave_os_args[0] != master_os_args[0]: mount_res = ''.join( ssh_input( slave_os_args, f'sudo mount -t nfs {master_os_args[0]}:{xbakup_dir} {xbakup_dir} -o proto=tcp -o nolock' )) if 'already mounted' in mount_res or mount_res == '': print(f"INFO: IP:{slave_db_args[0]} already mounted.") print( "===============INFO:NFS MOUNTED COMPLETE====================" ) return "nfs mount complete" else: print(f"WARNING: IP:{slave_db_args[0]} were mount failed.") return "nfs mount failed" else: print("ERROR:Please choose a Two level directory!\n") return "invaild dir"
def mysqldump(master_db_args, slave_db_args, master_os_args, slave_os_args, xbakup_dir): m_ip, m_db_user, m_db_port, m_db_pwd = master_db_args s_ip, s_db_user, s_db_port, s_db_pwd = slave_db_args m_db_pwd = m_db_pwd.replace('!', '\\!') s_db_pwd = s_db_pwd.replace('!', '\\!') slave_base_dir = get_all(slave_db_args, " show variables like 'basedir';")[0][1] print(f"INFO:\nIP:{s_ip} PORT:{s_db_port} MYSQLDUMP NOW.\n") exp_dir = xbakup_dir check_exp_dir = ssh_input_noprint(slave_os_args, f"ls {exp_dir}") if check_exp_dir != [] and 'no ac' in check_exp_dir[0]: ssh_input_noprint( slave_os_args, f"sudo mkdir -p {exp_dir}\nsudo chmod -R 777 {exp_dir}") print(f"INFO:\nmkdir the directory :{exp_dir} now.\n") elif exp_dir == '/': print("PLEASE DONT CHOOSE THE '/' DIRECTORY!\n") os._exit(0) else: ssh_input_noprint(slave_os_args, f"sudo chmod -R 777 {exp_dir}") ssh_input_noprint(slave_os_args, f"rm -rf {exp_dir}/exp_{s_ip}_{s_db_port}.txt") exp_dbs_yn = 'Y' if exp_dbs_yn.upper() == 'Y': exp_dbs = ssh_input( slave_os_args, f"{slave_base_dir}/bin/mysql -e 'show databases;' -u{m_db_user} -p{m_db_pwd} -P{m_db_port} -h{m_ip}| \ grep -Ev 'Database|information_schema|mysql|performance_schema|sys' |xargs" ) if exp_dbs != []: exp_dbs = exp_dbs[0].replace('\n', '') exp_cmd = f"{slave_base_dir}/bin/mysqldump -u{m_db_user} -p{m_db_pwd} -P{m_db_port} -h{m_ip} \ --databases {exp_dbs} --single-transaction --master-data=2 -E -R > {exp_dir}/exp_{s_ip}_{s_db_port}.txt" else: print("INFO:There are no business databases.") os._exit(0) else: exp_cmd = f"{slave_base_dir}/bin/mysqldump -u{m_db_user} -p{m_db_pwd} -P{m_db_port} -h{m_ip} \ --single-transaction --master-data=2 -E -R --all-databases > {exp_dir}/exp_{s_ip}_{s_db_port}.txt" imp_cmd = f"{slave_base_dir}/bin/mysql -u{s_db_user} -p{s_db_pwd} -P{s_db_port} -h{s_ip} <{exp_dir}/exp_{s_ip}_{s_db_port}.txt" exp_res = ''.join(ssh_input(slave_os_args, exp_cmd)) if 'ERROR' not in exp_res.upper(): exp_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) print( f"INFO:\n{exp_time} IP:{s_ip} PORT:{s_db_port} EXPORT DATABASE COMPLETE.\n" ) run_noprint(slave_db_args, "reset master;") imp_res = ''.join(ssh_input(slave_os_args, imp_cmd)) imp_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) if 'ERROR' not in imp_res.upper() and 'bash:' not in imp_res: print( f"INFO:\n{imp_time} IP:{s_ip} PORT:{s_db_port} IMPORT DATABASE COMPLETE.\n" ) print( f"===============INFO:MYSQLDUMP IP:{s_ip} PORT:{s_db_port} COMPLETE====================" ) ssh_input_noprint( slave_os_args, f"rm -fr /tmp/{s_ip}_{s_db_port}.log\necho '{exp_dir}/exp_{s_ip}_{s_db_port}.txt'>/tmp/{s_ip}_{s_db_port}.log" ) return "imp complete" else: print( f"ERROR:\n{imp_time} IP:{s_ip} PORT:{s_db_port} IMPORT DATABASE FAILED.\n" ) ssh_input_noprint( slave_os_args, f"rm -fr /tmp/{s_ip}_{s_db_port}.log\necho 'imp failed'>/tmp/{s_ip}_{s_db_port}.log" ) return "imp failed" else: print(f"ERROR:\nIP:{s_ip} PORT:{s_db_port} EXPORT DATABASE FAILED.\n") ssh_input_noprint( slave_os_args, f"rm -fr /tmp/{s_ip}_{s_db_port}.log\necho 'exp failed'>/tmp/{s_ip}_{s_db_port}.log" ) return "exp failed"