1
0
mirror of https://github.com/ceph/ceph synced 2025-04-10 03:32:25 +00:00
Commit Graph

247 Commits

Author SHA1 Message Date
Patrick Donnelly
97170e78e6
qa/tasks/vstart_runner: run daemons in foreground
This mirrors teuthology and makes it possible to check the exit status of a
daemon.

Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
(cherry picked from commit e2e2144a56)
2025-02-25 11:17:15 -05:00
Patrick Donnelly
fd8ea7ba82
qa/tasks/vstart_runner: add missing poll method
Otherwise you cannot use LocalDaemon.check_status.

Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
(cherry picked from commit 9748d0c465)
2025-02-25 11:17:15 -05:00
Rishabh Dave
e94ab39c2e qa/cephfs: log commands on INFO logging level
Commands issued by negtest_ceph_cmd() aren't printed because log level
(due to code for teuthology) changes from DEBUG to INFO in case of some
files.

This patch ensures that users can see commands being executed regardless
of whether log level is changed or not.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
(cherry picked from commit 03df86b7c5)
2024-04-06 15:44:16 +05:30
Milind Changire
3d3300469f
qa: bump up scrub status command timeout
A journal flush sometimes takes more than 120 seconds and so the 'scrub
status' command after blocking for more than 120 seconds is declared
failed causing the job to be declared as failed.

This bumping up of the timeout gives more time for the 'scrub status'
command to wait and eventually let the journal flush to complete.

Fixes: https://tracker.ceph.com/issues/63411
Signed-off-by: Milind Changire <mchangir@redhat.com>
(cherry picked from commit 33899fdaac)

Conflicts:
	qa/tasks/ceph_manager.py
	- fixed diff between main and reef
	qa/tasks/cephfs/filesystem.py
	- fixed diff between main and reef
	qa/tasks/vstart_runner.py
	- fixed diff between main and reef
2024-03-04 15:13:32 +05:30
Sridhar Seshasayee
b56ac878ce qa/tasks: Allow override of recovery configs for tests
With mClock scheduler enabled, a small subset of config options related
to recovery limits are not allowed to be modified unless
osd_mclock_override_recovery_settings option is enabled. This override
option is disabled by default. The following options cannot be modified
without enabling the override option:

 - osd_max_backfills
 - osd_recovery_max_active[_(hdd|ssd)]

The above options are removed from the mon kv store which effectively
restores them to the default values.

This was resulting in tests for example,
test_cluster_configuration.ClusterConfigurationTest to fail since it
modifies the recovery options and expects to verify the modified value.

Therefore, for tests, osd_mclock_override_recovery_settings option is
enabled in vstart_runner.py so that current and future tests
are not affected.

Fixes: https://tracker.ceph.com/issues/61155
Signed-off-by: Sridhar Seshasayee <sseshasa@redhat.com>
(cherry picked from commit aed71b56be)
2023-05-22 17:07:45 +05:30
Venky Shankar
ab8fbe4e59 Merge PR into main
* refs/pull/48473/head:
	qa: fix _run_mount_cmd() and _get_mount_cmd() args in vstart_runner

Reviewed-by: Rishabh Dave <ridave@redhat.com>
Reviewed-by: Venky Shankar <vshankar@redhat.com>
Reviewed-by: Neeraj Pratap Singh <neesingh@redhat.com>
2022-12-19 16:17:15 +05:30
dparmar18
d96a7347d8 qa: fix _run_mount_cmd() and _get_mount_cmd() args in vstart_runner
commit 483b16062d
brought in a new arg 'mntargs' and this resulted in errors like:

