diff options
Diffstat (limited to 'storperf')
-rw-r--r-- | storperf/carbon/converter.py | 19 | ||||
-rw-r--r-- | storperf/carbon/emitter.py | 14 | ||||
-rw-r--r-- | storperf/fio/fio_invoker.py | 22 | ||||
-rw-r--r-- | storperf/main.py | 75 | ||||
-rw-r--r-- | storperf/test_executor.py | 137 | ||||
-rw-r--r-- | storperf/tests/carbon_tests/__init__.py | 0 | ||||
-rw-r--r-- | storperf/tests/carbon_tests/emitter_test.py | 68 | ||||
-rw-r--r-- | storperf/tests/carbon_tests/json_to_carbon_test.py | 118 | ||||
-rw-r--r-- | storperf/workloads/__init__.py | 0 | ||||
-rw-r--r-- | storperf/workloads/_base_workload.py | 54 | ||||
-rw-r--r-- | storperf/workloads/_ssd_preconditioning.py | 16 | ||||
-rw-r--r-- | storperf/workloads/_warm_up.py | 17 | ||||
-rw-r--r-- | storperf/workloads/rr.py | 16 | ||||
-rw-r--r-- | storperf/workloads/rs.py | 16 | ||||
-rw-r--r-- | storperf/workloads/rw.py | 18 | ||||
-rw-r--r-- | storperf/workloads/wr.py | 16 | ||||
-rw-r--r-- | storperf/workloads/ws.py | 16 |
17 files changed, 571 insertions, 51 deletions
diff --git a/storperf/carbon/converter.py b/storperf/carbon/converter.py index 42dbeef..d551822 100644 --- a/storperf/carbon/converter.py +++ b/storperf/carbon/converter.py @@ -10,7 +10,9 @@ import calendar import logging import time + class JSONToCarbon(object): + def __init__(self): self.logger = logging.getLogger(__name__) @@ -18,11 +20,13 @@ class JSONToCarbon(object): # Use the timestamp reported by fio, or current time if # not present. if 'timestamp' in json_object: - self.timestamp = str(json_object['timestamp']) + timestamp = str(json_object.pop('timestamp')) else: - self.timestamp = str(calendar.timegm(time.gmtime())) + timestamp = str(calendar.timegm(time.gmtime())) self.flat_dictionary = {} + self.flat_dictionary['timestamp'] = timestamp + self.resurse_to_flat_dictionary(json_object, prefix) return self.flat_dictionary @@ -36,19 +40,18 @@ class JSONToCarbon(object): if hasattr(v, '__iter__'): self.resurse_to_flat_dictionary(v, key) else: - self.flat_dictionary[key] = str(v).replace(" ", "_") + " " + self.timestamp + self.flat_dictionary[key] = str(v).replace(" ", "_") elif type(json) == list: index = 0 for v in json: index += 1 if hasattr(v, '__iter__'): - self.resurse_to_flat_dictionary(v, prefix+"."+str(index)) + self.resurse_to_flat_dictionary( + v, prefix + "." + str(index)) else: if prefix is None: self.flat_dictionary[index] = str(v).replace(" ", "_") + " " + self.timestamp else: - key = prefix + "." + index; - self.flat_dictionary[key] = str(v).replace(" ", "_") + " " + self.timestamp - else: - self.flat_dictionary[json] = self.timestamp + key = prefix + "." + index + self.flat_dictionary[key] = str(v).replace(" ", "_") diff --git a/storperf/carbon/emitter.py b/storperf/carbon/emitter.py index 526a96f..e949238 100644 --- a/storperf/carbon/emitter.py +++ b/storperf/carbon/emitter.py @@ -8,7 +8,10 @@ ############################################################################## import logging +import calendar import socket +import time + class CarbonMetricTransmitter(): @@ -19,12 +22,17 @@ class CarbonMetricTransmitter(): self.logger = logging.getLogger(__name__) def transmit_metrics(self, metrics): + if 'timestamp' in metrics: + timestamp = metrics.pop('timestamp') + else: + timestamp = str(calendar.timegm(time.gmtime())) + self.carbon_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.carbon_socket.connect((self.carbon_host, self.carbon_port)) for key, metric in metrics.items(): - message = key + " " + metric + "\n" - print message - self.carbon_socket.send(message) + message = key + " " + metric + " " + timestamp + self.logger.debug("Metric: " + message) + self.carbon_socket.send(message + '\n') self.carbon_socket.close() diff --git a/storperf/fio/fio_invoker.py b/storperf/fio/fio_invoker.py index 722b051..be1b37c 100644 --- a/storperf/fio/fio_invoker.py +++ b/storperf/fio/fio_invoker.py @@ -7,19 +7,15 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -import sys -import getopt import subprocess import json -from threading import Thread +from threading import Thread import logging -class Usage(Exception): - def __init__(self, msg): - self.msg = msg class FIOInvoker(object): + def __init__(self): self.logger = logging.getLogger(__name__) self.event_listeners = set() @@ -39,7 +35,8 @@ class FIOInvoker(object): self.json_body += line try: if line == "}\n": - self.logger.debug("Have a json snippet: %s", self.json_body) + self.logger.debug( + "Have a json snippet: %s", self.json_body) json_metric = json.loads(self.json_body) self.json_body = "" @@ -59,9 +56,13 @@ class FIOInvoker(object): self.fio_process.stderr.close() def execute(self, args=[]): - self.fio_process = subprocess.Popen(['fio']+args, - universal_newlines=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE); + for arg in args: + self.logger.debug("FIO arg: " + arg) + + self.fio_process = subprocess.Popen(['fio'] + args, + universal_newlines=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) t = Thread(target=self.stdout_handler, args=()) t.daemon = False @@ -71,3 +72,4 @@ class FIOInvoker(object): t.daemon = False t.start() + t.join() diff --git a/storperf/main.py b/storperf/main.py index a40d656..2423b99 100644 --- a/storperf/main.py +++ b/storperf/main.py @@ -8,32 +8,24 @@ ############################################################################## import getopt import json -import logging import logging.config import os -import socket import sys -from fio.fio_invoker import FIOInvoker -from carbon.emitter import CarbonMetricTransmitter -from carbon.converter import JSONToCarbon +from test_executor import TestExecutor, UnknownWorkload """ """ + class Usage(Exception): + def __init__(self, msg): self.msg = msg -def event(metric): - metrics_converter = JSONToCarbon() - metrics_emitter = CarbonMetricTransmitter() - prefix = socket.getfqdn() - carbon_metrics = metrics_converter.convert_to_dictionary(metric, prefix) - metrics_emitter.transmit_metrics(carbon_metrics) def setup_logging( - default_path='logging.json', + default_path='storperf/logging.json', default_level=logging.INFO, env_key='LOG_CFG' ): @@ -51,39 +43,62 @@ def setup_logging( else: logging.basicConfig(level=default_level) -def main(argv=None): +def event(event_string): + logging.getLogger(__name__).info(event_string) + + +def main(argv=None): setup_logging() + test_executor = TestExecutor() + verbose = False + workloads = None if argv is None: argv = sys.argv try: try: - opts = getopt.getopt(argv[1:], "h", ["help"]) + opts, args = getopt.getopt(argv[1:], "t:w:scvh", + ["target=", + "workload=", + "nossd", + "nowarm", + "verbose", + "help", + ]) except getopt.error, msg: raise Usage(msg) + for o, a in opts: + if o in ("-h", "--help"): + print __doc__ + return 0 + elif o in ("-t", "--target"): + test_executor.filename = a + elif o in ("-v", "--verbose"): + verbose = True + elif o in ("-s", "--nossd"): + test_executor.precondition = False + elif o in ("-c", "--nowarm"): + test_executor.warm = False + elif o in ("-w", "--workload"): + workloads = a.split(",") + + test_executor.register_workloads(workloads) + except Usage, err: print >> sys.stderr, err.msg print >> sys.stderr, "for help use --help" return 2 + except UnknownWorkload, err: + print >> sys.stderr, err.msg + print >> sys.stderr, "for help use --help" + return 2 + + if (verbose): + test_executor.register(event) - for o in opts: - if o in ("-h", "--help"): - print __doc__ - return 0 - - simple_args = ['--rw=randread', '--size=32m', - '--directory=.', - '--iodepth=2', - '--direct=1', '--invalidate=1', '--numjobs=4', - '--name=random-read', '--output-format=json', - '--status-interval=60', - '--time_based', '--runtime=6000'] - - invoker = FIOInvoker() - invoker.register(event) - invoker.execute(simple_args) + test_executor.execute() if __name__ == "__main__": sys.exit(main()) diff --git a/storperf/test_executor.py b/storperf/test_executor.py new file mode 100644 index 0000000..5fb88d4 --- /dev/null +++ b/storperf/test_executor.py @@ -0,0 +1,137 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import imp +import logging +import os +import socket + +from os import listdir +from os.path import isfile, join + +from fio.fio_invoker import FIOInvoker +from carbon.emitter import CarbonMetricTransmitter +from carbon.converter import JSONToCarbon + + +class UnknownWorkload(Exception): + + def __init__(self, msg): + self.msg = msg + + +class TestExecutor(object): + + def __init__(self): + self.logger = logging.getLogger(__name__) + self.workload_modules = [] + self.filename = "storperf.dat" + self.precondition = True + self.warm = True + self.event_listeners = set() + self.metrics_converter = JSONToCarbon() + self.metrics_emitter = CarbonMetricTransmitter() + self.prefix = socket.getfqdn() + self.job_id = None + + def register(self, event_listener): + self.event_listeners.add(event_listener) + + def unregister(self, event_listener): + self.event_listeners.discard(event_listener) + + def event(self, metric): + carbon_metrics = self.metrics_converter.convert_to_dictionary( + metric, + self.prefix) + read_latency = carbon_metrics[self.prefix + ".jobs.1.read.lat.mean"] + write_latency = carbon_metrics[self.prefix + ".jobs.1.write.lat.mean"] + read_iops = carbon_metrics[self.prefix + ".jobs.1.read.iops"] + write_iops = carbon_metrics[self.prefix + ".jobs.1.write.iops"] + + message = "Average Latency us Read/Write: " + read_latency \ + + "/" + write_latency + " IOPS r/w: " + \ + read_iops + "/" + write_iops + + for event_listener in self.event_listeners: + event_listener(message) + + self.metrics_emitter.transmit_metrics(carbon_metrics) + + def register_workloads(self, workloads): + + if (workloads is None or workloads.length() == 0): + workload_dir = os.path.normpath( + os.path.join(os.path.dirname(__file__), "workloads")) + + workload_files = [ + f for f in listdir(workload_dir) + if isfile(join(workload_dir, f))] + + workloads = [] + + for filename in workload_files: + mname, ext = os.path.splitext(filename) + if (not mname.startswith('_')): + workloads.append(mname) + + if (self.warm is True): + workloads.insert(0, "_warm_up") + + if (self.precondition is True): + workloads.insert(0, "_ssd_preconditioning") + + for workload in workloads: + try: + workload_module = self.load_from_file("workloads/" + + workload + ".py") + self.logger.debug("Found: " + str(workload_module)) + if(workload_module is None): + raise UnknownWorkload("Unknown workload: " + workload) + self.workload_modules.append(workload_module) + except ImportError, err: + raise UnknownWorkload(err) + + def load_from_file(self, uri): + uri = os.path.normpath(os.path.join(os.path.dirname(__file__), uri)) + path, fname = os.path.split(uri) + mname, ext = os.path.splitext(fname) + no_ext = os.path.join(path, mname) + self.logger.debug("Looking for: " + no_ext) + if os.path.exists(no_ext + '.pyc'): + self.logger.debug("Loading compiled: " + mname + " from " + no_ext) + return imp.load_compiled(mname, no_ext + '.pyc') + if os.path.exists(no_ext + '.py'): + self.logger.debug("Compiling: " + mname + " from " + no_ext) + return imp.load_source(mname, no_ext + '.py') + return None + + def create_job_id(self): + return 1234 + + def execute(self): + if (self.job_id is None): + self.job_id = self.create_job_id() + + invoker = FIOInvoker() + invoker.register(self.event) + + for numjobs in [1, 2, 4]: + + for workload_module in self.workload_modules: + constructor = getattr(workload_module, "__name__") + constructorMethod = getattr(workload_module, constructor) + self.logger.debug( + "Found constructor: " + str(constructorMethod)) + workload = constructorMethod() + workload.filename = self.filename + workload.invoker = invoker + workload.options['iodepth'] = str(numjobs) + self.logger.info("Executing workload: " + constructor) + workload.execute() diff --git a/storperf/tests/carbon_tests/__init__.py b/storperf/tests/carbon_tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/storperf/tests/carbon_tests/__init__.py diff --git a/storperf/tests/carbon_tests/emitter_test.py b/storperf/tests/carbon_tests/emitter_test.py new file mode 100644 index 0000000..c26e837 --- /dev/null +++ b/storperf/tests/carbon_tests/emitter_test.py @@ -0,0 +1,68 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import unittest + +import json +import SocketServer +import threading +from time import sleep + +from carbon import converter +from carbon.emitter import CarbonMetricTransmitter + + +class MetricsHandler(SocketServer.BaseRequestHandler): + + def handle(self): + # Echo the back to the client + CarbonMetricTransmitterTest.response = self.request.recv(1024) + return + + +class MetricsServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): + pass + + +class CarbonMetricTransmitterTest(unittest.TestCase): + listen_port = 0 + response = None + + def setUp(self): + + address = ('localhost', 0) + server = MetricsServer(address, MetricsHandler) + ip, self.listen_port = server.server_address + + t = threading.Thread(target=server.serve_forever) + t.setDaemon(True) + t.start() + + def test_transmit_metrics(self): + + testconv = converter.JSONToCarbon() + json_object = json.loads("""{"timestamp" : "12345", "key":"value" }""") + result = testconv.convert_to_dictionary(json_object, "host.run-name") + + emitter = CarbonMetricTransmitter() + emitter.carbon_port = self.listen_port + emitter.transmit_metrics(result) + + count = 0 + + while (CarbonMetricTransmitterTest.response is None and count < 10): + count += 1 + sleep(0.1) + + self.assertEqual("host.run-name.key value 12345\n", + CarbonMetricTransmitterTest.response, + CarbonMetricTransmitterTest.response) + +if __name__ == '__main__': + unittest.main() diff --git a/storperf/tests/carbon_tests/json_to_carbon_test.py b/storperf/tests/carbon_tests/json_to_carbon_test.py new file mode 100644 index 0000000..6d62418 --- /dev/null +++ b/storperf/tests/carbon_tests/json_to_carbon_test.py @@ -0,0 +1,118 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import unittest +import json + +from carbon.converter import JSONToCarbon + + +class JSONToCarbonTest(unittest.TestCase): + + single_json_text_element = """{ "key" : "value" }""" + single_json_numeric_element = """{ "key" : 123 }""" + single_json_key_with_spaces = """{ "key with spaces" : "value" }""" + single_json_value_with_spaces = """{ "key" : "value with spaces" }""" + json_map_name_with_spaces = \ + """{ "map with spaces" : { "key" : "value" } }""" + json_list_name_with_spaces = \ + """{ "list with spaces" : [{ "key" : "value" }] }""" + + simple_fio_json = """ +{ + "fio version" : "fio-2.2.10", + "timestamp" : 1444144664, + "time" : "Tue Oct 6 11:17:44 2015", + "jobs" : [ + { + "jobname" : "random-read", + "groupid" : 0, + "error" : 0, + "eta" : 0, + "elapsed" : 26, + "read" : { + "io_bytes" : 7116, + "bw" : 275, + "iops" : 68.99, + "runtime" : 25788, + "total_ios" : 1779, + "short_ios" : 0, + "drop_ios" : 0, + "slat" : { + "min" : 0, + "max" : 0, + "mean" : 0.00, + "stddev" : 0.00 + } + } + }] +} +""" + + def setUp(self): + pass + + def test_to_string(self): + testconv = JSONToCarbon() + json_object = json.loads(self.simple_fio_json) + result = testconv.convert_to_dictionary(json_object, "host.run-name") + self.assertEqual("7116", result[ + "host.run-name.jobs.1.read.io_bytes"], + result["host.run-name.jobs.1.read.io_bytes"]) + + def test_single_text_element_no_prefix(self): + testconv = JSONToCarbon() + result = testconv.convert_to_dictionary( + json.loads(self.single_json_text_element)) + + self.assertEqual("value", result["key"], result["key"]) + + def test_single_numeric_element_no_prefix(self): + testconv = JSONToCarbon() + result = testconv.convert_to_dictionary( + json.loads(self.single_json_numeric_element)) + + self.assertEqual("123", result["key"], result["key"]) + + def test_single_text_key_space_element_no_prefix(self): + testconv = JSONToCarbon() + result = testconv.convert_to_dictionary( + json.loads(self.single_json_key_with_spaces)) + + self.assertEqual( + "value", result["key_with_spaces"], result["key_with_spaces"]) + + def test_single_text_value_space_element_no_prefix(self): + testconv = JSONToCarbon() + result = testconv.convert_to_dictionary( + json.loads(self.single_json_value_with_spaces)) + + self.assertEqual("value_with_spaces", result["key"], result["key"]) + + def test_map_name_with_space_no_prefix(self): + testconv = JSONToCarbon() + result = testconv.convert_to_dictionary( + json.loads(self.json_map_name_with_spaces)) + + self.assertEqual( + "value", result["map_with_spaces.key"], + result["map_with_spaces.key"]) + + def test_list_name_with_space_no_prefix(self): + testconv = JSONToCarbon() + result = testconv.convert_to_dictionary( + json.loads(self.json_list_name_with_spaces)) + + self.assertEqual( + "value", result["list_with_spaces.1.key"], + result["list_with_spaces.1.key"]) + + +if __name__ == '__main__': + unittest.main() diff --git a/storperf/workloads/__init__.py b/storperf/workloads/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/storperf/workloads/__init__.py diff --git a/storperf/workloads/_base_workload.py b/storperf/workloads/_base_workload.py new file mode 100644 index 0000000..7e13e45 --- /dev/null +++ b/storperf/workloads/_base_workload.py @@ -0,0 +1,54 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import logging + + +class _base_workload(object): + + def __init__(self): + self.logger = logging.getLogger(__name__) + self.default_filesize = "128M" + self.filename = 'storperf.dat' + self.options = { + 'ioengine': 'libaio', + 'direct': '1', + 'rw': 'read', + 'bs': '4k', + 'iodepth': '1', + 'numjobs': '1', + 'loops': '2', + 'output-format': 'json', + 'status-interval': '60' + } + self.invoker = None + + def execute(self): + args = [] + + if self.filename.startswith("/dev"): + self.options['size'] = "100%" + self.logger.debug( + "Profiling a device, using 100% of " + self.filename) + else: + self.options['size'] = self.default_filesize + self.logger.debug("Profiling a filesystem, using " + + self.default_filesize + " file") + + self.options['filename'] = self.filename + + self.setup() + + for key, value in self.options.iteritems(): + args.append('--' + key + "=" + value) + + self.invoker.execute(args) + + def setup(self): + pass diff --git a/storperf/workloads/_ssd_preconditioning.py b/storperf/workloads/_ssd_preconditioning.py new file mode 100644 index 0000000..66d5fa1 --- /dev/null +++ b/storperf/workloads/_ssd_preconditioning.py @@ -0,0 +1,16 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from workloads import _base_workload + + +class _ssd_preconditioning(_base_workload._base_workload): + + def setup(self): + self.options['name'] = 'ssd_preconditioning' + self.options['rw'] = 'write' diff --git a/storperf/workloads/_warm_up.py b/storperf/workloads/_warm_up.py new file mode 100644 index 0000000..8eaa2f1 --- /dev/null +++ b/storperf/workloads/_warm_up.py @@ -0,0 +1,17 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from workloads import _base_workload + + +class _warm_up(_base_workload._base_workload): + + def setup(self): + self.options['name'] = 'ssd_preconditioning' + self.options['rw'] = 'randwrite' + self.options['loops'] = '4' diff --git a/storperf/workloads/rr.py b/storperf/workloads/rr.py new file mode 100644 index 0000000..824974d --- /dev/null +++ b/storperf/workloads/rr.py @@ -0,0 +1,16 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from workloads import _base_workload + + +class rr(_base_workload._base_workload): + + def setup(self): + self.options['name'] = 'random_read' + self.options['rw'] = 'randread' diff --git a/storperf/workloads/rs.py b/storperf/workloads/rs.py new file mode 100644 index 0000000..92e3ce6 --- /dev/null +++ b/storperf/workloads/rs.py @@ -0,0 +1,16 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from workloads import _base_workload + + +class rs(_base_workload._base_workload): + + def setup(self): + self.options['name'] = 'sequential_read' + self.options['rw'] = 'read' diff --git a/storperf/workloads/rw.py b/storperf/workloads/rw.py new file mode 100644 index 0000000..2132a81 --- /dev/null +++ b/storperf/workloads/rw.py @@ -0,0 +1,18 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from workloads import _base_workload + + +class rw(_base_workload._base_workload): + + def setup(self): + self.options['name'] = 'random_readwrite' + self.options['rwmixread'] = '70' + self.options['rw'] = 'rw' + self.logger.debug(self.options) diff --git a/storperf/workloads/wr.py b/storperf/workloads/wr.py new file mode 100644 index 0000000..19b2c61 --- /dev/null +++ b/storperf/workloads/wr.py @@ -0,0 +1,16 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from workloads import _base_workload + + +class wr(_base_workload._base_workload): + + def setup(self): + self.options['name'] = 'random_write' + self.options['rw'] = 'randwrite' diff --git a/storperf/workloads/ws.py b/storperf/workloads/ws.py new file mode 100644 index 0000000..8ec2ebe --- /dev/null +++ b/storperf/workloads/ws.py @@ -0,0 +1,16 @@ +############################################################################## +# Copyright (c) 2015 EMC and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from workloads import _base_workload + + +class ws(_base_workload._base_workload): + + def setup(self): + self.options['name'] = 'sequential_write' + self.options['rw'] = 'write' |