Skip to content

Commit

Permalink
Added log_states command. (#684)
Browse files Browse the repository at this point in the history
* Added log_states command.

* style

* style again.

* Minor style and documentation additions.
  • Loading branch information
Paul-Ferrell authored Sep 5, 2023
1 parent 341857f commit fa1428a
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
9 changes: 5 additions & 4 deletions RELEASE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@ RELEASE=2.4

## 2.5 Pre-release notes
- In the 'modules' section of 'run' or 'build' in test configs, modules specified without a version
no longer verify that the default was loaded.
no longer verify that the default was loaded.
- Added the ability to configure module wrappers in test/host configs.
- This breaks backwards compatibility with existing module wrapper plugins. The 'load()' method
now takes an addtional, required 'name' argument.

- Added the ability to extend lists via inheritance across all test configs.
- Added `pav series sets` and `pav series cancel` commands.
- Added `pav series sets` and `pav series cancel` commands.

- `pav series history` is now `pav series `states`.
- Added `-c` 'overrides' to `pav series run`, and an overrides section to the series config.
- `pav cancel` no longer cancels series, just tests.

- The `SCHED_RUNNING` state is now `SCHED_STARTUP` - existing scheduler plugins that use
`SCHED_RUNNING` should still work.
- Added `pav log states` command, which lists all states a test has had.

## 2.4 Release Notes
- Minimum supported python version is now 3.6
Expand Down
43 changes: 43 additions & 0 deletions lib/pavilion/commands/log.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Print out the contents of the various log files for a given test run.
"""

import datetime
import errno
import time
import sys
Expand Down Expand Up @@ -83,6 +85,16 @@ def _setup_arguments(self, parser):
description="Displays Pavilion's global output log."
)

states_cmd = subparsers.add_parser(
'states',
help="Show a tests's state history.",
description="Displays the state ('<test_id>/status' file in full for a given test.")
states_cmd.add_argument(
'--raw', action='store_true', help="Print the state file as is.")
states_cmd.add_argument(
'--raw_time', action='store_true', help="Print raw unix timestamps.")
states_cmd.add_argument('id', help="The test id to show states for.")

subparsers.add_parser(
'all_results',
aliases=['allresults', 'all-results'],
Expand Down Expand Up @@ -132,6 +144,8 @@ def run(self, pav_cfg, args):
else:
cmd_name = args.log_cmd

if cmd_name == 'states':
return self._states(pav_cfg, args.id, raw=args.raw, raw_time=args.raw_time)

if cmd_name in ['global', 'all_results', 'allresults', 'all-results']:
if 'results' in cmd_name:
Expand Down Expand Up @@ -204,3 +218,32 @@ def run(self, pav_cfg, args):
if self.follow_testing:
break
return 0

def _states(self, pav_cfg, test_id: str, raw: bool = False, raw_time: bool = False):
"""Print the states for a test."""

try:
test = TestRun.load_from_raw_id(pav_cfg, test_id)
except errors.TestRunError as err:
output.fprint(self.errfile, "Error loading test.", err, color=output.RED)
return 1

states = test.status.history()

states = [state.as_dict() for state in states]

if not raw_time:
for state in states:
state['time'] = datetime.datetime.fromtimestamp(state['time']).isoformat(' ')

if raw:
for state in states:
output.fprint(self.outfile,
"{time} {state} {note}".format(**state))
else:
output.draw_table(
self.outfile,
rows=states,
fields=['time', 'state', 'note'],)

return 0
35 changes: 28 additions & 7 deletions test/tests/log_cmd_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
import threading
import time

import pavilion.commands
import pavilion.schedulers
from pavilion import commands
from pavilion import schedulers
from pavilion.unittest import PavTestCase


class LogCmdTest(PavTestCase):

def test_log_arguments(self):
log_cmd = pavilion.commands.get_command('log')
log_cmd = commands.get_command('log')

parser = argparse.ArgumentParser()
log_cmd._setup_arguments(parser)

# run a simple test
test = self._quick_test(finalize=False)
raw = pavilion.schedulers.get_plugin('raw')
raw = schedulers.get_plugin('raw')

raw.schedule_tests(self.pav_cfg, [test])

Expand Down Expand Up @@ -86,7 +86,7 @@ def test_log_arguments(self):
self.assertEqual(err.getvalue(), '')

def test_log_tail(self):
log_cmd = pavilion.commands.get_command('log')
log_cmd = commands.get_command('log')

parser = argparse.ArgumentParser()
log_cmd._setup_arguments(parser)
Expand All @@ -103,7 +103,7 @@ def test_log_tail(self):
'echo "crazy"', 'echo "long"', 'echo "output"']
test = self._quick_test(cfg=test_cfg)

raw = pavilion.schedulers.get_plugin('raw')
raw = schedulers.get_plugin('raw')
raw.schedule_tests(self.pav_cfg, [test])

end = time.time() + 5
Expand All @@ -124,7 +124,7 @@ def test_log_tail(self):
log_cmd.outfile = sys.stderr

def test_follow(self):
log_cmd = pavilion.commands.get_command('log')
log_cmd = commands.get_command('log')
log_cmd.silence()

test_cfg = self._quick_test_cfg()
Expand All @@ -146,3 +146,24 @@ def test_follow(self):
out, err = log_cmd.clear_output()
self.assertIn('output', out)
log_cmd.follow_testing = True

def test_log_states(self):
"""Test the 'log states' command."""


test = self._quick_test()

log_cmd = commands.get_command('log')
log_cmd.silence()

parser = argparse.ArgumentParser()
log_cmd._setup_arguments(parser)

for args in (
('states', test.full_id),
('states', '--raw', test.full_id),
('states', '--raw_time', test.full_id),
('states', '--raw', '--raw_time', test.full_id),
):
args = parser.parse_args(args)
self.assertEqual(log_cmd.run(self.pav_cfg, args), 0)

0 comments on commit fa1428a

Please sign in to comment.