1 # Copyright 2016 Intel Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """ Vsperf specific scenario definition """
21 import yardstick.ssh as ssh
22 from yardstick.benchmark.scenarios import base
24 LOG = logging.getLogger(__name__)
27 class Vsperf(base.Scenario):
28 """Execute vsperf with defined parameters
31 traffic_type - to specify the type of traffic executed by traffic generator
32 the valid values are "rfc2544", "continuous", "back2back"
35 pkt_sizes - a packet size for which test should be executed;
36 Multiple packet sizes can be tested by modification of Sequence runner
37 section inside TC YAML definition.
40 duration - sets duration for which traffic will be generated
43 bidirectional - speficies if traffic will be uni (False) or bi-directional
47 iload - specifies frame rate
50 rfc2544_trials - the number of trials performed for each packet size
53 multistream - the number of simulated streams
56 stream_type - specifies network layer used for multistream simulation
57 the valid values are "L4", "L3" and "L2"
60 conf-file - path to the vsperf configuration file, which will be uploaded
64 setup-script - path to the setup script, which will be executed during
65 setup and teardown phases
68 trafficgen_port1 - specifies device name of 1st interface connected to
72 trafficgen_port2 - specifies device name of 2nd interface connected to
76 external_bridge - specifies name of external bridge configured in OVS
81 __scenario_type__ = "Vsperf"
83 VSPERF_CONF = '~/vsperf-yardstick.conf'
85 def __init__(self, scenario_cfg, context_cfg):
86 self.scenario_cfg = scenario_cfg
87 self.context_cfg = context_cfg
88 self.setup_done = False
90 self.tg_port1 = self.scenario_cfg['options'].get('trafficgen_port1',
92 self.tg_port2 = self.scenario_cfg['options'].get('trafficgen_port2',
94 self.br_ex = self.scenario_cfg['options'].get('external_bridge',
96 self.vsperf_conf = os.path.expanduser(
97 self.scenario_cfg['options'].get('conf-file', Vsperf.VSPERF_CONF))
98 self.setup_script = self.scenario_cfg['options'].get('setup-script',
100 if self.setup_script:
101 self.setup_script = os.path.expanduser(self.setup_script)
105 vsperf = self.context_cfg['host']
106 vsperf_user = vsperf.get('user', 'ubuntu')
107 vsperf_password = vsperf.get('password', 'ubuntu')
108 vsperf_ip = vsperf.get('ip', None)
110 # add trafficgen interfaces to the external bridge
112 subprocess.call('sudo bash -c "ovs-vsctl add-port %s %s"' %
113 (self.br_ex, self.tg_port1), shell=True)
115 subprocess.call('sudo bash -c "ovs-vsctl add-port %s %s"' %
116 (self.br_ex, self.tg_port2), shell=True)
118 # copy vsperf conf to VM
119 LOG.info("user:%s, host:%s", vsperf_user, vsperf_ip)
120 self.client = ssh.SSH(vsperf_user, vsperf_ip,
121 password=vsperf_password)
122 # traffic generation could last long
123 self.client.wait(timeout=1800)
125 # copy script to host
126 self.client.run("cat > ~/vsperf.conf",
127 stdin=open(self.vsperf_conf, "rb"))
129 # execute external setup script
130 if self.setup_script:
131 cmd = "%s setup" % (self.setup_script)
132 LOG.info("Execute setup script \"%s\"", cmd)
133 subprocess.call(cmd, shell=True)
135 self.setup_done = True
137 def run(self, result):
138 """ execute the vsperf benchmark and return test results
139 within result dictionary
141 def add_test_params(options, option, default_value):
142 """return parameter and its value as a string to be passed
143 to the VSPERF inside --test-params argument
146 options - dictionary with scenario options
147 option - a name of option to be added to the string
148 default_value - value to be used in case that option
149 is not defined inside scenario options
151 if option in options:
152 return "%s=%s" % (option, options[option])
153 elif default_value is not None:
154 return "%s=%s" % (option, default_value)
158 if not self.setup_done:
161 # remove results from previous tests
162 self.client.execute("rm -rf /tmp/results*")
165 options = self.scenario_cfg['options']
167 test_params.append(add_test_params(options, "traffic_type", "rfc2544"))
168 test_params.append(add_test_params(options, "pkt_sizes", "64"))
169 test_params.append(add_test_params(options, "duration", None))
170 test_params.append(add_test_params(options, "bidirectional", "False"))
171 test_params.append(add_test_params(options, "iload", 100))
172 test_params.append(add_test_params(options, "rfc2544_trials", None))
173 test_params.append(add_test_params(options, "multistream", None))
174 test_params.append(add_test_params(options, "stream_type", None))
177 cmd = "source ~/vsperfenv/bin/activate ; cd vswitchperf ; "
178 cmd += "./vsperf --mode trafficgen --conf-file ~/vsperf.conf "
179 cmd += "--test-params=\"%s\"" % (';'.join(filter(None, test_params)))
180 LOG.debug("Executing command: %s", cmd)
181 status, stdout, stderr = self.client.execute(cmd)
184 raise RuntimeError(stderr)
187 cmd = "cat /tmp/results*/result.csv"
188 LOG.debug("Executing command: %s", cmd)
189 status, stdout, stderr = self.client.execute(cmd)
192 raise RuntimeError(stderr)
194 # convert result.csv to JSON format
195 reader = csv.DictReader(stdout.split('\r\n'))
196 result.update(reader.next())
198 # sla check; go through all defined SLAs and check if values measured
199 # by VSPERF are higher then those defined by SLAs
200 if 'sla' in self.scenario_cfg and \
201 'metrics' in self.scenario_cfg['sla']:
202 for metric in self.scenario_cfg['sla']['metrics'].split(','):
203 assert metric in result, \
204 '%s is not collected by VSPERF' % (metric)
205 assert metric in self.scenario_cfg['sla'], \
206 '%s is not defined in SLA' % (metric)
207 vs_res = float(result[metric])
208 sla_res = float(self.scenario_cfg['sla'][metric])
209 assert vs_res >= sla_res, \
210 'VSPERF_%s(%f) < SLA_%s(%f)' % \
211 (metric, vs_res, metric, sla_res)
214 """cleanup after the test execution"""
215 # remove trafficgen interfaces from the external bridge
217 subprocess.call('sudo bash -c "ovs-vsctl del-port %s %s"' %
218 (self.br_ex, self.tg_port1), shell=True)
220 subprocess.call('sudo bash -c "ovs-vsctl del-port %s %s"' %
221 (self.br_ex, self.tg_port2), shell=True)
223 # execute external setup script
224 if self.setup_script:
225 cmd = "%s teardown" % (self.setup_script)
226 LOG.info("Execute setup script \"%s\"", cmd)
227 subprocess.call(cmd, shell=True)
229 self.setup_done = False