Skip to content

Commit e8e20dd

Browse files
authored
Final minor bug fixes. (#290)
* Final minor bug fixes. * More small fixes. - draw_table now just uses the first 20 rows to figure out column widths. - Handle non-datetime objects in rel_time * Fixed yaml_config. * Addressed comments.
1 parent 8c332eb commit e8e20dd

File tree

6 files changed

+83
-22
lines changed

6 files changed

+83
-22
lines changed

docs/install.rst

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Installing Pavilion
66
===================
77

88
Installing Pavilion is mostly a matter of placing it's source somewhere,
9-
providing it's (few) dependencies, and creating a pavilion.yaml config
9+
providing its (few) dependencies, and creating a pavilion.yaml config
1010
file.
1111

1212
.. contents::
@@ -16,8 +16,9 @@ Requirements
1616

1717
Pavilion has very few dependencies and requirements:
1818

19-
- Python 3.4 or newer
20-
- A writeable space on a filesystem shared across all (tested) hosts in each cluster.
19+
- Python 3.5 or newer
20+
- A writeable space on a filesystem shared across all (tested) hosts in
21+
each cluster. (Assuming you're scheduling jobs across a cluster).
2122

2223
- The path to this directory must be consistent across all cluster hosts.
2324
- It must support atomic file creation and appends of < 4kb.
@@ -30,7 +31,7 @@ Filesystems
3031

3132
Pavilion works by recursively running itself in different modes at
3233
different points in the testing process. This means certain paths, like
33-
the Pavilion **root directory**, **working directory**, and used
34+
the Pavilion **source directory**, **working directory**, and used
3435
**config directories** must have paths that are consistent across the
3536
nodes and front-ends of any given system.
3637

@@ -45,6 +46,16 @@ to ``~/.pavilion/``).
4546
your cluster NFS partitions. Lustre filesystems are not recommended, mostly
4647
due to the type of load Pavilion presents to these.
4748

49+
Testing Filesystems
50+
~~~~~~~~~~~~~~~~~~~
51+
52+
If you're unsure if your shared filesystem is reliable, there's a test for
53+
that in `test/utils`.
54+
55+
.. code-block:: bash
56+
57+
$ python3 lock_test.py --help
58+
4859
Result Log
4960
~~~~~~~~~~
5061

@@ -84,6 +95,21 @@ starts with a git pull of the latest release of Pavilion.
8495
8596
You can also simply download and extract the source.
8697

98+
Releases
99+
~~~~~~~~
100+
101+
You should probably pick the latest Pavilion *release* when installing
102+
Pavilion for a couple reasons.
103+
104+
1) While we try to maintain backwards compatibility as much as possible,
105+
the reality is that every release contains several major compatibility
106+
breaks both for test configurations and plugins. These are documented
107+
per-release in the `_static/RELEASE.txt`_ file.
108+
2) We run a large bevy of unit tests against every change in Pavilion, but
109+
each release is used in production before it is actually tagged. This
110+
often reveals bug, regressions, and practical usage issues. We fix those
111+
issues, then tag the release. Bugfix releases are provided as needed.
112+
87113
Dependencies
88114
------------
89115

@@ -95,10 +121,10 @@ supported and tests versions for each are recorded in ``requirements.txt``.
95121

96122
- `yaml\_config <https://github.com/lanl/yaml_config>`__ **(required)**
97123
- Used to define the test and pavilion configurations.
98-
- `**yc\_yaml** <https://github.com/pflarr/yc_yaml>`__ **(required)** - A
99-
modified pyyaml used by yaml\_config.
100-
- `**yapsy** <http://yapsy.sourceforge.net/>`__ **(required)** - The basis
124+
- `yapsy <http://yapsy.sourceforge.net/>`__ **(required)** - The basis
101125
for Pavilion's plugin architecture.
126+
- `lark <https://github.com/lark-parser/lark>`__ **(required)** - Used for
127+
Pavilion string value and expression parsing.
102128
- `requests <https://pypi.org/project/requests/2.7.0/>`__ - Used for
103129
automatic downloads of test source files. This feature is disabled in
104130
the absence of this library, and tests that use it will fail with an

lib/pavilion/output.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -707,17 +707,20 @@ def dt_auto_widths(rows, table_width, min_widths, max_widths):
707707
the column that will benefit the most from a single character of width
708708
increase. In case of a tie, two characters of width are considered, and
709709
so on. Remaining extra space is distributed amongst the final tied
710-
columns."""
710+
columns. To limit how long this takes, this makes a best guess using
711+
the first 20 rows."""
711712