2022-10-13 01:57:37,519.519 INFO:__main__:ERROR: test_client_metrics_and_metadata (tasks.cephfs.test_mds_metrics.TestMDSMetrics)
2022-10-13 01:57:37,519.519 INFO:__main__:----------------------------------------------------------------------
2022-10-13 01:57:37,519.519 INFO:__main__:Traceback (most recent call last):
2022-10-13 01:57:37,519.519 INFO:__main__:  File "/home/dparmar/cephbuild_run_but_no_edits/ceph/qa/tasks/cephfs/test_mds_metrics.py", line 21, in setUp
2022-10-13 01:57:37,519.519 INFO:__main__:    super(TestMDSMetrics, self).setUp()
2022-10-13 01:57:37,519.519 INFO:__main__:  File "/home/dparmar/cephbuild_run_but_no_edits/ceph/qa/tasks/cephfs/cephfs_test_case.py", line 180, in setUp
2022-10-13 01:57:37,519.519 INFO:__main__:    self.mounts[i].mount_wait()
2022-10-13 01:57:37,519.519 INFO:__main__:  File "/home/dparmar/cephbuild_run_but_no_edits/ceph/qa/tasks/cephfs/mount.py", line 505, in mount_wait
2022-10-13 01:57:37,519.519 INFO:__main__:    self.mount(**kwargs)
2022-10-13 01:57:37,519.519 INFO:__main__:  File "/home/dparmar/cephbuild_run_but_no_edits/ceph/qa/tasks/cephfs/fuse_mount.py", line 52, in mount
2022-10-13 01:57:37,519.519 INFO:__main__:    return self._mount(mntopts, mntargs, check_status)
2022-10-13 01:57:37,519.519 INFO:__main__:  File "/home/dparmar/cephbuild_run_but_no_edits/ceph/qa/tasks/cephfs/fuse_mount.py", line 68, in _mount
2022-10-13 01:57:37,519.519 INFO:__main__:    retval = self._run_mount_cmd(mntopts, mntargs, check_status)
2022-10-13 01:57:37,519.519 INFO:__main__:TypeError: LocalFuseMount._run_mount_cmd() takes 3 positional arguments but 4 were given

This new arg needs to be added in vstart_runner to prevent this.

Introduced-By: 483b16062d
Fixes: https://tracker.ceph.com/issues/58088
Signed-off-by: Dhairya Parmar <dparmar@redhat.com>
2022-11-29 16:42:22 +05:30
Kefu Chai
9bdf050b92 qa/tasks/vstart_runner: do not fail if stop.sh fails
stop.sh might fail, but let's keep moving on.

See-also: https://tracker.ceph.com/issues/57834
Signed-off-by: Kefu Chai <tchaikov@gmail.com>
2022-10-22 01:24:32 +08:00
Xiubo Li
6bbb29cb3a qa: the default CEPH_ASOK_DIR is asok/ now
Or the find_admin_socket() couldn't find the correct asok path.

Signed-off-by: Xiubo Li <xiubli@redhat.com>
2022-09-13 13:49:22 +08:00
Rishabh Dave
c279b47ec9 qa/cephfs: lazy-force unmount clients that have been evicted
Before unmounting check if the client has been evicted and, if so, run
"umount -f -l" for the mount point of the client and cleanup the mount
right after it.

Attempting to unmount, cleanup or operate in any way over mount point
of a evicted client will hang the operation (and thereby our Python
code too). Lazy-force unmount prevents such hangs for our Python code
and also frees the mount point.

This commit also adds code to gather session info for kernel mounts
after mounting is successful. This is a necessity since network address
of session is needed to check if it is blocked by Ceph cluster.

Fixes: https://tracker.ceph.com/issues/56476
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-08-19 21:00:00 +05:30
Rishabh Dave
9703369979 qa/ceph_manager: clean up CephManager.do_rados()
do_rados() prefixes extra arguments to every command because they are
helpful during execution of tests with teuthology. This patch
eliminates these extra arguments entirely (through overriding) for test
executions with vstart_runner.py.

Note: "timeout 120" is now prefixed to rados commands too. AFAIS, it
shouldn't have any side-effects on anything.

This commit is similar to commit 93677576c1.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-06-27 21:58:16 +05:30
Venky Shankar
2ab2777722
Merge pull request from rishabh-d-dave/qa-omit-sudo
qa/cephfs: set omit_sudo False when sudo is set to True

Reviewed-by: Venky Shankar <vshankar@redhat.com>
Reviewed-by: Dhairya Parmar <dparmar@redhat.com>
Reviewed-by: Nikhilkumar Shelke <nshelke@redhat.com>
2022-06-06 11:23:11 +05:30
Rishabh Dave
59273966f1 qa/vstart_runner: store FSID in LocalContext instances
1. Method cluster() in ceph.py creates a dictionary "ctx.ceph", attaches
   a namespace to ctx.ceph[cluster_name], create an attribute "fsid" and
   stores Ceph cluster's FSID in it.

2. The method kernel_mount.KernelMount._get_debug_dir() uses that "fsid"
   attribute to get Ceph cluster's FSID. (The exact that does that is
   "fsid = self.ctx.ceph[cluster_name].fsid").

3. Test test_readahead.TestReadahead.test_flush() crashes with
   vstart_runner.py because that test eventually calls _get_debug_dir()
   and "ctx" in case of vstart_runner.py doesn't hold "ceph" dictionary
   or anything similar.

Adding a dictionary, similar to the one added in ceph.py, to
vstart_runner.LocalContext's instances will fix this issue.

