Skip to content

Implemented the show-log command along with flag: -f, --filepath #17

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
9 changes: 9 additions & 0 deletions ceph_devstack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ def parse_args(args: List[str]) -> argparse.Namespace:
default=False,
help="Leave the cluster running - and don't auto-schedule anything",
)

parser_show_log = subparsers.add_parser("show-log", help="Show test logs")
parser_show_log.add_argument(
"-f",
"--filepath",
action="store_true",
default=False,
help="Output just the full path of the logfile instead of its content"
)
subparsers.add_parser("remove", help="Destroy the cluster")
subparsers.add_parser("start", help="Start the cluster")
subparsers.add_parser("stop", help="Stop the cluster")
Expand Down
2 changes: 2 additions & 0 deletions ceph_devstack/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ async def run():
return
elif args.command == "wait":
return await obj.wait(container_name=args.container)
elif args.command == "show-log":
return await obj.show_log(filepath=args.filepath)
else:
await obj.apply(args.command)
return 0
Expand Down
66 changes: 66 additions & 0 deletions ceph_devstack/resources/ceph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import contextlib
import os
import tempfile
from datetime import datetime

from subprocess import CalledProcessError

Expand Down Expand Up @@ -226,3 +227,68 @@ async def wait(self, container_name: str):
return await object.wait()
logger.error(f"Could not find container {container_name}")
return 1

async def show_log(self, filepath: bool = False):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: boolean variables can be named something like is_filepath for readability

home_dir = os.path.expanduser("~")
target_dir = os.path.join(home_dir, ".local", "share", "ceph-devstack", "archive")
Copy link
Collaborator

@VallariAg VallariAg Apr 9, 2025

Choose a reason for hiding this comment

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

~/.local/share/ceph-devstack is the default directory where archives are stored but it can be configureable with --data-dir so it's a good idea to not hardcode the archive path here

run_directories_list = None
if os.path.exists(target_dir) and os.path.isdir(target_dir):
run_directories_list = os.listdir(target_dir)
else:
logger.error(f"Error: {target_dir} does not exist or is not a directory")
return 1
def extract_timestamp(dir_name):
try:
parts = dir_name.split("-")
year, month, day_time = parts[1], parts[2], parts[3]
day, time = day_time.split("_")
timestamp = f"{year}-{month}-{day} {time}"
return datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S")
except Exception as e:
logger.error(f"Error extracting timestamp from {dir_name}: {e}")
return None
run_directories_list.sort(key=lambda dir: extract_timestamp(dir), reverse=True)
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is nice!

latest_directory = run_directories_list[0] if run_directories_list else None
try:
latest_directory = os.path.join(target_dir, latest_directory)
all_job_ids = [jobID for jobID in os.listdir(latest_directory) if os.path.isdir(os.path.join(latest_directory, jobID)) and jobID.isdigit()]
if not all_job_ids:
logger.info("No latest jobIDs") # We could add a feature to go to the "next" latest directory
else:
if(len(all_job_ids)>1):
print("ALERT: Multiple jobIDs found: ", ", ".join(all_job_ids))
while True:
selected_jobID = input("Select jobID to view corresponding log: ")
if selected_jobID in all_job_ids:
log_file_path = os.path.join(latest_directory, selected_jobID, "teuthology.log")
if os.path.exists(log_file_path) and os.path.isfile(log_file_path) and not filepath:
print("<-----------teuthology.log contents----------->")
with open(log_file_path, "r") as file:
print(file.read())
return 0
elif filepath:
logger.info(f"{log_file_path}")
return 0
Comment on lines +269 to +271
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
elif filepath:
logger.info(f"{log_file_path}")
return 0
elif os.path.exists(log_file_path) and os.path.isfile(log_file_path) and filepath:
logger.info(f"{log_file_path}")
return 0

otherwise it'll print the teuthology.log file path even if job directory exists but teuthology.log file does not exist

else:
logger.error(f"Error: teuthology.log file not found in {os.path.join(latest_directory, selected_jobID)}")
return 1
else:
logger.error(f"Error: {selected_jobID} is not a valid jobID")
else:
selected_jobID = all_job_ids[0]
log_file_path = os.path.join(latest_directory, selected_jobID, "teuthology.log")
if os.path.exists(log_file_path) and os.path.isfile(log_file_path) and not filepath:
print("<-----------teuthology.log contents----------->")
with open(log_file_path, "r") as file:
print(file.read())
return 0
elif filepath:
logger.info(f"{log_file_path}")
Comment on lines +285 to +286
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
elif filepath:
logger.info(f"{log_file_path}")
elif os.path.exists(log_file_path) and os.path.isfile(log_file_path) and filepath:
logger.info(f"{log_file_path}")

same comment as above

return 0
else:
logger.error(f"Error: teuthology.log file not found in {os.path.join(latest_directory, selected_jobID)}")
return 1
return 0
except Exception as e:
logger.error(f"Error: {e}")