Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

20 bootflash fail over 50 if node already staged #108

Merged
merged 7 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 35 additions & 8 deletions aci-preupgrade-validation-script.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
warnings.simplefilter(action='ignore', category=FutureWarning)


class OldVerPropNotFound(Exception):
""" Later versions of ACI can have class properties not found in older versions """
pass


class Connection(object):
"""
Object built primarily for executing commands on Cisco IOS/NXOS devices. The following
Expand Down Expand Up @@ -613,7 +618,10 @@ def icurl(apitype, query):
logging.debug('response: ' + str(response))
imdata = json.loads(response)['imdata']
if imdata and "error" in imdata[0].keys():
monrog2 marked this conversation as resolved.
Show resolved Hide resolved
raise Exception('API call failed! Check debug log')
if imdata and "not found in class" in imdata[0]['error']['attributes']['text']:
monrog2 marked this conversation as resolved.
Show resolved Hide resolved
raise OldVerPropNotFound('cversion does not have requested property')
else:
raise Exception('API call failed! Check debug log')
else:
return imdata

Expand Down Expand Up @@ -984,33 +992,52 @@ def switch_group_guideline_check(index, total_checks, **kwargs):
return result


def switch_bootflash_usage_check(index, total_checks, **kwargs):
def switch_bootflash_usage_check(index, total_checks, tversion, **kwargs):
title = 'Switch Node /bootflash usage'
result = FAIL_UF
msg = ''
headers = ["Pod-ID", "Node-ID", "Utilization", "Alert"]
data = []
print_title(title, index, total_checks)

response_json = icurl('class',
'eqptcapacityFSPartition.json?query-target-filter=eq(eqptcapacityFSPartition.path,"/bootflash")')
if not response_json:
partitions_api = 'eqptcapacityFSPartition.json'
partitions_api += '?query-target-filter=eq(eqptcapacityFSPartition.path,"/bootflash")'

download_sts_api = 'maintUpgJob.json'
download_sts_api += '?query-target-filter=and(eq(maintUpgJob.dnldStatus,"downloaded")'
download_sts_api += ',eq(maintUpgJob.desiredVersion,"n9000-1{}"))'.format(tversion)

partitions = icurl('class', partitions_api)
if not partitions:
result = ERROR
msg = 'bootflash objects not found'

for eqptcapacityFSPartition in response_json:
predownloaded_nodes = []
try:
download_sts = icurl('class', download_sts_api)
except OldVerPropNotFound:
# Older versions don't have 'dnldStatus' param
download_sts = []

for maintUpgJob in download_sts:
dn = re.search(node_regex, maintUpgJob['maintUpgJob']['attributes']['dn'])
node = dn.group("node")
predownloaded_nodes.append(node)

for eqptcapacityFSPartition in partitions:
dn = re.search(node_regex, eqptcapacityFSPartition['eqptcapacityFSPartition']['attributes']['dn'])
pod = dn.group("pod")
node = dn.group("node")
avail = int(eqptcapacityFSPartition['eqptcapacityFSPartition']['attributes']['avail'])
used = int(eqptcapacityFSPartition['eqptcapacityFSPartition']['attributes']['used'])

usage = (used / (avail + used)) * 100
if usage >= 50:
if (usage >= 50) and (node not in predownloaded_nodes):
data.append([pod, node, usage, "Over 50% usage! Contact Cisco TAC for Support"])

if not data:
result = PASS
msg = 'all below 50%'
msg = 'All below 50% or pre-downloaded'
print_result(title, result, msg, headers, data)
return result

Expand Down
10 changes: 9 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ def mock_icurl(monkeypatch, icurl_outputs):
def _mock_icurl(apitype, query):
if icurl_outputs.get(query) is None:
log.error("Query `%s` not found in test data", query)
return icurl_outputs.get(query, [])

imdata = icurl_outputs.get(query, [])
if imdata and "error" in imdata[0].keys():
monrog2 marked this conversation as resolved.
Show resolved Hide resolved
if "not found in class" in imdata[0]['error']['attributes']['text']:
monrog2 marked this conversation as resolved.
Show resolved Hide resolved
raise script.OldVerPropNotFound('cversion does not have requested property')
else:
raise Exception('API call failed! Check debug log')
else:
return imdata

monkeypatch.setattr(script, "icurl", _mock_icurl)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"error": {
"attributes": {
"code": "121",
"text": "Prop 'dnldStatus' not found in class 'maintUpgJob' property table"
}
}
}
]
16 changes: 16 additions & 0 deletions tests/switch_bootflash_usage_check/maintUpgJob_pre_downloaded.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"maintUpgJob": {
"attributes": {
"desiredVersion": "n9000-16.0(2h)",
"dn": "topology/pod-1/node-101/sys/fwstatuscont/upgjob",
"dnldPercent": "100",
"dnldStatus": "downloaded",
"startDate": "2023-11-16T10:15:22.894-08:00",
"status": "",
"upgradeStatus": "scheduled",
"upgradeStatusStr": "Scheduled"
}
}
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,36 @@


# icurl queries
partitions = 'eqptcapacityFSPartition.json?query-target-filter=eq(eqptcapacityFSPartition.path,"/bootflash")'
partitions = 'eqptcapacityFSPartition.json'
partitions += '?query-target-filter=eq(eqptcapacityFSPartition.path,"/bootflash")'

download_sts = 'maintUpgJob.json'
download_sts += '?query-target-filter=and(eq(maintUpgJob.dnldStatus,"downloaded")'
download_sts += ',eq(maintUpgJob.desiredVersion,"n9000-16.0(2h)"))'

@pytest.mark.parametrize(
"icurl_outputs, expected_result",
"icurl_outputs, tversion, expected_result",
[
(
{partitions: read_data(dir, "eqptcapacityFSPartition_pos.json")},
{partitions: read_data(dir, "eqptcapacityFSPartition.json"),
download_sts: read_data(dir, "maintUpgJob_not_downloaded.json")},
"6.0(2h)",
script.FAIL_UF,
),
(
{partitions: read_data(dir, "eqptcapacityFSPartition.json"),
download_sts: read_data(dir, "maintUpgJob_pre_downloaded.json")},
"6.0(2h)",
script.PASS,
),
(
{partitions: read_data(dir, "eqptcapacityFSPartition.json"),
download_sts: read_data(dir, "maintUpgJob_old_ver_no_prop.json")},
"6.0(2h)",
script.FAIL_UF,
),
],
)
def test_logic(mock_icurl, expected_result):
result = script.switch_bootflash_usage_check(1, 1)
def test_logic(mock_icurl, tversion, expected_result):
result = script.switch_bootflash_usage_check(1, 1, script.AciVersion(tversion))
assert result == expected_result