Add Cyclictest scenario and sample
[yardstick.git] / yardstick / benchmark / scenarios / compute / cyclictest.py
1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9 import pkg_resources
10 import logging
11 import json
12
13 import yardstick.ssh as ssh
14 from yardstick.benchmark.scenarios import base
15
16 LOG = logging.getLogger(__name__)
17 LOG.setLevel(logging.DEBUG)
18
19
20 class Cyclictest(base.Scenario):
21     """Execute cyclictest benchmark on guest vm
22
23   Parameters
24     affinity - run thread #N on processor #N, if possible
25         type:    int
26         unit:    na
27         default: 1
28     interval - base interval of thread
29         type:    int
30         unit:    us
31         default: 1000
32     loops - number of loops, 0 for endless
33         type:    int
34         unit:    na
35         default: 1000
36     priority - priority of highest prio thread
37         type:    int
38         unit:    na
39         default: 99
40     threads - number of threads
41         type:    int
42         unit:    na
43         default: 1
44     histogram - dump a latency histogram to stdout after the run
45                 here set the max time to be tracked
46         type:    int
47         unit:    ms
48         default: 90
49
50     Read link below for more fio args description:
51         https://rt.wiki.kernel.org/index.php/Cyclictest
52     """
53     __scenario_type__ = "Cyclictest"
54
55     TARGET_SCRIPT = "cyclictest_benchmark.bash"
56
57     def __init__(self, context):
58         self.context = context
59         self.setup_done = False
60
61     def setup(self):
62         '''scenario setup'''
63         self.target_script = pkg_resources.resource_filename(
64             "yardstick.benchmark.scenarios.compute",
65             Cyclictest.TARGET_SCRIPT)
66         user = self.context.get("user", "root")
67         host = self.context.get("host", None)
68         key_filename = self.context.get("key_filename", "~/.ssh/id_rsa")
69
70         LOG.debug("user:%s, host:%s", user, host)
71         print "key_filename:" + key_filename
72         self.client = ssh.SSH(user, host, key_filename=key_filename)
73         self.client.wait(timeout=600)
74
75         # copy script to host
76         self.client.run("cat > ~/cyclictest_benchmark.sh",
77                         stdin=open(self.target_script, "rb"))
78
79         self.setup_done = True
80
81     def run(self, args):
82         """execute the benchmark"""
83         default_args = "-m -n -q"
84
85         if not self.setup_done:
86             self.setup()
87
88         options = args["options"]
89         affinity = options.get("affinity", 1)
90         interval = options.get("interval", 1000)
91         priority = options.get("priority", 99)
92         loops = options.get("loops", 1000)
93         threads = options.get("threads", 1)
94         histogram = options.get("histogram", 90)
95
96         cmd_args = "-a %s -i %s -p %s -l %s -t %s -h %s %s" \
97                    % (affinity, interval, priority, loops,
98                       threads, histogram, default_args)
99         cmd = "sudo bash cyclictest_benchmark.sh %s" % (cmd_args)
100         LOG.debug("Executing command: %s", cmd)
101         status, stdout, stderr = self.client.execute(cmd)
102         if status:
103             raise RuntimeError(stderr)
104
105         data = json.loads(stdout)
106
107         if "sla" in args:
108             for t, latency in data.items():
109                 if 'max_%s_latency' % t not in args['sla']:
110                     continue
111
112                 sla_latency = int(args['sla']['max_%s_latency' % t])
113                 latency = int(latency)
114                 assert latency <= sla_latency, "%s latency %d > " \
115                     "sla:max_%s_latency(%d)" % (t, latency, t, sla_latency)
116
117         return data
118
119
120 def _test():
121     '''internal test function'''
122     key_filename = pkg_resources.resource_filename("yardstick.resources",
123                                                    "files/yardstick_key")
124     ctx = {
125         "host": "192.168.50.28",
126         "user": "root",
127         "key_filename": key_filename
128     }
129
130     logger = logging.getLogger("yardstick")
131     logger.setLevel(logging.DEBUG)
132
133     cyclictest = Cyclictest(ctx)
134
135     options = {
136         "affinity": 2,
137         "interval": 100,
138         "priority": 88,
139         "loops": 10000,
140         "threads": 2,
141         "histogram": 80
142     }
143     sla = {
144         "max_min_latency": 100,
145         "max_avg_latency": 500,
146         "max_max_latency": 1000,
147     }
148     args = {
149         "options": options,
150         "sla": sla
151     }
152
153     result = cyclictest.run(args)
154     print result
155
156 if __name__ == '__main__':
157     _test()