6868RESULT_FILE = DIR + 'preupgrade_validator_%s%s.txt' % (ts , tz )
6969SUMMARY_FILE = DIR + 'summary.json'
7070LOG_FILE = DIR + 'preupgrade_validator_debug.log'
71- fmt = '[%(asctime)s.%(msecs)03d{} %(levelname)-8s %(funcName)20s:%(lineno)-4d] %(message)s' .format (tz )
72- if os .path .isdir (DIR ):
73- shutil .rmtree (DIR )
74- os .mkdir (DIR )
75- os .mkdir (JSON_DIR )
76- logging .basicConfig (level = logging .DEBUG , filename = LOG_FILE , format = fmt , datefmt = '%Y-%m-%d %H:%M:%S' )
7771warnings .simplefilter (action = 'ignore' , category = FutureWarning )
7872
73+ log = logging .getLogger ()
74+
7975
8076class OldVerClassNotFound (Exception ):
8177 """ Later versions of ACI can have class properties not found in older versions """
@@ -147,7 +143,7 @@ def __init__(self, hostname):
147143 def __connected (self ):
148144 # determine if a connection is already open
149145 connected = (self .child is not None and self .child .isatty ())
150- logging .debug ("check for valid connection: %r" % connected )
146+ log .debug ("check for valid connection: %r" % connected )
151147 return connected
152148
153149 @property
@@ -173,7 +169,7 @@ def start_log(self):
173169 self ._log = open (self .log , "ab" )
174170 else :
175171 self ._log = self .log
176- logging .debug ("setting logfile to %s" % self ._log .name )
172+ log .debug ("setting logfile to %s" % self ._log .name )
177173 if self .child is not None :
178174 self .child .logfile = self ._log
179175
@@ -195,18 +191,18 @@ def connect(self):
195191 self .port = 23
196192 # spawn new thread
197193 if self .protocol .lower () == "ssh" :
198- logging .debug (
194+ log .debug (
199195 "spawning new pexpect connection: ssh %s@%s -p %d" % (self .username , self .hostname , self .port ))
200196 no_verify = " -o StrictHostKeyChecking=no -o LogLevel=ERROR -o UserKnownHostsFile=/dev/null"
201197 if self .verify : no_verify = ""
202198 self .child = pexpect .spawn ("ssh %s %s@%s -p %d" % (no_verify , self .username , self .hostname , self .port ),
203199 searchwindowsize = self .searchwindowsize )
204200 elif self .protocol .lower () == "telnet" :
205- logging .info ("spawning new pexpect connection: telnet %s %d" % (self .hostname , self .port ))
201+ log .info ("spawning new pexpect connection: telnet %s %d" % (self .hostname , self .port ))
206202 self .child = pexpect .spawn ("telnet %s %d" % (self .hostname , self .port ),
207203 searchwindowsize = self .searchwindowsize )
208204 else :
209- logging .error ("unknown protocol %s" % self .protocol )
205+ log .error ("unknown protocol %s" % self .protocol )
210206 raise Exception ("Unsupported protocol: %s" % self .protocol )
211207
212208 # start logging
@@ -215,7 +211,7 @@ def connect(self):
215211 def close (self ):
216212 # try to gracefully close the connection if opened
217213 if self .__connected ():
218- logging .info ("closing current connection" )
214+ log .info ("closing current connection" )
219215 self .child .close ()
220216 self .child = None
221217 self ._login = False
@@ -241,24 +237,24 @@ def __expect(self, matches, timeout=None):
241237 indexed .append (matches [i ])
242238 mapping .append (i )
243239 result = self .child .expect (indexed , timeout )
244- logging .debug ("timeout: %d, matched: '%s'\n pexpect output: '%s%s'" % (
240+ log .debug ("timeout: %d, matched: '%s'\n pexpect output: '%s%s'" % (
245241 timeout , self .child .after , self .child .before , self .child .after ))
246242 if result <= len (mapping ) and result >= 0 :
247- logging .debug ("expect matched result[%d] = %s" % (result , mapping [result ]))
243+ log .debug ("expect matched result[%d] = %s" % (result , mapping [result ]))
248244 return mapping [result ]
249245 ds = ''
250- logging .error ("unexpected pexpect return index: %s" % result )
246+ log .error ("unexpected pexpect return index: %s" % result )
251247 for i in range (0 , len (mapping )):
252248 ds += '[%d] %s\n ' % (i , mapping [i ])
253- logging .debug ("mapping:\n %s" % ds )
249+ log .debug ("mapping:\n %s" % ds )
254250 raise Exception ("Unexpected pexpect return index: %s" % result )
255251
256252 def login (self , max_attempts = 7 , timeout = 17 ):
257253 """
258254 returns true on successful login, else returns false
259255 """
260256
261- logging .debug ("Logging into host" )
257+ log .debug ("Logging into host" )
262258
263259 # successfully logged in at a different time
264260 if not self .__connected (): self .connect ()
@@ -277,35 +273,35 @@ def login(self, max_attempts=7, timeout=17):
277273 max_attempts -= 1
278274 match = self .__expect (matches , timeout )
279275 if match == "console" : # press return to get started
280- logging .debug ("matched console, send enter" )
276+ log .debug ("matched console, send enter" )
281277 self .child .sendline ("\r \n " )
282278 elif match == "refuse" : # connection refused
283- logging .error ("connection refused by host" )
279+ log .error ("connection refused by host" )
284280 return False
285281 elif match == "yes/no" : # yes/no for SSH key acceptance
286- logging .debug ("received yes/no prompt, send yes" )
282+ log .debug ("received yes/no prompt, send yes" )
287283 self .child .sendline ("yes" )
288284 elif match == "username" : # username/login prompt
289- logging .debug ("received username prompt, send username" )
285+ log .debug ("received username prompt, send username" )
290286 self .child .sendline (self .username )
291287 elif match == "password" :
292288 # don't log passwords to the logfile
293289 self .stop_log ()
294- logging .debug ("matched password prompt, send password" )
290+ log .debug ("matched password prompt, send password" )
295291 self .child .sendline (self .password )
296292 # restart logging
297293 self .start_log ()
298294 elif match == "prompt" :
299- logging .debug ("successful login" )
295+ log .debug ("successful login" )
300296 self ._login = True
301297 # force terminal length at login
302298 self .term_len = self ._term_len
303299 return True
304300 elif match == "timeout" :
305- logging .debug ("timeout received but connection still opened, send enter" )
301+ log .debug ("timeout received but connection still opened, send enter" )
306302 self .child .sendline ("\r \n " )
307303 # did not find prompt within max attempts, failed login
308- logging .error ("failed to login after multiple attempts" )
304+ log .error ("failed to login after multiple attempts" )
309305 return False
310306
311307 def cmd (self , command , ** kargs ):
@@ -348,7 +344,7 @@ def cmd(self, command, **kargs):
348344 self .output = ""
349345 # check if we've ever logged into device or currently connected
350346 if (not self .__connected ()) or (not self ._login ):
351- logging .debug ("no active connection, attempt to login" )
347+ log .debug ("no active connection, attempt to login" )
352348 if not self .login ():
353349 raise Exception ("failed to login to host" )
354350
@@ -357,7 +353,7 @@ def cmd(self, command, **kargs):
357353 if not echo_cmd : self .stop_log ()
358354
359355 # execute command
360- logging .debug ("cmd command: %s" % command )
356+ log .debug ("cmd command: %s" % command )
361357 if sendline :
362358 self .child .sendline (command )
363359 else :
@@ -373,7 +369,7 @@ def cmd(self, command, **kargs):
373369 result = self .__expect (matches , timeout )
374370 self .output = "%s%s" % (self .child .before .decode ("utf-8" ), self .child .after .decode ("utf-8" ))
375371 if result == "eof" or result == "timeout" :
376- logging .warning ("unexpected %s occurred" % result )
372+ log .warning ("unexpected %s occurred" % result )
377373 return result
378374
379375
@@ -693,7 +689,7 @@ def get_node_ids_from_ifp(self, ifp_dn):
693689 def get_node_ids_from_ifsel (self , ifsel_dn ):
694690 ifp = self .get_parent (ifsel_dn , self .IFP )
695691 if not ifp :
696- logging .warning ("No I/F Profile for Selector (%s)" , ifsel_dn )
692+ log .warning ("No I/F Profile for Selector (%s)" , ifsel_dn )
697693 return []
698694 node_ids = self .get_node_ids_from_ifp (ifp ["dn" ])
699695 return node_ids
@@ -765,7 +761,7 @@ def create_port_data(self):
765761 node2fexid [_node_id ] = fex_id
766762 node_ids = node2fexid .keys ()
767763 if len (node_ids ) > 2 :
768- logging .error (
764+ log .error (
769765 "FEX HIF handling failed as it shows more than 2 nodes."
770766 )
771767 break
@@ -1045,7 +1041,7 @@ def wrapper(index, total_checks, *args, **kwargs):
10451041 r = check_func (* args , ** kwargs )
10461042 except Exception as e :
10471043 r = Result (result = ERROR , msg = 'Unexpected Error: {}' .format (e ))
1048- logging .exception (e )
1044+ log .exception (e )
10491045
10501046 # Print `[Check 1/81] <title>... <result> + <failure details>`
10511047 print_result (title = check_title , ** r .as_dict ())
@@ -1241,9 +1237,9 @@ def _icurl(apitype, query, page=0, page_size=100000):
12411237 query += '{}page={}&page-size={}' .format (pre , page , page_size )
12421238 uri = 'http://127.0.0.1:7777/api/{}/{}' .format (apitype , query )
12431239 cmd = ['icurl' , '-gs' , uri ]
1244- logging .info ('cmd = ' + ' ' .join (cmd ))
1240+ log .info ('cmd = ' + ' ' .join (cmd ))
12451241 response = subprocess .check_output (cmd )
1246- logging .debug ('response: ' + str (response ))
1242+ log .debug ('response: ' + str (response ))
12471243 data = json .loads (response )
12481244 _icurl_error_handler (data ['imdata' ])
12491245 return data
@@ -1569,7 +1565,7 @@ def switch_group_guideline_check(**kwargs):
15691565 if nodes [key ]['role' ] == 'spine' :
15701566 dn = re .search (node_regex , key )
15711567 if not dn :
1572- logging .error ('Failed to parse - %s' , key )
1568+ log .error ('Failed to parse - %s' , key )
15731569 continue
15741570 f_spines [0 ][dn .group ('pod' )].append (int (dn .group ('node' )))
15751571
@@ -1586,7 +1582,7 @@ def switch_group_guideline_check(**kwargs):
15861582 if nodes .get (tDn , {}).get ('role' ) == 'spine' :
15871583 dn = re .search (node_regex , tDn )
15881584 if not dn :
1589- logging .error ('Failed to parse - %s' , tDn )
1585+ log .error ('Failed to parse - %s' , tDn )
15901586 continue
15911587 f_spines [2 ][dn .group ('pod' )].append (int (dn .group ('node' )))
15921588
@@ -1595,7 +1591,7 @@ def switch_group_guideline_check(**kwargs):
15951591 for lldp in lldps :
15961592 dn = re .search (node_regex , lldp ['lldpCtrlrAdjEp' ]['attributes' ]['dn' ])
15971593 if not dn :
1598- logging .error ('Failed to parse - %s' , lldp ['lldpCtrlrAdjEp' ]['attributes' ]['dn' ])
1594+ log .error ('Failed to parse - %s' , lldp ['lldpCtrlrAdjEp' ]['attributes' ]['dn' ])
15991595 continue
16001596 apic_id_pod = '-' .join ([lldp ['lldpCtrlrAdjEp' ]['attributes' ]['id' ], dn .group ('pod' )])
16011597 apic_leafs [apic_id_pod ].add (int (dn .group ('node' )))
@@ -2663,7 +2659,7 @@ def l3out_overlapping_loopback_check(**kwargs):
26632659 node = np_child ['l3extRsNodeL3OutAtt' ]
26642660 m = re .search (node_regex , node ['attributes' ]['tDn' ])
26652661 if not m :
2666- logging .error ('Failed to parse tDn - %s' , node ['attributes' ]['tDn' ])
2662+ log .error ('Failed to parse tDn - %s' , node ['attributes' ]['tDn' ])
26672663 continue
26682664 node_id = m .group ('node' )
26692665
@@ -2694,7 +2690,7 @@ def l3out_overlapping_loopback_check(**kwargs):
26942690 port = ifp_child ['l3extRsPathL3OutAtt' ]
26952691 m = re .search (path_regex , port ['attributes' ]['tDn' ])
26962692 if not m :
2697- logging .error ('Failed to parse tDn - %s' , port ['attributes' ]['tDn' ])
2693+ log .error ('Failed to parse tDn - %s' , port ['attributes' ]['tDn' ])
26982694 continue
26992695 node1_id = m .group ('node1' )
27002696 node2_id = m .group ('node2' )
@@ -3178,7 +3174,7 @@ def intersight_upgrade_status_check(**kwargs):
31783174
31793175 cmd = ['icurl' , '-gks' , 'https://127.0.0.1/connector/UpgradeStatus' ]
31803176
3181- logging .info ('cmd = ' + ' ' .join (cmd ))
3177+ log .info ('cmd = ' + ' ' .join (cmd ))
31823178 response = subprocess .check_output (cmd )
31833179 try :
31843180 resp_json = json .loads (response )
@@ -3550,16 +3546,16 @@ def apic_ca_cert_validation(**kwargs):
35503546 '''
35513547 # Re-run cleanup for Issue #120
35523548 if os .path .exists (cert_gen_filename ):
3553- logging .debug ('CA CHECK file found and removed: ' + '' .join (cert_gen_filename ))
3549+ log .debug ('CA CHECK file found and removed: ' + '' .join (cert_gen_filename ))
35543550 os .remove (cert_gen_filename )
35553551 if os .path .exists (key_pem ):
3556- logging .debug ('CA CHECK file found and removed: ' + '' .join (key_pem ))
3552+ log .debug ('CA CHECK file found and removed: ' + '' .join (key_pem ))
35573553 os .remove (key_pem )
35583554 if os .path .exists (csr_pem ):
3559- logging .debug ('CA CHECK file found and removed: ' + '' .join (csr_pem ))
3555+ log .debug ('CA CHECK file found and removed: ' + '' .join (csr_pem ))
35603556 os .remove (csr_pem )
35613557 if os .path .exists (sign ):
3562- logging .debug ('CA CHECK file found and removed: ' + '' .join (sign ))
3558+ log .debug ('CA CHECK file found and removed: ' + '' .join (sign ))
35633559 os .remove (sign )
35643560
35653561 with open (cert_gen_filename , 'w' ) as f :
@@ -3569,7 +3565,7 @@ def apic_ca_cert_validation(**kwargs):
35693565 cmd = 'openssl genrsa -out ' + key_pem + ' 2048'
35703566 cmd = cmd + ' && openssl req -config ' + cert_gen_filename + ' -new -key ' + key_pem + ' -out ' + csr_pem
35713567 cmd = cmd + ' && openssl dgst -sha256 -hmac ' + passphrase + ' -out ' + sign + ' ' + csr_pem
3572- logging .debug ('cmd = ' + '' .join (cmd ))
3568+ log .debug ('cmd = ' + '' .join (cmd ))
35733569 genrsa_proc = subprocess .Popen (cmd , stdout = subprocess .PIPE , stderr = subprocess .STDOUT , shell = True )
35743570 genrsa_proc .communicate ()[0 ].strip ()
35753571 if genrsa_proc .returncode != 0 :
@@ -3589,11 +3585,11 @@ def apic_ca_cert_validation(**kwargs):
35893585 payload = '{"aaaCertGenReq":{"attributes":{"type":"csvc","hmac":"%s", "certreq": "%s", ' \
35903586 '"podip": "None", "podmac": "None", "podname": "None"}}}' % (hmac , certreq )
35913587 cmd = 'icurl -kX POST %s -d \' %s \' ' % (url , payload )
3592- logging .debug ('cmd = ' + '' .join (cmd ))
3588+ log .debug ('cmd = ' + '' .join (cmd ))
35933589 certreq_proc = subprocess .Popen (cmd , stdout = subprocess .PIPE , stderr = subprocess .STDOUT , shell = True )
35943590 certreq_out = certreq_proc .communicate ()[0 ].strip ()
35953591
3596- logging .debug (certreq_out )
3592+ log .debug (certreq_out )
35973593 if '"error":{"attributes"' in str (certreq_out ):
35983594 # Spines can crash on 5.2(6e)+, but APIC CA Certs should be fixed regardless of tver
35993595 data .append ([certreq_out ])
@@ -4431,7 +4427,7 @@ def vzany_vzany_service_epg_check(cversion, tversion, **kwargs):
44314427 elif "vzRtAnyToProv" in vzRtAny :
44324428 rel_class = "vzRtAnyToProv"
44334429 else :
4434- logging .warning ("Unexpected class - %s" , vzRtAny .keys ())
4430+ log .warning ("Unexpected class - %s" , vzRtAny .keys ())
44354431 continue
44364432 vrf_tdn = vzRtAny [rel_class ]["attributes" ]["tDn" ]
44374433 vrf_match = re .search (vrf_regex , vrf_tdn )
@@ -5010,7 +5006,7 @@ def service_bd_forceful_routing_check(cversion, tversion, **kwargs):
50105006 for fvRtEPpInfoToBD in fvRtEPpInfoToBDs :
50115007 m = re .search (dn_regex , fvRtEPpInfoToBD ["fvRtEPpInfoToBD" ]["attributes" ]["dn" ])
50125008 if not m :
5013- logging .error ("Failed to match %s" , fvRtEPpInfoToBD ["fvRtEPpInfoToBD" ]["attributes" ]["dn" ])
5009+ log .error ("Failed to match %s" , fvRtEPpInfoToBD ["fvRtEPpInfoToBD" ]["attributes" ]["dn" ])
50145010 unformatted_data .append ([fvRtEPpInfoToBD ["fvRtEPpInfoToBD" ]["attributes" ]["dn" ]])
50155011 continue
50165012 data .append ([
@@ -5225,6 +5221,21 @@ def parse_args(args):
52255221 return parsed_args
52265222
52275223
5224+ def initialize ():
5225+ """
5226+ Initialize the script environment, create necessary directories and set up log.
5227+ Not required for some options such as `--version` or `--total-checks`.
5228+ """
5229+ if os .path .isdir (DIR ):
5230+ log .info ("Cleaning up previous run files in %s" , DIR )
5231+ shutil .rmtree (DIR )
5232+ log .info ("Creating directories %s and %s" , DIR , JSON_DIR )
5233+ os .mkdir (DIR )
5234+ os .mkdir (JSON_DIR )
5235+ fmt = '[%(asctime)s.%(msecs)03d{} %(levelname)-8s %(funcName)20s:%(lineno)-4d] %(message)s' .format (tz )
5236+ logging .basicConfig (level = logging .DEBUG , filename = LOG_FILE , format = fmt , datefmt = '%Y-%m-%d %H:%M:%S' )
5237+
5238+
52285239def prepare (api_only , arg_tversion , arg_cversion , total_checks ):
52295240 prints (' ==== %s%s, Script Version %s ====\n ' % (ts , tz , SCRIPT_VERSION ))
52305241 prints ('!!!! Check https://github.com/datacenter/ACI-Pre-Upgrade-Validation-Script for Latest Release !!!!\n ' )
@@ -5240,7 +5251,7 @@ def prepare(api_only, arg_tversion, arg_cversion, total_checks):
52405251 except Exception as e :
52415252 prints ('\n \n Error: %s' % e )
52425253 prints ("Initial query failed. Ensure APICs are healthy. Ending script run." )
5243- logging .exception (e )
5254+ log .exception (e )
52445255 sys .exit ()
52455256 inputs = {'username' : username , 'password' : password ,
52465257 'cversion' : cversion , 'tversion' : tversion ,
@@ -5409,18 +5420,21 @@ def wrapup(no_cleanup):
54095420
54105421 # puv integration needs to keep reading files from `JSON_DIR` under `DIR`.
54115422 if not no_cleanup and os .path .isdir (DIR ):
5423+ log .info ('Cleaning up temporary files and directories...' )
54125424 shutil .rmtree (DIR )
54135425
54145426
54155427def main (_args = None ):
54165428 args = parse_args (_args )
54175429 if args .version :
5418- prints (SCRIPT_VERSION )
5430+ print (SCRIPT_VERSION )
54195431 return
54205432 checks = get_checks (args .api_only , args .debug_function )
54215433 if args .total_checks :
5422- prints ("Total Number of Checks: {}" .format (len (checks )))
5434+ print ("Total Number of Checks: {}" .format (len (checks )))
54235435 return
5436+
5437+ initialize ()
54245438 inputs = prepare (args .api_only , args .tversion , args .cversion , len (checks ))
54255439 run_checks (checks , inputs )
54265440 wrapup (args .no_cleanup )
0 commit comments