Skip to content

ark_ssh_connection

ArkSSHConnection

Bases: ArkConnection

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
class ArkSSHConnection(ArkConnection):
    def __init__(self):
        super().__init__()
        self.__is_connected: bool = False
        self.__is_suspended: bool = False
        self.__ssh_client: Optional[Any] = None

    @overrides
    def connect(self, connection_details: ArkConnectionDetails) -> None:
        """
        Performs SSH connection with given details or keys
        Saves the ssh session to be used for command executions

        Args:
            connection_details (ArkConnectionDetails): _description_

        Raises:
            ArkException: _description_
        """
        import paramiko

        if self.__is_connected:
            return
        try:
            target_port = SSH_PORT
            user = None
            password = None
            private_key_data = None
            private_key = None
            if connection_details.port:
                target_port = connection_details.port
            if connection_details.credentials:
                user = connection_details.credentials.user
                if connection_details.credentials.password:
                    password = connection_details.credentials.password.get_secret_value()
                elif connection_details.credentials.private_key_filepath:
                    path = Path(connection_details.credentials.private_key_filepath)
                    if not path.exists():
                        raise ArkException(f'Given private key path [{path}] does not exist')
                    private_key_data = path.read_text(encoding='utf-8')
                elif connection_details.credentials.private_key_contents:
                    private_key_data = connection_details.credentials.private_key_contents
                if private_key_data:
                    private_key_io = StringIO(private_key_data)
                    private_key = paramiko.RSAKey.from_private_key(private_key_io)
                    private_key_io.close()
            self.__ssh_client = paramiko.SSHClient()
            self.__ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.__ssh_client.connect(
                hostname=connection_details.address, port=target_port, username=user, password=password, pkey=private_key
            )
            self.__is_connected = True
            self.__is_suspended = False
        except Exception as ex:
            raise ArkException(f'Failed to ssh connect [{str(ex)}]') from ex

    @overrides
    def disconnect(self) -> None:
        """
        Disconnects the ssh session
        """
        if not self.__is_connected:
            return
        self.__ssh_client.close()
        self.__ssh_client = None
        self.__is_connected = False
        self.__is_suspended = False

    @overrides
    def suspend_connection(self) -> None:
        """
        Suspends execution of ssh commands
        """
        self.__is_suspended = True

    @overrides
    def restore_connection(self) -> None:
        """
        Restores execution of ssh commands
        """
        self.__is_suspended = False

    @overrides
    def is_suspended(self) -> bool:
        """
        Checks whether ssh commands can be executed or not

        Returns:
            bool: _description_
        """
        return self.__is_suspended

    @overrides
    def is_connected(self) -> bool:
        """
        Checks whether theres a ssh session connected

        Returns:
            bool: _description_
        """
        return self.__is_connected

    @overrides
    def run_command(self, command: ArkConnectionCommand) -> ArkConnectionResult:
        """
        Runs a command over ssh session, returning the result accordingly

        Args:
            command (ArkConnectionCommand): _description_

        Raises:
            ArkException: _description_

        Returns:
            ArkConnectionResult: _description_
        """
        if not self.__is_connected or self.__is_suspended:
            raise ArkException('Cannot run command while not being connected')
        self._logger.debug(f'Running command [{command.command}]')
        _, stdout_stream, stderr_stream = self.__ssh_client.exec_command(command=command.command)
        rc = stdout_stream.channel.recv_exit_status()
        stdout = ''.join(stdout_stream.readlines())
        stderr = ''.join(stderr_stream.readlines())
        if rc != command.expected_rc and command.raise_on_error:
            raise ArkException(f'Failed to execute command [{command.command}] - [{rc}] - [{stderr}]')
        self._logger.debug(f'Command rc: [{rc}]')
        self._logger.debug(f'Command stdout: [{stdout}]')
        self._logger.debug(f'Command stderr: [{stderr}]')
        return ArkConnectionResult(stdout=stdout, stderr=stderr, rc=rc)

connect(connection_details)

Performs SSH connection with given details or keys Saves the ssh session to be used for command executions

Parameters:

Name Type Description Default
connection_details ArkConnectionDetails

description

required

Raises:

Type Description
ArkException

