Skip to content

Commit

Permalink
mysql_replication: fix crashes caused by deprecated terminology
Browse files Browse the repository at this point in the history
  • Loading branch information
Andersson007 committed Dec 9, 2020
1 parent d309d5a commit 1d5430f
Showing 1 changed file with 66 additions and 20 deletions.
86 changes: 66 additions & 20 deletions plugins/modules/mysql_replication.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,17 +244,57 @@
executed_queries = []


def uses_replica_terminology(cursor):
"""Checks if REPLICA must be used instead of SLAVE"""
cursor.execute("SELECT VERSION()")
result = cursor.fetchone()
version_str = result[0]
version = version_str.split('.')

ver_major = version[0]
ver_minor = version[1]
ver_patch = version[2].split('-')[0]

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

else:
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

else:
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
Expand All @@ -264,11 +304,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
Expand All @@ -286,11 +326,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
Expand All @@ -308,11 +348,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
Expand Down Expand Up @@ -345,11 +385,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
Expand Down Expand Up @@ -465,6 +505,12 @@ 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):
Expand All @@ -474,7 +520,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:
Expand Down Expand Up @@ -529,13 +575,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:
Expand All @@ -547,13 +593,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:
Expand Down

0 comments on commit 1d5430f

Please sign in to comment.