def listdbs(server, args_array, **kwargs): """Function: listdbs Description: List user or user/system databases in the database instance. Arguments: (input) server -> Server instance. (input) args_array -> Dictionary of command line options. (input) **kwargs: sys_dbs -> List of system databases. """ args_array = dict(args_array) sys_dbs = list(kwargs.get("sys_dbs", [])) db_list = gen_libs.dict_2_list(mysql_libs.fetch_db_dict(server), "Database") if "-k" in args_array: print("List of user and system databases:") for item in db_list: print(" %s" % (item)) else: print("List of user databases:") for item in gen_libs.del_not_and_list(db_list, sys_dbs): print(" %s" % (item))
def set_db_list(server, args_array): """Function: set_db_list Description: Get the database list and check if all databases or a single database is being selected. Arguments: (input) server -> Database server instance. (input) args_array -> Array of command line options and values. (output) -> Database list. """ args_array = dict(args_array) dump_list = [] db_list = gen_libs.dict_2_list(mysql_libs.fetch_db_dict(server), "Database") # Specified databases. if "-B" in args_array: # Difference of -B databases to database list. for item in set(args_array["-B"]) - set(db_list): print("Warning: Database(%s) does not exist." % (item)) # Intersect of -B databases to database list. dump_list = list(set(args_array["-B"]) & set(db_list)) # All databases. elif "-A" in args_array: dump_list = list(db_list) return dump_list
def _proc_all_tbls(server, func_name, db_list, db_name, dict_key, **kwargs): """Function: _proc_all_tbls Description: Private function for process_requests(). Process all tables in listed databases. Arguments: (input) server -> Server instance. (input) func_name -> Name of a function. (input) db_list -> List of all databases. (input) db_name -> List of database names. (input) dict_key -> Dictionary key for fetch_tbl_dict call. (input) **kwargs: sys_dbs -> List of system databases. multi_val -> List of options that may have multiple values. """ db_name = list(db_name) db_list = list(db_list) detect_dbs(db_name, db_list, **kwargs) for dbs in set(db_name) & set(db_list): for tbl in gen_libs.dict_2_list(mysql_libs.fetch_tbl_dict(server, dbs), dict_key): func_name(server, dbs, tbl, **kwargs)
def process_logs_list(server, args_array, **kwargs): """Function: process_logs_list Description: Get a list of binary log file names from the source database. Clean up the list if the -f and/or -g options are used. Arguments: (input) server -> Server instance. (input) args_array -> Array of command line options and values. (output) status -> Tuple on process status. status[0] - True|False - Process successful. status[1] - Error message if process failed. (output) binlog_list -> List of binary log file names. """ args_array = dict(args_array) status = (True, None) binlog_list = [] # Is -f and -g in the argument list and in the correct order. if ("-f" in args_array and "-g" in args_array) \ and args_array["-g"] < args_array["-f"]: status = (False, "Error: Option -g: '%s' is before -f '%s'." % (args_array["-g"], args_array["-f"])) return status, binlog_list binlog_list = gen_libs.dict_2_list(mysql_libs.fetch_logs(server), "Log_name") if "-f" in args_array and args_array["-f"] in binlog_list: # Remove any logs before log file name. while binlog_list[0] < args_array["-f"]: binlog_list.pop(0) elif "-f" in args_array: status = (False, "Error: Option -f: '%s' not found in binary log list." % (args_array["-f"])) return status, binlog_list if "-g" in args_array and args_array["-g"] in binlog_list: # Remove any logs after log file name. while binlog_list[-1] > args_array["-g"]: binlog_list.pop(-1) elif "-g" in args_array: status = (False, "Error: Option -g: '%s' not found in binary log list." % (args_array["-g"])) return status, binlog_list
def process_request(server, func_name, db_name=None, tbl_name=None, **kwargs): """Function: process_request Description: Prepares for the type of check based on the arguments passed to the function and then calls the "func_name" function. NOTE: If db_name and/or tbl_name is set to None, then assumes to process all databases/tables repsectively. Arguments: (input) server -> Server instance. (input) func_name -> Name of a function. (input) db_name -> Database name. (input) tbl_name -> Table name. (input) **kwargs: sys_dbs -> List of system databases. multi_val -> List of options that may have multiple values. """ db_name = list() if db_name is None else list(db_name) tbl_name = list() if tbl_name is None else list(tbl_name) db_list = gen_libs.dict_2_list(mysql_libs.fetch_db_dict(server), "Database") dict_key = "table_name" # Determine the MySQL version for dictionary key name if mysql_class.fetch_sys_var(server, "version", level="session")["version"] >= "8.0": dict_key = "TABLE_NAME" # Process all databases if not db_name: _proc_all_dbs(server, func_name, db_list, dict_key, **kwargs) # Process all tables in some databases elif not tbl_name: _proc_all_tbls(server, func_name, db_list, db_name, dict_key, **kwargs) # Process specific tables. else: _proc_some_tbls(server, func_name, db_list, db_name, tbl_name, dict_key, **kwargs)
def fetch_db_list(server, ign_db_list=None, db_name=None): """Function: fetch_db_list Description: Return list of database(s) minus any in the ignore database list or return the databases in the do list. Arguments: (input) server -> Server instance. (input) ign_db_list -> List of databases to be ignored. (input) db_name -> List of specify database names to be checked. (output) db_list | db_name -> List of databases. """ if ign_db_list is None: ign_db_list = list() else: ign_db_list = list(ign_db_list) if db_name is None: db_name = list() else: db_name = list(db_name) if server.do_db: db_list = server.fetch_do_db() else: db_list = gen_libs.dict_2_list(mysql_libs.fetch_db_dict(server), "Database") if server.ign_db: ign_db_list = server.fetch_ign_db() + ign_db_list # Remove "ignore" databases from database list. db_list = gen_libs.del_not_and_list(db_list, ign_db_list) if db_name: return gen_libs.del_not_in_list(db_name, db_list) return db_list
def run_program(args_array, sys_ign_db, **kwargs): """Function: run_program Description: Creates class instance(s) and controls flow of the program. Arguments: (input) args_array -> Array of command line options and values. (input) sys_ign_db -> List of system databases to ignore. """ global SUBJ_LINE args_array = dict(args_array) sys_ign_db = list(sys_ign_db) mail = None use_mailx = False no_std = args_array.get("-z", False) master = mysql_libs.create_instance(args_array["-c"], args_array["-d"], mysql_class.MasterRep) master.connect(silent=True) slave = mysql_libs.create_instance(args_array["-r"], args_array["-d"], mysql_class.SlaveRep) slave.connect(silent=True) if master.conn_msg or slave.conn_msg: print("run_program: Error encountered with connection of master/slave") print("\tMaster: %s" % (master.conn_msg)) print("\tSlave: %s" % (slave.conn_msg)) else: if args_array.get("-e", None): mail = gen_class.setup_mail(args_array.get("-e"), subj=args_array.get("-s", SUBJ_LINE)) use_mailx = args_array.get("-u", False) # Determine datatype of server_id and convert appropriately. # Required for mysql.connector v1.1.6 as this version assigns the # id to a different datatype then later mysql.connector versions. slv_list = gen_libs.dict_2_list(master.show_slv_hosts(), "Server_id") slv_id = str(slave.server_id) \ if isinstance(slv_list[0], str) else slave.server_id # Is slave in replication with master if slv_id in slv_list: # Check specified tables in database if "-t" in args_array: setup_cmp(master, slave, sys_ign_db, args_array["-B"], args_array["-t"], mail=mail, no_std=no_std, use_mailx=use_mailx, **kwargs) # Check single database elif "-B" in args_array: setup_cmp(master, slave, sys_ign_db, args_array["-B"], "", mail=mail, no_std=no_std, use_mailx=use_mailx, **kwargs) # Check all tables in all databases else: setup_cmp(master, slave, sys_ign_db, "", "", mail=mail, no_std=no_std, use_mailx=use_mailx, **kwargs) mysql_libs.disconnect(master, slave) else: mysql_libs.disconnect(master, slave) print("Error: Replica is not in replication with Master.")
def setup_cmp(master, slave, sys_ign_db, db_name=None, tbl_name=None, **kwargs): """Function: setup_cmp Description: Setup the comparsion check getting list of databases and tables then calling the compare function. Arguments: (input) master -> Master instance. (input) slave -> Slave instance. (input) sys_ign_db -> List of system databases to ignore. (input) db_name -> List of database names. (input) tbl_name -> List of table names. (input) **kwargs: ign_db_tbl -> Dictionary-List of dbs & tables to be ignored. mail -> Mail class instance. no_std -> Suppress standard out. use_mailx -> Use the mailx command for sending emails. """ db_name = list() if db_name is None else list(db_name) tbl_name = list() if tbl_name is None else list(tbl_name) sys_ign_db = list(sys_ign_db) ign_db_tbl = kwargs.get("ign_db_tbl", dict()) mail = kwargs.get("mail", None) no_std = kwargs.get("no_std", False) mst_dbs = fetch_db_list(master) slv_dbs = fetch_db_list(slave, sys_ign_db, db_name) db_list = gen_libs.del_not_in_list(mst_dbs, slv_dbs) slv_do_dict = slave.fetch_do_tbl() slv_ign_dict = slave.fetch_ign_tbl() dict_key = "table_name" # Determine the MySQL version for dictionary key name if mysql_class.fetch_sys_var(master, "version", level="session")["version"] >= "8.0": dict_key = "TABLE_NAME" for dbs in db_list: # Get master list of tables. mst_tbl_list = gen_libs.dict_2_list( mysql_libs.fetch_tbl_dict(master, dbs), dict_key) # Database in "to do" list. if dbs in slv_do_dict: slv_tbl_list = slv_do_dict[dbs] else: # Get list of tables from slave. slv_tbl_list = gen_libs.dict_2_list( mysql_libs.fetch_tbl_dict(slave, dbs), dict_key) slv_ign_tbl = [] # Database in slave "ignore" list if dbs in slv_ign_dict: slv_ign_tbl = slv_ign_dict[dbs] if dbs in ign_db_tbl: slv_ign_tbl = slv_ign_tbl + ign_db_tbl[dbs] # Drop "ignore" tables. slv_tbl_list = gen_libs.del_not_and_list(slv_tbl_list, slv_ign_tbl) tbl_list = gen_libs.del_not_in_list(mst_tbl_list, slv_tbl_list) if tbl_name: tbl_list = gen_libs.del_not_in_list(tbl_list, tbl_name) run_cmp(master, slave, dbs, tbl_list, mail=mail, no_std=no_std) if mail: mail.send_mail(use_mailx=kwargs.get("use_mailx", False))