Fixes: https://tracker.ceph.com/issues/55694
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-18 19:44:34 +05:30
Venky Shankar
6f459d8bf2
Merge pull request from rishabh-d-dave/vstart-minor-fixes
qa/vstart_runner: minor bug fix and minor adjustments

Reviewed-by: Venky Shankar <vshankar@redhat.com>
2022-05-11 11:26:09 +05:30
Venky Shankar
338e18b893
Merge pull request from rishabh-d-dave/vr-run-mnt-cmd
qa/vstart_runner: fix bug in LocalFuseMount._run_mount_cmd()

Reviewed-by: Venky Shankar <vshankar@redhat.com>
2022-05-10 15:08:01 +05:30
Rishabh Dave
c9807d35e0 qa/vstart_runner: fix args to os.path.join()
Result of os.path.join() before "./bin/ceph-mds" and after
"./bin/./ceph-mds".

Before -

	2022-05-05 19:36:11,100.100 DEBUG:__main__:> ./bin/./ceph-mds -i a

After -

	2022-05-05 19:38:48,179.179 DEBUG:__main__:> ./bin/ceph-mds -i a

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-10 11:03:24 +05:30
Rishabh Dave
3dd150959e qa/vstart_runner: minor bug fix and minor adjustments
The message regarding deletion of helper tools is printed for every
command. This message should be printed only when applicable.

Besides -

* Move XXX comments to _do_run() since it increases visibility of
  these messages.
* Move omission of arguments stuff to new method clear up the clutter.
* And remove shell as a parameter from _perform_checks_and_adjustments
  since it's redundant.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-10 11:02:08 +05:30
Rishabh Dave
94d2b1048f qa/vstart_runner: fix bug in LocalFuseMount._run_mount_cmd()
This methods fails to collect return value from
FuseMount._run_mount_cmd() and return it. This leads to a bug for tests
that expect mount command to fail when executed with vstart_runner.py.

Fixes: https://tracker.ceph.com/issues/55553
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-05 21:03:46 +05:30
Rishabh Dave
76edd3bb32 qa/cephfs: set omit_sudo False when sudo is set to True
In these methods, parameter "sudo" indicates whether or not sudo is set
to True but the same is not indicated to methods underneath. This value
needs to be passed for the parameter to fulfill it's commitment.

Fixes: https://tracker.ceph.com/issues/55557
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-05 20:03:28 +05:30
Rishabh Dave
04209a1e7e vstart_runner: make LocalRemote inherit RemoteShell
And therefore get rid of methods duplicated in LocalRemote and add a
call to empty constructor of RemoteShell in LocalRemote.__init__().

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-05 12:30:24 +05:30
Rishabh Dave
acc923c8a4 qa/vstart_runner: add a helper method to run commands
It's more convenient to not to pass stdout, stdin, and stderr every
single time.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:25:19 +05:30
Rishabh Dave
f12536fed1 qa/vstart_runner: don't use os.kill for passing SIGKILL
vstart_runner.py is written assuming that it can run commands with
superuser privileges whenever possible and vstart_runner.py is meant to
be executed without sudo.

So, it's better kill a process using "sudo kill -9 <PID>", instead of
using os.kill() because os.kill() can't kill process launched with
superuser privileges.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:25:19 +05:30
Rishabh Dave
8d4ef76923 qa/vstart_runner.py: add a note about omitting sudo
About the commit date: this commit got dropped from the patch series
during some PR branch update but is added back now.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:25:19 +05:30
Rishabh Dave
43b170ab18 qa/vstart_runner: get rid of "exec sudo" from "ceph -w" cmd args
Passing "exec sudo" to "ceph -w" caused "Ceph API test" CI job to fail.
Error was not related to this tracker issue but the code added for it
is reversed now in this commit. The tracker issue -
https://tracker.ceph.com/issues/49644.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:25:19 +05:30
Rishabh Dave
a67d500ee1 qa/vstart_runner: keep cmd args as passed by user as well
We convert all cmd args to str and pass bash functions along to override
certain arguments in those command arguments. Let's save cmd args
without those bash functions since they can be useful later (for
example, printing cmd args in logs, which is the case in this patch.)

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:25:19 +05:30
Rishabh Dave
8fc635c28c qa/vstart_runner: copy few more note points from dev guide
The intention behind copying these note points is to document the
behaviour of vstart_runner.py inside vstart_runner.py as well so that
developer don't miss it out while working on it.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:25:19 +05:30
Rishabh Dave
7d53423439 qa/vstart_runner: override adjust-ulimits, ceph-coverage & sudo
Overridding commands is much better than deleting these commands from
command argument string using Python since, unlike deleting, overridding
doesn't require parsing. A note has been added for this to
vstart_runner.py's module docstring and to Ceph Developer's Guide
document.

