def close_connection(self):
        """
        This sends exit to the remote shell. If there are stopped jobs then
        this automatically sends exit twice.
        :return:
        """

        try:
            self.sendline(Common.Utilities.Enums.ControlKeys.ctr_c)
            self.sendline("exit")
            index = self.expect(
                [pexpect.EOF, "(?i)there are stopped jobs", pexpect.TIMEOUT])

            if index == 1:
                self.sendline("exit")
                self.expect(pexpect.EOF)
            elif index == 2:
                PExpectWrapper.display_before_n_after(self)
        except OSError:
            pass

        self.close()

        PrintMessage('Connection closed: {0}@{1}:{2}'.format(
            self.username, self.host, self.port))
    def get_json_data(self,
                      command_line,
                      delay=None,
                      data_struct=None,
                      show_details=False):
        """
        Sends command to cli and gets the json data formatted into dictionary
        :param data_struct: expected data format, almost like a schema check ;)
        Expected string type. Format:
        ['data']['corero-cms-system:system']['software']['installed']

        :param command_line: Command is expected to contain '| nomore | display json'
        :param delay: wait after sending command
        :param show_details: Adds ' | details' to the command line, if missing
        :return:
        """
        if show_details and SHOW_DETAILS not in command_line:
            command_line += SHOW_DETAILS

        if SHOW_JSON not in command_line:
            command_line += SHOW_JSON
        self.send_cmd(command_line, expected_value='json', delay=delay)

        json_data = PExpectWrapper.get_json_from_cli(self.cli)

        if data_struct:
            try:
                return eval(str(json_data) + data_struct)
            except (TypeError, KeyError):
                PExpectWrapper.display_before_n_after(self.cli)
                return None

        return json_data
    def expect(self, expect_value):
        try:
            PrintMessage("Expect value: {0}".format(expect_value))
            return self.cli.expect(expect_value)

        except:
            PExpectWrapper.display_before_n_after(self.cli)
            raise
    def setup_time(self, time_zone, enable_ntp='N', ntp_server=None):
        PrintMessage('Changing time zone to {0}, ntp server to {1} '.format(
            time_zone, ntp_server))

        self.send_cmd('setup time')
        self.send_cmd(enable_ntp)
        if enable_ntp.lower() == 'y':
            self.send_cmd(ntp_server)
            self.send_cmd(
                'none')  # secondary server, none to finish server insertion

        self.send_cmd(time_zone)

        # expects [A]ccept, [C]hange
        if self.expect(['Enter \[A\]ccept', 'Enter \[C\]hange']) == 0:
            # save changes
            self.send_cmd('a', delay=60, expected_value='Applying changes...')
        else:
            # exit without saving as no modification was made
            self.send_cmd('e')

        # Added check to fish out any warnings SWALL-5007
        index = self.expect([self.cli_prompt, 'WARNING'])
        if index == 0:
            return
        elif index == 1:
            self.expect(self.cli_prompt)
            PrintMessage(PExpectWrapper.display_before_n_after(self.cli))
            assert False, "WARNING message is displayed: SWALL-5738"
    def log_with_ssh(self, username, password, host, port=None, expect=None):
        """
        Helper method used to login with SSH
        method removes host from known_host list
        method creates a connection string

        :param expect:
        :param username:
        :param password:
        :param host:
        :param port:
        :return:
        """
        PrintMessage("ssh-ing to {0}@{1}:{2}".format(username, host, port))
        self.username = username
        self.host = host
        self.port = port

        self.remove_known_host_entry(host, port)

        connection_string = self.get_connection_string(username, host, port)

        pexpect.spawn._spawn(self, connection_string)

        expect_at_connection = [
            "password", "Failed to connect to server", "Connection refused",
            "No route to host", pexpect.TIMEOUT, pexpect.EOF
        ]

        index = self.expect(expect_at_connection)

        if index == 0:
            if password:
                self.sendline(password)

            if expect:
                expect_ = [expect, pexpect.TIMEOUT, pexpect.EOF]
                index = self.expect(expect_)

                if index == 0:
                    return True
                else:
                    raise FailedLoginError

        else:
            PExpectWrapper.display_before_n_after(self)
            raise FailedLoginError
    def send_cmd(self, command_line='', expected_value="[ok]", delay=None):
        """
        Wrapper around PExpect sendline command

        :param command_line:
        :param expected_value: by default it expects an [ok] string, this is tuned towards CMS communication
        However, this can be used by any ssh type connection
        :param delay: wait after sending command
        :return:
        """
        PrintMessage("cmd({0}): {1}".format(self.user.name, command_line))
        self.cli.sendline(command_line)

        if delay is not None:
            time.sleep(delay)

        if expected_value is not None:
            try:
                if '[error]' in self.cli.before:
                    PrintMessage('ERROR noted in cli', LoggingLevel.warning)
                    PExpectWrapper.display_before_n_after(self.cli)

                index = self.cli.expect(expected_value)
                if '[error]' in self.cli.before:
                    PrintMessage('ERROR noted in cli', LoggingLevel.warning)
                    PExpectWrapper.display_before_n_after(self.cli)

                return index

            except:
                PExpectWrapper.display_before_n_after(self.cli)
                raise

        return self.cli.before
    def send_cmd(self, command_line='', expected_value=None, delay=None):
        """
        Wrapper around PExpect sendline command

        :param command_line:
        :param expected_value: Often used to reset position in pexpect buffer stream.
        :param delay: wait after sending command
        :return:
        """
        PrintMessage("cmd({0}): {1}".format(self.user.name, command_line))
        self.cli.sendline(command_line)

        if delay is not None:
            time.sleep(delay)

        if expected_value is not None:
            try:
                return self.cli.expect_exact(expected_value)
            except:
                PExpectWrapper.display_before_n_after(self.cli)
                raise

        return self.cli.before