description

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@overrides
def connect(self, connection_details: ArkConnectionDetails) -> None:
    """
    Performs SSH connection with given details or keys
    Saves the ssh session to be used for command executions

    Args:
        connection_details (ArkConnectionDetails): _description_

    Raises:
        ArkException: _description_
    """
    import paramiko

    if self.__is_connected:
        return
    try:
        target_port = SSH_PORT
        user = None
        password = None
        private_key_data = None
        private_key = None
        if connection_details.port:
            target_port = connection_details.port
        if connection_details.credentials:
            user = connection_details.credentials.user
            if connection_details.credentials.password:
                password = connection_details.credentials.password.get_secret_value()
            elif connection_details.credentials.private_key_filepath:
                path = Path(connection_details.credentials.private_key_filepath)
                if not path.exists():
                    raise ArkException(f'Given private key path [{path}] does not exist')
                private_key_data = path.read_text(encoding='utf-8')
            elif connection_details.credentials.private_key_contents:
                private_key_data = connection_details.credentials.private_key_contents
            if private_key_data:
                private_key_io = StringIO(private_key_data)
                private_key = paramiko.RSAKey.from_private_key(private_key_io)
                private_key_io.close()
        self.__ssh_client = paramiko.SSHClient()
        self.__ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.__ssh_client.connect(
            hostname=connection_details.address, port=target_port, username=user, password=password, pkey=private_key
        )
        self.__is_connected = True
        self.__is_suspended = False
    except Exception as ex:
        raise ArkException(f'Failed to ssh connect [{str(ex)}]') from ex

disconnect()

Disconnects the ssh session

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
72
73
74
75
76
77
78
79
80
81
82
@overrides
def disconnect(self) -> None:
    """
    Disconnects the ssh session
    """
    if not self.__is_connected:
        return
    self.__ssh_client.close()
    self.__ssh_client = None
    self.__is_connected = False
    self.__is_suspended = False

is_connected()

Checks whether theres a ssh session connected

Returns:

Name Type Description
bool bool

description

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
108
109
110
111
112
113
114
115
116
@overrides
def is_connected(self) -> bool:
    """
    Checks whether theres a ssh session connected

    Returns:
        bool: _description_
    """
    return self.__is_connected

is_suspended()

Checks whether ssh commands can be executed or not

Returns:

Name Type Description
bool bool

description

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
 98
 99
100
101
102
103
104
105
106
@overrides
def is_suspended(self) -> bool:
    """
    Checks whether ssh commands can be executed or not

    Returns:
        bool: _description_
    """
    return self.__is_suspended

restore_connection()

Restores execution of ssh commands

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
91
92
93
94
95
96
@overrides
def restore_connection(self) -> None:
    """
    Restores execution of ssh commands
    """
    self.__is_suspended = False

run_command(command)

Runs a command over ssh session, returning the result accordingly

Parameters:

Name Type Description Default
command ArkConnectionCommand

description

required

Raises:

Type Description
ArkException

description

Returns:

Name Type Description
ArkConnectionResult ArkConnectionResult

description

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
@overrides
def run_command(self, command: ArkConnectionCommand) -> ArkConnectionResult:
    """
    Runs a command over ssh session, returning the result accordingly

    Args:
        command (ArkConnectionCommand): _description_

    Raises:
        ArkException: _description_

    Returns:
        ArkConnectionResult: _description_
    """
    if not self.__is_connected or self.__is_suspended:
        raise ArkException('Cannot run command while not being connected')
    self._logger.debug(f'Running command [{command.command}]')
    _, stdout_stream, stderr_stream = self.__ssh_client.exec_command(command=command.command)
    rc = stdout_stream.channel.recv_exit_status()
    stdout = ''.join(stdout_stream.readlines())
    stderr = ''.join(stderr_stream.readlines())
    if rc != command.expected_rc and command.raise_on_error:
        raise ArkException(f'Failed to execute command [{command.command}] - [{rc}] - [{stderr}]')
    self._logger.debug(f'Command rc: [{rc}]')
    self._logger.debug(f'Command stdout: [{stdout}]')
    self._logger.debug(f'Command stderr: [{stderr}]')
    return ArkConnectionResult(stdout=stdout, stderr=stderr, rc=rc)

suspend_connection()

Suspends execution of ssh commands

Source code in ark_sdk_python/common/connections/ssh/ark_ssh_connection.py
84
85
86
87
88
89
@overrides
def suspend_connection(self) -> None:
    """
    Suspends execution of ssh commands
    """
    self.__is_suspended = True