Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ endif
build: ##@ Build the python package
python setup.py sdist

clean: ##@ Clean up build
rm -rf dist/*
rm -rf redfish_utilities.egg-info

install: ##@ Install with pip
pip install dist/redfish_utilities-${VERSION}.tar.gz

install-uv: ##@ Install with uv
uv pip install dist/redfish_utilities-${VERSION}.tar.gz

lint: ##@ Run linting
black .
black .
ruff check .
43 changes: 43 additions & 0 deletions redfish_utilities/arguments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import argparse


def validate_auth(args):
if (args.user and args.password and not args.session_token) or (
args.session_token and not (args.user or args.password)
):
return
else:
print("You must specify both --user and --password or --session-token")
quit(1)


def create_parent_parser(description: str = "", auth: bool = False, rhost: bool = False):
parent_parser = argparse.ArgumentParser(description=description, add_help=False)

parent_parser.add_argument(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we maintain parity with the existing --debug argument for the time being? I have a lot of folks relying on this usage now to debug everything.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I'm back to this. Sorry it took me so long. I believe I added back the existing --debug functionality in diagnostic_data. I may have misunderstood you though.

"--log-level",
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
default="INFO",
help="Creates debug file showing HTTP traces and exceptions",
)
parent_parser.add_argument("--log-to-console", action="store_true", help="Enable logging to console")
parent_parser.add_argument("--log-to-file", action="store_true", help="Enable logging to a file")
parent_parser.add_argument(
"--debug", action="store_true", help="Creates debug file showing HTTP traces and exceptions"
)

if auth:
parent_parser.add_argument("--user", "-u", type=str, help="The user name for authentication")
parent_parser.add_argument("--password", "-p", type=str, help="The password for authentication")
parent_parser.add_argument("--session-token", "-t", type=str, help="The session token for authentication")

if rhost:
parent_parser.add_argument(
"--rhost", "-r", type=str, required=True, help="The address of the Redfish service (with scheme)"
)

return parent_parser


def validate_args(args):
validate_auth(args)
42 changes: 42 additions & 0 deletions redfish_utilities/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import logging
import datetime
import redfish
import os


def get_debug_level(level):
if level == "DEBUG":
return logging.DEBUG
elif level == "INFO":
return logging.INFO
elif level == "WARNING":
return logging.WARNING
elif level == "ERROR":
return logging.ERROR
elif level == "CRITICAL":
return logging.CRITICAL
else:
raise ValueError(f"Invalid debug level: {level}")


def setup_logger(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the --debug option isn't used when setting up the debug output. Can we add it in so that if specified, it logs to a file (and is set to "loggingDEBUG")?

file_log: bool = False, stream_log: bool = True, log_level: str = "INFO", file_name: str = "redfish_utils"
):
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
log_level = get_debug_level(log_level)
logger = logging.getLogger(__name__)

if file_log:
file_name = os.path.basename(file_name)
timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S")
log_file = f"{file_name}-{timestamp}.log".format()
logger = redfish.redfish_logger(log_file, log_format, log_level)

if stream_log:
formatter = logging.Formatter(log_format)
sh = logging.StreamHandler()
sh.setFormatter(formatter)
logger.addHandler(sh)
logger.setLevel(log_level)

return logger
55 changes: 30 additions & 25 deletions scripts/rf_diagnostic_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@
"""

import argparse
import datetime
import logging

# import logging
import os
import redfish
import redfish_utilities
import traceback
import sys
from redfish.messages import RedfishPasswordChangeRequiredError
from redfish_utilities.arguments import create_parent_parser, validate_args
from redfish_utilities.logger import setup_logger

# Get the input arguments
argget = argparse.ArgumentParser(
description="A tool to collect diagnostic data from a log service on a Redfish service"
)
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)")
description = "A tool to collect diagnostic data from a log service on a Redfish service"
parent_parser = create_parent_parser(description=description, auth=True, rhost=True)
argget = argparse.ArgumentParser(parents=[parent_parser])

argget.add_argument(
"--manager", "-m", type=str, nargs="?", default=False, help="The ID of the manager containing the log service"
)
Expand All @@ -38,6 +38,7 @@
"--chassis", "-c", type=str, nargs="?", default=False, help="The ID of the chassis containing the log service"
)
argget.add_argument("--log", "-l", type=str, help="The ID of the log service")

argget.add_argument(
"--type",
"-type",
Expand All @@ -59,8 +60,13 @@
help="The directory to save the diagnostic data; defaults to the current directory if not specified",
default=".",
)
argget.add_argument("--debug", action="store_true", help="Creates debug file showing HTTP traces and exceptions")

args = argget.parse_args()
validate_args(args)
logger = setup_logger(
file_log=args.log_to_file, stream_log=args.log_to_console, log_level=args.log_level, file_name=__file__
)


# Determine the target log service based on the inputs
# Effectively if the user gives multiple targets, some will be ignored
Expand All @@ -76,19 +82,18 @@
container_type = redfish_utilities.log_container.CHASSIS
container_id = args.chassis

if args.debug:
log_file = "rf_diagnostic_data-{}.log".format(datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S"))
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
logger = redfish.redfish_logger(log_file, log_format, logging.DEBUG)
logger.info("rf_diagnostic_data Trace")

# 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=15, max_retry=3
)
redfish_obj.login(auth="session")
if args.session_token:
sessionkey = str.encode(args.session_token)
redfish_obj = redfish.redfish_client(base_url=args.rhost, sessionkey=sessionkey, timeout=15, max_retry=3)
else:
redfish_obj = redfish.redfish_client(
base_url=args.rhost, username=args.user, password=args.password, timeout=15, max_retry=3
)
# Don't need to login if we're using a session key
redfish_obj.login(auth="session")
except RedfishPasswordChangeRequiredError:
redfish_utilities.print_password_change_required_and_logout(redfish_obj, args)
sys.exit(1)
Expand All @@ -97,7 +102,7 @@

exit_code = 0
try:
print("Collecting diagnostic data...")
logger.info("Collecting diagnostic data...")
response = redfish_utilities.collect_diagnostic_data(
redfish_obj, container_type, container_id, args.log, args.type, args.oemtype
)
Expand All @@ -119,13 +124,13 @@
path = os.path.join(args.directory, filename)
with open(path, "wb") as file:
file.write(data)
print("Saved diagnostic data to '{}'".format(path))
logger.info("Saved diagnostic data to '{}'".format(path))
except Exception as e:
if args.debug:
logger.error("Caught exception:\n\n{}\n".format(traceback.format_exc()))
logger.debug("Caught exception:\n\n{}\n".format(traceback.format_exc()))
exit_code = 1
print(e)
logger.info(e)
finally:
# Log out
redfish_utilities.logout(redfish_obj)
if not args.session_token:
redfish_utilities.logout(redfish_obj)
sys.exit(exit_code)