Since functions don't work with sh shell, to make overriding work
vstart_runner.py will use bash shell here onwards.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:25:17 +05:30
Rishabh Dave
27eaacd98a qa/vstart_runner: accept multiple commands as str
Convert all command arguments to str from list, update checks and
adjustments performed on command arguments accordingly and update
documentation to include warnings about some critical parts of
vstart_runner.py and update tasks.cephfs.mount.MountCephFS.run_shell().

Fixes: https://tracker.ceph.com/issues/47849
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-05-02 20:24:08 +05:30
Rishabh Dave
d9fbf65f77 qa/vstart_runner: set LocalCephManager.cluster
Use LocalContext instance to set LocalCephManager.cluster.

Fixes: https://tracker.ceph.com/issues/53601
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-04-27 16:02:34 +05:30
Kotresh HR
c57a13f8be qa: Fix a few tracebacks in vstart_runner
1. CommandFailedError: Command failed with status 127: \
	['None/archive/coverage', 'rados' ...]
2. TypeError: a bytes-like object is required, not '_io.BytesIO'

Fixes: https://tracker.ceph.com/issues/53601
Signed-off-by: Kotresh HR <khiremat@redhat.com>
2022-04-27 16:02:32 +05:30
Rishabh Dave
902420cbd4 qa/vstart_runner: print "success" explicitly
This makes it effortless for new vstart_runner.py users to spot that the
test passed.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2022-04-18 10:39:08 +05:30
Xiubo Li
3b44f20ac0 qa: move the optional client_config parameter to the end
Fixes: https://tracker.ceph.com/issues/53216
Signed-off-by: Xiubo Li <xiubli@redhat.com>
2021-12-01 15:05:58 +08:00
Matt Benjamin
0046803534 qa/rgw: use local runner with cmdline radosgw_admin.py
Restore ability to run radosgw_admin.py unit standalone--improved
to use vstart_runner hooks.

Local rgwadmin(...) wrapper suggested as a cleanup in review by Casey.

Fixes: https://tracker.ceph.com/issues/52837

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
2021-11-17 11:22:32 -05:00
Rishabh Dave
e650bc6e87 qa/vstart_runner: add "managers" to LocalContext instances
Without this plenty tests become incompatible with vstart_runner.py.
Ideally, vstart_runner.py should've been updated in commit 7812cfb674.

Fixes: https://tracker.ceph.com/issues/53043
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2021-10-26 20:51:09 +05:30
Rishabh Dave
485841b255 qa: import CommandFailedError from exceptions not run
Stop importing CommandFailedError from teuthology.orchestra.run, it is
actually defined in teuthology.exception.

Fixes: https://tracker.ceph.com/issues/51226
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2021-10-05 23:41:09 +05:30
Patrick Donnelly
ec69208deb Merge PR into master
* refs/pull/38481/head:
	qa/vstart_runner: inherit methods instead of duplicating them
	qa/ceph_manager: make it possible to reuse few methods
	qa/vstart_runner: don't use "shell=False" in run_ceph_w()
	qa/ceph_manager: minor refactor

Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
2021-08-27 21:26:41 -04:00
Kefu Chai
62944aefa0
Merge pull request from tchaikov/wip-vstart-runner-cleanups
qa/tasks/vstart_runner: do not send SIGTERM if no matched pid

Reviewed-by: Rishabh Dave <ridave@redhat.com>
2021-08-06 10:33:19 +08:00
Rishabh Dave
d86bfbfe2d qa/vstart_runner: inherit methods instead of duplicating them
Inherit methods run_ceph_w(), run_cluster_cmd(), raw_cluster_cmd() and
raw_cluster_cmd_result() from ceph_manager.CephManager in
vstart_runner.LocalCephManager instead of duplicating them.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2021-08-02 11:37:49 +05:30
Rishabh Dave
047c90f881 qa/vstart_runner: don't use "shell=False" in run_ceph_w()
Instead prepend "exec sudo" to the command arguments of
LocalCephManager.run_ceph_w(). This makes the default parameter
"shell=False" redundant in case of
ceph_manager.CephManager.run_ceph_w(), so get rid of it too and update
calls to run_ceph_w() accordingly.

The reason behind using any of these workarounds is that running "ceph
-w" with "shell" set to True leads to crash for Ceph API CI job. See
this ticket for more details: https://tracker.ceph.com/issues/49644.

