예제 #1
0
    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()
예제 #2
0
    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()
예제 #3
0
    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()
예제 #4
0
    def tearDown(self):
        """ Disconnect base server (for all tests).
        """
        # reconnect the server.
        self.server.connect()

        leave(self.server)

        # reconnect the server.
        self.server.connect()

        self.server.exec_query("drop user if exists 'rpl_user'")
        self.server.exec_query("drop user if exists 'nop_user'@'localhost'")
        self.server.exec_query("drop user if exists 'new_rpl_user'")
        self.server.disconnect()
        self.server2.disconnect()
예제 #5
0
    def tearDown(self):
        """ Disconnect base server (for all tests).
        """
        # reconnect the server.
        self.server.connect()

        leave(self.server)

        # reconnect the server.
        self.server.connect()

        self.server.exec_query("drop user if exists 'rpl_user'")
        self.server.exec_query("drop user if exists 'nop_user'@'localhost'")
        self.server.exec_query("drop user if exists 'new_rpl_user'")
        self.server.disconnect()
        self.server2.disconnect()
예제 #6
0
    def test_leave_with_none_values(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: not a member of a Group
        with self.assertRaises(GadgetError) as test_raises:
            leave(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:
            leave(self.mock_no_member, **options)
        exception = test_raises.exception
        self.assertTrue("not a member of a Group" in exception.errmsg,
                        "The exception message was not the expected: {0}"
                        "".format(exception.errmsg))
    try:
        if command == CHECK:
            check(**cmd_options)

        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.
예제 #8
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)
예제 #9
0
    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()
예제 #10
0
    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))
예제 #11
0
    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()
예제 #12
0
    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()
예제 #13
0
    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))
예제 #14
0
    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()
예제 #15
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)