712713
fields = list(min_widths.keys())
713714

714715
extra_spaces = table_width - sum(min_widths.values())
715716

716717
final_widths = min_widths.copy()
717718

719+
# Limit to just the first 20 rows for speed.
720+
rows = rows[:20]
721+
718722
def calc_wraps(fld_, width_):
719-
"""Calculate the wraps for a given field at the given width across
720-
all rows."""
723+
"""Calculate the wraps for a given field at the given width."""
721724
return sum([len(row_[fld_].wrap(width=width_))
722725
for row_ in rows])
723726

lib/pavilion/plugins/commands/status.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def get_all_tests(pav_cfg, args):
8383
'test_id': test_id,
8484
'name': "",
8585
'state': STATES.UNKNOWN,
86-
'time': "",
86+
'time': None,
8787
'note': "Test not found: {}".format(err)
8888
})
8989

@@ -162,7 +162,7 @@ def get_statuses(pav_cfg, args, errfile):
162162
'test_id': test_id,
163163
'name': "",
164164
'state': STATES.UNKNOWN,
165-
'time': "",
165+
'time': None,
166166
'note': "Error loading test: {}".format(err),
167167
})
168168

lib/pavilion/plugins/commands/wait.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def _setup_arguments(self, parser):
3535
)
3636
parser.add_argument(
3737
'-t', '--timeout', action='store',
38-
help='Maximum time to wait for results in seconds. Default is to'
38+
help='Maximum time to wait for results in seconds. Default is to '
3939
'wait indefinitely.'
4040
)
4141
parser.add_argument(

lib/pavilion/utils.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,16 @@ def get_login():
130130
"""Get the current user's login, either through os.getlogin or
131131
the environment, or the id command."""
132132

133+
# We've found this to be generally more reliable in sudo situations
134+
# than getlogin.
135+
if 'USER' in os.environ:
136+
return os.environ['USER']
137+
133138
try:
134139
return os.getlogin()
135140
except OSError:
136141
pass
137142

138-
if 'USER' in os.environ:
139-
return os.environ['USER']
140-
141143
try:
142144
name = subprocess.check_output(['id', '-un'],
143145
stderr=subprocess.DEVNULL)

test/utils/lock_test.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
1-
"""Run this simultaniously on multiple hosts that share an NFS filesystem to test cross-system NFS
2-
locking. The tests do a synchronized start at the top of the minute according to the system clock, so
3-
make sure the system clocks are close (within .5 seconds will do). Any locking errors will be
4-
printed."""
1+
"""
2+
Multi-host lockfile test.
3+
4+
Usage: python3 lock_test.py <lockfile_dir>
5+
6+
Run this simultaniously on multiple hosts that share an NFS filesystem
7+
to test cross-system NFS locking. The tests do a synchronized start at the top
8+
of the minute according to the system clock, so make sure the system clocks are close
9+
(within .5 seconds will do). Any locking errors will be
10+
printed.
11+
12+
The shared lockfile is placed in this directory
13+
14+
The test should complete on all systems without errors.
15+
16+
"""
517

6-
from pavilion import lockfile
718
from pathlib import Path
19+
import sys
20+
libdir = (Path(__file__).resolve().parents[2]/'lib').as_posix()
21+
sys.path.append(libdir)
22+
23+
from pavilion import lockfile
824
import time
925

26+
lock_dir = None
27+
if len(sys.argv) == 2:
28+
try:
29+
lock_dir = Path(sys.argv[1])
30+
except:
31+
pass
32+
33+
if ('--help' in sys.argv or '-h' in sys.argv
34+
or lock_dir is None or not lock_dir.exists()):
35+
print(__doc__)
36+
sys.exit(1)
37+
1038
acquires = 500
1139
acquired = 0
1240

@@ -20,12 +48,14 @@
2048

2149
print('starting', time.time(), flush=True)
2250

51+
lock_path = lock_dir/'test.lockfile'
52+
2353
# Acquire a bunch of locks to give plenty of chances for things to break.
2454
# More locking attempts also mean more time for runs on multiple systems
2555
# to overlap.
2656
while acquired < acquires:
2757
start = time.time()
28-
with lockfile.LockFile('/usr/projects/hpctest/.locktest'):
58+
with lockfile.LockFile(lock_path):
2959
acquire_times.append(time.time() - start)
3060
print(".", end="", flush=True)
3161
acquired += 1

0 commit comments

Comments
 (0)