Skip to content

Commit ea94ea9

Browse files
committed
adds cli option '--ignore_unavailable_resources' #147
1 parent e1da476 commit ea94ea9

12 files changed

Lines changed: 223 additions & 152 deletions

check_redfish.py

Lines changed: 3 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525

2626
import logging
27-
from argparse import ArgumentParser, RawDescriptionHelpFormatter
2827

2928
from cr_module.classes.plugin import PluginData
3029
from cr_module.system_chassi import get_system_info, get_chassi_data, get_system_data
@@ -33,122 +32,14 @@
3332
from cr_module.bmc import get_bmc_info
3433
from cr_module.firmware import get_firmware_info
3534
from cr_module.event import get_event_log
36-
from cr_module.classes.redfish import default_conn_max_retries, default_conn_timeout
37-
from cr_module.classes.inventory import Fan, PowerSupply, Temperature, Memory, Processor
38-
35+
from cr_module.args import parse_command_line
3936

40-
def parse_command_line():
41-
"""parse command line arguments
42-
Also add current version and version date to description
43-
"""
44-
45-
# define command line options
46-
parser = ArgumentParser(
47-
description=f"{description}\nVersion: {__version__} ({__version_date__})",
48-
formatter_class=RawDescriptionHelpFormatter, add_help=False)
49-
50-
group = parser.add_argument_group(title="mandatory arguments")
51-
group.add_argument("-H", "--host",
52-
help="define the host to request. To change the port just add ':portnumber' to this parameter")
53-
54-
group = parser.add_argument_group(title="authentication arguments")
55-
group.add_argument("-u", "--username", help="the login user name")
56-
group.add_argument("-p", "--password", help="the login password")
57-
group.add_argument("-f", "--authfile", help="authentication file with user name and password")
58-
group.add_argument("--sessionfile", help="define name of session file")
59-
group.add_argument("--sessionfiledir", help="define directory where the plugin saves session files")
60-
group.add_argument("--sessionlock", action='store_true', help="prevents multiple sessions and locks the session file when connecting")
61-
group.add_argument("--nosession", action='store_true',
62-
help="Don't establish a persistent session and log out after check is finished")
63-
64-
group = parser.add_argument_group(title="optional arguments")
65-
group.add_argument("-h", "--help", action='store_true',
66-
help="show this help message and exit")
67-
group.add_argument("-w", "--warning", default="",
68-
help="set warning value")
69-
group.add_argument("-c", "--critical", default="",
70-
help="set critical value")
71-
group.add_argument("-v", "--verbose", action='store_true',
72-
help="this will add all https requests and responses to output, "
73-
"also adds inventory source data to all inventory objects")
74-
group.add_argument("-d", "--detailed", action='store_true',
75-
help="always print detailed result")
76-
group.add_argument("-m", "--max", type=int,
77-
help="set maximum of returned items for --sel or --mel")
78-
group.add_argument("-r", "--retries", type=int, default=default_conn_max_retries,
79-
help=f"set number of maximum retries (default: {default_conn_max_retries})")
80-
group.add_argument("-t", "--timeout", type=int, default=default_conn_timeout,
81-
help=f"set number of request timeout per try/retry (default: {default_conn_timeout})")
82-
group.add_argument("--log_exclude",
83-
help="a comma separated list of log lines (regex) "
84-
"to exclude from log status checks (--sel, --mel)")
85-
group.add_argument("--ignore_missing_ps", action='store_true',
86-
help="ignore the fact that no power supplies are present and report the status "
87-
"of the power subsystem")
88-
group.add_argument("--enable_bmc_security_warning", action='store_true',
89-
help="return status WARNING if BMC security issues are detected (HPE iLO only)")
90-
91-
# require at least one argument
92-
group = parser.add_argument_group(title="query status/health information (at least one is required)")
93-
group.add_argument("--storage", dest="requested_query", action='append_const', const="storage",
94-
help="request storage health")
95-
group.add_argument("--proc", dest="requested_query", action='append_const', const="proc",
96-
help="request processor health")
97-
group.add_argument("--memory", dest="requested_query", action='append_const', const="memory",
98-
help="request memory health")
99-
group.add_argument("--power", dest="requested_query", action='append_const', const="power",
100-
help="request power supply health")
101-
group.add_argument("--temp", dest="requested_query", action='append_const', const="temp",
102-
help="request temperature sensors status")
103-
group.add_argument("--fan", dest="requested_query", action='append_const', const="fan",
104-
help="request fan status")
105-
group.add_argument("--nic", dest="requested_query", action='append_const', const="nic",
106-
help="request network interface status")
107-
group.add_argument("--bmc", dest="requested_query", action='append_const', const="bmc",
108-
help="request bmc info and status")
109-
group.add_argument("--info", dest="requested_query", action='append_const', const="info",
110-
help="request system information")
111-
group.add_argument("--firmware", dest="requested_query", action='append_const', const="firmware",
112-
help="request firmware information")
113-
group.add_argument("--sel", dest="requested_query", action='append_const', const="sel",
114-
help="request System Log status")
115-
group.add_argument("--mel", dest="requested_query", action='append_const', const="mel",
116-
help="request Management Processor Log status")
117-
group.add_argument("--all", dest="requested_query", action='append_const', const="all",
118-
help="request all of the above information at once")
119-
120-
# inventory
121-
group = parser.add_argument_group(title="query inventory information (no health check)")
122-
group.add_argument("-i", "--inventory", action='store_true',
123-
help="return inventory in json format instead of regular plugin output")
124-
group.add_argument("--inventory_id",
125-
help="set an ID which can be used to identify this host in the destination inventory")
126-
group.add_argument("--inventory_name",
127-
help="set a name which can be used to identify this host in the destination inventory")
128-
group.add_argument("--inventory_file",
129-
help="set file to write the inventory output to. Otherwise stdout will be used.")
130-
131-
result = parser.parse_args()
132-
133-
if result.help:
134-
parser.print_help()
135-
print("")
136-
exit(0)
137-
138-
if result.requested_query is None:
139-
parser.error("You need to specify at least one query command.")
140-
141-
# need to check this our self otherwise it's not
142-
# possible to put the help command into an arguments group
143-
if result.host is None:
144-
parser.error("No remote host defined")
145-
146-
return result
37+
from cr_module.classes.inventory import Fan, PowerSupply, Temperature, Memory, Processor
14738

