def test_textfsm_direct_template():
    """Convert raw CLI output to structured data using TextFSM template (no index)."""
    raw_output = "Cisco IOS Software, Catalyst 4500 L3 Switch Software"
    result = utilities.get_structured_data(
        raw_output,
        platform="cisco_ios",
        command="show version",
        template=f"{RESOURCE_FOLDER}/cisco_ios_show_version.template",
    )
    assert result == [{"model": "4500"}]

    # Should also work with no-platform or command
    result = utilities.get_structured_data(
        raw_output,
        template=f"{RESOURCE_FOLDER}/cisco_ios_show_version.template")
    assert result == [{"model": "4500"}]
예제 #2
0
def test_get_structured_data():
    """Convert raw CLI output to structured data using TextFSM template"""
    environ["NET_TEXTFSM"] = RESOURCE_FOLDER
    raw_output = "Cisco IOS Software, Catalyst 4500 L3 Switch Software"
    result = utilities.get_structured_data(
        raw_output, platform="cisco_ios", command="show version"
    )
    assert result == [{"model": "4500"}]
def test_textfsm_index_relative_path():
    """Test relative path for textfsm ntc directory"""
    os.environ["NET_TEXTFSM"] = RELATIVE_RESOURCE_FOLDER
    raw_output = "Cisco IOS Software, Catalyst 4500 L3 Switch Software"
    result = utilities.get_structured_data(raw_output,
                                           platform="cisco_ios",
                                           command="show version")
    assert result == [{"model": "4500"}]
def test_textfsm_w_index():
    """Convert raw CLI output to structured data using TextFSM template"""
    os.environ["NET_TEXTFSM"] = RESOURCE_FOLDER
    raw_output = "Cisco IOS Software, Catalyst 4500 L3 Switch Software"
    result = utilities.get_structured_data(raw_output,
                                           platform="cisco_ios",
                                           command="show version")
    assert result == [{"model": "4500"}]
def test_textfsm_missing_template():
    """Verify raw_output is returned if TextFSM template is missing."""
    raw_output = "Cisco IOS Software, Catalyst 4500 L3 Switch Software"
    result = utilities.get_structured_data(
        raw_output,
        platform="cisco_ios",
        command="show version",
        template=f"{RESOURCE_FOLDER}/nothinghere",
    )
    assert result == raw_output
def test_textfsm_failed_parsing():
    """Verify raw_output is returned if TextFSM template parsing fails."""
    raw_output = "This is not 'show version' output"
    result = utilities.get_structured_data(
        raw_output,
        platform="cisco_ios",
        command="show version",
        template=f"{RESOURCE_FOLDER}/nothinghere",
    )
    assert result == raw_output
예제 #7
0
    def send_command_timing(self, command_string, delay_factor=1, max_loops=150,
                            strip_prompt=True, strip_command=True, normalize=True,
                            use_textfsm=False):
        """Execute command_string on the SSH channel using a delay-based mechanism. Generally
        used for show commands.

        :param command_string: The command to be executed on the remote device.
        :type command_string: str
        :param delay_factor: Multiplying factor used to adjust delays (default: 1).
        :type delay_factor: int or float
        :param max_loops: Controls wait time in conjunction with delay_factor. Will default to be
            based upon self.timeout.
        :type max_loops: int
        :param strip_prompt: Remove the trailing router prompt from the output (default: True).
        :type strip_prompt: bool
        :param strip_command: Remove the echo of the command from the output (default: True).
        :type strip_command: bool
        :param normalize: Ensure the proper enter is sent at end of command (default: True).
        :type normalize: bool
        :param use_textfsm: Process command output through TextFSM template (default: False).
        :type normalize: bool
        """
        output = ''
        delay_factor = self.select_delay_factor(delay_factor)
        self.clear_buffer()
        if normalize:
            command_string = self.normalize_cmd(command_string)

        self.write_channel(command_string)
        output = self._read_channel_timing(delay_factor=delay_factor, max_loops=max_loops)
        output = self._sanitize_output(output, strip_command=strip_command,
                                       command_string=command_string, strip_prompt=strip_prompt)
        if use_textfsm:
            output = get_structured_data(output, platform=self.device_type,
                                         command=command_string.strip())
        return output
예제 #8
0
    def send_command(self, command_string, expect_string=None,
                     delay_factor=1, max_loops=500, auto_find_prompt=True,
                     strip_prompt=True, strip_command=True, normalize=True,
                     use_textfsm=False):
        """Execute command_string on the SSH channel using a pattern-based mechanism. Generally
        used for show commands. By default this method will keep waiting to receive data until the
        network device prompt is detected. The current network device prompt will be determined
        automatically.

        :param command_string: The command to be executed on the remote device.
        :type command_string: str

        :param expect_string: Regular expression pattern to use for determining end of output.
            If left blank will default to being based on router prompt.
        :type expect_string: str

        :param delay_factor: Multiplying factor used to adjust delays (default: 1).
        :type delay_factor: int

        :param max_loops: Controls wait time in conjunction with delay_factor. Will default to be
            based upon self.timeout.
        :type max_loops: int

        :param strip_prompt: Remove the trailing router prompt from the output (default: True).
        :type strip_prompt: bool

        :param strip_command: Remove the echo of the command from the output (default: True).
        :type strip_command: bool

        :param normalize: Ensure the proper enter is sent at end of command (default: True).
        :type normalize: bool

        :param use_textfsm: Process command output through TextFSM template (default: False).
        :type normalize: bool
        """
        # Time to delay in each read loop
        loop_delay = .2

        # Default to making loop time be roughly equivalent to self.timeout (support old max_loops
        # and delay_factor arguments for backwards compatibility).
        delay_factor = self.select_delay_factor(delay_factor)
        if delay_factor == 1 and max_loops == 500:
            # Default arguments are being used; use self.timeout instead
            max_loops = int(self.timeout / loop_delay)

        # Find the current router prompt
        if expect_string is None:
            if auto_find_prompt:
                try:
                    prompt = self.find_prompt(delay_factor=delay_factor)
                except ValueError:
                    prompt = self.base_prompt
            else:
                prompt = self.base_prompt
            search_pattern = re.escape(prompt.strip())
        else:
            search_pattern = expect_string

        if normalize:
            command_string = self.normalize_cmd(command_string)

        time.sleep(delay_factor * loop_delay)
        self.clear_buffer()
        self.write_channel(command_string)

        i = 1
        output = ''
        # Keep reading data until search_pattern is found or until max_loops is reached.
        while i <= max_loops:
            new_data = self.read_channel()
            if new_data:
                output += new_data
                try:
                    lines = output.split(self.RETURN)
                    first_line = lines[0]
                    # First line is the echo line containing the command. In certain situations
                    # it gets repainted and needs filtered
                    if BACKSPACE_CHAR in first_line:
                        pattern = search_pattern + r'.*$'
                        first_line = re.sub(pattern, repl='', string=first_line)
                        lines[0] = first_line
                        output = self.RETURN.join(lines)
                except IndexError:
                    pass
                if re.search(search_pattern, output):
                    break
            else:
                time.sleep(delay_factor * loop_delay)
            i += 1
        else:   # nobreak
            raise IOError("Search pattern never detected in send_command_expect: {}".format(
                search_pattern))

        output = self._sanitize_output(output, strip_command=strip_command,
                                       command_string=command_string, strip_prompt=strip_prompt)
        if use_textfsm:
            output = get_structured_data(output, platform=self.device_type,
                                         command=command_string.strip())
        return output