The reason behind switching the workaround is that in the following
commits to reduce duplication LocalCephManager.run_ceph_w() will be
deleted and CephManager.run_ceph_w() will be used by LocalCephManager
via inheritance. However, due to the issue described above, Ceph API
test will fail since "shell" is set to "True" for the command issued by
CephManager.run_ceph_w(). Prepending "exec sudo" to the command when it
is used in LocalCephManager makes this duplication unnecessary and also
prevents Ceph API test from failing.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2021-08-02 11:37:44 +05:30
Kefu Chai
0017df2006 qa/tasks/vstart_runner: add optional "sudo" param to _run_python()
to silence mypy warnings like:

tasks/vstart_runner.py:691: error: Definition of "_run_python" in base class "LocalCephFSMount" is incompatible with definition in base class "CephFSMount"
tasks/vstart_runner.py:705: error: Definition of "_run_python" in base class "LocalCephFSMount" is incompatible with definition in base class "CephFSMount"

Signed-off-by: Kefu Chai <kchai@redhat.com>
2021-07-22 10:08:27 +08:00
Patrick Donnelly
9f3e49389b
Merge PR into master
* refs/pull/42029/head:
	vstart_runner: use FileNotFoundError when os.stat() fails

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
2021-07-13 08:07:22 -07:00
Patrick Donnelly
6470e7cdcd
Merge PR into master
* refs/pull/42030/head:
	vstart_runner: maintain log level when --debug is passed

Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
2021-07-13 08:05:25 -07:00
Patrick Donnelly
a20300d4f0
Merge PR into master
* refs/pull/42033/head:
	vstart_runner: add log messages to vstart_runner.py

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
2021-07-13 08:03:18 -07:00
Kefu Chai
58841419be qa/tasks/vstart_runner: do not send SIGTERM if no matched pid
otherwise following error is expected in some cases:

INFO:__main__:Traceback (most recent call last):
INFO:__main__:  File "/home/jenkins-build/build/workspace/ceph-api/qa/tasks/mgr/test_dashboard.py", line 18, in setUp
INFO:__main__:    self._assign_ports("dashboard", "ssl_server_port")
INFO:__main__:  File "/home/jenkins-build/build/workspace/ceph-api/qa/tasks/mgr/mgr_test_case.py", line 197, in _assign_ports
INFO:__main__:    cls.mgr_cluster.mgr_stop(mgr_id)
INFO:__main__:  File "/home/jenkins-build/build/workspace/ceph-api/qa/tasks/mgr/mgr_test_case.py", line 30, in mgr_stop
INFO:__main__:    self.mgr_daemons[mgr_id].stop()
INFO:__main__:  File "../qa/tasks/vstart_runner.py", line 558, in stop
INFO:__main__:    os.kill(pid, signal.SIGTERM)
INFO:__main__:TypeError: an integer is required (got type NoneType)

Signed-off-by: Kefu Chai <kchai@redhat.com>
2021-07-12 13:25:44 +08:00
Kefu Chai
e15ceb6bae qa/tasks/vstart_runner: consolidate logging message in LocalDaemon
it's more readable if we have a single logging message when no matching
pid is found.

Signed-off-by: Kefu Chai <kchai@redhat.com>
2021-07-12 13:25:44 +08:00
Sage Weil
1bfa812f5d qa/tasks/vstart_runner: add LocalCluster.run
Signed-off-by: Sage Weil <sage@newdream.net>
2021-06-26 08:47:06 -04:00
Rishabh Dave
3fc7003608 vstart_runner: use FileNotFoundError when os.stat() fails
Fixes: https://tracker.ceph.com/issues/51369
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2021-06-25 21:21:14 +05:30
Rishabh Dave
4733402c4e vstart_runner: add log messages to vstart_runner.py
Add log messages to indicate start and end of execution of stop.sh and
vstart.sh. Running both of these scripts is a major step in execution of
vstart_runner.py and not passing --debug makes it impossible to know
whether these scripts have started or finished running.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
2021-06-25 21:16:19 +05:30
Rishabh Dave
73567a1447 vstart_runner: maintain log level when --debug is passed
When --debug and --clear-old-log options are passed to vstart_runner.py,
it ends up resetting log level to the default level (which is
logging.INFO) despite of --debug. Set "log_level" as default parameter
to init_log() so that the log level code for clearing old log can pass
current logging level to init_log() to maintain the log level user
desired for.

Fixes: https://tracker.ceph.com/issues/51344
Signed-off-by: Rishabh Dave <ridave@redhat.com>
2021-06-24 18:07:49 +05:30
Patrick Donnelly
2a81253141
Merge PR into master
* refs/pull/40412/head:
	vstart_runner: reuse code in LocalRemoteProcess

Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
2021-04-15 21:05:51 -07:00