-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'red-hat-storage:main' into earmark_feature
- Loading branch information
Showing
104 changed files
with
5,225 additions
and
1,273 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,29 @@ | ||
# These owners will be the default owners for everything in this repo. | ||
# all changes. | ||
* @red-hat-storage/cephci-top-reviewers | ||
* @red-hat-storage/ceph-qe-ci @red-hat-storage/ceph-qe-admin | ||
|
||
# for RGW | ||
rgw/ @red-hat-storage/teams/cephci-rgw | ||
rgw/ @mkasturi18 @ckulal @TejasC88 | ||
|
||
# for RBD team | ||
rbd/ @red-hat-storage/teams/cephci-block | ||
rbd_mirror/ @red-hat-storage/teams/cephci-block | ||
rbd/ @Manohar-Murthy | ||
rbd_mirror/ @Manohar-Murthy | ||
|
||
# for NVMe-oF | ||
nvmeof/ @Manohar-Murthy @HaruChebrolu | ||
|
||
# for RADOS | ||
rados/ @ed-hat-storage/teams/cephci-rados | ||
rados/ @neha-gangadhar @pdhiran | ||
|
||
# for FS | ||
cephfs/ @red-hat-storage/teams/cephci-fs | ||
cephfs/ @neha-gangadhar @AmarnatReddy @Manimaran-MM | ||
|
||
# smb | ||
smb/ @vdas-redhat @pranavprakash20 | ||
|
||
# for DMFG | ||
ansible/ @red-hat-storage/teams/cephci-dm | ||
upgrades/ @red-hat-storage/teams/cephci-dm | ||
dashboard/ @red-hat-storage/teams/cephci-dm | ||
cephadm/ @red-hat-storage/teams/cephci-dm | ||
ceph_ansisble/ @red-hat-storage/teams/cephci-dm | ||
ceph_installer/ @red-hat-storage/teams/cephci-dm | ||
ceph_volume/ @vdas-redhat @pranavprakash20 | ||
cephadm/ @vdas-redhat @pranavprakash20 | ||
mgr/ @vdas-redhat @pranavprakash20 | ||
nfs/ @vdas-redhat @pranavprakash20 | ||
upgrades/ @vdas-redhat @pranavprakash20 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,121 +1,122 @@ | ||
import sys | ||
|
||
import gevent.pool | ||
import gevent.queue | ||
|
||
from utility.log import Log | ||
|
||
log = Log(__name__) | ||
|
||
|
||
class ExceptionHolder(object): | ||
def __init__(self, exc_info): | ||
self.exc_info = exc_info | ||
|
||
|
||
def capture_traceback(func, *args, **kwargs): | ||
""" | ||
Utility function to capture tracebacks of any exception func | ||
raises. | ||
""" | ||
try: | ||
return func(*args, **kwargs) | ||
except Exception: | ||
return ExceptionHolder(sys.exc_info()) | ||
|
||
|
||
def resurrect_traceback(exc): | ||
if isinstance(exc, ExceptionHolder): | ||
exc_info = exc.exc_info | ||
elif isinstance(exc, BaseException): | ||
exc_info = (type(exc), exc, None) | ||
else: | ||
return | ||
|
||
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2]) | ||
|
||
|
||
class parallel(object): | ||
""" | ||
This class is a context manager for running functions in parallel. | ||
You add functions to be run with the spawn method:: | ||
with parallel() as p: | ||
for foo in bar: | ||
p.spawn(quux, foo, baz=True) | ||
You can iterate over the results (which are in arbitrary order):: | ||
with parallel() as p: | ||
for foo in bar: | ||
p.spawn(quux, foo, baz=True) | ||
for result in p: | ||
print result | ||
If one of the spawned functions throws an exception, it will be thrown | ||
when iterating over the results, or when the with block ends. | ||
At the end of the with block, the main thread waits until all | ||
spawned functions have completed, or, if one exited with an exception, | ||
kills the rest and raises the exception. | ||
""" | ||
|
||
def __init__(self): | ||
self.group = gevent.pool.Group() | ||
self.results = gevent.queue.Queue() | ||
self.count = 0 | ||
self.any_spawned = False | ||
self.iteration_stopped = False | ||
|
||
def spawn(self, func, *args, **kwargs): | ||
self.count += 1 | ||
self.any_spawned = True | ||
greenlet = self.group.spawn(capture_traceback, func, *args, **kwargs) | ||
greenlet.link(self._finish) | ||
# -*- code: utf-8 -*- | ||
""" | ||
This module provides a context manager for running methods concurrently. | ||
For backward compatability, spawn method is leveraged however one can also | ||
choose to move submit. Likewise, thread pool executor is the default executor. | ||
Timeout is an inherited feature provided by concurrent futures. Additionally, | ||
one wait for all the threads/process to complete even when on thread or process | ||
encounters an exception. This is useful when multiple test modules are | ||
executing different test scenarios. | ||
When a test module controls the threads then it can forcefully terminate all | ||
threads when an exception is encountered. | ||
Changelog: | ||
Version 1.0 used gevent module for parallel method execution. | ||
Version 2.0 uses concurrent.futures module instead of gevent. | ||
You add functions to be run with the spawn method:: | ||
with parallel() as p: | ||
for foo in bar: | ||
p.spawn(quux, foo, baz=True) | ||
You can iterate over the results (which are in arbitrary order):: | ||
with parallel() as p: | ||
for foo in bar: | ||
p.spawn(quux, foo, baz=True) | ||
for result in p: | ||
print result | ||
In version 2, you can choose whether to use threads or processes by | ||
with parallel(thread_pool=False, timeout=10) as p: | ||
_r = [p.spawn(quux, x) for name in names] | ||
If one of the spawned functions throws an exception, it will be thrown | ||
when iterating over the results, or when the with block ends. | ||
At the end of the with block, the main thread waits until all | ||
spawned functions have completed, or, if one exited with an exception, | ||
kills the rest and raises the exception. | ||
""" | ||
import logging | ||
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class parallel: | ||
"""This class is a context manager for concurrent method execution.""" | ||
|
||
def __init__( | ||
self, | ||
thread_pool=True, | ||
timeout=None, | ||
shutdown_wait=True, | ||
shutdown_cancel_pending=False, | ||
): | ||
"""Object initialization method. | ||
Args: | ||
thread_pool (bool) Whether to use threads or processes. | ||
timeout (int | float) Maximum allowed time. | ||
shutdown_wait (bool) If disabled, it would not wait for executing | ||
threads/process to complete. | ||
shutdown_cancel_pending (bool) If enabled, it would cancel pending tasks. | ||
""" | ||
self._executor = ThreadPoolExecutor() if thread_pool else ProcessPoolExecutor() | ||
self._timeout = timeout | ||
self._shutdown_wait = shutdown_wait | ||
self._cancel_pending = shutdown_cancel_pending | ||
self._futures = list() | ||
self._results = list() | ||
|
||
def spawn(self, fun, *args, **kwargs): | ||
"""Triggers the first class method. | ||
Args: | ||
func: Function to be executed. | ||
args: A list of variables to be passed to the function. | ||
kwargs A dictionary of named variables. | ||
Returns: | ||
None | ||
""" | ||
_future = self._executor.submit(fun, *args, **kwargs) | ||
self._futures.append(_future) | ||
|
||
def __enter__(self): | ||
return self | ||
|
||
def __exit__(self, type_, value, traceback): | ||
self.group.join() | ||
def __exit__(self, exc_type, exc_value, trackback): | ||
_exceptions = [] | ||
exception_count = 0 | ||
|
||
for _f in as_completed(self._futures, timeout=self._timeout): | ||
try: | ||
self._results.append(_f.result()) | ||
except Exception as e: | ||
logger.exception(e) | ||
_exceptions.append(e) | ||
exception_count += 1 | ||
|
||
if exception_count > 0 and not self._shutdown_wait: | ||
# At this point we are ignoring results | ||
self._executor.shutdown(wait=False, cancel_futures=self._cancel_pending) | ||
raise _exceptions[0] | ||
|
||
if value is not None: | ||
return False | ||
if len(_exceptions) > 0: | ||
raise _exceptions[0] | ||
|
||
try: | ||
# raises if any greenlets exited with an exception | ||
for result in self: | ||
log.debug("result is %s", repr(result)) | ||
pass | ||
except Exception: | ||
# Emit message here because traceback gets stomped when we re-raise | ||
log.exception("Exception in parallel execution") | ||
raise | ||
return True | ||
return False if exception_count == 0 else True | ||
|
||
def __iter__(self): | ||
return self | ||
|
||
def __next__(self): | ||
if not self.any_spawned or self.iteration_stopped: | ||
raise StopIteration() | ||
result = self.results.get() | ||
|
||
try: | ||
resurrect_traceback(result) | ||
except StopIteration: | ||
self.iteration_stopped = True | ||
raise | ||
|
||
return result | ||
|
||
def _finish(self, greenlet): | ||
if greenlet.successful(): | ||
self.results.put(greenlet.value) | ||
else: | ||
self.results.put(greenlet.exception) | ||
|
||
self.count -= 1 | ||
if self.count <= 0: | ||
self.results.put(StopIteration()) | ||
for r in self._results: | ||
yield r |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.