def get_mysqlops_connections(): """ Get a connection to mysqlops for reporting Returns: A mysql connection """ (reporting_host, port, _, _) = mysql_connect.get_mysql_connection('mysqlopsdb001') reporting = host_utils.HostAddr(''.join((reporting_host, ':', str(port)))) return connect_mysql(reporting, 'scriptrw')
def get_master_from_instance(instance): """ Determine if an instance thinks it is a slave and if so from where Args: instance - A hostaddr object Returns: master - A hostaddr object or None """ try: ss = get_slave_status(instance) except ReplicationError: return None return host_utils.HostAddr(''.join( (ss['Master_Host'], ':', str(ss['Master_Port']))))
def get_host_from_backup(full_path): """ Parse the filename of a backup to determine the source of a backup Note: there is a strong assumption that the port number matches 330[0-9] Args: full_path - Path to a backup file. Example: /backup/tmp/mysql-legaldb001c-3306-2014-06-06.xbstream Example: /backup/tmp/mysql-legaldb-1-1-3306-2014-06-06.xbstream Returns: host - A hostaddr object """ filename = os.path.basename(full_path) pattern = 'mysql-([a-z0-9-]+)-(330[0-9])-.+' res = re.match(pattern, filename) return host_utils.HostAddr(''.join((res.group(1), ':', res.group(2))))
def get_metadata_from_backup_file(full_path): """ Parse the filename of a backup to determine the source of a backup Note: there is a strong assumption that the port number matches 330[0-9] Args: full_path - Path to a backup file. Example: xtrabackup/standard/testmodsharddb-1/testmodsharddb-1-79-3306-2016-05-18-22:34:39.xbstream Returns: host - A hostaddr object creation - a datetime object describing creation date """ filename = os.path.basename(full_path) pattern = '([a-z0-9-]+)-(330[0-9])-(\d{4})-(\d{2})-(\d{2}).*' res = re.match(pattern, filename) host = host_utils.HostAddr(':'.join((res.group(1), res.group(2)))) creation = datetime.date(int(res.group(3)), int(res.group(4)), int(res.group(5))) return host, creation
def assert_replication_sanity(instance, checks=ALL_REPLICATION_CHECKS): """ Confirm that a replica has replication running and from the correct source if the replica is in zk. If not, throw an exception. args: instance - A hostAddr object """ problems = set() slave_status = get_slave_status(instance) if (CHECK_IO_THREAD in checks and slave_status['Slave_IO_Running'] != 'Yes'): problems.add('Replica {r} has IO thread not running' ''.format(r=instance)) if (CHECK_SQL_THREAD in checks and slave_status['Slave_SQL_Running'] != 'Yes'): problems.add('Replcia {r} has SQL thread not running' ''.format(r=instance)) if CHECK_CORRECT_MASTER in checks: zk = host_utils.MysqlZookeeper() try: (replica_set, replica_type) = zk.get_replica_set_from_instance(instance) except: # must not be in zk, returning return expected_master = zk.get_mysql_instance_from_replica_set(replica_set) actual_master = host_utils.HostAddr(':'.join( (slave_status['Master_Host'], str(slave_status['Master_Port'])))) if expected_master != actual_master: problems.add('Master is {actual} rather than expected {expected}' 'for replica {r}'.format(actual=actual_master, expected=expected_master, r=instance)) if problems: raise Exception(', '.join(problems))
def get_metadata_from_backup_file(full_path): """ Parse the filename of a backup to determine the source of a backup Note: there is a strong assumption that the port number matches 330[0-9] Args: full_path - Path to a backup file. Example: /backup/tmp/mysql-legaldb001c-3306-2014-06-06.xbstream Example: /backup/tmp/mysql-legaldb-1-1-3306-2014-06-06.xbstream Returns: host - A hostaddr object creation - a datetime object describing creation date extension - file extension """ filename = os.path.basename(full_path) pattern = 'mysql-([a-z0-9-]+)-(330[0-9])-(\d{4})-(\d{2})-(\d{2}).*\.(.+)' res = re.match(pattern, filename) host = host_utils.HostAddr(':'.join((res.group(1), res.group(2)))) creation = datetime.date(int(res.group(3)), int(res.group(4)), int(res.group(5))) extension = res.group(6) return host, creation, extension
def calc_slave_lag(slave_hostaddr, dead_master=False): """ Determine MySQL replication lag in bytes and binlogs Args: slave_hostaddr - A HostAddr object for a replica Returns: io_binlogs - Number of undownloaded binlogs. This is only slightly useful as io_bytes spans binlogs. It mostly exists for dba amussement io_bytes - Bytes of undownloaded replication logs. sbm - Number of seconds of replication lag as determined by computing the difference between current time and what exists in a heartbeat table as populated by replication sql_binlogs - Number of unprocessed binlogs. This is only slightly useful as sql_bytes spans binlogs. It mostly exists for dba amussement sql_bytes - Bytes of unprocessed replication logs ss - None or the results of running "show slave status' """ ret = { 'sql_bytes': INVALID, 'sql_binlogs': INVALID, 'io_bytes': INVALID, 'io_binlogs': INVALID, 'sbm': INVALID, 'ss': { 'Slave_IO_Running': INVALID, 'Slave_SQL_Running': INVALID, 'Master_Host': INVALID, 'Master_Port': INVALID } } try: ss = get_slave_status(slave_hostaddr) except ReplicationError: # Not a slave, so return dict of INVALID return ret except MySQLdb.OperationalError as detail: (error_code, msg) = detail.args if error_code == MYSQL_ERROR_CONN_HOST_ERROR: # Host down, but exists. return ret else: # Host does not exist or something else funky raise ret['ss'] = ss slave_sql_pos = ss['Exec_Master_Log_Pos'] slave_sql_binlog = ss['Relay_Master_Log_File'] _, slave_sql_binlog_num = re.split('\.', slave_sql_binlog) slave_io_pos = ss['Read_Master_Log_Pos'] slave_io_binlog = ss['Master_Log_File'] _, slave_io_binlog_num = re.split('\.', slave_io_binlog) master_hostaddr = host_utils.HostAddr(':'.join( (ss['Master_Host'], str(ss['Master_Port'])))) if not dead_master: try: master_logs = get_master_logs(master_hostaddr) (ret['sql_bytes'], ret['sql_binlogs']) = calc_binlog_behind(slave_sql_binlog_num, slave_sql_pos, master_logs) (ret['io_bytes'], ret['io_binlogs']) = calc_binlog_behind(slave_io_binlog_num, slave_io_pos, master_logs) except _mysql_exceptions.OperationalError as detail: (error_code, msg) = detail.args if error_code != MYSQL_ERROR_CONN_HOST_ERROR: raise # we can compute real lag because the master is dead try: ret['sbm'] = calc_alt_sbm(slave_hostaddr, ss['Master_Server_Id']) except MySQLdb.ProgrammingError as detail: (error_code, msg) = detail.args if error_code != MYSQL_ERROR_NO_SUCH_TABLE: raise # We can not compute a real sbm, so the caller will get # None default pass return ret