def _post_send_command(raw_response: bytes, processed_response: bytes,
                           response: Response) -> Response:
        """
        Handle post "send_command" tasks for consistency between sync/async versions

        Args:
            raw_response: raw response returned from the channel
            processed_response: processed response returned from the channel
            response: response object to update with channel results

        Returns:
            Response: Scrapli Response object

        Raises:
            N/A

        """
        response._record_response(result=processed_response)  # pylint: disable=W0212
        response.raw_result = raw_response
        return response
Example #2
0
    def send_command(
        self,
        command: str,
        strip_prompt: bool = True,
        failed_when_contains: Optional[Union[str, List[str]]] = None,
    ) -> Response:
        """
        Send a command

        Args:
            command: string to send to device in privilege exec mode
            strip_prompt: True/False strip prompt from returned output
            failed_when_contains: string or list of strings indicating failure if found in response

        Returns:
            Response: Scrapli Response object

        Raises:
            TypeError: if command is anything but a string

        """
        if not isinstance(command, str):
            raise TypeError(
                f"`send_command` expects a single string, got {type(command)}. "
                "to send a list of commands use the `send_commands` method instead."
            )

        response = Response(
            host=self.transport.host,
            channel_input=command,
            failed_when_contains=failed_when_contains,
        )
        raw_response, processed_response = self.channel.send_input(
            channel_input=command, strip_prompt=strip_prompt
        )
        response._record_response(result=processed_response)  # pylint: disable=W0212
        response.raw_result = raw_response

        return response
Example #3
0
    def send_inputs_interact(self,
                             channel_inputs: List[str],
                             hidden_response: bool = False) -> Response:
        """
        Send inputs in an interactive fashion, used to handle prompts that occur after an input.

        Args:
            channel_inputs: list of four string elements representing...
                channel_input - initial input to send
                expected_prompt - prompt to expect after initial input
                response - response to prompt
                final_prompt - final prompt to expect
            hidden_response: True/False response is hidden (i.e. password input)

        Returns:
            Response: scrapli Response object

        Raises:
            TypeError: if inputs is not tuple or list

        """
        if not isinstance(channel_inputs, list):
            raise TypeError(
                f"`send_inputs_interact` expects a List, got {type(channel_inputs)}"
            )
        channel_input, expectation, channel_response, finale = channel_inputs
        response = Response(
            self.transport.host,
            channel_input,
            expectation=expectation,
            channel_response=channel_response,
            finale=finale,
        )
        raw_result, processed_result = self._send_input_interact(
            channel_input, expectation, channel_response, finale,
            hidden_response)
        response.raw_result = raw_result.decode()
        response.record_response(processed_result.decode().strip())
        return response
Example #4
0
    def send_interactive(
        self,
        interact_events: List[Tuple[str, str, Optional[bool]]],
        failed_when_contains: Optional[Union[str, List[str]]] = None,
        privilege_level: str = "",
    ) -> Response:
        """
        Interact with a device with changing prompts per input.

        Used to interact with devices where prompts change per input, and where inputs may be hidden
        such as in the case of a password input. This can be used to respond to challenges from
        devices such as the confirmation for the command "clear logging" on IOSXE devices for
        example. You may have as many elements in the "interact_events" list as needed, and each
        element of that list should be a tuple of two or three elements. The first element is always
        the input to send as a string, the second should be the expected response as a string, and
        the optional third a bool for whether or not the input is "hidden" (i.e. password input)

        An example where we need this sort of capability:

        ```
        3560CX#copy flash: scp:
        Source filename []? test1.txt
        Address or name of remote host []? 172.31.254.100
        Destination username [carl]?
        Writing test1.txt
        Password:

        Password:
         Sink: C0644 639 test1.txt
        !
        639 bytes copied in 12.066 secs (53 bytes/sec)
        3560CX#
        ```

        To accomplish this we can use the following:

        ```
        interact = conn.channel.send_inputs_interact(
            [
                ("copy flash: scp:", "Source filename []?", False),
                ("test1.txt", "Address or name of remote host []?", False),
                ("172.31.254.100", "Destination username [carl]?", False),
                ("carl", "Password:"******"super_secure_password", prompt, True),
            ]
        )
        ```

        If we needed to deal with more prompts we could simply continue adding tuples to the list of
        interact "events".

        Args:
            interact_events: list of tuples containing the "interactions" with the device
                each list element must have an input and an expected response, and may have an
                optional bool for the third and final element -- the optional bool specifies if the
                input that is sent to the device is "hidden" (ex: password), if the hidden param is
                not provided it is assumed the input is "normal" (not hidden)
            failed_when_contains: list of strings that, if present in final output, represent a
                failed command/interaction
            privilege_level: ignored in this base class; for LSP reasons for subclasses

        Returns:
            Response: scrapli Response object

        Raises:
            N/A

        """
        _ = privilege_level

        joined_input = ", ".join([event[0] for event in interact_events])
        response = Response(
            self.transport.host,
            channel_input=joined_input,
            failed_when_contains=failed_when_contains,
        )
        raw_response, processed_response = self.channel.send_inputs_interact(
            interact_events=interact_events
        )
        response._record_response(result=processed_response)  # pylint: disable=W0212
        response.raw_result = raw_response

        return response