def test_re_bootstrap(self): """Tests start method over actively replicating server """ # Fill the options options = { "group_name": None, "replication_user": None, "rep_user_passwd": "passwd", "gr_host": "", } # test start if is_member_of_group(self.server): leave(self.server, **options) # reconnect the server. self.server.connect() self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() # test health health(self.server, **options) # reconnect the server. self.server.connect() # Trying to start a group with a server that is already a member # expect GadgetError: Query failed: is already a member of a GR group. with self.assertRaises(GadgetError) as test_raises: start(self.server, **options) exception = test_raises.exception self.assertTrue("is already a member" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. self.server.connect() # Bootstrap with dry-run options["dry_run"] = True # Trying to start a group with a server that is already a member # expect GadgetError: Query failed: is already a member of a GR group. with self.assertRaises(GadgetError) as test_raises: start(self.server, **options) exception = test_raises.exception self.assertTrue("is already a member" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. self.server.connect() self.assertTrue(leave(self.server, **options)) # reconnect the server. self.server.connect()
def test_health_with_not_a_member(self): """Test the commands that requires a GR member or None value for a required server connection information. """ # Fill the options options = {} # expect GadgetError: Query failed: no server was given with self.assertRaises(GadgetError) as test_raises: health(None, **options) exception = test_raises.exception self.assertTrue( "No server was given" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # expect GadgetError: Query failed: not a member of a Group with self.assertRaises(GadgetError) as test_raises: health(self.mock_no_member, **options) exception = test_raises.exception self.assertTrue( "not a member of a GR group" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # Fill the options options = { "group_name": None, "replication_user": None, "rep_user_passwd": "passwd", } # expect GadgetError: Query failed: No server was given with self.assertRaises(GadgetError) as test_raises: start(None, **options) exception = test_raises.exception self.assertTrue( "No server was given" in exception.errmsg, "The exception message was not the expected: {0}" "".format(exception.errmsg))
def test_re_join(self): """Tests join method over actively replicating server """ # Fill the options options = { "group_name": None, "gr_host": self.server.host, "replication_user": "******", "rep_user_passwd": "passwd", "verbose": False, "dry_run": False, } # test start leave(self.server, **options) # reconnect the server. self.server.connect() self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() # test health health(self.server, **options) # reconnect the server. self.server.connect() options["dry_run"] = True # test join mock_server = get_mock_server(self.server) # Trying to add server to a group while is already a member of a group # expect GadgetError: Query failed: is already a member of a GR group. with self.assertRaises(GadgetError) as test_raises: join(self.server, mock_server, **options) exception = test_raises.exception self.assertTrue( "is already a member" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. self.server.connect() self.assertTrue(leave(self.server, **options)) # reconnect the server. self.server.connect()
def test_health_with_not_a_member(self): """Test the commands that requires a GR member or None value for a required server connection information. """ # Fill the options options = {} # expect GadgetError: Query failed: no server was given with self.assertRaises(GadgetError) as test_raises: health(None, **options) exception = test_raises.exception self.assertTrue("No server was given" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # expect GadgetError: Query failed: not a member of a Group with self.assertRaises(GadgetError) as test_raises: health(self.mock_no_member, **options) exception = test_raises.exception self.assertTrue("not a member of a GR group" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # Fill the options options = { "group_name": None, "replication_user": None, "rep_user_passwd": "passwd", } # expect GadgetError: Query failed: No server was given with self.assertRaises(GadgetError) as test_raises: start(None, **options) exception = test_raises.exception self.assertTrue("No server was given" in exception.errmsg, "The exception message was not the expected: {0}" "".format(exception.errmsg))
def test_re_join(self): """Tests join method over actively replicating server """ # Fill the options options = { "group_name": None, "gr_host": self.server.host, "replication_user": "******", "rep_user_passwd": "passwd", "verbose": False, "dry_run": False, } # test start leave(self.server, **options) # reconnect the server. self.server.connect() self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() # test health health(self.server, **options) # reconnect the server. self.server.connect() options["dry_run"] = True # test join mock_server = get_mock_server(self.server) # Trying to add server to a group while is already a member of a group # expect GadgetError: Query failed: is already a member of a GR group. with self.assertRaises(GadgetError) as test_raises: join(self.server, mock_server, **options) exception = test_raises.exception self.assertTrue("is already a member" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. self.server.connect() self.assertTrue(leave(self.server, **options)) # reconnect the server. self.server.connect()
elif command == HEALTH: health(args.server, detailed=True, **cmd_options) elif command == STATUS: health(args.server, **cmd_options) elif command == JOIN: if join(args.server, args.peer_server, **cmd_options): health(args.server, **cmd_options) elif command == LEAVE: leave(args.server, **cmd_options) elif command == START: if start(args.server, **cmd_options): health(args.server, **cmd_options) except GadgetError as err: _LOGGER.error("Error executing the '%s' command: %s", command, str(err)) sys.exit(1) except Exception as err: _LOGGER.error("Unexpected error executing the '%s' command: %s", command, str(err)) sys.exit(1) # Operation completed with success. _LOGGER.step("Operation completed with success.") sys.exit(0)
def main(): # Get the provided command command = sys.argv[1] # Read options from stdin data = "" while True: line = sys.stdin.readline() if line == ".\n": break data += line shell_options = json.loads(fs_decode(data)) cmd_options = shell_options[0] del shell_options[0] # Setup logging with the appropriate verbosity level. setup_logging(verbosity=int(cmd_options['verbose'])) logging.setLoggerClass(CustomLevelLogger) _LOGGER = logging.getLogger(_SCRIPT_NAME) # Handle keyboard interrupt on password retrieve and command execution. try: # Perform command command_error_msg = "executing operation" try: if command == CHECK: if cmd_options.get("update", False): command_error_msg = "configuring instance" else: command_error_msg = "checking instance" check(**cmd_options) elif command == JOIN: command_error_msg = "joining instance to cluster" server = shell_options[0] peer_server = shell_options[1] join(server, peer_server, **cmd_options) elif command == LEAVE: command_error_msg = "leaving cluster" server = shell_options[0] leave(server, **cmd_options) elif command == START: command_error_msg = "starting cluster" server = shell_options[0] start(server, **cmd_options) elif command == SANDBOX: sandbox_cmd = cmd_options["sandbox_cmd"] command = '{0} {1}'.format(command, sandbox_cmd) command_error_msg = "executing sandbox operation" if sandbox_cmd == SANDBOX_START: command_error_msg = "starting sandbox" start_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_CREATE: command_error_msg = "creating sandbox" create_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_STOP: command_error_msg = "stopping sandbox" stop_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_KILL: command_error_msg = "killing sandbox" kill_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_DELETE: command_error_msg = "deleting sandbox" delete_sandbox(**cmd_options) except GadgetError: _, err, _ = sys.exc_info() # the check for mysql.get_classic_session is a hack to prevent # double printing of the DB error if err.cause and u"mysql.get_classic_session" not in unicode(err): _LOGGER.error(u"Error %s: %s: %s", command_error_msg, unicode(err), unicode(err.cause)) else: _LOGGER.error(u"Error %s: %s", command_error_msg, unicode(err)) if _LOGGER.level <= logging.DEBUG: import traceback _LOGGER.debug("%s", traceback.format_exc()) sys.exit(1) except UnicodeEncodeError: _, err, _ = sys.exc_info() _LOGGER.error( u"Unicode error %s: %s. Make sure your locale " u"system settings support UTF-8 to use non-ASCII " u"values.", command_error_msg, unicode(err)) if _LOGGER.level <= logging.DEBUG: import traceback _LOGGER.debug("%s", traceback.format_exc()) sys.exit(1) except Exception: # pylint: disable=broad-except _, err, _ = sys.exc_info() _LOGGER.error(u"Unexpected error %s: %s", command_error_msg, unicode(err)) if _LOGGER.level <= logging.DEBUG: import traceback _LOGGER.debug("%s", traceback.format_exc()) sys.exit(1) # Operation completed with success. sys.exit(0) except KeyboardInterrupt: _LOGGER.error("keyboard interruption (^C) received, stopping...") if os.name == "nt": # Using signal.CTRL_C_EVENT on windows will not set any error code. # Simulate the Unix signal exit code 130 - Script terminated by # Control-C for ngshell to interpreted it as the same way as on # linux. sys.exit(130) else: signal.signal(signal.SIGINT, signal.SIG_DFL) os.kill(os.getpid(), signal.SIGINT)
def test_join(self): """Tests join method """ # Fill the options options = { "group_name": None, "gr_host": "{0}:{1}".format(self.server.host, self.server.port), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": False, "dry_run": False, } # join needs start if is_member_of_group(self.server): leave(self.server, **options) # reconnect the server. self.server.connect() self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() # health health(self.server, **options) # reconnect the server. self.server.connect() leave(self.server, **options) # reconnect the server. self.server.connect() member_state_qry = ("SELECT MEMBER_STATE FROM {0} as m JOIN {1} " "as s on m.MEMBER_ID = s.MEMBER_ID" "".format(REP_GROUP_MEMBERS_TABLE, REP_MEMBER_STATS_TABLE)) frozen_queries = { member_state_qry: [ [ 'ONLINE', ], ], } mock_server = get_mock_server(self.server, queries=frozen_queries) # Join with defaults ("dry_run": True) and required password options = { "dry_run": True, "replication_user": "******", "rep_user_passwd": "passwd", } join(self.server, mock_server, **options) # reconnect the server. self.server.connect() # Join with no defaults ("dry_run": True) options = { "group_name": None, "gr_host": "{0}:{1}".format(self.server.host, self.server.port), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": False, "dry_run": True, } # leave the group if is_member_of_group(self.server): leave(self.server, **options) self.assertFalse(join(self.server, mock_server, **options)) # reconnect the server. self.server.connect() self.assertFalse(leave(self.server, **options)) # reconnect the server. self.server.connect()
def test_bootstrap_noselect_priv(self): """Tests commands without Select privilege. """ self.server.exec_query("drop user if exists 'not_select'@'%'") change_user_privileges(self.server, "not_select", "%", user_passwd="pass", create_user=True) server1 = Server( {"conn_info": "not_select@localhost:{0}".format(self.server.port)}) server1.passwd = "pass" server1.connect() # Fill the options options = { "group_name": "b7286041-3016-11e6-ba52-507b9d87510a", "gr_host": ":{0}".format(self.server.port), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": True, "dry_run": False, } # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: leave(server1, **options) exception = test_raises.exception self.assertTrue( "not have enough privileges to verify server" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. server1.connect() # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: start(server1, **options) exception = test_raises.exception self.assertTrue( "The operation could not continue due to" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. server1.connect() # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: health(server1, **options) exception = test_raises.exception self.assertTrue( "not have enough privileges to verify server" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. server1.connect() # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: leave(server1, **options) exception = test_raises.exception self.assertTrue( "not have enough privileges to verify server" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg))
def test_bootstrap(self): """Tests start method """ # Fill the options options = { "group_name": None, "replication_user": None, "rep_user_passwd": "passwd", "verbose": True } # test start if is_member_of_group(self.server): leave(self.server, **options) # reconnect the server. self.server.connect() self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() # health health(self.server, **options) # reconnect the server. self.server.connect() # Bootstrap active server # Trying to start a group with a server that is already a member # expect GadgetError: Query failed: is already a member of a GR group. with self.assertRaises(GadgetError) as test_raises: start(self.server, **options) exception = test_raises.exception self.assertTrue( "is already a member" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. self.server.connect() leave(self.server, **options) # reconnect the server. self.server.connect() group_name = "b7286041-3016-11e6-ba52-507b9d87510a" # start using not defaults options = { "group_name": "b7286041-3016-11e6-ba52-507b9d87510a", "gr_host": "{0}:".format(self.server.host), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": True, "dry_run": False, } self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() self.assertTrue(is_member_of_group(self.server, group_name)) self.assertFalse(is_member_of_group(self.server, "group_name")) if is_member_of_group(self.server): leave(self.server, **options) # reconnect the server. self.server.connect()
def test_join(self): """Tests join method """ # Fill the options options = { "group_name": None, "gr_host": "{0}:{1}".format(self.server.host, self.server.port), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": False, "dry_run": False, } # join needs start if is_member_of_group(self.server): leave(self.server, **options) # reconnect the server. self.server.connect() self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() # health health(self.server, **options) # reconnect the server. self.server.connect() leave(self.server, **options) # reconnect the server. self.server.connect() member_state_qry = ("SELECT MEMBER_STATE FROM {0} as m JOIN {1} " "as s on m.MEMBER_ID = s.MEMBER_ID" "".format(REP_GROUP_MEMBERS_TABLE, REP_MEMBER_STATS_TABLE)) frozen_queries = { member_state_qry: [['ONLINE', ], ], } mock_server = get_mock_server(self.server, queries=frozen_queries) # Join with defaults ("dry_run": True) and required password options = { "dry_run": True, "replication_user": "******", "rep_user_passwd": "passwd", } join(self.server, mock_server, **options) # reconnect the server. self.server.connect() # Join with no defaults ("dry_run": True) options = { "group_name": None, "gr_host": "{0}:{1}".format(self.server.host, self.server.port), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": False, "dry_run": True, } # leave the group if is_member_of_group(self.server): leave(self.server, **options) self.assertFalse(join(self.server, mock_server, **options)) # reconnect the server. self.server.connect() self.assertFalse(leave(self.server, **options)) # reconnect the server. self.server.connect()
def test_bootstrap_noselect_priv(self): """Tests commands without Select privilege. """ self.server.exec_query("drop user if exists 'not_select'@'%'") change_user_privileges(self.server, "not_select", "%", user_passwd="pass", create_user=True) server1 = Server({ "conn_info": "not_select@localhost:{0}".format(self.server.port)}) server1.passwd = "pass" server1.connect() # Fill the options options = { "group_name": "b7286041-3016-11e6-ba52-507b9d87510a", "gr_host": ":{0}".format(self.server.port), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": True, "dry_run": False, } # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: leave(server1, **options) exception = test_raises.exception self.assertTrue("not have enough privileges to verify server" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. server1.connect() # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: start(server1, **options) exception = test_raises.exception self.assertTrue("The operation could not continue due to" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. server1.connect() # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: health(server1, **options) exception = test_raises.exception self.assertTrue("not have enough privileges to verify server" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. server1.connect() # expect GadgetError: Query failed: not have enough privileges to # verify server with self.assertRaises(GadgetError) as test_raises: leave(server1, **options) exception = test_raises.exception self.assertTrue("not have enough privileges to verify server" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg))
def test_bootstrap(self): """Tests start method """ # Fill the options options = { "group_name": None, "replication_user": None, "rep_user_passwd": "passwd", "verbose": True } # test start if is_member_of_group(self.server): leave(self.server, **options) # reconnect the server. self.server.connect() self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() # health health(self.server, **options) # reconnect the server. self.server.connect() # Bootstrap active server # Trying to start a group with a server that is already a member # expect GadgetError: Query failed: is already a member of a GR group. with self.assertRaises(GadgetError) as test_raises: start(self.server, **options) exception = test_raises.exception self.assertTrue("is already a member" in exception.errmsg, "The exception message was not the expected. {0}" "".format(exception.errmsg)) # reconnect the server. self.server.connect() leave(self.server, **options) # reconnect the server. self.server.connect() group_name = "b7286041-3016-11e6-ba52-507b9d87510a" # start using not defaults options = { "group_name": "b7286041-3016-11e6-ba52-507b9d87510a", "gr_host": "{0}:".format(self.server.host), "replication_user": "******", "rep_user_passwd": "passwd", "verbose": True, "dry_run": False, } self.assertTrue(start(self.server, **options)) # reconnect the server. self.server.connect() self.assertTrue(is_member_of_group(self.server, group_name)) self.assertFalse(is_member_of_group(self.server, "group_name")) if is_member_of_group(self.server): leave(self.server, **options) # reconnect the server. self.server.connect()
def main(): # Get the provided command command = sys.argv[1] # Read options from stdin data = "" while True: line = sys.stdin.readline() if line == ".\n": break data += line shell_options = json.loads(fs_decode(data)) cmd_options = shell_options[0] del shell_options[0] # Setup logging with the appropriate verbosity level. setup_logging(verbosity=int(cmd_options['verbose'])) logging.setLoggerClass(CustomLevelLogger) _LOGGER = logging.getLogger(_SCRIPT_NAME) # Handle keyboard interrupt on password retrieve and command execution. try: # Perform command command_error_msg = "executing operation" try: if command == CHECK: if cmd_options.get("update", False): command_error_msg = "configuring instance" else: command_error_msg = "checking instance" check(**cmd_options) elif command == JOIN: command_error_msg = "joining instance to cluster" server = shell_options[0] peer_server = shell_options[1] join(server, peer_server, **cmd_options) elif command == LEAVE: command_error_msg = "leaving cluster" server = shell_options[0] leave(server, **cmd_options) elif command == START: command_error_msg = "starting cluster" server = shell_options[0] start(server, **cmd_options) elif command == SANDBOX: sandbox_cmd = cmd_options["sandbox_cmd"] command = '{0} {1}'.format(command, sandbox_cmd) command_error_msg = "executing sandbox operation" if sandbox_cmd == SANDBOX_START: command_error_msg = "starting sandbox" start_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_CREATE: command_error_msg = "creating sandbox" create_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_STOP: command_error_msg = "stopping sandbox" stop_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_KILL: command_error_msg = "killing sandbox" kill_sandbox(**cmd_options) elif sandbox_cmd == SANDBOX_DELETE: command_error_msg = "deleting sandbox" delete_sandbox(**cmd_options) except GadgetError: _, err, _ = sys.exc_info() # the check for mysql.get_classic_session is a hack to prevent # double printing of the DB error if err.cause and u"mysql.get_classic_session" not in unicode(err): _LOGGER.error(u"Error %s: %s: %s", command_error_msg, unicode(err), unicode(err.cause)) else: _LOGGER.error(u"Error %s: %s", command_error_msg, unicode(err)) if _LOGGER.level <= logging.DEBUG: import traceback _LOGGER.debug("%s", traceback.format_exc()) sys.exit(1) except UnicodeEncodeError: _, err, _ = sys.exc_info() _LOGGER.error(u"Unicode error %s: %s. Make sure your locale " u"system settings support UTF-8 to use non-ASCII " u"values.", command_error_msg, unicode(err)) if _LOGGER.level <= logging.DEBUG: import traceback _LOGGER.debug("%s", traceback.format_exc()) sys.exit(1) except Exception: # pylint: disable=broad-except _, err, _ = sys.exc_info() _LOGGER.error(u"Unexpected error %s: %s", command_error_msg, unicode(err)) if _LOGGER.level <= logging.DEBUG: import traceback _LOGGER.debug("%s", traceback.format_exc()) sys.exit(1) # Operation completed with success. sys.exit(0) except KeyboardInterrupt: _LOGGER.error("keyboard interruption (^C) received, stopping...") if os.name == "nt": # Using signal.CTRL_C_EVENT on windows will not set any error code. # Simulate the Unix signal exit code 130 - Script terminated by # Control-C for ngshell to interpreted it as the same way as on # linux. sys.exit(130) else: signal.signal(signal.SIGINT, signal.SIG_DFL) os.kill(os.getpid(), signal.SIGINT)