mysql_replication: fix crashes caused by deprecated terminology

This commit is contained in:
Andrew Klychkov 2020-12-09 10:27:36 +03:00
parent d309d5af2d
commit e07e96bf6d

View file

@ -244,17 +244,67 @@ from ansible.module_utils._text import to_native
executed_queries = []
def uses_replica_terminology(cursor):
"""Checks if REPLICA must be used instead of SLAVE"""
cursor.execute("SELECT VERSION()")
result = cursor.fetchone()
if isinstance(result, dict):
if 'VERSION()' in result:
version_str = result['VERSION()']
else:
version_str = result['version()']
else:
version_str = result[0]
version = version_str.split('.')
ver_major = int(version[0])
ver_minor = int(version[1])
if '-' in version[2]:
ver_patch = int(version[2].split('-')[0])
else:
ver_patch = int(version[2])
if 'mariadb' in version_str.lower():
# Since MariaDB 10.5.1
if ver_major > 10:
return True
elif ver_major == 10 and ver_minor > 5:
return True
elif ver_major == 10 and ver_minor == 5 and ver_patch >= 1:
return True
return False
else:
# Since MySQL 8.0.22
if ver_major > 8:
return True
elif ver_major == 8 and ver_minor > 0:
return True
elif ver_major == 8 and ver_minor == 0 and ver_patch >= 22:
return True
return False
def get_master_status(cursor):
cursor.execute("SHOW MASTER STATUS")
masterstatus = cursor.fetchone()
return masterstatus
def get_slave_status(cursor, connection_name='', channel=''):
def get_slave_status(cursor, connection_name='', channel='', term='REPLICA'):
if connection_name:
query = "SHOW SLAVE '%s' STATUS" % connection_name
query = "SHOW %s '%s' STATUS" % (term, connection_name)
else:
query = "SHOW SLAVE STATUS"
query = "SHOW %s STATUS" % term
if channel:
query += " FOR CHANNEL '%s'" % channel
@ -264,11 +314,11 @@ def get_slave_status(cursor, connection_name='', channel=''):
return slavestatus
def stop_slave(module, cursor, connection_name='', channel='', fail_on_error=False):
def stop_slave(module, cursor, connection_name='', channel='', fail_on_error=False, term='REPLICA'):
if connection_name:
query = "STOP SLAVE '%s'" % connection_name
query = "STOP %s '%s'" % (term, connection_name)
else:
query = 'STOP SLAVE'
query = 'STOP %s' % term
if channel:
query += " FOR CHANNEL '%s'" % channel
@ -286,11 +336,11 @@ def stop_slave(module, cursor, connection_name='', channel='', fail_on_error=Fal
return stopped
def reset_slave(module, cursor, connection_name='', channel='', fail_on_error=False):
def reset_slave(module, cursor, connection_name='', channel='', fail_on_error=False, term='REPLICA'):
if connection_name:
query = "RESET SLAVE '%s'" % connection_name
query = "RESET %s '%s'" % (term, connection_name)
else:
query = 'RESET SLAVE'
query = 'RESET %s' % term
if channel:
query += " FOR CHANNEL '%s'" % channel
@ -308,11 +358,11 @@ def reset_slave(module, cursor, connection_name='', channel='', fail_on_error=Fa
return reset
def reset_slave_all(module, cursor, connection_name='', channel='', fail_on_error=False):
def reset_slave_all(module, cursor, connection_name='', channel='', fail_on_error=False, term='REPLICA'):
if connection_name:
query = "RESET SLAVE '%s' ALL" % connection_name
query = "RESET %s '%s' ALL" % (term, connection_name)
else:
query = 'RESET SLAVE ALL'
query = 'RESET %s ALL' % term
if channel:
query += " FOR CHANNEL '%s'" % channel
@ -345,11 +395,11 @@ def reset_master(module, cursor, fail_on_error=False):
return reset
def start_slave(module, cursor, connection_name='', channel='', fail_on_error=False):
def start_slave(module, cursor, connection_name='', channel='', fail_on_error=False, term='REPLICA'):
if connection_name:
query = "START SLAVE '%s'" % connection_name
query = "START %s '%s'" % (term, connection_name)
else:
query = 'START SLAVE'
query = 'START %s' % term
if channel:
query += " FOR CHANNEL '%s'" % channel
@ -465,6 +515,13 @@ def main():
else:
module.fail_json(msg="unable to find %s. Exception message: %s" % (config_file, to_native(e)))
# Since MySQL 8.0.22 and MariaDB 10.5.1,
# "REPLICA" must be used instead of "SLAVE"
if uses_replica_terminology(cursor):
replica_term = 'REPLICA'
else:
replica_term = 'SLAVE'
if mode in "getmaster":
status = get_master_status(cursor)
if not isinstance(status, dict):
@ -474,7 +531,7 @@ def main():
module.exit_json(queries=executed_queries, **status)
elif mode in "getslave":
status = get_slave_status(cursor, connection_name, channel)
status = get_slave_status(cursor, connection_name, channel, replica_term)
if not isinstance(status, dict):
status = dict(Is_Slave=False, msg="Server is not configured as mysql slave")
else:
@ -529,13 +586,13 @@ def main():
result['changed'] = True
module.exit_json(queries=executed_queries, **result)
elif mode in "startslave":
started = start_slave(module, cursor, connection_name, channel, fail_on_error)
started = start_slave(module, cursor, connection_name, channel, fail_on_error, replica_term)
if started is True:
module.exit_json(msg="Slave started ", changed=True, queries=executed_queries)
else:
module.exit_json(msg="Slave already started (Or cannot be started)", changed=False, queries=executed_queries)
elif mode in "stopslave":
stopped = stop_slave(module, cursor, connection_name, channel, fail_on_error)
stopped = stop_slave(module, cursor, connection_name, channel, fail_on_error, replica_term)
if stopped is True:
module.exit_json(msg="Slave stopped", changed=True, queries=executed_queries)
else:
@ -547,13 +604,13 @@ def main():
else:
module.exit_json(msg="Master already reset", changed=False, queries=executed_queries)
elif mode in "resetslave":
reset = reset_slave(module, cursor, connection_name, channel, fail_on_error)
reset = reset_slave(module, cursor, connection_name, channel, fail_on_error, replica_term)
if reset is True:
module.exit_json(msg="Slave reset", changed=True, queries=executed_queries)
else:
module.exit_json(msg="Slave already reset", changed=False, queries=executed_queries)
elif mode in "resetslaveall":
reset = reset_slave_all(module, cursor, connection_name, channel, fail_on_error)
reset = reset_slave_all(module, cursor, connection_name, channel, fail_on_error, replica_term)
if reset is True:
module.exit_json(msg="Slave reset", changed=True, queries=executed_queries)
else: