1-
21#
32# (c) 2015 Peter Sprygada, <[email protected] > 43#
2928# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
3029# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3130#
32-
3331import re
3432
35- from ansible .module_utils .shell import CliBase
36- from ansible .module_utils .network import Command , register_transport , to_list
33+ from ansible .module_utils .basic import env_fallback
34+ from ansible .module_utils .network_common import to_list , ComplexList
35+ from ansible .module_utils .connection import exec_command
3736from ansible .module_utils .netcfg import NetworkConfig , ConfigLine , ignore_line , DEFAULT_COMMENT_TOKENS
3837
38+ _DEVICE_CONFIGS = {}
39+
40+ WARNING_PROMPTS_RE = [
41+ r"[\r\n]?\[confirm yes/no\]:\s?$" ,
42+ r"[\r\n]?\[y/n\]:\s?$" ,
43+ r"[\r\n]?\[yes/no\]:\s?$"
44+ ]
45+
46+ dellos6_argument_spec = {
47+ 'host' : dict (),
48+ 'port' : dict (type = 'int' ),
49+ 'username' : dict (fallback = (env_fallback , ['ANSIBLE_NET_USERNAME' ])),
50+ 'password' : dict (fallback = (env_fallback , ['ANSIBLE_NET_PASSWORD' ]), no_log = True ),
51+ 'ssh_keyfile' : dict (fallback = (env_fallback , ['ANSIBLE_NET_SSH_KEYFILE' ]), type = 'path' ),
52+ 'authorize' : dict (fallback = (env_fallback , ['ANSIBLE_NET_AUTHORIZE' ]), type = 'bool' ),
53+ 'auth_pass' : dict (fallback = (env_fallback , ['ANSIBLE_NET_AUTH_PASS' ]), no_log = True ),
54+ 'timeout' : dict (type = 'int' ),
55+ 'provider' : dict (type = 'dict' ),
56+ }
57+
58+
59+ def check_args (module , warnings ):
60+ provider = module .params ['provider' ] or {}
61+ for key in dellos6_argument_spec :
62+ if key != 'provider' and module .params [key ]:
63+ warnings .append ('argument %s has been deprecated and will be '
64+ 'removed in a future version' % key )
65+
66+
67+ def get_config (module , flags = []):
68+ cmd = 'show running-config '
69+ cmd += ' ' .join (flags )
70+ cmd = cmd .strip ()
71+
72+ try :
73+ return _DEVICE_CONFIGS [cmd ]
74+ except KeyError :
75+ rc , out , err = exec_command (module , cmd )
76+ if rc != 0 :
77+ module .fail_json (msg = 'unable to retrieve current config' , stderr = err )
78+ cfg = str (out ).strip ()
79+ _DEVICE_CONFIGS [cmd ] = cfg
80+ return cfg
81+
82+
83+ def to_commands (module , commands ):
84+ spec = {
85+ 'command' : dict (key = True ),
86+ 'prompt' : dict (),
87+ 'answer' : dict ()
88+ }
89+ transform = ComplexList (spec , module )
90+ return transform (commands )
91+
92+
93+ def run_commands (module , commands , check_rc = True ):
94+ responses = list ()
95+ commands = to_commands (module , to_list (commands ))
96+ for cmd in commands :
97+ cmd = module .jsonify (cmd )
98+ rc , out , err = exec_command (module , cmd )
99+ if check_rc and rc != 0 :
100+ module .fail_json (msg = err , rc = rc )
101+ responses .append (out )
102+ return responses
103+
104+
105+ def load_config (module , commands ):
106+ rc , out , err = exec_command (module , 'configure terminal' )
107+ if rc != 0 :
108+ module .fail_json (msg = 'unable to enter configuration mode' , err = err )
109+
110+ for command in to_list (commands ):
111+ if command == 'end' :
112+ continue
113+ cmd = {'command' : command , 'prompt' : WARNING_PROMPTS_RE , 'answer' : 'yes' }
114+ rc , out , err = exec_command (module , module .jsonify (cmd ))
115+ if rc != 0 :
116+ module .fail_json (msg = err , command = command , rc = rc )
117+ exec_command (module , 'end' )
39118
40- def get_config (module ):
41- contents = module .params ['config' ]
42- if not contents :
43- contents = module .config .get_config ()
44- module .params ['config' ] = contents
45- return Dellos6NetworkConfig (indent = 0 , contents = contents [0 ])
46- else :
47- return Dellos6NetworkConfig (indent = 0 , contents = contents )
48119
49120def get_sublevel_config (running_config , module ):
50121 contents = list ()
51122 current_config_contents = list ()
52123 sublevel_config = Dellos6NetworkConfig (indent = 0 )
53124 obj = running_config .get_object (module .params ['parents' ])
54125 if obj :
55- contents = obj .children
126+ contents = obj ._children
56127 for c in contents :
57128 if isinstance (c , ConfigLine ):
58129 current_config_contents .append (c .raw )
@@ -104,42 +175,42 @@ def os6_parse(lines, indent=None, comment_tokens=None):
104175 continue
105176
106177 else :
107- parent_match = False
178+ parent_match = False
108179 # handle sublevel parent
109180 for pr in sublevel_cmds :
110181 if pr .match (line ):
111182 if len (parent ) != 0 :
112- cfg .parents .extend (parent )
183+ cfg ._parents .extend (parent )
113184 parent .append (cfg )
114185 config .append (cfg )
115186 if children :
116- children .insert (len (parent ) - 1 ,[])
187+ children .insert (len (parent ) - 1 , [])
117188 children [len (parent ) - 2 ].append (cfg )
118- parent_match = True
189+ parent_match = True
119190 continue
120191 # handle exit
121192 if childline .match (line ):
122193 if children :
123- parent [len (children ) - 1 ].children .extend (children [len (children ) - 1 ])
124- if len (children )> 1 :
125- parent [len (children ) - 2 ].children .extend (parent [len (children ) - 1 ].children )
126- cfg .parents .extend (parent )
194+ parent [len (children ) - 1 ]._children .extend (children [len (children ) - 1 ])
195+ if len (children ) > 1 :
196+ parent [len (children ) - 2 ]._children .extend (parent [len (children ) - 1 ]._children )
197+ cfg ._parents .extend (parent )
127198 children .pop ()
128199 parent .pop ()
129200 if not children :
130201 children = list ()
131202 if parent :
132- cfg .parents .extend (parent )
203+ cfg ._parents .extend (parent )
133204 parent = list ()
134205 config .append (cfg )
135206 # handle sublevel children
136- elif parent_match is False and len (parent )> 0 :
207+ elif parent_match is False and len (parent ) > 0 :
137208 if not children :
138- cfglist = [cfg ]
209+ cfglist = [cfg ]
139210 children .append (cfglist )
140211 else :
141212 children [len (parent ) - 1 ].append (cfg )
142- cfg .parents .extend (parent )
213+ cfg ._parents .extend (parent )
143214 config .append (cfg )
144215 # handle global commands
145216 elif not parent :
@@ -150,71 +221,16 @@ def os6_parse(lines, indent=None, comment_tokens=None):
150221class Dellos6NetworkConfig (NetworkConfig ):
151222
152223 def load (self , contents ):
153- self ._config = os6_parse (contents , self .indent , DEFAULT_COMMENT_TOKENS )
224+ self ._items = os6_parse (contents , self ._indent , DEFAULT_COMMENT_TOKENS )
154225
155- def diff_line (self , other , path = None ):
226+ def _diff_line (self , other , path = None ):
156227 diff = list ()
157228 for item in self .items :
158229 if str (item ) == "exit" :
159230 for diff_item in diff :
160- if item .parents == diff_item .parents :
231+ if item ._parents == diff_item ._parents :
161232 diff .append (item )
162233 break
163234 elif item not in other :
164235 diff .append (item )
165236 return diff
166-
167-
168- class Cli (CliBase ):
169-
170- NET_PASSWD_RE = re .compile (r"[\r\n]?password:\s?$" , re .I )
171-
172- CLI_PROMPTS_RE = [
173- re .compile (r"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$" ),
174- re .compile (r"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$" )
175- ]
176-
177- CLI_ERRORS_RE = [
178- re .compile (r"% ?Error" ),
179- re .compile (r"% ?Bad secret" ),
180- re .compile (r"invalid input" , re .I ),
181- re .compile (r"(?:incomplete|ambiguous) command" , re .I ),
182- re .compile (r"connection timed out" , re .I ),
183- re .compile (r"[^\r\n]+ not found" , re .I ),
184- re .compile (r"'[^']' +returned error code: ?\d+" )]
185-
186-
187- def connect (self , params , ** kwargs ):
188- super (Cli , self ).connect (params , kickstart = False , ** kwargs )
189-
190-
191- def authorize (self , params , ** kwargs ):
192- passwd = params ['auth_pass' ]
193- self .run_commands (
194- Command ('enable' , prompt = self .NET_PASSWD_RE , response = passwd )
195- )
196- self .run_commands ('terminal length 0' )
197-
198-
199- def configure (self , commands , ** kwargs ):
200- cmds = ['configure terminal' ]
201- cmds .extend (to_list (commands ))
202- cmds .append ('end' )
203- responses = self .execute (cmds )
204- responses .pop (0 )
205- return responses
206-
207-
208- def get_config (self , ** kwargs ):
209- return self .execute (['show running-config' ])
210-
211-
212- def load_config (self , commands , ** kwargs ):
213- return self .configure (commands )
214-
215-
216- def save_config (self ):
217- self .execute (['copy running-config startup-config' ])
218-
219-
220- Cli = register_transport ('cli' , default = True )(Cli )
0 commit comments