From 1e49fefc35b8d549946211306e337b7e7cef439f Mon Sep 17 00:00:00 2001 From: Mike Raineri Date: Mon, 14 Aug 2023 10:25:43 -0400 Subject: [PATCH] Cleanup prior to release Signed-off-by: Mike Raineri --- README.md | 2 + redfish_utilities/accounts.py | 9 +++-- redfish_utilities/messages.py | 9 ++--- redfish_utilities/misc.py | 44 +++++++++++++++------- redfish_utilities/sensors.py | 71 +++++++++++++++++++---------------- redfish_utilities/update.py | 47 ++++++++++++++++------- requirements.txt | 2 +- scripts/rf_accounts.py | 43 +++++++++++---------- scripts/rf_bios_settings.py | 17 +++------ scripts/rf_boot_override.py | 17 +++------ scripts/rf_diagnostic_data.py | 17 +++------ scripts/rf_discover.py | 6 +-- scripts/rf_event_service.py | 17 +++------ scripts/rf_licenses.py | 17 +++------ scripts/rf_logs.py | 17 +++------ scripts/rf_manager_config.py | 17 +++------ scripts/rf_power_reset.py | 18 +++------ scripts/rf_raw_request.py | 62 ++++++++++++++++-------------- scripts/rf_sensor_list.py | 22 ++++------- scripts/rf_sys_inventory.py | 18 +++------ scripts/rf_update.py | 18 +++------ scripts/rf_virtual_media.py | 18 +++------ setup.py | 2 +- 23 files changed, 237 insertions(+), 273 deletions(-) diff --git a/README.md b/README.md index ae6097d..ea6b7ac 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ required arguments: optional arguments: -h, --help show this help message and exit + --id, -i Construct sensor names using 'Id' values + --name, -n Construct sensor names using 'Name' values --debug Creates debug file showing HTTP traces and exceptions ``` diff --git a/redfish_utilities/accounts.py b/redfish_utilities/accounts.py index cf9b23b..4bf6566 100644 --- a/redfish_utilities/accounts.py +++ b/redfish_utilities/accounts.py @@ -13,7 +13,6 @@ """ from .messages import verify_response -from .messages import RedfishPasswordChangeRequiredError class RedfishAccountCollectionNotFoundError( Exception ): """ @@ -146,7 +145,7 @@ def delete_user( context, user_name ): verify_response( response ) return response -def modify_user( context, user_name, new_name = None, new_password = None, new_role = None, new_locked = None, new_enabled = None , user_uri = None): +def modify_user( context, user_name, new_name = None, new_password = None, new_role = None, new_locked = None, new_enabled = None, user_uri = None ): """ Modifies an existing user account @@ -158,13 +157,14 @@ def modify_user( context, user_name, new_name = None, new_password = None, new_r new_role: The new role of the user new_locked: The new locked flag of the user new_enabled: The new enabled flag of the user + user_uri: The URI of the user to modify Returns: The response of the PATCH """ # Get the current user info - user_uri, user_info = get_user( context, user_name , user_uri = user_uri) + user_uri, user_info = get_user( context, user_name , user_uri = user_uri ) # Build the payload for the new user new_info = {} @@ -216,6 +216,7 @@ def get_user( context, user_name, user_uri = None ): Args: context: The Redfish client object with an open session user_name: The name of the user to find + user_uri: The URI of the user to get Returns: The URI for the user account @@ -225,7 +226,7 @@ def get_user( context, user_name, user_uri = None ): avail_users = [] if user_uri is not None: - account = context.get(user_uri) + account = context.get( user_uri ) if account.dict["UserName"] == user_name: return user_uri, account diff --git a/redfish_utilities/messages.py b/redfish_utilities/messages.py index 33696d3..cfa5b94 100644 --- a/redfish_utilities/messages.py +++ b/redfish_utilities/messages.py @@ -23,19 +23,16 @@ def verify_response( response ): """ if response.status >= 400: - messages_detail = get_messages_detail(response) + messages_detail = get_messages_detail( response ) exception_string = get_error_messages( messages_detail ) - message_item = search_message(messages_detail, "Base", "PasswordChangeRequired") + message_item = search_message( messages_detail, "Base", "PasswordChangeRequired" ) if not message_item is None: - raise RedfishPasswordChangeRequiredError( "Operation failed: HTTP {}\n{}".format( response.status, exception_string ), message_item["MessageArgs"][0]) + raise RedfishPasswordChangeRequiredError( "Operation failed: HTTP {}\n{}".format( response.status, exception_string ), message_item["MessageArgs"][0] ) else: raise RedfishOperationFailedError( "Operation failed: HTTP {}\n{}".format( response.status, exception_string ) ) return -""" - for backend capability -""" def print_error_payload( response ): """ Prints an error payload, which can also be used for action responses diff --git a/redfish_utilities/misc.py b/redfish_utilities/misc.py index 2838424..424d8c8 100644 --- a/redfish_utilities/misc.py +++ b/redfish_utilities/misc.py @@ -4,26 +4,44 @@ # License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/Redfish-Tacklebox/blob/main/LICENSE.md """ -some misc function implment in here +Miscellaneous File : misc.py -Brief : some misc function implment in here +Brief : Miscellaneous functions with common script logic """ + import sys -from redfish.rest.v1 import BadRequestError -def logout(redfish_obj, print_error = False): - if redfish_obj is not None: + +def logout( context, ignore_error = False ): + """ + Performs a logout of the service and allows for exceptions to be ignored + + Args: + context: The Redfish client object with an open session + ignore_error: Indicates if exceptions during logout are ignored + """ + + if context is not None: try: - redfish_obj.logout() - except BadRequestError as e: - pass + context.logout() except Exception as e: - if print_error is True: - print(e) + if ignore_error: + pass + else: + raise return -def print_password_change_required_and_logout(redfish_obj, args): - print("Password change required\n run rf_accounts.py -r {} -u {} -p --setpassword {} \nto set your password\n".format(args.rhost ,args.user, args.user)) - logout(redfish_obj, print_error = True) +def print_password_change_required_and_logout( context, args ): + """ + Common help text when handling password change required conditions + + Args: + context: The Redfish client object with an open session + args: The argparse object from the calling script + """ + + print( "Password change required. To set a new password, run the following:" ) + print( "rf_accounts.py -r {} -u {} -p --setpassword {} ".format( args.rhost, args.user, args.user ) ) + logout( context, ignore_error = True ) # Some services do not allow session logout in this condition return diff --git a/redfish_utilities/sensors.py b/redfish_utilities/sensors.py index 7cafae1..48b9b5b 100644 --- a/redfish_utilities/sensors.py +++ b/redfish_utilities/sensors.py @@ -12,12 +12,13 @@ Redfish service's Power and Thermal properties for sensor readings """ -def get_sensors( context , use_id = False): +def get_sensors( context , use_id = False ): """ Walks a Redfish service for sensor information Args: context: The Redfish client object with an open session + use_id: Indicates whether to construct names from 'Id' property values Returns: A list containing all sensor readings @@ -37,9 +38,8 @@ def get_sensors( context , use_id = False): chassis = context.get( chassis_member["@odata.id"] ) chassis_name = "Chassis " + chassis.dict["Id"] - if use_id is False: - if "Name" in chassis.dict: - chassis_name = chassis.dict["Name"] + if use_id is False and "Name" in chassis.dict: + chassis_name = chassis.dict["Name"] # Get the chassis status chassis_instance = { @@ -71,9 +71,8 @@ def get_sensors( context , use_id = False): for power_supply_member in power_supplies.dict["Members"]: power_supply = context.get( power_supply_member["@odata.id"] ) power_supply_name = "Power Supply " + power_supply.dict["Id"] - if use_id is False: - if "Name" in power_supply.dict: - power_supply_name = power_supply.dict["Name"] + if use_id is False and "Name" in power_supply.dict: + power_supply_name = power_supply.dict["Name"] get_discrete_status( power_supply_name + " State", power_supply.dict, chassis_instance["Readings"] ) if "Metrics" in power_supply.dict: metrics = context.get( power_supply.dict["Metrics"]["@odata.id"] ) @@ -95,9 +94,8 @@ def get_sensors( context , use_id = False): for battery_member in batteries.dict["Members"]: battery = context.get( battery_member["@odata.id"] ) battery_name = "Battery " + battery.dict["Id"] - if use_id is False: - if "Name" in battery.dict: - battery_name = battery.dict["Name"] + if use_id is False and "Name" in battery.dict: + battery_name = battery.dict["Name"] get_discrete_status( battery_name + " State", battery.dict, chassis_instance["Readings"] ) get_excerpt_status( battery_name, "StateOfHealthPercent", "%", battery.dict, chassis_instance["Readings"]) if "Metrics" in battery.dict: @@ -115,7 +113,10 @@ def get_sensors( context , use_id = False): # Add information for each of the redundancy groups reported if "PowerSupplyRedundancy" in power.dict: for i, redundancy in enumerate( power.dict["PowerSupplyRedundancy"] ): - get_discrete_status( "Power Supply Redundancy " + str( i ), redundancy, chassis_instance["Readings"] ) + redundancy_name = "Power Supply Redundancy " + str( i ) + if use_id is False and "Name" in redundancy: + redundancy_name = redundancy["Name"] + get_discrete_status( redundancy_name, redundancy, chassis_instance["Readings"] ) # Get readings from the ThermalSubsystem resource if available if "ThermalSubsystem" in chassis.dict: @@ -136,16 +137,18 @@ def get_sensors( context , use_id = False): for fan_member in fans.dict["Members"]: fan = context.get( fan_member["@odata.id"] ) fan_name = "Fan " + fan.dict["Id"] - if use_id is False: - if "Name" in fan.dict: - fan_name = fan.dict["Name"] + if use_id is False and "Name" in fan.dict: + fan_name = fan.dict["Name"] get_discrete_status( fan_name + " State", fan.dict, chassis_instance["Readings"] ) get_excerpt_status( fan_name, "SpeedPercent", "%", fan.dict, chassis_instance["Readings"]) # Add information for each of the redundancy groups reported if "FanRedundancy" in thermal.dict: for i, redundancy in enumerate( thermal.dict["FanRedundancy"] ): - get_discrete_status( "Fan Redundancy " + str( i ), redundancy, chassis_instance["Readings"] ) + redundancy_name = "Fan Redundancy " + str( i ) + if use_id is False and "Name" in redundancy: + redundancy_name = redundancy["Name"] + get_discrete_status( redundancy_name, redundancy, chassis_instance["Readings"] ) # Get all sensor readings if available if "Sensors" in chassis.dict: @@ -164,9 +167,8 @@ def get_sensors( context , use_id = False): if "PowerSupplies" in power.dict: for power_supply in power.dict["PowerSupplies"]: power_supply_name = "Power Supply " + power_supply["MemberId"] - if use_id is False: - if "Name" in power_supply: - power_supply_name = power_supply["Name"] + if use_id is False and "Name" in power_supply: + power_supply_name = power_supply["Name"] get_discrete_status( power_supply_name + " State", power_supply, chassis_instance["Readings"] ) get_analog_status_small( power_supply_name, "ReadingVolts", "V", power_supply, chassis_instance["Readings"] ) get_analog_status_small( power_supply_name, "LineInputVoltage", "V", power_supply, chassis_instance["Readings"] ) @@ -177,15 +179,17 @@ def get_sensors( context , use_id = False): if "Voltages" in power.dict: for voltage in power.dict["Voltages"]: voltage_name = "Voltage " + voltage["MemberId"] - if use_id is False: - if "Name" in voltage: - voltage_name = voltage["Name"] + if use_id is False and "Name" in voltage: + voltage_name = voltage["Name"] get_analog_status_full( voltage_name, voltage, chassis_instance["Readings"] ) # Add information for each of the redundancy groups reported if "Redundancy" in power.dict: for i, redundancy in enumerate( power.dict["Redundancy"] ): - get_discrete_status( "Power Supply Redundancy " + str( i ), redundancy, chassis_instance["Readings"] ) + redundancy_name = "Power Supply Redundancy " + str( i ) + if use_id is False and "Name" in redundancy: + redundancy_name = redundancy["Name"] + get_discrete_status( redundancy_name, redundancy, chassis_instance["Readings"] ) # Get readings from the Thermal resource if available if "Thermal" in chassis.dict: @@ -195,24 +199,25 @@ def get_sensors( context , use_id = False): if "Temperatures" in thermal.dict: for temperature in thermal.dict["Temperatures"]: temperature_name = "Temperature " + temperature["MemberId"] - if use_id is False: - if "Name" in temperature: - temperature_name = temperature["Name"] + if use_id is False and "Name" in temperature: + temperature_name = temperature["Name"] get_analog_status_full( temperature_name, temperature, chassis_instance["Readings"] ) # Add information for each of the fans reported if "Fans" in thermal.dict: for fan in thermal.dict["Fans"]: fan_name = "Fan " + fan["MemberId"] - if use_id is False: - if "Name" in fan: - fan_name = fan["Name"] + if use_id is False and "Name" in fan: + fan_name = fan["Name"] get_analog_status_full( fan_name, fan, chassis_instance["Readings"] ) # Add information for each of the redundancy groups reported if "Redundancy" in thermal.dict: for i, redundancy in enumerate( thermal.dict["Redundancy"] ): - get_discrete_status( "Fan Redundancy " + str( i ), redundancy, chassis_instance["Readings"] ) + redundancy_name = "Fan Redundancy " + str( i ) + if use_id is False and "Name" in redundancy: + redundancy_name = redundancy["Name"] + get_discrete_status( redundancy_name, redundancy, chassis_instance["Readings"] ) return sensor_list @@ -375,13 +380,14 @@ def get_excerpt_status( name, field, units, object, readings ): } readings.append( reading ) -def get_sensor_status( sensor, readings , use_id = False): +def get_sensor_status( sensor, readings , use_id = False ): """ Builds an analog reading from a sensor Args: sensor: The sensor readings: The list of readings to update + use_id: Indicates whether to construct names from 'Id' property values """ state, health = get_status( sensor ) @@ -390,11 +396,10 @@ def get_sensor_status( sensor, readings , use_id = False): if reading_val is None: reading_val = state - name = sensor.get( "Name", None ) - + sensor_name = sensor.get( "Name", None ) name = "Sensor " + sensor["Id"] if use_id is False and name is not None: - name = name + name = sensor_name reading = { "Name": name, diff --git a/redfish_utilities/update.py b/redfish_utilities/update.py index b49da16..ea28b16 100644 --- a/redfish_utilities/update.py +++ b/redfish_utilities/update.py @@ -129,17 +129,27 @@ def simple_update( context, image_uri, protocol = None, targets = None, username verify_response( response ) return response -def get_size(file_path, unit='bytes'): - file_size = os.path.getsize(file_path) - exponents_map = {'bytes': 0, 'kb': 1, 'mb': 2, 'gb': 3} +def get_size( file_path, unit = 'bytes' ): + """ + Determines the size of a local file + + Args: + file_path: The path to the file + unit: The units to apply to the return value + + Returns: + The size of the file in the specified units + """ + + file_size = os.path.getsize( file_path ) + exponents_map = { 'bytes': 0, 'kb': 1, 'mb': 2, 'gb': 3 } if unit not in exponents_map: - raise ValueError("Must select from \ - ['bytes', 'kb', 'mb', 'gb']") + raise ValueError( "Must select from ['bytes', 'kb', 'mb', 'gb']" ) else: size = file_size / 1024 ** exponents_map[unit] - return round(size, 3) + return round( size, 3 ) -def multipart_push_update( context, image_path, targets = None , timeout = None): +def multipart_push_update( context, image_path, targets = None, timeout = None ): """ Performs an HTTP Multipart push update request @@ -147,21 +157,32 @@ def multipart_push_update( context, image_path, targets = None , timeout = None) context: The Redfish client object with an open session image_path: The filepath to the image for the update targets: The targets receiving the update + timeout: The timeout to apply to the update Returns: The response from the request """ - if os.path.isfile(image_path) is False: - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), image_path) - # Get the update service + # Ensure the file exists + if os.path.isfile( image_path ) is False: + raise FileNotFoundError( errno.ENOENT, os.strerror( errno.ENOENT ), image_path ) + + # If no update is specified, determine an appropriate timeout to apply if timeout is None: + """TODO: See what a 'reasonable' timeout is when accounting for slow networks + for now, keeping the timeout conservative (2 seconds per MB) timeout = 5 - file_size = get_size(image_path, "mb") + file_size = get_size( image_path, "mb" ) if file_size >= 16: - timeout = math.ceil((5 / 16)* file_size) + timeout = math.ceil( ( 5 / 16 ) * file_size ) + """ + timeout = 30 + file_size = get_size( image_path, "mb" ) + if file_size >= 15: + timeout = 2 * file_size + # Get the update service update_service = get_update_service( context ) if "MultipartHttpPushUri" not in update_service.dict: raise RedfishUpdateServiceNotFoundError( "Service does not support MultipartHttpPushUri" ) @@ -175,7 +196,7 @@ def multipart_push_update( context, image_path, targets = None , timeout = None) "UpdateFile": ( image_path.split( os.path.sep )[-1], open( image_path, "rb" ), "application/octet-stream" ) } - response = context.post( update_service.dict["MultipartHttpPushUri"], body = body, headers = { "Content-Type": "multipart/form-data" } , timeout=timeout, max_retry=3) + response = context.post( update_service.dict["MultipartHttpPushUri"], body = body, headers = { "Content-Type": "multipart/form-data" }, timeout = timeout, max_retry = 3 ) verify_response( response ) return response diff --git a/requirements.txt b/requirements.txt index 8d254f5..d50bf91 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -redfish>=2.1.0 +redfish>=3.2.1 XlsxWriter>=1.2.7 \ No newline at end of file diff --git a/scripts/rf_accounts.py b/scripts/rf_accounts.py index 03ba765..872b9bb 100644 --- a/scripts/rf_accounts.py +++ b/scripts/rf_accounts.py @@ -46,32 +46,35 @@ user_uri = None redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: if args.setpassword is None: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) else: user_uri = e.args[1] if args.setpassword[0] == args.user: - print( "Changing password of user '{}'".format( args.setpassword[0] ) ) - redfish_utilities.modify_user( redfish_obj, args.setpassword[0], new_password = args.setpassword[1], user_uri = user_uri ) - redfish_utilities.logout(redfish_obj, print_error = True) - sys.exit(0) + # The user is requesting to change their own password + # Allow the request to go through directly, and log out + exit_code = 0 + try: + print( "Changing password of user '{}'".format( args.setpassword[0] ) ) + redfish_utilities.modify_user( redfish_obj, args.setpassword[0], new_password = args.setpassword[1], user_uri = user_uri ) + except Exception as e: + if args.debug: + logger.error( "Caught exception:\n\n{}\n".format( traceback.format_exc() ) ) + exit_code = 1 + print( e ) + finally: + # Log out + redfish_utilities.logout( redfish_obj, ignore_error = True ) # Some services do not allow session logout in this condition + sys.exit( exit_code ) else: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -90,7 +93,7 @@ print_accounts = False if args.setpassword is not None: print( "Changing password of user '{}'".format( args.setpassword[0] ) ) - redfish_utilities.modify_user( redfish_obj, args.setpassword[0], new_password = args.setpassword[1]) + redfish_utilities.modify_user( redfish_obj, args.setpassword[0], new_password = args.setpassword[1] ) print_accounts = False if args.setrole is not None: print( "Changing role of user '{}' to '{}'".format( args.setrole[0], args.setrole[1] ) ) @@ -118,5 +121,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_bios_settings.py b/scripts/rf_bios_settings.py index 1611275..cda5172 100644 --- a/scripts/rf_bios_settings.py +++ b/scripts/rf_bios_settings.py @@ -43,20 +43,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -96,5 +89,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_boot_override.py b/scripts/rf_boot_override.py index 4b56402..cf115b6 100644 --- a/scripts/rf_boot_override.py +++ b/scripts/rf_boot_override.py @@ -50,20 +50,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -99,5 +92,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_diagnostic_data.py b/scripts/rf_diagnostic_data.py index a4b1532..a30ae11 100644 --- a/scripts/rf_diagnostic_data.py +++ b/scripts/rf_diagnostic_data.py @@ -59,20 +59,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -104,5 +97,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_discover.py b/scripts/rf_discover.py index 9940587..cb5e086 100644 --- a/scripts/rf_discover.py +++ b/scripts/rf_discover.py @@ -24,7 +24,7 @@ services = redfish.discover_ssdp() if len( services ) == 0: print( "No Redfish services discovered" ) - sys.exit(1) + sys.exit( 1 ) else: print( "Redfish services:" ) @@ -37,9 +37,9 @@ # Need to strip off /redfish/v1 from the SSDP response to use the URL with the library groups = re.search( "^(.+)\/redfish\/v1\/?$", services[service] ) url = groups.group( 1 ) - redfish_obj = redfish.redfish_client( base_url = url, timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = url, timeout = 15, max_retry = 3 ) print( "{}: {} ({})".format( service, services[service], redfish_obj.root["Product"] ) ) except: print( "{}: {}".format( service, services[service] ) ) -sys.exit(0) \ No newline at end of file +sys.exit( 0 ) diff --git a/scripts/rf_event_service.py b/scripts/rf_event_service.py index 31040da..924b712 100644 --- a/scripts/rf_event_service.py +++ b/scripts/rf_event_service.py @@ -49,20 +49,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -86,5 +79,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_licenses.py b/scripts/rf_licenses.py index 749cfb1..9373e68 100644 --- a/scripts/rf_licenses.py +++ b/scripts/rf_licenses.py @@ -44,20 +44,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -84,5 +77,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_logs.py b/scripts/rf_logs.py index 0ab809f..e1eb4f4 100644 --- a/scripts/rf_logs.py +++ b/scripts/rf_logs.py @@ -57,20 +57,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 30, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -92,5 +85,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_manager_config.py b/scripts/rf_manager_config.py index 213f726..a97ff72 100644 --- a/scripts/rf_manager_config.py +++ b/scripts/rf_manager_config.py @@ -63,20 +63,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -175,5 +168,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_power_reset.py b/scripts/rf_power_reset.py index c327968..11a2e34 100644 --- a/scripts/rf_power_reset.py +++ b/scripts/rf_power_reset.py @@ -40,20 +40,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -83,6 +76,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) - + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_raw_request.py b/scripts/rf_raw_request.py index d98b86a..698f8a8 100644 --- a/scripts/rf_raw_request.py +++ b/scripts/rf_raw_request.py @@ -20,6 +20,30 @@ import re from redfish.messages import RedfishPasswordChangeRequiredError +def ifmatch_header( redfish_obj, path, headers = None ): + """ + Generates If-Match header for PATCH and PUT operations + + Args: + redfish_obj: The Redfish client object with an open session + path: The URI of the resource + headers: Dictionary of HTTP headers to provide in the request + + Returns: + Updated dictionary of HTTP headers with If-Match, if an ETag was found + """ + + if headers is None: + headers = {} + try: + response = redfish_obj.get( path ) + etag = response.getheader( "ETag" ) + if etag is not None: + headers["If-Match"] = etag + except Exception: + pass + return headers + # Get the input arguments argget = argparse.ArgumentParser( description = "A tool perform a raw request to a Redfish service" ) argget.add_argument( "--user", "-u", type = str, required = True, help = "The user name for authentication" ) @@ -31,34 +55,16 @@ argget.add_argument( "--verbose", "-v", action = "store_true", help = "Indicates if HTTP response codes and headers are displayed", default = False ) args = argget.parse_args() -def ifmatch_header(redfish_obj, path, headers=None): - if headers is None: - headers = {} - try: - response = redfish_obj.get(path) - etag = response.getheader( "ETag" ) - if etag is not None: - headers[ "If-Match"] = etag - except Exception: - pass - return headers # Connect to the service redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise # Encode the body # If the body argument points to a file, load the file @@ -82,11 +88,11 @@ def ifmatch_header(redfish_obj, path, headers=None): elif args.method == "POST": resp = redfish_obj.post( args.request, body = body ) elif args.method == "PATCH": - headers = ifmatch_header(redfish_obj, args.request, headers = headers) - resp = redfish_obj.patch( args.request, body = body, headers = headers) + headers = ifmatch_header( redfish_obj, args.request, headers = headers ) + resp = redfish_obj.patch( args.request, body = body, headers = headers ) elif args.method == "PUT": - headers = ifmatch_header(redfish_obj, args.request, headers = headers) - resp = redfish_obj.put( args.request, body = body, headers = headers) + headers = ifmatch_header( redfish_obj, args.request, headers = headers ) + resp = redfish_obj.put( args.request, body = body, headers = headers ) elif args.method == "DELETE": resp = redfish_obj.delete( args.request ) else: @@ -110,5 +116,5 @@ def ifmatch_header(redfish_obj, path, headers=None): print( "No response body" ) # Log out -redfish_utilities.logout(redfish_obj, print_error = True) -sys.exit(0) \ No newline at end of file +redfish_utilities.logout( redfish_obj ) +sys.exit( 0 ) diff --git a/scripts/rf_sensor_list.py b/scripts/rf_sensor_list.py index 5e63c98..edf01a4 100644 --- a/scripts/rf_sensor_list.py +++ b/scripts/rf_sensor_list.py @@ -25,8 +25,8 @@ argget.add_argument( "--user", "-u", type = str, required = True, help = "The user name for authentication" ) argget.add_argument( "--password", "-p", type = str, required = True, help = "The password for authentication" ) argget.add_argument( "--rhost", "-r", type = str, required = True, help = "The address of the Redfish service (with scheme)" ) -argget.add_argument( "--id", "-i", action = "store_true", help = "list sensor info using Id" ) -argget.add_argument( "--name", "-n", action = "store_true", help = "list sensor info using Name" ) +argget.add_argument( "--id", "-i", action = "store_true", help = "Construct sensor names using 'Id' values" ) +argget.add_argument( "--name", "-n", action = "store_true", help = "Construct sensor names using 'Name' values" ) argget.add_argument( "--debug", action = "store_true", help = "Creates debug file showing HTTP traces and exceptions" ) args = argget.parse_args() @@ -39,20 +39,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -71,6 +64,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) - + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_sys_inventory.py b/scripts/rf_sys_inventory.py index bf8ec13..a0101bf 100644 --- a/scripts/rf_sys_inventory.py +++ b/scripts/rf_sys_inventory.py @@ -45,20 +45,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -75,6 +68,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) - + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_update.py b/scripts/rf_update.py index 659500f..c0b70b7 100644 --- a/scripts/rf_update.py +++ b/scripts/rf_update.py @@ -99,20 +99,13 @@ def print_error_payload( response ): # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise start_path = os.getcwd() targets = None @@ -175,6 +168,5 @@ def print_error_payload( response ): except: pass # Log out - redfish_utilities.logout(redfish_obj, print_error = True) - + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/scripts/rf_virtual_media.py b/scripts/rf_virtual_media.py index e2848e9..4e5a411 100644 --- a/scripts/rf_virtual_media.py +++ b/scripts/rf_virtual_media.py @@ -48,20 +48,13 @@ # Set up the Redfish object redfish_obj = None try: - redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password , timeout=5, max_retry=3) + redfish_obj = redfish.redfish_client( base_url = args.rhost, username = args.user, password = args.password, timeout = 15, max_retry = 3 ) redfish_obj.login( auth = "session" ) except RedfishPasswordChangeRequiredError as e: - redfish_utilities.print_password_change_required_and_logout(redfish_obj, args) - sys.exit(1) + redfish_utilities.print_password_change_required_and_logout( redfish_obj, args ) + sys.exit( 1 ) except Exception as e: - # other error - error_string = str(e) - if len(error_string) > 0: - print("{}\nLogin Failed\n".format(error_string)) - else: - print("Login Failed\n") - redfish_utilities.logout(redfish_obj, print_error = False) - sys.exit(1) + raise exit_code = 0 try: @@ -81,6 +74,5 @@ print( e ) finally: # Log out - redfish_utilities.logout(redfish_obj, print_error = True) - + redfish_utilities.logout( redfish_obj ) sys.exit( exit_code ) diff --git a/setup.py b/setup.py index fe3b30e..5aa5b94 100644 --- a/setup.py +++ b/setup.py @@ -77,7 +77,7 @@ def run(self): "scripts/rf_update.py", "scripts/rf_virtual_media.py" ], - install_requires = [ "redfish", "XlsxWriter" ], + install_requires = [ "redfish>=3.2.1", "XlsxWriter>=1.2.7" ], cmdclass={ 'pyinstaller': Pyinstaller }