mirror of
https://github.com/ceph/ceph
synced 2025-01-20 01:51:34 +00:00
qa: test_rbd_wnbd.py improvements
We'll make the following improvements to the Windows rbd-wnbd Python test: * expose fio write validation, defaulting to crc32c * change the default fio operation to "rw" * enable the disk and clear the "rw" flag only if required by the test and if "--skip-enabling-disk" is not set (useful with custom SAN policies). This operation can take a significant amount of time under heavy load. * print fio read and write results separately instead of aggregating them, useful when running rw tests Signed-off-by: Lucian Petrut <lpetrut@cloudbasesolutions.com>
This commit is contained in:
parent
cceeb8be9f
commit
d9decba6ba
@ -34,12 +34,19 @@ parser.add_argument('--fio-depth',
|
||||
help='The number of concurrent asynchronous operations '
|
||||
'executed per disk',
|
||||
default=64, type=int)
|
||||
parser.add_argument('--fio-verify',
|
||||
help='The mechanism used to validate the written '
|
||||
'data. Examples: crc32c, md5, sha1, null, etc. '
|
||||
'If set to null, the written data will not be '
|
||||
'verified.',
|
||||
default='crc32c')
|
||||
parser.add_argument('--bs',
|
||||
help='Benchmark block size.',
|
||||
default="2M")
|
||||
parser.add_argument('--op',
|
||||
help='Benchmark operation.',
|
||||
default="read")
|
||||
help='Benchmark operation. '
|
||||
'Examples: read, randwrite, rw, etc.',
|
||||
default="rw")
|
||||
parser.add_argument('--image-prefix',
|
||||
help='The image name prefix.',
|
||||
default="cephTest-")
|
||||
@ -49,6 +56,10 @@ parser.add_argument('--image-size-mb',
|
||||
parser.add_argument('--map-timeout',
|
||||
help='Image map timeout.',
|
||||
default=60, type=int)
|
||||
parser.add_argument('--skip-enabling-disk', action='store_true',
|
||||
help='If set, the disk will not be turned online and the '
|
||||
'read-only flag will not be removed. Useful when '
|
||||
'the SAN policy is set to "onlineAll".')
|
||||
parser.add_argument('--verbose', action='store_true',
|
||||
help='Print info messages.')
|
||||
parser.add_argument('--debug', action='store_true',
|
||||
@ -292,6 +303,13 @@ class RbdImage(object):
|
||||
"Set-Disk", "-Number", str(self.disk_number),
|
||||
"-IsReadOnly", "$false")
|
||||
|
||||
@Tracer.trace
|
||||
def set_online(self):
|
||||
execute(
|
||||
"powershell.exe", "-command",
|
||||
"Set-Disk", "-Number", str(self.disk_number),
|
||||
"-IsOffline", "$false")
|
||||
|
||||
@Tracer.trace
|
||||
def map(self, timeout: int = 60):
|
||||
LOG.info("Mapping image: %s", self.name)
|
||||
@ -305,8 +323,6 @@ class RbdImage(object):
|
||||
elapsed = time.time() - tstart
|
||||
self._wait_for_disk(timeout=timeout - elapsed)
|
||||
|
||||
self.set_writable()
|
||||
|
||||
@Tracer.trace
|
||||
def unmap(self):
|
||||
if self.mapped:
|
||||
@ -331,6 +347,10 @@ class RbdImage(object):
|
||||
class RbdTest(object):
|
||||
image: RbdImage
|
||||
|
||||
# Windows disks must be turned online before accessing partitions.
|
||||
requires_disk_online = False
|
||||
requires_disk_write = False
|
||||
|
||||
def __init__(self,
|
||||
image_prefix: str = "cephTest-",
|
||||
image_size_mb: int = 1024,
|
||||
@ -339,6 +359,7 @@ class RbdTest(object):
|
||||
self.image_size_mb = image_size_mb
|
||||
self.image_name = image_prefix + str(uuid.uuid4())
|
||||
self.map_timeout = map_timeout
|
||||
self.skip_enabling_disk = kwargs.get("skip_enabling_disk")
|
||||
|
||||
@Tracer.trace
|
||||
def initialize(self):
|
||||
@ -347,6 +368,13 @@ class RbdTest(object):
|
||||
self.image_size_mb)
|
||||
self.image.map(timeout=self.map_timeout)
|
||||
|
||||
if not self.skip_enabling_disk:
|
||||
if self.requires_disk_write:
|
||||
self.image.set_writable()
|
||||
|
||||
if self.requires_disk_online:
|
||||
self.image.set_online()
|
||||
|
||||
def run(self):
|
||||
pass
|
||||
|
||||
@ -362,7 +390,8 @@ class RbdTest(object):
|
||||
|
||||
|
||||
class RbdFioTest(RbdTest):
|
||||
data: typing.List[typing.Dict[str, str]] = []
|
||||
data: typing.DefaultDict[str, typing.List[typing.Dict[str, str]]] = (
|
||||
collections.defaultdict(list))
|
||||
lock = threading.Lock()
|
||||
|
||||
def __init__(self,
|
||||
@ -372,7 +401,8 @@ class RbdFioTest(RbdTest):
|
||||
workers: int = 1,
|
||||
bs: str = "2M",
|
||||
iodepth: int = 64,
|
||||
op: str = "read",
|
||||
op: str = "rw",
|
||||
verify: str = "crc32c",
|
||||
**kwargs):
|
||||
|
||||
super(RbdFioTest, self).__init__(*args, **kwargs)
|
||||
@ -383,19 +413,25 @@ class RbdFioTest(RbdTest):
|
||||
self.bs = bs
|
||||
self.iodepth = iodepth
|
||||
self.op = op
|
||||
if op not in ("read", "randread"):
|
||||
self.requires_disk_write = True
|
||||
self.verify = verify
|
||||
|
||||
def process_result(self, raw_fio_output: str):
|
||||
result = json.loads(raw_fio_output)
|
||||
with self.lock:
|
||||
for job in result["jobs"]:
|
||||
self.data.append({
|
||||
# Fio doesn't support trim on Windows
|
||||
for op in ['read', 'write']:
|
||||
if op in job:
|
||||
self.data[op].append({
|
||||
'error': job['error'],
|
||||
'io_bytes': job[self.op]['io_bytes'],
|
||||
'bw_bytes': job[self.op]['bw_bytes'],
|
||||
'runtime': job[self.op]['runtime'] / 1000, # seconds
|
||||
'total_ios': job[self.op]['short_ios'],
|
||||
'short_ios': job[self.op]['short_ios'],
|
||||
'dropped_ios': job[self.op]['short_ios'],
|
||||
'io_bytes': job[op]['io_bytes'],
|
||||
'bw_bytes': job[op]['bw_bytes'],
|
||||
'runtime': job[op]['runtime'] / 1000, # seconds
|
||||
'total_ios': job[op]['short_ios'],
|
||||
'short_ios': job[op]['short_ios'],
|
||||
'dropped_ios': job[op]['short_ios'],
|
||||
})
|
||||
|
||||
@Tracer.trace
|
||||
@ -411,6 +447,8 @@ class RbdFioTest(RbdTest):
|
||||
"--numjobs=%s" % self.workers,
|
||||
"--filename=%s" % self.image.path,
|
||||
]
|
||||
if self.verify:
|
||||
cmd += ["--verify=%s" % self.verify]
|
||||
result = execute(*cmd)
|
||||
LOG.info("Completed FIO test.")
|
||||
self.process_result(result.stdout)
|
||||
@ -421,37 +459,43 @@ class RbdFioTest(RbdTest):
|
||||
description: str = None):
|
||||
if description:
|
||||
title = "%s (%s)" % (title, description)
|
||||
table = prettytable.PrettyTable(title=title)
|
||||
|
||||
for op in cls.data.keys():
|
||||
op_title = "%s op=%s" % (title, op)
|
||||
|
||||
table = prettytable.PrettyTable(title=op_title)
|
||||
table.field_names = ["stat", "min", "max", "mean",
|
||||
"median", "std_dev",
|
||||
"max 90%", "min 90%", "total"]
|
||||
table.float_format = ".4"
|
||||
|
||||
s = array_stats([float(i["bw_bytes"]) / 1000_000 for i in cls.data])
|
||||
op_data = cls.data[op]
|
||||
|
||||
s = array_stats([float(i["bw_bytes"]) / 1000_000 for i in op_data])
|
||||
table.add_row(["bandwidth (MB/s)",
|
||||
s['min'], s['max'], s['mean'],
|
||||
s['median'], s['std_dev'],
|
||||
s['max_90'], s['min_90'], 'N/A'])
|
||||
|
||||
s = array_stats([float(i["runtime"]) / 1000 for i in cls.data])
|
||||
s = array_stats([float(i["runtime"]) / 1000 for i in op_data])
|
||||
table.add_row(["duration (s)",
|
||||
s['min'], s['max'], s['mean'],
|
||||
s['median'], s['std_dev'],
|
||||
s['max_90'], s['min_90'], s['sum']])
|
||||
|
||||
s = array_stats([i["error"] for i in cls.data])
|
||||
s = array_stats([i["error"] for i in op_data])
|
||||
table.add_row(["errors",
|
||||
s['min'], s['max'], s['mean'],
|
||||
s['median'], s['std_dev'],
|
||||
s['max_90'], s['min_90'], s['sum']])
|
||||
|
||||
s = array_stats([i["short_ios"] for i in cls.data])
|
||||
s = array_stats([i["short_ios"] for i in op_data])
|
||||
table.add_row(["incomplete IOs",
|
||||
s['min'], s['max'], s['mean'],
|
||||
s['median'], s['std_dev'],
|
||||
s['max_90'], s['min_90'], s['sum']])
|
||||
|
||||
s = array_stats([i["dropped_ios"] for i in cls.data])
|
||||
s = array_stats([i["dropped_ios"] for i in op_data])
|
||||
table.add_row(["dropped IOs",
|
||||
s['min'], s['max'], s['mean'],
|
||||
s['median'], s['std_dev'],
|
||||
@ -460,6 +504,8 @@ class RbdFioTest(RbdTest):
|
||||
|
||||
|
||||
class RbdStampTest(RbdTest):
|
||||
requires_disk_write = True
|
||||
|
||||
@staticmethod
|
||||
def _rand_float(min_val: float, max_val: float):
|
||||
return min_val + (random.random() * max_val - min_val)
|
||||
@ -586,8 +632,10 @@ if __name__ == '__main__':
|
||||
image_prefix=args.image_prefix,
|
||||
bs=args.bs,
|
||||
op=args.op,
|
||||
verify=args.fio_verify,
|
||||
iodepth=args.fio_depth,
|
||||
map_timeout=args.map_timeout
|
||||
map_timeout=args.map_timeout,
|
||||
skip_enabling_disk=args.skip_enabling_disk,
|
||||
)
|
||||
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user