11import builtins
22from enum import Enum
3- from typing import List , Union
3+ from typing import List , Union , Any
4+
5+ try :
6+ from ttp_templates import list_templates_refs , list_templates
7+
8+ HAS_TTP_TEMPLATES = True
9+ except Exception as e :
10+ HAS_TTP_TEMPLATES = False
411
512from picle .models import Outputters , PipeFunctionsModel
6- from pydantic import (
7- BaseModel ,
8- Field ,
9- StrictStr ,
10- )
13+ from pydantic import BaseModel , Field , StrictStr , StrictBool , model_validator
1114
1215from ..common import ClientRunJobArgs , listen_events , log_error_or_result
1316from .nornir_picle_shell_common import (
1417 NorniHostsFilters ,
1518 NornirCommonArgs ,
1619)
20+ from .nornir_picle_shell_cli import (
21+ NrCliPluginNetmiko ,
22+ NrCliPluginScrapli ,
23+ NrCliPluginNapalm ,
24+ )
25+ from norfab .workers .nornir_worker .parse_task import ParseTTPInput
1726
1827
1928class NapalmGettersEnum (str , Enum ):
@@ -49,7 +58,9 @@ class NapalmGettersEnum(str, Enum):
4958
5059
5160class NapalmGettersModel (NorniHostsFilters , NornirCommonArgs , ClientRunJobArgs ):
52- getters : NapalmGettersEnum = Field (..., description = "Select NAPALM getters" )
61+ getters : Union [NapalmGettersEnum , List [NapalmGettersEnum ]] = Field (
62+ ..., description = "Select NAPALM getters"
63+ )
5364
5465 @staticmethod
5566 @listen_events
@@ -62,10 +73,10 @@ def run(uuid, *args, **kwargs):
6273
6374 result = NFCLIENT .run_job (
6475 "nornir" ,
65- "parse " ,
76+ "parse_napalm " ,
6677 workers = workers ,
6778 args = args ,
68- kwargs = { "plugin" : "napalm" , ** kwargs } ,
79+ kwargs = kwargs ,
6980 uuid = uuid ,
7081 timeout = timeout ,
7182 nowait = nowait ,
@@ -80,16 +91,119 @@ class PicleConfig:
8091 outputter = Outputters .outputter_nested
8192
8293
83- class TTPParseModel (NorniHostsFilters , NornirCommonArgs , ClientRunJobArgs ):
84- template : StrictStr = Field (
85- ..., description = "TTP Template to parse commands output"
94+ class TTPStructureOptions (str , Enum ):
95+ list_ = "list"
96+ dictionary = "dictionary"
97+ flat_list = "flat_list"
98+
99+
100+ class TTPParseNrCliPluginNetmiko (NrCliPluginNetmiko ):
101+ @staticmethod
102+ def run (* args , ** kwargs ):
103+ kwargs ["plugin" ] = "netmiko"
104+ return TTPParseModel .run (* args , ** kwargs )
105+
106+
107+ class TTPParseNrCliPluginScrapli (NrCliPluginScrapli ):
108+ @staticmethod
109+ def run (* args , ** kwargs ):
110+ kwargs ["plugin" ] = "scrapli"
111+ return TTPParseModel .run (* args , ** kwargs )
112+
113+
114+ class TTPParseNrCliPluginNapalm (NrCliPluginNapalm ):
115+ @staticmethod
116+ def run (* args , ** kwargs ):
117+ kwargs ["plugin" ] = "napalm"
118+ return TTPParseModel .run (* args , ** kwargs )
119+
120+
121+ class TTPParseNrCliPlugins (BaseModel ):
122+ netmiko : TTPParseNrCliPluginNetmiko = Field (
123+ None , description = "Use Netmiko plugin to collect output from devices"
124+ )
125+ scrapli : TTPParseNrCliPluginScrapli = Field (
126+ None , description = "Use Scrapli plugin to collect output from devices"
127+ )
128+ napalm : TTPParseNrCliPluginNapalm = Field (
129+ None , description = "Use NAPALM plugin to collect output from devices"
130+ )
131+
132+
133+ class TTPParseModel (
134+ NorniHostsFilters , NornirCommonArgs , ClientRunJobArgs , ParseTTPInput
135+ ):
136+ commands : Union [StrictStr , List [StrictStr ]] = Field (
137+ None ,
138+ description = "List of commands to collect form devices" ,
139+ json_schema_extra = {"multiline" : True },
140+ )
141+ plugin : TTPParseNrCliPlugins = Field (
142+ None , description = "CLI connection plugin parameters"
86143 )
87- commands : Union [ List [ StrictStr ], StrictStr ] = Field (
88- None , description = "Commands to collect form devices"
144+ enable : StrictBool = Field (
145+ None , description = "Enter exec mode" , json_schema_extra = { "presence" : True }
89146 )
147+ strict : StrictBool = Field (
148+ True ,
149+ description = "Strict mode, raise error on empty results" ,
150+ json_schema_extra = {"presence" : True },
151+ )
152+
153+ @staticmethod
154+ def source_template (choice ):
155+ if choice and choice .startswith ("nf://" ):
156+ return ClientRunJobArgs .walk_norfab_files ()
157+ elif choice and choice .startswith ("ttp://" ) and HAS_TTP_TEMPLATES :
158+ return list_templates_refs ()
159+ else :
160+ return ["nf://" , "ttp://" ]
90161
91162 @staticmethod
92- def source_template ():
163+ def source_get ():
164+ if HAS_TTP_TEMPLATES :
165+ return [t .replace (".txt" , "" ) for t in list_templates ()["get" ]]
166+ return []
167+
168+ @staticmethod
169+ @listen_events
170+ def run (uuid , * args , ** kwargs ):
171+ NFCLIENT = builtins .NFCLIENT
172+ workers = kwargs .pop ("workers" , "all" )
173+ timeout = kwargs .pop ("timeout" , 600 )
174+ verbose_result = kwargs .pop ("verbose_result" , False )
175+ nowait = kwargs .pop ("nowait" , False )
176+
177+ result = NFCLIENT .run_job (
178+ "nornir" ,
179+ "parse_ttp" ,
180+ workers = workers ,
181+ args = args ,
182+ kwargs = kwargs ,
183+ uuid = uuid ,
184+ timeout = timeout ,
185+ nowait = nowait ,
186+ )
187+
188+ if nowait :
189+ return result , Outputters .outputter_nested
190+
191+ return log_error_or_result (result , verbose_result = verbose_result )
192+
193+ class PicleConfig :
194+ outputter = Outputters .outputter_nested
195+
196+
197+ class TextFSMParseModel (NorniHostsFilters , NornirCommonArgs , ClientRunJobArgs ):
198+ template : StrictStr = Field (None , description = "Path to a TextFSM template file" )
199+ commands : Union [StrictStr , List [StrictStr ]] = Field (
200+ None ,
201+ description = "List of commands to parse form devices" ,
202+ json_schema_extra = {"multiline" : True },
203+ )
204+
205+ @staticmethod
206+ def source_template (choice ):
93207 return ClientRunJobArgs .walk_norfab_files ()
94208
95209 @staticmethod
@@ -103,10 +217,10 @@ def run(uuid, *args, **kwargs):
103217
104218 result = NFCLIENT .run_job (
105219 "nornir" ,
106- "parse " ,
220+ "parse_textfsm " ,
107221 workers = workers ,
108222 args = args ,
109- kwargs = { "plugin" : "ttp" , ** kwargs } ,
223+ kwargs = kwargs ,
110224 uuid = uuid ,
111225 timeout = timeout ,
112226 nowait = nowait ,
@@ -128,6 +242,9 @@ class NornirParseShell(BaseModel):
128242 ttp : TTPParseModel = Field (
129243 None , description = "Parse devices output using TTP templates"
130244 )
245+ textfsm : TextFSMParseModel = Field (
246+ None , description = "Parse devices output using TextFSM templates"
247+ )
131248
132249 class PicleConfig :
133250 subshell = True
0 commit comments