Esempio n. 1
0
def genie_parse(platform: str, command: str,
                output: str) -> Union[List[Any], Dict[str, Any]]:
    """
    Parse output with Cisco genie parsers, try to return structured output

    Args:
        platform: genie device type; i.e. iosxe, iosxr, etc.
        command: string of command that was executed (to find appropriate parser)
        output: unstructured output from device to parse

    Returns:
        output: structured data

    Raises:
        N/A

    """
    try:
        Device = getattr(
            importlib.import_module(name=".conf.base", package="genie"),
            "Device")
        get_parser = getattr(
            importlib.import_module(name=".libs.parser.utils",
                                    package="genie"), "get_parser")
    except ModuleNotFoundError as exc:
        title = "Optional Extra Not Installed!"
        message = (
            "Optional extra 'genie' is not installed!\n"
            f"To resolve this issue, install '{exc.name}'. You can do this in one of the following"
            " ways:\n"
            "1: 'pip install -r requirements-genie.txt'\n"
            "2: 'pip install scrapli[genie]'")
        user_warning(title=title, message=message)
        return []

    genie_device = Device("scrapli_device",
                          custom={"abstraction": {
                              "order": ["os"]
                          }},
                          os=platform)

    try:
        get_parser(command, genie_device)
        genie_parsed_result = genie_device.parse(command, output=output)
        if isinstance(genie_parsed_result, (list, dict)):
            return genie_parsed_result
    except Exception as exc:  # pylint: disable=W0703
        logger.warning(
            f"failed to parse data with genie, genie raised exception: `{exc}`"
        )
    return []
Esempio n. 2
0
def user_warning(title: str, message: str) -> None:
    """
    Nicely raise warning messages for users

    Args:
        title: title of the warning message
        message: actual message body

    Returns:
        None

    Raises:
        N/A

    """
    warning_message = format_user_warning(title=title, message=message)
    logger.warning(warning_message)
    warn(warning_message)
Esempio n. 3
0
def _textfsm_get_template(platform: str, command: str) -> Optional[TextIO]:
    """
    Find correct TextFSM template based on platform and command executed

    Args:
        platform: ntc-templates device type; i.e. cisco_ios, arista_eos, etc.
        command: string of command that was executed (to find appropriate template)

    Returns:
        None or TextIO of opened template

    Raises:
        N/A

    """
    try:
        importlib.import_module(name=".templates", package="ntc_templates")
        CliTable = getattr(
            importlib.import_module(name=".clitable", package="textfsm"),
            "CliTable")
    except ModuleNotFoundError as exc:
        title = "Optional Extra Not Installed!"
        message = (
            "Optional extra 'textfsm' is not installed!\n"
            f"To resolve this issue, install '{exc.name}'. You can do this in one of the following"
            " ways:\n"
            "1: 'pip install -r requirements-textfsm.txt'\n"
            "2: 'pip install scrapli[textfsm]'")
        user_warning(title=title, message=message)
        return None
    template_dir = pkg_resources.resource_filename("ntc_templates",
                                                   "templates")
    cli_table = CliTable("index", template_dir)
    template_index = cli_table.index.GetRowMatch({
        "Platform": platform,
        "Command": command
    })
    if not template_index:
        logger.warning(
            f"No match in ntc_templates index for platform `{platform}` and command `{command}`"
        )
        return None
    template_name = cli_table.index.index[template_index]["Template"]
    return open(f"{template_dir}/{template_name}", encoding="utf-8")
Esempio n. 4
0
def textfsm_parse(template: Union[str, TextIOWrapper],
                  output: str,
                  to_dict: bool = True) -> Union[List[Any], Dict[str, Any]]:
    """
    Parse output with TextFSM and ntc-templates, try to return structured output

    Args:
        template: TextIOWrapper or string of URL or filesystem path to template to use to parse data
        output: unstructured output from device to parse
        to_dict: convert textfsm output from list of lists to list of dicts -- basically create dict
            from header and row data so it is easier to read/parse the output

    Returns:
        output: structured data

    Raises:
        N/A

    """
    import textfsm  # pylint: disable=C0415

    if not isinstance(template, TextIOWrapper):
        if template.startswith("http://") or template.startswith("https://"):
            with urllib.request.urlopen(template) as response:
                template_file = TextIOWrapper(
                    BytesIO(response.read()),
                    encoding=response.headers.get_content_charset(),
                )
        else:
            template_file = TextIOWrapper(open(template, mode="rb"))  # pylint: disable=R1732
    else:
        template_file = template
    re_table = textfsm.TextFSM(template_file)
    try:
        structured_output: Union[List[Any],
                                 Dict[str, Any]] = re_table.ParseText(output)
        if to_dict:
            structured_output = _textfsm_to_dict(
                structured_output=structured_output, header=re_table.header)
        return structured_output
    except textfsm.parser.TextFSMError:
        logger.warning("failed to parse data with textfsm")
    return []
Esempio n. 5
0
def user_warning(title: str, message: str) -> None:
    """
    Nicely raise warning messages for users

    Args:
        title: title of the warning message
        message: actual message body

    Returns:
        None

    Raises:
        N/A

    """
    warning_message = format_user_warning(title=title, message=message)
    logger.warning(warning_message)

    if Settings.SUPPRESS_USER_WARNINGS is False:
        warn(warning_message)
Esempio n. 6
0
def textfsm_parse(
    template: Union[str, TextIOWrapper], output: str, to_dict: bool = True
) -> Union[List[Any], Dict[str, Any]]:
    """
    Parse output with TextFSM and ntc-templates, try to return structured output

    Args:
        template: TextIOWrapper or string path to template to use to parse data
        output: unstructured output from device to parse
        to_dict: convert textfsm output from list of lists to list of dicts -- basically create dict
            from header and row data so it is easier to read/parse the output

    Returns:
        output: structured data

    Raises:
        N/A

    """
    import textfsm  # pylint: disable=C0415

    if not isinstance(template, TextIOWrapper):
        template_file = open(template)
    else:
        template_file = template
    re_table = textfsm.TextFSM(template_file)
    try:
        structured_output: Union[List[Any], Dict[str, Any]] = re_table.ParseText(output)
        if to_dict:
            structured_output = _textfsm_to_dict(
                structured_output=structured_output, header=re_table.header
            )
        return structured_output
    except textfsm.parser.TextFSMError:
        logger.warning("failed to parse data with textfsm")
    return []