14839

14940
if __name__ == "__main__":
15041
# start here
151-
args = parse_command_line()
42+
args = parse_command_line(description, __version__, __version_date__)
15243

15344
if args.verbose:
15445
# initialize logger

contrib/icinga2_check_redfish_command.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ object CheckCommand "redfish" {
140140
set_if = "$redfish_enable_bmc_security_warning$"
141141
description = "return status WARNING if BMC security issues are detected (HPE iLO only)"
142142
}
143+
"--ignore_unavailable_resources" = {
144+
set_if = "$redfish_ignore_unavailable_resources$"
145+
description = "ignore all 'UNKNOWN' errors which indicate missing resources and report as OK"
146+
}
143147
}
144148

145149
env = {

contrib/icinga2_check_redfish_director_basket.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@
7979
"description": "Directory where the session files should be stored",
8080
"value": "$redfish_sessionfiledir$"
8181
},
82+
"--sessionlock": {
83+
"description": "Create a session lock file to prevent parallel connection sessions",
84+
"set_if": "$redfish_sessionlock$"
85+
},
8286
"--storage": {
8387
"description": "request storage health",
8488
"set_if": "$redfish_storage$"
@@ -130,6 +134,10 @@
130134
"--enable_bmc_security_warning": {
131135
"description": "return status WARNING if BMC security issues are detected (HPE iLO only)",
132136
"set_if": "$redfish_enable_bmc_security_warning$"
137+
},
138+
"--ignore_unavailable_resources": {
139+
"description": "ignore all 'UNKNOWN' errors which indicate missing resources and report as OK",
140+
"set_if": "$redfish_ignore_unavailable_resources$"
133141
}
134142
},
135143
"command": "check_redfish.py",

