1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
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 from __future__ import absolute_import
10 from __future__ import print_function
18 from oslo_serialization import jsonutils
20 import yardstick.ssh as ssh
21 from yardstick.benchmark.scenarios import base
23 LOG = logging.getLogger(__name__)
24 LOG.setLevel(logging.DEBUG)
27 class Cyclictest(base.Scenario):
28 """Execute cyclictest benchmark on guest vm
31 affinity - run thread #N on processor #N, if possible
35 interval - base interval of thread
39 loops - number of loops, 0 for endless
43 priority - priority of highest prio thread
47 threads - number of threads
51 histogram - dump a latency histogram to stdout after the run
52 here set the max time to be tracked
57 Read link below for more fio args description:
58 https://rt.wiki.kernel.org/index.php/Cyclictest
60 __scenario_type__ = "Cyclictest"
62 TARGET_SCRIPT = "cyclictest_benchmark.bash"
63 WORKSPACE = "/root/workspace/"
64 REBOOT_CMD_PATTERN = r";\s*reboot\b"
66 def __init__(self, scenario_cfg, context_cfg):
67 self.scenario_cfg = scenario_cfg
68 self.context_cfg = context_cfg
69 self.setup_done = False
71 def _put_files(self, client):
72 setup_options = self.scenario_cfg["setup_options"]
73 rpm_dir = setup_options["rpm_dir"]
74 script_dir = setup_options["script_dir"]
75 image_dir = setup_options["image_dir"]
76 LOG.debug("Send RPMs from %s to workspace %s",
77 rpm_dir, self.WORKSPACE)
78 client.put(rpm_dir, self.WORKSPACE, recursive=True)
79 LOG.debug("Send scripts from %s to workspace %s",
80 script_dir, self.WORKSPACE)
81 client.put(script_dir, self.WORKSPACE, recursive=True)
82 LOG.debug("Send guest image from %s to workspace %s",
83 image_dir, self.WORKSPACE)
84 client.put(image_dir, self.WORKSPACE, recursive=True)
86 def _connect_host(self):
87 host = self.context_cfg["host"]
88 user = host.get("user", "root")
89 ip = host.get("ip", None)
90 key_filename = host.get("key_filename", "~/.ssh/id_rsa")
92 LOG.debug("user:%s, host:%s", user, ip)
93 self.host = ssh.SSH(user, ip, key_filename=key_filename)
94 self.host.wait(timeout=600)
96 def _connect_guest(self):
97 host = self.context_cfg["host"]
98 user = host.get("user", "root")
99 ip = host.get("ip", None)
100 ssh_port = host.get("ssh_port", 5555)
101 key_filename = host.get("key_filename", "~/.ssh/id_rsa")
103 LOG.debug("user:%s, host:%s", user, ip)
104 self.guest = ssh.SSH(user, ip, port=ssh_port,
105 key_filename=key_filename)
106 self.guest.wait(timeout=600)
108 def _run_setup_cmd(self, client, cmd):
109 LOG.debug("Run cmd: %s", cmd)
110 status, stdout, stderr = client.execute(cmd)
112 if re.search(self.REBOOT_CMD_PATTERN, cmd):
113 LOG.debug("Error on reboot")
115 raise RuntimeError(stderr)
117 def _run_host_setup_scripts(self, scripts):
118 setup_options = self.scenario_cfg["setup_options"]
119 script_dir = os.path.basename(setup_options["script_dir"])
121 for script in scripts:
122 cmd = "cd %s/%s; export PATH=./:$PATH; %s" %\
123 (self.WORKSPACE, script_dir, script)
124 self._run_setup_cmd(self.host, cmd)
126 if re.search(self.REBOOT_CMD_PATTERN, cmd):
130 def _run_guest_setup_scripts(self, scripts):
131 setup_options = self.scenario_cfg["setup_options"]
132 script_dir = os.path.basename(setup_options["script_dir"])
134 for script in scripts:
135 cmd = "cd %s/%s; export PATH=./:$PATH; %s" %\
136 (self.WORKSPACE, script_dir, script)
137 self._run_setup_cmd(self.guest, cmd)
139 if re.search(self.REBOOT_CMD_PATTERN, cmd):
141 self._connect_guest()
145 setup_options = self.scenario_cfg["setup_options"]
146 host_setup_seqs = setup_options["host_setup_seqs"]
147 guest_setup_seqs = setup_options["guest_setup_seqs"]
150 self._put_files(self.host)
151 self._run_host_setup_scripts(host_setup_seqs)
153 self._connect_guest()
154 self._put_files(self.guest)
155 self._run_guest_setup_scripts(guest_setup_seqs)
157 # copy script to host
158 self.target_script = pkg_resources.resource_filename(
159 "yardstick.benchmark.scenarios.compute",
160 Cyclictest.TARGET_SCRIPT)
161 self.guest._put_file_shell(
162 self.target_script, '~/cyclictest_benchmark.sh')
164 self.setup_done = True
166 def run(self, result):
167 """execute the benchmark"""
168 default_args = "-m -n -q"
170 if not self.setup_done:
173 options = self.scenario_cfg["options"]
174 affinity = options.get("affinity", 1)
175 interval = options.get("interval", 1000)
176 priority = options.get("priority", 99)
177 loops = options.get("loops", 1000)
178 threads = options.get("threads", 1)
179 histogram = options.get("histogram", 90)
181 cmd_args = "-a %s -i %s -p %s -l %s -t %s -h %s %s" \
182 % (affinity, interval, priority, loops,
183 threads, histogram, default_args)
184 cmd = "bash cyclictest_benchmark.sh %s" % (cmd_args)
185 LOG.debug("Executing command: %s", cmd)
186 status, stdout, stderr = self.guest.execute(cmd)
188 raise RuntimeError(stderr)
190 result.update(jsonutils.loads(stdout))
192 if "sla" in self.scenario_cfg:
194 for t, latency in result.items():
195 if 'max_%s_latency' % t not in self.scenario_cfg['sla']:
198 sla_latency = int(self.scenario_cfg['sla'][
199 'max_%s_latency' % t])
200 latency = int(latency)
201 if latency > sla_latency:
202 sla_error += "%s latency %d > sla:max_%s_latency(%d); " % \
203 (t, latency, t, sla_latency)
204 assert sla_error == "", sla_error
207 def _test(): # pragma: no cover
208 """internal test function"""
209 key_filename = pkg_resources.resource_filename("yardstick.resources",
210 "files/yardstick_key")
213 "ip": "10.229.47.137",
215 "key_filename": key_filename
219 logger = logging.getLogger("yardstick")
220 logger.setLevel(logging.DEBUG)
231 "max_min_latency": 100,
232 "max_avg_latency": 500,
233 "max_max_latency": 1000,
241 cyclictest = Cyclictest(args, ctx)
242 cyclictest.run(result)
246 if __name__ == '__main__': # pragma: no cover