Skip to content

Commit 68be98a

Browse files
committed
Do not touch log folders with some options like --version
1 parent c46c9c1 commit 68be98a

3 files changed

Lines changed: 71 additions & 53 deletions

File tree

aci-preupgrade-validation-script.py

Lines changed: 65 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,10 @@
6868
RESULT_FILE = DIR + 'preupgrade_validator_%s%s.txt' % (ts, tz)
6969
SUMMARY_FILE = DIR + 'summary.json'
7070
LOG_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')
7771
warnings.simplefilter(action='ignore', category=FutureWarning)
7872

73+
log = logging.getLogger()
74+
7975

8076
class 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'\npexpect output: '%s%s'" % (
240+
log.debug("timeout: %d, matched: '%s'\npexpect 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+
52285239
def 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\nError: %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

54155427
def 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)

tests/conftest.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010

1111
script = importlib.import_module("aci-preupgrade-validation-script")
1212

13-
log = logging.getLogger(__name__)
13+
log = logging.getLogger()
14+
15+
16+
@pytest.fixture(scope="session", autouse=True)
17+
def init():
18+
script.initialize()
1419

1520

1621
@pytest.fixture

tests/test_main.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import pytest
22
import importlib
3-
import sys
43

54
script = importlib.import_module("aci-preupgrade-validation-script")
65
AciVersion = script.AciVersion

0 commit comments

Comments
 (0)