cr_module/args.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) 2020 - 2025 Ricardo Bartels. All rights reserved.
3+
#
4+
# check_redfish.py
5+
#
6+
# This work is licensed under the terms of the MIT license.
7+
# For a copy, see file LICENSE.txt included in this
8+
# repository or visit: <https://opensource.org/licenses/MIT>.
9+
10+
from argparse import ArgumentParser, RawDescriptionHelpFormatter
11+
12+
from cr_module.classes.redfish import default_conn_max_retries, default_conn_timeout
13+
14+
def parse_command_line(description: str, version: str, version_date: str):
15+
"""parse command line arguments
16+
Also add current version and version date to description
17+
"""
18+
19+
# define command line options
20+
parser = ArgumentParser(
21+
description=f"{description}\nVersion: {version} ({version_date})",
22+
formatter_class=RawDescriptionHelpFormatter, add_help=False)
23+
24+
group = parser.add_argument_group(title="mandatory arguments")
25+
group.add_argument("-H", "--host",
26+
help="define the host to request. To change the port just add ':portnumber' to this parameter")
27+
28+
group = parser.add_argument_group(title="authentication arguments")
29+
group.add_argument("-u", "--username", help="the login user name")
30+
group.add_argument("-p", "--password", help="the login password")
31+
group.add_argument("-f", "--authfile", help="authentication file with user name and password")
32+
group.add_argument("--sessionfile", help="define name of session file")
33+
group.add_argument("--sessionfiledir", help="define directory where the plugin saves session files")
34+
group.add_argument("--sessionlock", action='store_true', help="prevents multiple sessions and locks the session file when connecting")
35+
group.add_argument("--nosession", action='store_true',
36+
help="Don't establish a persistent session and log out after check is finished")
37+
38+
group = parser.add_argument_group(title="optional arguments")
39+
group.add_argument("-h", "--help", action='store_true',
40+
help="show this help message and exit")
41+
group.add_argument("-w", "--warning", default="",
42+
help="set warning value")
43+
group.add_argument("-c", "--critical", default="",
44+
help="set critical value")
45+
group.add_argument("-v", "--verbose", action='store_true',
46+
help="this will add all https requests and responses to output, "
47+
"also adds inventory source data to all inventory objects")
48+
group.add_argument("-d", "--detailed", action='store_true',
49+
help="always print detailed result")
50+
group.add_argument("-m", "--max", type=int,
51+
help="set maximum of returned items for --sel or --mel")
52+
group.add_argument("-r", "--retries", type=int, default=default_conn_max_retries,
53+
help=f"set number of maximum retries (default: {default_conn_max_retries})")
54+
group.add_argument("-t", "--timeout", type=int, default=default_conn_timeout,
55+
help=f"set number of request timeout per try/retry (default: {default_conn_timeout})")
56+
group.add_argument("--log_exclude",
57+
help="a comma separated list of log lines (regex) "
58+
"to exclude from log status checks (--sel, --mel)")
59+
group.add_argument("--ignore_missing_ps", action='store_true',
60+
help="ignore the fact that no power supplies are present and report the status "
61+
"of the power subsystem")
62+
group.add_argument("--ignore_unavailable_resources", action='store_true',
63+
help="ignore all 'UNKNOWN' errors which indicate missing resources and report as OK")
64+
group.add_argument("--enable_bmc_security_warning", action='store_true',
65+
help="return status WARNING if BMC security issues are detected (HPE iLO only)")
66+
67+
# require at least one argument
68+
group = parser.add_argument_group(title="query status/health information (at least one is required)")
69+
group.add_argument("--storage", dest="requested_query", action='append_const', const="storage",
70+
help="request storage health")
71+
group.add_argument("--proc", dest="requested_query", action='append_const', const="proc",
72+
help="request processor health")
73+
group.add_argument("--memory", dest="requested_query", action='append_const', const="memory",
74+
help="request memory health")
75+
group.add_argument("--power", dest="requested_query", action='append_const', const="power",
76+
help="request power supply health")
77+
group.add_argument("--temp", dest="requested_query", action='append_const', const="temp",
78+
help="request temperature sensors status")
79+
group.add_argument("--fan", dest="requested_query", action='append_const', const="fan",
80+
help="request fan status")
81+
group.add_argument("--nic", dest="requested_query", action='append_const', const="nic",
82+
help="request network interface status")
83+
group.add_argument("--bmc", dest="requested_query", action='append_const', const="bmc",
84+
help="request bmc info and status")
85+
group.add_argument("--info", dest="requested_query", action='append_const', const="info",
86+
help="request system information")
87+
group.add_argument("--firmware", dest="requested_query", action='append_const', const="firmware",
88+
help="request firmware information")
89+
group.add_argument("--sel", dest="requested_query", action='append_const', const="sel",
90+
help="request System Log status")
91+
group.add_argument("--mel", dest="requested_query", action='append_const', const="mel",
92+
help="request Management Processor Log status")
93+
group.add_argument("--all", dest="requested_query", action='append_const', const="all",
94+
help="request all of the above information at once")
95+
96+
# inventory
97+
group = parser.add_argument_group(title="query inventory information (no health check)")
98+
group.add_argument("-i", "--inventory", action='store_true',
99+
help="return inventory in json format instead of regular plugin output")
100+
group.add_argument("--inventory_id",
101+
help="set an ID which can be used to identify this host in the destination inventory")
102+
group.add_argument("--inventory_name",
103+
help="set a name which can be used to identify this host in the destination inventory")
104+
group.add_argument("--inventory_file",
105+
help="set file to write the inventory output to. Otherwise stdout will be used.")
106+
107+
result = parser.parse_args()
108+
109+
if result.help:
110+
parser.print_help()
111+
print("")
112+
exit(0)
113+
114+
if result.requested_query is None:
115+
parser.error("You need to specify at least one query command.")
116+
117+
# need to check this our self otherwise it's not
118+
# possible to put the help command into an arguments group
119+
if result.host is None:
120+
parser.error("No remote host defined")
121+
122+
return result

