Source code for nettoolkit.yaml_facts.common.parser

"""Description: 
"""

# ==============================================================================================
#  Imports
# ==============================================================================================
from dataclasses import dataclass, field
from pathlib import Path
import sys, os
import textfsm
from nettoolkit.nettoolkit_common import get_file_name, get_file_path, DIC
from nettoolkit.nettoolkit_db import dict_to_yaml

merge_dict = DIC.merge_dict

# ==============================================================================================
#  Local Statics
# ==============================================================================================


# ==============================================================================================
#  Local Functions
# ==============================================================================================
[docs] def parse_to_list_cmd(abs_cmd, data_list, cmd_parser_file_map): """parse the output Args: abs_cmd (str): absolute command data_list (list): list of output cmd_parser_file_map (dict): command parser map Returns: list: parsed data in list format """ template_file = get_template_file(abs_cmd, cmd_parser_file_map) return parse_to_list(template_file, data_list)
[docs] def parse_to_dict_cmd(abs_cmd, data_list, cmd_parser_file_map): """parse the output Args: abs_cmd (str): absolute command data_list (list): list of output cmd_parser_file_map (dict): command parser map Returns: list: parsed data in dictionary format """ template_file = get_template_file(abs_cmd, cmd_parser_file_map) return parse_to_dict(template_file, data_list)
[docs] def parse_to_list(template_file, data_list): """Parse the data_list using template file. And returns data as list Args: template_file (str): template file data_list (list): output in list formate Returns: list: parsed data in list format """ data = "\n".join(data_list) with open(template_file) as f: textfsm_parser = textfsm.TextFSM(f) parsed_data = textfsm_parser.ParseText(data) return parsed_data
[docs] def parse_to_dict(template_file, data_list): """Parse the data_list using template file. And returns data as dictionary Args: template_file (str): template file data_list (list): output in list formate Returns: dict: parsed data in dictionary format """ data = "\n".join(data_list) with open(template_file) as f: textfsm_parser = textfsm.TextFSM(f) parsed_data = textfsm_parser.ParseTextToDicts(data) return parsed_data
[docs] def get_template_dir(template_path): """returns template directory Args: template_path (str): source of template path Returns: Path: Path where templates are stored. """ folder = "" for path in sys.path: p = Path(path) if not p.is_dir(): continue if p.name == "site-packages" : folder = p break if not folder: print(f"[-] Could not locate ntc template directory...") # template_dir = os.path.join(p, "templates") template_dir = p.resolve().parents[0].joinpath(template_path) return template_dir
[docs] def get_template_file(abs_cmd, cmd_parser_file_map): """returns template file with full path for provided command. Args: abs_cmd (str): absolute command cmd_parser_file_map (dict): parser map to select the template file based on absolute command Raises: Exception: if template file not found or unable to read template. Returns: str: template file """ if not cmd_parser_file_map.get(abs_cmd): return "" # file = get_ntc_template_file(abs_cmd, cmd_parser_file_map) if is_exist(file): return file # file = get_self_template_file(abs_cmd, cmd_parser_file_map) if is_exist(file): return file else: raise Exception(f"[-] Unable to read file {file}, check file does exist..")
[docs] def get_ntc_template_file(abs_cmd, cmd_parser_file_map): """returns ntc template file. Args: abs_cmd (str): absolute command cmd_parser_file_map (dict): parser map to select the template file based on absolute command Returns: str: template file """ p = get_template_dir("site-packages/ntc_templates/templates") return str(p.joinpath(cmd_parser_file_map[abs_cmd]))
[docs] def get_self_template_file(abs_cmd, cmd_parser_file_map): """returns nettoolkit template file. Args: abs_cmd (str): absolute command cmd_parser_file_map (dict): parser map to select the template file based on absolute command Returns: str: template file """ p = get_template_dir("site-packages/nettoolkit/yaml_facts/templates") return str(p.joinpath(cmd_parser_file_map[abs_cmd]))
[docs] def is_exist(file): """check if template file exist or not Args: file (str): file name with full path Returns: bool: True if found else False """ try: with open(file, 'r') as f: pass return True except: return False
# ============================================================================================== # Classes # ==============================================================================================
[docs] @dataclass class CommonParser(): """Common parser methods class. Provide captures, and output_folder to begin. Raises: Exception: for invalid inputs """ captures: any output_folder: str='' def __post_init__(self): self.device_dict = {} self.parse() self.set_output_yaml_filename() self.write_yaml() @property def output_yaml(self): """output yaml file name with full path Returns: str: yaml output file """ return self._yaml_file # sets output yaml file name
[docs] def set_output_yaml_filename(self): try: if not self.output_folder: self.output_folder = get_file_path(self.captures.capture_log_file) else: self.output_folder = Path(self.output_folder) hostname = get_file_name(self.captures.capture_log_file) self._yaml_file = self.output_folder.joinpath(hostname + ".yaml") except: raise Exception(f"[-] Error determining output yaml file, either input is invalid.")
# writes out yaml file (owerright)
[docs] def write_yaml(self): dict_to_yaml(self.device_dict, file=self.output_yaml, mode='w')
# start parsing the outputs
[docs] def parse(self): self.unavailable_cmds = set() for cmd, funcs in self.cmd_fn_parser_map.items(): cmd_output = self.captures.cmd_output(cmd) if not cmd_output: self.unavailable_cmds.add(cmd) continue for fn in funcs: self.parse_func(fn, cmd_output)
# parse a command output using a single function
[docs] def parse_func(self, fn, cmd_output): parsed_fields = fn(cmd_output) self.add_parsed_fields_to_device_dict(parsed_fields)
# merge parsed field with device dictionary
[docs] def add_parsed_fields_to_device_dict(self, parsed_fields): merge_dict(self.device_dict, parsed_fields)
# ============================================================================================== # Main # ============================================================================================== if __name__ == '__main__': pass # ==============================================================================================