* Introduced a Thrasher base class.
* Updated thrashers to inherit from Thrasher.
* Replaced the magic variable e with Thrasher.exception as per the discussion.
Now the exception variable sets by default as the thrashers are inheriting
from the Thrasher class.
Fixes: https://github.com/ceph/ceph/pull/28378#discussion_r309337928
Fixes: https://tracker.ceph.com/issues/41133
Signed-off-by: Jos Collin <jcollin@redhat.com>
from teuthology.orchestra.remote import Remote
from teuthology.orchestra import run
from teuthology.exceptions import CommandFailedError
+from tasks.thrasher import Thrasher
try:
from subprocess import DEVNULL # py3k
ERASURE_CODED = 3
-class Thrasher:
+class OSDThrasher(Thrasher):
"""
Object used to thrash Ceph
"""
def __init__(self, manager, config, logger):
+ super(OSDThrasher, self).__init__()
self.ceph_manager = manager
self.cluster = manager.cluster
self.ceph_manager.wait_for_clean()
val -= prob
return None
+ def do_thrash(self):
+ """
+ _do_thrash() wrapper.
+ """
+ try:
+ self._do_thrash()
+ except Exception as e:
+ # See _run exception comment for MDSThrasher
+ self.exception = e
+ self.logger.exception("exception:")
+ # Allow successful completion so gevent doesn't see an exception.
+ # The DaemonWatchdog will observe the error and tear down the test.
+
def log_exc(func):
@wraps(func)
def wrapper(self):
self.ceph_manager.raw_cluster_cmd('osd', 'unset', 'nodeep-scrub')
@log_exc
- def do_thrash(self):
+ def _do_thrash(self):
"""
Loop to select random actions to thrash ceph manager with.
"""
"""
def __init__(self, ctx, config, thrashers):
- Greenlet.__init__(self)
+ super(DaemonWatchdog, self).__init__()
self.ctx = ctx
self.config = config
self.e = None
del daemon_failure_time[name]
for thrasher in self.thrashers:
- if thrasher.e is not None:
+ if thrasher.exception is not None:
self.log("thrasher on fs.{name} failed".format(name=thrasher.fs.name))
bark = True
from teuthology import misc as teuthology
from tasks.cephfs.filesystem import MDSCluster, Filesystem
+from tasks.thrasher import Thrasher
log = logging.getLogger(__name__)
-class MDSThrasher(Greenlet):
+class MDSThrasher(Greenlet, Thrasher, object):
"""
MDSThrasher::
"""
def __init__(self, ctx, manager, config, fs, max_mds):
- Greenlet.__init__(self)
+ super(MDSThrasher, self).__init__()
self.config = config
self.ctx = ctx
- self.e = None
self.logger = log.getChild('fs.[{f}]'.format(f = fs.name))
self.fs = fs
self.manager = manager
# File "/usr/lib/python2.7/traceback.py", line 13, in _print
# file.write(str+terminator)
# 2017-02-03T14:34:01.261 CRITICAL:root:IOError
- self.e = e
+ self.exception = e
self.logger.exception("exception:")
# allow successful completion so gevent doesn't see an exception...
finally:
log.info('joining mds_thrasher')
thrasher.stop()
- if thrasher.e:
+ if thrasher.exception is not None:
raise RuntimeError('error during thrashing')
thrasher.join()
log.info('done joining')
import math
from teuthology import misc as teuthology
from tasks.cephfs.filesystem import MDSCluster
+from tasks.thrasher import Thrasher
log = logging.getLogger(__name__)
mons = [f[len('mon.'):] for f in teuthology.get_mon_names(ctx)]
return mons
-class MonitorThrasher:
+class MonitorThrasher(Thrasher):
"""
How it works::
- mon/workloadgen.sh
"""
def __init__(self, ctx, manager, config, logger):
+ super(MonitorThrasher, self).__init__()
self.ctx = ctx
self.manager = manager
self.manager.wait_for_clean()
- self.e = None
self.stopping = False
self.logger = logger
self.config = config
self._do_thrash()
except Exception as e:
# See _run exception comment for MDSThrasher
- self.e = e
+ self.exception = e
self.logger.exception("exception:")
# Allow successful completion so gevent doesn't see an exception.
# The DaemonWatchdog will observe the error and tear down the test.
from teuthology.exceptions import CommandFailedError
from teuthology.task import Task
from teuthology.orchestra import run
+from tasks.thrasher import Thrasher
log = logging.getLogger(__name__)
-class RBDMirrorThrasher(Greenlet):
+class RBDMirrorThrasher(Greenlet, Thrasher, object):
"""
RBDMirrorThrasher::
"""
def __init__(self, ctx, config, cluster, daemons):
- Greenlet.__init__(self)
+ super(RBDMirrorThrasher, self).__init__()
self.ctx = ctx
self.config = config
self.cluster = cluster
self.daemons = daemons
- self.e = None
self.logger = log
self.name = 'thrasher.rbd_mirror.[{cluster}]'.format(cluster = cluster)
self.stopping = Event()
try:
self.do_thrash()
except Exception as e:
- self.e = e
+ # See _run exception comment for MDSThrasher
+ self.exception = e
self.logger.exception("exception:")
+ # Allow successful completion so gevent doesn't see an exception.
+ # The DaemonWatchdog will observe the error and tear down the test.
def log(self, x):
"""Write data to logger assigned to this RBDMirrorThrasher"""
finally:
log.info('joining rbd_mirror_thrash')
thrasher.stop()
- if thrasher.e:
+ if thrasher.exception is not None:
raise RuntimeError('error during thrashing')
thrasher.join()
log.info('done joining')
--- /dev/null
+"""
+Thrasher base class
+"""
+class Thrasher(object):
+
+ def __init__(self):
+ super(Thrasher, self).__init__()
+ self.exception = None
+
+ @property
+ def exception(self):
+ return self._exception
+
+ @exception.setter
+ def exception(self, e):
+ self._exception = e
'true')
log.info('Beginning thrashosds...')
- thrash_proc = ceph_manager.Thrasher(
+ thrash_proc = ceph_manager.OSDThrasher(
cluster_manager,
config,
logger=log.getChild('thrasher')