cr_module/bmc.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ def get_bmc_info_generic(redfish_url):
118118
if manager_nic_response.get("error"):
119119
plugin_object.add_data_retrieval_error(NetworkPort, manager_nic_response, redfish_url)
120120

121+
nic_issue_detected = False
122+
manager_nics_detected = False
121123
if manager_nic_response is not None:
122124

123125
if manager_nic_response.get("Members") is None or len(manager_nic_response.get("Members")) == 0:
@@ -127,9 +129,6 @@ def get_bmc_info_generic(redfish_url):
127129
plugin_object.inventory.add_issue(NetworkPort, "No information about the BMC network interfaces found")
128130
else:
129131

130-
# if args.detailed is False:
131-
status_text = f"{status_text} and all nics are in 'OK' state."
132-
133132
for manager_nic_member in manager_nic_response.get("Members"):
134133

135134
if manager_nic_member.get("@odata.context"):
@@ -235,6 +234,10 @@ def get_bmc_info_generic(redfish_url):
235234
nic_status_text += f"(speed: {network_inventory.current_speed}, " \
236235
f"autoneg: {autoneg}, duplex: {duplex}) status: {nic_status}"
237236

237+
manager_nics_detected = True
238+
if nic_status != "OK":
239+
nic_issue_detected = True
240+
238241
plugin_object.add_output_data("CRITICAL" if nic_status not in ["OK", "WARNING"] else nic_status,
239242
nic_status_text, location=f"Manager {manager_inventory.id}")
240243

@@ -443,6 +446,9 @@ def get_bmc_info_generic(redfish_url):
443446
else:
444447
status_text += f" {location_string}"
445448

449+
if manager_nics_detected is True and nic_issue_detected is False:
450+
status_text = f"{status_text}, all nics are in 'OK' state."
451+
446452
plugin_object.add_output_data("CRITICAL" if bmc_status not in ["OK", "WARNING"] else bmc_status, status_text,
447453
summary=True, location=f"Manager {manager_inventory.id}")
448454

0 commit comments

Comments
 (0)