aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/benchmark/scenarios
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick/benchmark/scenarios')
-rw-r--r--yardstick/benchmark/scenarios/availability/actionplayers.py4
-rw-r--r--yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py5
-rw-r--r--yardstick/benchmark/scenarios/availability/attacker/attacker_process.py4
-rw-r--r--yardstick/benchmark/scenarios/availability/attacker_conf.yaml7
-rw-r--r--yardstick/benchmark/scenarios/availability/director.py7
-rwxr-xr-xyardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash42
-rwxr-xr-xyardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash65
-rw-r--r--yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash2
-rw-r--r--yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash2
-rw-r--r--yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash2
-rwxr-xr-xyardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash70
-rw-r--r--yardstick/benchmark/scenarios/availability/monitor/monitor_command.py5
-rw-r--r--yardstick/benchmark/scenarios/availability/monitor_conf.yaml2
-rw-r--r--yardstick/benchmark/scenarios/availability/operation/baseoperation.py1
-rw-r--r--yardstick/benchmark/scenarios/availability/operation/operation_general.py20
-rw-r--r--yardstick/benchmark/scenarios/availability/scenario_general.py4
-rw-r--r--yardstick/benchmark/scenarios/availability/util.py33
-rw-r--r--yardstick/benchmark/scenarios/base.py12
-rw-r--r--yardstick/benchmark/scenarios/compute/lmbench.py13
-rw-r--r--yardstick/benchmark/scenarios/compute/ramspeed.py6
-rw-r--r--yardstick/benchmark/scenarios/lib/__init__.py0
-rw-r--r--yardstick/benchmark/scenarios/lib/add_memory_load.py57
-rw-r--r--yardstick/benchmark/scenarios/lib/check_numa_info.py61
-rw-r--r--yardstick/benchmark/scenarios/lib/check_value.py58
-rw-r--r--yardstick/benchmark/scenarios/lib/get_migrate_target_host.py56
-rw-r--r--yardstick/benchmark/scenarios/lib/get_numa_info.py79
-rw-r--r--yardstick/benchmark/scenarios/lib/get_server.py83
-rw-r--r--yardstick/benchmark/scenarios/lib/get_server_ip.py38
-rw-r--r--yardstick/benchmark/scenarios/lib/migrate.py155
-rw-r--r--yardstick/benchmark/scenarios/networking/iperf3.py26
-rw-r--r--yardstick/benchmark/scenarios/networking/ping.py6
-rw-r--r--yardstick/benchmark/scenarios/networking/pktgen.py242
-rw-r--r--yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash139
-rw-r--r--yardstick/benchmark/scenarios/networking/vnf_generic.py106
-rw-r--r--yardstick/benchmark/scenarios/storage/fio.py32
-rw-r--r--yardstick/benchmark/scenarios/storage/storperf.py7
36 files changed, 1318 insertions, 133 deletions
diff --git a/yardstick/benchmark/scenarios/availability/actionplayers.py b/yardstick/benchmark/scenarios/availability/actionplayers.py
index 420626413..c5e199ba6 100644
--- a/yardstick/benchmark/scenarios/availability/actionplayers.py
+++ b/yardstick/benchmark/scenarios/availability/actionplayers.py
@@ -29,8 +29,10 @@ class AttackerPlayer(ActionPlayer):
class OperationPlayer(ActionPlayer):
- def __init__(self, operation):
+ def __init__(self, operation, intermediate_variables):
self.underlyingOperation = operation
+ self.underlyingOperation.intermediate_variables \
+ = intermediate_variables
def action(self):
self.underlyingOperation.run()
diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py
index 22de0b645..50d44c1ca 100644
--- a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py
+++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py
@@ -9,7 +9,6 @@
from __future__ import absolute_import
import logging
import subprocess
-import traceback
import yardstick.ssh as ssh
from yardstick.benchmark.scenarios.availability.attacker.baseattacker import \
@@ -26,9 +25,7 @@ def _execute_shell_command(command, stdin=None):
output = subprocess.check_output(command, stdin=stdin, shell=True)
except Exception:
exitcode = -1
- output = traceback.format_exc()
- LOG.error("exec command '%s' error:\n ", command)
- LOG.error(traceback.format_exc())
+ LOG.error("exec command '%s' error:\n ", command, exc_info=True)
return exitcode, output
diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py
index f7ab23dcd..cb171eafa 100644
--- a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py
+++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py
@@ -47,11 +47,11 @@ class ProcessAttacker(BaseAttacker):
stdin=stdin_file)
if stdout:
- LOG.info("check the envrioment success!")
+ LOG.info("check the environment success!")
return int(stdout.strip('\n'))
else:
LOG.error(
- "the host envrioment is error, stdout:%s, stderr:%s",
+ "the host environment is error, stdout:%s, stderr:%s",
stdout, stderr)
return False
diff --git a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
index b8c34ad44..aa144ab50 100644
--- a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
+++ b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
@@ -16,6 +16,11 @@ kill-process:
inject_script: ha_tools/fault_process_kill.bash
recovery_script: ha_tools/start_service.bash
+kill-lxc-process:
+ check_script: ha_tools/check_lxc_process_python.bash
+ inject_script: ha_tools/fault_lxc_process_kill.bash
+ recovery_script: ha_tools/start_lxc_service.bash
+
bare-metal-down:
check_script: ha_tools/check_host_ping.bash
recovery_script: ha_tools/ipmi_power.bash
@@ -34,4 +39,4 @@ stress-cpu:
block-io:
inject_script: ha_tools/disk/block_io.bash
- recovery_script: ha_tools/disk/recovery_disk_io.bash \ No newline at end of file
+ recovery_script: ha_tools/disk/recovery_disk_io.bash
diff --git a/yardstick/benchmark/scenarios/availability/director.py b/yardstick/benchmark/scenarios/availability/director.py
index e0d05ebf5..c9187c34d 100644
--- a/yardstick/benchmark/scenarios/availability/director.py
+++ b/yardstick/benchmark/scenarios/availability/director.py
@@ -65,7 +65,9 @@ class Director(object):
self.resultCheckerMgr = baseresultchecker.ResultCheckerMgr()
self.resultCheckerMgr.init_ResultChecker(result_check_cfgs, nodes)
- def createActionPlayer(self, type, key):
+ def createActionPlayer(self, type, key, intermediate_variables=None):
+ if intermediate_variables is None:
+ intermediate_variables = {}
LOG.debug(
"the type of current action is %s, the key is %s", type, key)
if type == ActionType.ATTACKER:
@@ -76,7 +78,8 @@ class Director(object):
return actionplayers.ResultCheckerPlayer(
self.resultCheckerMgr[key])
if type == ActionType.OPERATION:
- return actionplayers.OperationPlayer(self.operationMgr[key])
+ return actionplayers.OperationPlayer(self.operationMgr[key],
+ intermediate_variables)
LOG.debug("something run when creatactionplayer")
def createActionRollbacker(self, type, key):
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash b/yardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash
new file mode 100755
index 000000000..6d2f4dd51
--- /dev/null
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+##############################################################################
+# Copyright (c) 2015 Huawei Technologies Co.,Ltd 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
+##############################################################################
+
+# check the status of a service
+
+set -e
+
+NOVA_API_PROCESS_1="nova-api-os-compute"
+NOVA_API_PROCESS_2="nova-api-metadata"
+NOVA_API_LXC_FILTER_1="nova_api_os_compute"
+NOVA_API_LXC_FILTER_2="nova_api_metadata"
+
+process_name=$1
+
+lxc_filter=$(echo "${process_name}" | sed 's/-/_/g')
+
+if [ "${lxc_filter}" = "glance_api" ]; then
+ lxc_filter="glance"
+fi
+
+if [ "${process_name}" = "nova-api" ]; then
+ container_1=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_1}")
+ container_2=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_2}")
+
+ echo $(($(lxc-attach -n "${container_1}" -- ps aux | grep -e "${NOVA_API_PROCESS_1}" | grep -v grep | grep -cv /bin/sh) + $(lxc-attach -n "${container_2}" -- ps aux | grep -e "${NOVA_API_PROCESS_2}" | grep -v grep | grep -cv /bin/sh)))
+else
+ container=$(lxc-ls -1 --filter="${lxc_filter}")
+
+ if [ "${process_name}" = "haproxy" ]; then
+ ps aux | grep -e "/usr/.*/${process_name}" | grep -v grep | grep -cv /bin/sh
+ else
+ lxc-attach -n "${container}" -- ps aux | grep -e "${process_name}" | grep -v grep | grep -cv /bin/sh
+ fi
+fi
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash b/yardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash
new file mode 100755
index 000000000..b0b86ab65
--- /dev/null
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+##############################################################################
+# Copyright (c) 2015 Huawei Technologies Co.,Ltd 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
+##############################################################################
+
+# Stop process by process name
+
+set -e
+
+NOVA_API_PROCESS_1="nova-api-os-compute"
+NOVA_API_PROCESS_2="nova-api-metadata"
+NOVA_API_LXC_FILTER_1="nova_api_os_compute"
+NOVA_API_LXC_FILTER_2="nova_api_metadata"
+
+process_name=$1
+
+lxc_filter=$(echo "${process_name}" | sed 's/-/_/g')
+
+if [ "${lxc_filter}" = "glance_api" ]; then
+ lxc_filter="glance"
+fi
+
+if [ "${process_name}" = "nova-api" ]; then
+ container_1=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_1}")
+ container_2=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_2}")
+
+ pids_1=$(lxc-attach -n "${container_1}" -- pgrep -f "/openstack/.*/${NOVA_API_PROCESS_1}")
+ for pid in ${pids_1};
+ do
+ lxc-attach -n "${container_1}" -- kill -9 "${pid}"
+ done
+
+ pids_2=$(lxc-attach -n "${container_2}" -- pgrep -f "/openstack/.*/${NOVA_API_PROCESS_2}")
+ for pid in ${pids_2};
+ do
+ lxc-attach -n "${container_2}" -- kill -9 "${pid}"
+ done
+else
+ container=$(lxc-ls -1 --filter="${lxc_filter}")
+
+ if [ "${process_name}" = "haproxy" ]; then
+ for pid in $(pgrep -cf "/usr/.*/${process_name}");
+ do
+ kill -9 "${pid}"
+ done
+ elif [ "${process_name}" = "keystone" ]; then
+ pids=$(lxc-attach -n "${container}" -- ps aux | grep "keystone" | grep -iv heartbeat | grep -iv monitor | grep -v grep | grep -v /bin/sh | awk '{print $2}')
+ for pid in ${pids};
+ do
+ lxc-attach -n "${container}" -- kill -9 "${pid}"
+ done
+ else
+ pids=$(lxc-attach -n "${container}" -- pgrep -f "/openstack/.*/${process_name}")
+ for pid in ${pids};
+ do
+ lxc-attach -n "${container}" -- kill -9 "${pid}"
+ done
+ fi
+fi
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash
index aee516ea9..7408409a9 100644
--- a/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash
@@ -20,4 +20,4 @@ else
SECURE=""
fi
-openstack "${SECURE}" flavor create $1 --id $2 --ram $3 --disk $4 --vcpus $5
+openstack ${SECURE} flavor create $1 --id $2 --ram $3 --disk $4 --vcpus $5
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash
index d39926fc5..7240476f7 100644
--- a/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash
@@ -20,4 +20,4 @@ else
SECURE=""
fi
-openstack "${SECURE}" flavor delete $1
+openstack ${SECURE} flavor delete $1
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash
index bd61ba9bb..e679fdb9e 100644
--- a/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash
@@ -19,4 +19,4 @@ else
SECURE=""
fi
-openstack "${SECURE}" flavor list
+openstack ${SECURE} flavor list
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash b/yardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash
new file mode 100755
index 000000000..36a673977
--- /dev/null
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+##############################################################################
+# Copyright (c) 2015 Huawei Technologies Co.,Ltd 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
+##############################################################################
+
+# Start a service and check the service is started
+
+set -e
+
+NOVA_API_SERVICE_1="nova-api-os-compute"
+NOVA_API_SERVICE_2="nova-api-metadata"
+NOVA_API_LXC_FILTER_1="nova_api_os_compute"
+NOVA_API_LXC_FILTER_2="nova_api_metadata"
+
+service_name=$1
+
+if [ "${service_name}" = "haproxy" ]; then
+ if which systemctl 2>/dev/null; then
+ systemctl start $service_name
+ else
+ service $service_name start
+ fi
+else
+ lxc_filter=${service_name//-/_}
+
+ if [ "${lxc_filter}" = "glance_api" ]; then
+ lxc_filter="glance"
+ fi
+
+ if [ "${service_name}" = "nova-api" ]; then
+ container_1=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_1}")
+ container_2=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_2}")
+
+ if lxc-attach -n "${container_1}" -- which systemctl 2>/dev/null; then
+ lxc-attach -n "${container_1}" -- systemctl start "${NOVA_API_SERVICE_1}"
+ else
+ lxc-attach -n "${container_1}" -- service "${NOVA_API_SERVICE_1}" start
+ fi
+
+ if lxc-attach -n "${container_2}" -- which systemctl 2>/dev/null; then
+ lxc-attach -n "${container_2}" -- systemctl start "${NOVA_API_SERVICE_2}"
+ else
+ lxc-attach -n "${container_2}" -- service "${NOVA_API_SERVICE_2}" start
+ fi
+ else
+ container=$(lxc-ls -1 --filter="${lxc_filter}")
+
+ Distributor=$(lxc-attach -n "${container}" -- lsb_release -a | grep "Distributor ID" | awk '{print $3}')
+
+ if [ "${Distributor}" != "Ubuntu" -a "${service_name}" != "keystone" -a "${service_name}" != "neutron-server" ]; then
+ service_name="openstack-"${service_name}
+ elif [ "${Distributor}" = "Ubuntu" -a "${service_name}" = "keystone" ]; then
+ service_name="apache2"
+ elif [ "${service_name}" = "keystone" ]; then
+ service_name="httpd"
+ fi
+
+ if lxc-attach -n "${container}" -- which systemctl 2>/dev/null; then
+ lxc-attach -n "${container}" -- systemctl start "${service_name}"
+ else
+ lxc-attach -n "${container}" -- service "${service_name}" start
+ fi
+ fi
+fi
diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py
index a0777f94e..a9488cc30 100644
--- a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py
+++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py
@@ -11,7 +11,6 @@ from __future__ import absolute_import
import os
import logging
import subprocess
-import traceback
import yardstick.ssh as ssh
from yardstick.benchmark.scenarios.availability.monitor import basemonitor
@@ -27,9 +26,7 @@ def _execute_shell_command(command):
output = subprocess.check_output(command, shell=True)
except Exception:
exitcode = -1
- output = traceback.format_exc()
- LOG.error("exec command '%s' error:\n ", command)
- LOG.error(traceback.format_exc())
+ LOG.error("exec command '%s' error:\n ", command, exc_info=True)
return exitcode, output
diff --git a/yardstick/benchmark/scenarios/availability/monitor_conf.yaml b/yardstick/benchmark/scenarios/availability/monitor_conf.yaml
index 511449221..a08347d2d 100644
--- a/yardstick/benchmark/scenarios/availability/monitor_conf.yaml
+++ b/yardstick/benchmark/scenarios/availability/monitor_conf.yaml
@@ -13,6 +13,8 @@ schema: "yardstick:task:0.1"
process-status:
monitor_script: ha_tools/check_process_python.bash
+lxc_process-status:
+ monitor_script: ha_tools/check_lxc_process_python.bash
nova-image-list:
monitor_script: ha_tools/nova_image_list.bash
service-status:
diff --git a/yardstick/benchmark/scenarios/availability/operation/baseoperation.py b/yardstick/benchmark/scenarios/availability/operation/baseoperation.py
index be286b8fd..88ca9e2bb 100644
--- a/yardstick/benchmark/scenarios/availability/operation/baseoperation.py
+++ b/yardstick/benchmark/scenarios/availability/operation/baseoperation.py
@@ -58,6 +58,7 @@ class BaseOperation(object):
self.key = ''
self._config = config
self._context = context
+ self.intermediate_variables = {}
@staticmethod
def get_operation_cls(type):
diff --git a/yardstick/benchmark/scenarios/availability/operation/operation_general.py b/yardstick/benchmark/scenarios/availability/operation/operation_general.py
index 8fd387e47..af1ae7469 100644
--- a/yardstick/benchmark/scenarios/availability/operation/operation_general.py
+++ b/yardstick/benchmark/scenarios/availability/operation/operation_general.py
@@ -15,7 +15,8 @@ from yardstick.benchmark.scenarios.availability.operation.baseoperation \
import yardstick.ssh as ssh
from yardstick.benchmark.scenarios.availability.util \
- import buildshellparams, execute_shell_command
+ import buildshellparams, execute_shell_command, \
+ read_stdout_item, build_shell_command
LOG = logging.getLogger(__name__)
@@ -39,11 +40,7 @@ class GeneralOperaion(BaseOperation):
self.operation_key = self._config['operation_key']
if "action_parameter" in self._config:
- actionParameter = self._config['action_parameter']
- str = buildshellparams(
- actionParameter, True if self.connection else False)
- l = list(item for item in actionParameter.values())
- self.action_param = str.format(*l)
+ self.actionParameter_config = self._config['action_parameter']
if "rollback_parameter" in self._config:
rollbackParameter = self._config['rollback_parameter']
@@ -61,6 +58,11 @@ class GeneralOperaion(BaseOperation):
def run(self):
if "action_parameter" in self._config:
+ self.action_param = \
+ build_shell_command(
+ self.actionParameter_config,
+ True if self.connection else False,
+ self.intermediate_variables)
if self.connection:
with open(self.action_script, "r") as stdin_file:
exit_status, stdout, stderr = self.connection.execute(
@@ -83,6 +85,12 @@ class GeneralOperaion(BaseOperation):
if exit_status == 0:
LOG.debug("success,the operation's output is: %s", stdout)
+ if "return_parameter" in self._config:
+ returnParameter = self._config['return_parameter']
+ for key, item in returnParameter.items():
+ value = read_stdout_item(stdout, key)
+ LOG.debug("intermediate variables %s: %s", item, value)
+ self.intermediate_variables[item] = value
else:
LOG.error(
"the operation's error, stdout:%s, stderr:%s",
diff --git a/yardstick/benchmark/scenarios/availability/scenario_general.py b/yardstick/benchmark/scenarios/availability/scenario_general.py
index 28bec8aff..17ad79f29 100644
--- a/yardstick/benchmark/scenarios/availability/scenario_general.py
+++ b/yardstick/benchmark/scenarios/availability/scenario_general.py
@@ -25,6 +25,7 @@ class ScenarioGeneral(base.Scenario):
"scenario_cfg:%s context_cfg:%s", scenario_cfg, context_cfg)
self.scenario_cfg = scenario_cfg
self.context_cfg = context_cfg
+ self.intermediate_variables = {}
def setup(self):
self.director = Director(self.scenario_cfg, self.context_cfg)
@@ -38,7 +39,8 @@ class ScenarioGeneral(base.Scenario):
orderedSteps.index(step) + 1)
try:
actionPlayer = self.director.createActionPlayer(
- step['actionType'], step['actionKey'])
+ step['actionType'], step['actionKey'],
+ self.intermediate_variables)
actionPlayer.action()
actionRollbacker = self.director.createActionRollbacker(
step['actionType'], step['actionKey'])
diff --git a/yardstick/benchmark/scenarios/availability/util.py b/yardstick/benchmark/scenarios/availability/util.py
index eadbfa53b..6fef622bd 100644
--- a/yardstick/benchmark/scenarios/availability/util.py
+++ b/yardstick/benchmark/scenarios/availability/util.py
@@ -14,13 +14,8 @@ LOG = logging.getLogger(__name__)
def buildshellparams(param, remote=True):
- i = 0
- values = []
result = '/bin/bash -s' if remote else ''
- for key in param.keys():
- values.append(param[key])
- result += " {%d}" % i
- i = i + 1
+ result += "".join(" {%d}" % i for i in range(len(param)))
return result
@@ -36,5 +31,29 @@ def execute_shell_command(command):
output = traceback.format_exc()
LOG.error("exec command '%s' error:\n ", command)
LOG.error(traceback.format_exc())
-
return exitcode, output
+
+PREFIX = '$'
+
+
+def build_shell_command(param_config, remote=True, intermediate_variables=None):
+ param_template = '/bin/bash -s' if remote else ''
+ if intermediate_variables:
+ for key, val in param_config.items():
+ if str(val).startswith(PREFIX):
+ try:
+ param_config[key] = intermediate_variables[val]
+ except KeyError:
+ pass
+ result = param_template + "".join(" {}".format(v) for v in param_config.values())
+ LOG.debug("THE RESULT OF build_shell_command IS: %s", result)
+ return result
+
+
+def read_stdout_item(stdout, key):
+ for item in stdout.splitlines():
+ if key in item:
+ attributes = item.split("|")
+ if attributes[1].lstrip().startswith(key):
+ return attributes[2].strip()
+ return None
diff --git a/yardstick/benchmark/scenarios/base.py b/yardstick/benchmark/scenarios/base.py
index 5d3c36c38..3cb138dd8 100644
--- a/yardstick/benchmark/scenarios/base.py
+++ b/yardstick/benchmark/scenarios/base.py
@@ -63,3 +63,15 @@ class Scenario(object):
return scenario.__module__ + "." + scenario.__name__
raise RuntimeError("No such scenario type %s" % scenario_type)
+
+ def _push_to_outputs(self, keys, values):
+ return dict(zip(keys, values))
+
+ def _change_obj_to_dict(self, obj):
+ dic = {}
+ for k, v in vars(obj).items():
+ try:
+ vars(v)
+ except TypeError:
+ dic[k] = v
+ return dic
diff --git a/yardstick/benchmark/scenarios/compute/lmbench.py b/yardstick/benchmark/scenarios/compute/lmbench.py
index c99fc988d..801f7fa80 100644
--- a/yardstick/benchmark/scenarios/compute/lmbench.py
+++ b/yardstick/benchmark/scenarios/compute/lmbench.py
@@ -15,6 +15,7 @@ import pkg_resources
from oslo_serialization import jsonutils
import yardstick.ssh as ssh
+from yardstick.common import utils
from yardstick.benchmark.scenarios import base
LOG = logging.getLogger(__name__)
@@ -127,30 +128,32 @@ class Lmbench(base.Scenario):
if status:
raise RuntimeError(stderr)
+ lmbench_result = {}
if test_type == 'latency':
- result.update(
+ lmbench_result.update(
{"latencies": jsonutils.loads(stdout)})
else:
- result.update(jsonutils.loads(stdout))
+ lmbench_result.update(jsonutils.loads(stdout))
+ result.update(utils.flatten_dict_key(lmbench_result))
if "sla" in self.scenario_cfg:
sla_error = ""
if test_type == 'latency':
sla_max_latency = int(self.scenario_cfg['sla']['max_latency'])
- for t_latency in result["latencies"]:
+ for t_latency in lmbench_result["latencies"]:
latency = t_latency['latency']
if latency > sla_max_latency:
sla_error += "latency %f > sla:max_latency(%f); " \
% (latency, sla_max_latency)
elif test_type == 'bandwidth':
sla_min_bw = int(self.scenario_cfg['sla']['min_bandwidth'])
- bw = result["bandwidth(MBps)"]
+ bw = lmbench_result["bandwidth(MBps)"]
if bw < sla_min_bw:
sla_error += "bandwidth %f < " \
"sla:min_bandwidth(%f)" % (bw, sla_min_bw)
elif test_type == 'latency_for_cache':
sla_latency = float(self.scenario_cfg['sla']['max_latency'])
- cache_latency = float(result['L1cache'])
+ cache_latency = float(lmbench_result['L1cache'])
if sla_latency < cache_latency:
sla_error += "latency %f > sla:max_latency(%f); " \
% (cache_latency, sla_latency)
diff --git a/yardstick/benchmark/scenarios/compute/ramspeed.py b/yardstick/benchmark/scenarios/compute/ramspeed.py
index 850ee5934..ca64935dd 100644
--- a/yardstick/benchmark/scenarios/compute/ramspeed.py
+++ b/yardstick/benchmark/scenarios/compute/ramspeed.py
@@ -14,6 +14,7 @@ import pkg_resources
from oslo_serialization import jsonutils
import yardstick.ssh as ssh
+from yardstick.common import utils
from yardstick.benchmark.scenarios import base
LOG = logging.getLogger(__name__)
@@ -128,12 +129,13 @@ class Ramspeed(base.Scenario):
if status:
raise RuntimeError(stderr)
- result.update(jsonutils.loads(stdout))
+ ramspeed_result = jsonutils.loads(stdout)
+ result.update(utils.flatten_dict_key(ramspeed_result))
if "sla" in self.scenario_cfg:
sla_error = ""
sla_min_bw = int(self.scenario_cfg['sla']['min_bandwidth'])
- for i in result["Result"]:
+ for i in ramspeed_result["Result"]:
bw = i["Bandwidth(MBps)"]
if bw < sla_min_bw:
sla_error += "Bandwidth %f < " \
diff --git a/yardstick/benchmark/scenarios/lib/__init__.py b/yardstick/benchmark/scenarios/lib/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/__init__.py
diff --git a/yardstick/benchmark/scenarios/lib/add_memory_load.py b/yardstick/benchmark/scenarios/lib/add_memory_load.py
new file mode 100644
index 000000000..26cf140d1
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/add_memory_load.py
@@ -0,0 +1,57 @@
+# ############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+import yardstick.ssh as ssh
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+
+class AddMemoryLoad(base.Scenario):
+ """Add memory load in server
+ """
+
+ __scenario_type__ = "AddMemoryLoad"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+
+ self.options = scenario_cfg.get('options', {})
+
+ self.client = ssh.SSH.from_node(self.context_cfg['host'])
+ self.client.wait(timeout=600)
+
+ def run(self, result):
+ self._add_load()
+
+ def _add_load(self):
+ try:
+ memory_load = self.options['memory_load']
+ except KeyError:
+ LOG.error('memory_load parameter must be provided')
+ else:
+ if float(memory_load) == 0:
+ return
+ cmd = 'free | awk "/Mem/ {print $2}"'
+ code, stdout, stderr = self.client.execute(cmd)
+ total = int(stdout.split()[1])
+ used = int(stdout.split()[2])
+ remain_memory = total * float(memory_load) - used
+ if remain_memory > 0:
+ count = remain_memory / 1024 / 128
+ LOG.info('Add %s vm load', count)
+ if count != 0:
+ cmd = 'stress -t 10 -m {} --vm-keep'.format(count)
+ self.client.execute(cmd)
diff --git a/yardstick/benchmark/scenarios/lib/check_numa_info.py b/yardstick/benchmark/scenarios/lib/check_numa_info.py
new file mode 100644
index 000000000..59a47547e
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/check_numa_info.py
@@ -0,0 +1,61 @@
+# ############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+
+class CheckNumaInfo(base.Scenario):
+ """
+ Execute a live migration for two hosts
+
+ """
+
+ __scenario_type__ = "CheckNumaInfo"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+
+ self.options = self.scenario_cfg.get('options', {})
+
+ self.cpu_set = self.options.get('cpu_set', '1,2,3,4,5,6')
+
+ def run(self, result):
+ info1 = self.options.get('info1')
+ info2 = self.options.get('info2')
+ LOG.debug('Origin numa info: %s', info1)
+ LOG.debug('Current numa info: %s', info2)
+ status = self._check_vm2_status(info1, info2)
+
+ keys = self.scenario_cfg.get('output', '').split()
+ values = [status]
+ return self._push_to_outputs(keys, values)
+
+ def _check_vm2_status(self, info1, info2):
+ if len(info1['pinning']) != 1 or len(info2['pinning']) != 1:
+ return False
+
+ for i in info1['vcpupin']:
+ for j in i['cpuset'].split(','):
+ if j not in self.cpu_set.split(','):
+ return False
+
+ for i in info2['vcpupin']:
+ for j in i['cpuset'].split(','):
+ if j not in self.cpu_set.split(','):
+ return False
+
+ return True
diff --git a/yardstick/benchmark/scenarios/lib/check_value.py b/yardstick/benchmark/scenarios/lib/check_value.py
new file mode 100644
index 000000000..759076068
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/check_value.py
@@ -0,0 +1,58 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+
+class CheckValue(base.Scenario):
+ """Check values between value1 and value2
+
+ options:
+ operator: equal(eq) and not equal(ne)
+ value1:
+ value2:
+ output: check_result
+ """
+
+ __scenario_type__ = "CheckValue"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+ self.options = self.scenario_cfg['options']
+
+ def run(self, result):
+ """execute the test"""
+
+ op = self.options.get("operator")
+ LOG.debug("options=%s", self.options)
+ value1 = str(self.options.get("value1"))
+ value2 = str(self.options.get("value2"))
+ check_result = "PASS"
+ if op == "eq" and value1 != value2:
+ LOG.info("value1=%s, value2=%s, error: should equal!!!", value1,
+ value2)
+ check_result = "FAIL"
+ assert value1 == value2, "Error %s!=%s" % (value1, value2)
+ elif op == "ne" and value1 == value2:
+ LOG.info("value1=%s, value2=%s, error: should not equal!!!",
+ value1, value2)
+ check_result = "FAIL"
+ assert value1 != value2, "Error %s==%s" % (value1, value2)
+ LOG.info("Check result is %s", check_result)
+ keys = self.scenario_cfg.get('output', '').split()
+ values = [check_result]
+ return self._push_to_outputs(keys, values)
diff --git a/yardstick/benchmark/scenarios/lib/get_migrate_target_host.py b/yardstick/benchmark/scenarios/lib/get_migrate_target_host.py
new file mode 100644
index 000000000..c19d96d68
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/get_migrate_target_host.py
@@ -0,0 +1,56 @@
+
+# ############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.common import openstack_utils
+from yardstick.common.utils import change_obj_to_dict
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+
+class GetMigrateTargetHost(base.Scenario):
+ """Get a migrate target host according server
+ """
+
+ __scenario_type__ = "GetMigrateTargetHost"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+
+ self.options = self.scenario_cfg.get('options', {})
+ default_instance_id = self.options.get('server', {}).get('id', '')
+ self.instance_id = self.options.get('server_id', default_instance_id)
+
+ self.nova_client = openstack_utils.get_nova_client()
+
+ def run(self, result):
+ current_host = self._get_current_host_name(self.instance_id)
+ target_host = self._get_migrate_host(current_host)
+
+ keys = self.scenario_cfg.get('output', '').split()
+ values = [target_host]
+ return self._push_to_outputs(keys, values)
+
+ def _get_current_host_name(self, server_id):
+
+ return change_obj_to_dict(self.nova_client.servers.get(server_id))['OS-EXT-SRV-ATTR:host']
+
+ def _get_migrate_host(self, current_host):
+ hosts = self.nova_client.hosts.list_all()
+ compute_hosts = [a.host for a in hosts if a.service == 'compute']
+ for host in compute_hosts:
+ if host.strip() != current_host.strip():
+ return host
diff --git a/yardstick/benchmark/scenarios/lib/get_numa_info.py b/yardstick/benchmark/scenarios/lib/get_numa_info.py
new file mode 100644
index 000000000..4e4a44d95
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/get_numa_info.py
@@ -0,0 +1,79 @@
+# ############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+import os
+
+import yaml
+from xml.etree import ElementTree as ET
+
+from yardstick import ssh
+from yardstick.benchmark.scenarios import base
+from yardstick.common import constants as consts
+from yardstick.common.utils import change_obj_to_dict
+from yardstick.common.openstack_utils import get_nova_client
+from yardstick.common.task_template import TaskTemplate
+
+LOG = logging.getLogger(__name__)
+
+
+class GetNumaInfo(base.Scenario):
+ """
+ Execute a live migration for two hosts
+
+ """
+
+ __scenario_type__ = "GetNumaInfo"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+ self.options = self.scenario_cfg.get('options', {})
+
+ server = self.options['server']
+ self.server_id = server['id']
+ self.host = self._get_current_host_name(self.server_id)
+
+ node_file = os.path.join(consts.YARDSTICK_ROOT_PATH,
+ self.options.get('file'))
+
+ with open(node_file) as f:
+ nodes = yaml.safe_load(TaskTemplate.render(f.read()))
+ self.nodes = {a['host_name']: a for a in nodes['nodes']}
+
+ def run(self, result):
+ numa_info = self._check_numa_node(self.server_id, self.host)
+
+ keys = self.scenario_cfg.get('output', '').split()
+ values = [numa_info]
+ return self._push_to_outputs(keys, values)
+
+ def _get_current_host_name(self, server_id):
+
+ return change_obj_to_dict(get_nova_client().servers.get(server_id))['OS-EXT-SRV-ATTR:host']
+
+ def _get_host_client(self, node_name):
+ self.host_client = ssh.SSH.from_node(self.nodes.get(node_name))
+ self.host_client.wait(timeout=600)
+
+ def _check_numa_node(self, server_id, host):
+ self._get_host_client(host)
+
+ cmd = "sudo virsh dumpxml %s" % server_id
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.host_client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ root = ET.fromstring(stdout)
+ vcpupin = [a.attrib for a in root.iter('vcpupin')]
+ pinning = [a.attrib for a in root.iter('memnode')]
+ return {"pinning": pinning, 'vcpupin': vcpupin}
diff --git a/yardstick/benchmark/scenarios/lib/get_server.py b/yardstick/benchmark/scenarios/lib/get_server.py
new file mode 100644
index 000000000..fcf47c80d
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/get_server.py
@@ -0,0 +1,83 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+import yardstick.common.openstack_utils as op_utils
+
+LOG = logging.getLogger(__name__)
+
+
+class GetServer(base.Scenario):
+ """Get a server instance
+
+ Parameters
+ server_id - ID of the server
+ type: string
+ unit: N/A
+ default: null
+ server_name - name of the server
+ type: string
+ unit: N/A
+ default: null
+
+ Either server_id or server_name is required.
+
+ Outputs
+ rc - response code of getting server instance
+ 0 for success
+ 1 for failure
+ type: int
+ unit: N/A
+ server - instance of the server
+ type: dict
+ unit: N/A
+ """
+
+ __scenario_type__ = "GetServer"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+ self.options = self.scenario_cfg.get('options', {})
+
+ self.server_id = self.options.get("server_id")
+ if self.server_id:
+ LOG.debug('Server id is %s', self.server_id)
+
+ default_name = self.scenario_cfg.get('host',
+ self.scenario_cfg.get('target'))
+ self.server_name = self.options.get('server_name', default_name)
+ if self.server_name:
+ LOG.debug('Server name is %s', self.server_name)
+
+ self.nova_client = op_utils.get_nova_client()
+
+ def run(self, result):
+ """execute the test"""
+
+ if self.server_id:
+ server = self.nova_client.servers.get(self.server_id)
+ else:
+ server = op_utils.get_server_by_name(self.server_name)
+
+ keys = self.scenario_cfg.get('output', '').split()
+
+ if server:
+ LOG.info("Get server successful!")
+ values = [0, self._change_obj_to_dict(server)]
+ else:
+ LOG.info("Get server failed!")
+ values = [1]
+
+ return self._push_to_outputs(keys, values)
diff --git a/yardstick/benchmark/scenarios/lib/get_server_ip.py b/yardstick/benchmark/scenarios/lib/get_server_ip.py
new file mode 100644
index 000000000..1eeeb7fca
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/get_server_ip.py
@@ -0,0 +1,38 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+
+class GetServerIp(base.Scenario):
+ """Get a server by name"""
+
+ __scenario_type__ = "GetServerIp"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+ self.options = self.scenario_cfg.get('options', {})
+ self.ip_type = self.options.get('ip_type', "floating")
+
+ def run(self, result):
+ server = self.options.get('server', {})
+ ip = next(n['addr'] for k, v in server['addresses'].items()
+ for n in v if n['OS-EXT-IPS:type'] == self.ip_type)
+
+ keys = self.scenario_cfg.get('output', '').split()
+ values = [ip]
+ return self._push_to_outputs(keys, values)
diff --git a/yardstick/benchmark/scenarios/lib/migrate.py b/yardstick/benchmark/scenarios/lib/migrate.py
new file mode 100644
index 000000000..116bae69e
--- /dev/null
+++ b/yardstick/benchmark/scenarios/lib/migrate.py
@@ -0,0 +1,155 @@
+# ############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+import subprocess
+import threading
+import time
+
+from datetime import datetime
+import ping
+
+from yardstick.common import openstack_utils
+from yardstick.common.utils import change_obj_to_dict
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+TIMEOUT = 0.05
+PACKAGE_SIZE = 64
+
+
+class Migrate(base.Scenario): # pragma: no cover
+ """
+ Execute a live migration for two hosts
+
+ """
+
+ __scenario_type__ = "Migrate"
+
+ def __init__(self, scenario_cfg, context_cfg):
+ self.scenario_cfg = scenario_cfg
+ self.context_cfg = context_cfg
+ self.options = self.scenario_cfg.get('options', {})
+
+ self.nova_client = openstack_utils.get_nova_client()
+
+ def run(self, result):
+ default_instance_id = self.options.get('server', {}).get('id', '')
+ instance_id = self.options.get('server_id', default_instance_id)
+ LOG.info('Instance id is %s', instance_id)
+
+ target_host = self.options.get('host')
+ LOG.info('Target host is %s', target_host)
+
+ instance_ip = self.options.get('server_ip')
+ if instance_ip:
+ LOG.info('Instance ip is %s', instance_ip)
+
+ self._ping_until_connected(instance_ip)
+ LOG.info('Instance is connected')
+
+ LOG.debug('Start to ping instance')
+ ping_thread = self._do_ping_task(instance_ip)
+
+ keys = self.scenario_cfg.get('output', '').split()
+ try:
+ LOG.info('Start to migrate')
+ self._do_migrate(instance_id, target_host)
+ except Exception as e:
+ return self._push_to_outputs(keys, [1, str(e).split('.')[0]])
+ else:
+ migrate_time = self._get_migrate_time(instance_id)
+ LOG.info('Migration time is %s s', migrate_time)
+
+ current_host = self._get_current_host_name(instance_id)
+ LOG.info('Current host is %s', current_host)
+ if current_host.strip() != target_host.strip():
+ LOG.error('current_host not equal to target_host')
+ values = [1, 'current_host not equal to target_host']
+ return self._push_to_outputs(keys, values)
+
+ if instance_ip:
+ ping_thread.flag = False
+ ping_thread.join()
+
+ downtime = ping_thread.get_delay()
+ LOG.info('Downtime is %s s', downtime)
+
+ values = [0, migrate_time, downtime]
+ return self._push_to_outputs(keys, values)
+ else:
+ values = [0, migrate_time]
+ return self._push_to_outputs(keys, values)
+
+ def _do_migrate(self, server_id, target_host):
+
+ cmd = ['nova', 'live-migration', server_id, target_host]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ p.communicate()
+
+ def _ping_until_connected(self, instance_ip):
+ for i in range(3000):
+ res = ping.do_one(instance_ip, TIMEOUT, PACKAGE_SIZE)
+ if res:
+ break
+
+ def _do_ping_task(self, instance_ip):
+ ping_thread = PingThread(instance_ip)
+ ping_thread.start()
+ return ping_thread
+
+ def _get_current_host_name(self, server_id):
+
+ return change_obj_to_dict(self.nova_client.servers.get(server_id))['OS-EXT-SRV-ATTR:host']
+
+ def _get_migrate_time(self, server_id):
+ while True:
+ status = self.nova_client.servers.get(server_id).status.lower()
+ if status == 'migrating':
+ start_time = datetime.now()
+ break
+ LOG.debug('Instance status change to MIGRATING')
+
+ while True:
+ status = self.nova_client.servers.get(server_id).status.lower()
+ if status == 'active':
+ end_time = datetime.now()
+ break
+ if status == 'error':
+ LOG.error('Instance status is ERROR')
+ raise RuntimeError('The instance status is error')
+ LOG.debug('Instance status change to ACTIVE')
+
+ duration = end_time - start_time
+ return duration.seconds + duration.microseconds * 1.0 / 1e6
+
+
+class PingThread(threading.Thread): # pragma: no cover
+
+ def __init__(self, target):
+ super(PingThread, self).__init__()
+ self.target = target
+ self.flag = True
+ self.delay = 0.0
+
+ def run(self):
+ count = 0
+ while self.flag:
+ res = ping.do_one(self.target, TIMEOUT, PACKAGE_SIZE)
+ if not res:
+ count += 1
+ time.sleep(0.01)
+ self.delay = (TIMEOUT + 0.01) * count
+
+ def get_delay(self):
+ return self.delay
diff --git a/yardstick/benchmark/scenarios/networking/iperf3.py b/yardstick/benchmark/scenarios/networking/iperf3.py
index 334f3a920..a3d273750 100644
--- a/yardstick/benchmark/scenarios/networking/iperf3.py
+++ b/yardstick/benchmark/scenarios/networking/iperf3.py
@@ -19,6 +19,7 @@ import pkg_resources
from oslo_serialization import jsonutils
import yardstick.ssh as ssh
+from yardstick.common import utils
from yardstick.benchmark.scenarios import base
LOG = logging.getLogger(__name__)
@@ -49,6 +50,17 @@ For more info see http://software.es.net/iperf
type: int
unit: bytes
default: -
+ length - length of buffer to read or write,
+ (default 128 KB for TCP, 8 KB for UDP)
+ type: int
+ unit: k
+ default: -
+ window - set window size / socket buffer size
+ set TCP windows size. for UDP way to test, this will set to accept UDP
+ packet buffer size, limit the max size of acceptable data packet.
+ type: int
+ unit: k
+ default: -
"""
__scenario_type__ = "Iperf3"
@@ -121,6 +133,12 @@ For more info see http://software.es.net/iperf
elif "blockcount" in options:
cmd += " --blockcount %d" % options["blockcount"]
+ if "length" in options:
+ cmd += " --length %s" % options["length"]
+
+ if "window" in options:
+ cmd += " --window %s" % options["window"]
+
LOG.debug("Executing command: %s", cmd)
status, stdout, stderr = self.host.execute(cmd)
@@ -131,8 +149,8 @@ For more info see http://software.es.net/iperf
# Note: convert all ints to floats in order to avoid
# schema conflicts in influxdb. We probably should add
# a format func in the future.
- result.update(
- jsonutils.loads(stdout, parse_int=float))
+ iperf_result = jsonutils.loads(stdout, parse_int=float)
+ result.update(utils.flatten_dict_key(iperf_result))
if "sla" in self.scenario_cfg:
sla_iperf = self.scenario_cfg["sla"]
@@ -141,7 +159,7 @@ For more info see http://software.es.net/iperf
# convert bits per second to bytes per second
bit_per_second = \
- int(result["end"]["sum_received"]["bits_per_second"])
+ int(iperf_result["end"]["sum_received"]["bits_per_second"])
bytes_per_second = bit_per_second / 8
assert bytes_per_second >= sla_bytes_per_second, \
"bytes_per_second %d < sla:bytes_per_second (%d); " % \
@@ -149,7 +167,7 @@ For more info see http://software.es.net/iperf
else:
sla_jitter = float(sla_iperf["jitter"])
- jitter_ms = float(result["end"]["sum"]["jitter_ms"])
+ jitter_ms = float(iperf_result["end"]["sum"]["jitter_ms"])
assert jitter_ms <= sla_jitter, \
"jitter_ms %f > sla:jitter %f; " % \
(jitter_ms, sla_jitter)
diff --git a/yardstick/benchmark/scenarios/networking/ping.py b/yardstick/benchmark/scenarios/networking/ping.py
index a929e5337..6a7927de4 100644
--- a/yardstick/benchmark/scenarios/networking/ping.py
+++ b/yardstick/benchmark/scenarios/networking/ping.py
@@ -15,6 +15,7 @@ import pkg_resources
import logging
import yardstick.ssh as ssh
+from yardstick.common import utils
from yardstick.benchmark.scenarios import base
LOG = logging.getLogger(__name__)
@@ -57,8 +58,8 @@ class Ping(base.Scenario):
destination = self.context_cfg['target'].get('ipaddr', '127.0.0.1')
dest_list = [s.strip() for s in destination.split(',')]
- result["rtt"] = {}
- rtt_result = result["rtt"]
+ rtt_result = {}
+ ping_result = {"rtt": rtt_result}
for pos, dest in enumerate(dest_list):
if 'targets' in self.scenario_cfg:
@@ -88,6 +89,7 @@ class Ping(base.Scenario):
(rtt_result[target_vm_name], sla_max_rtt)
else:
LOG.error("ping '%s' '%s' timeout", options, target_vm)
+ result.update(utils.flatten_dict_key(ping_result))
def _test(): # pragma: no cover
diff --git a/yardstick/benchmark/scenarios/networking/pktgen.py b/yardstick/benchmark/scenarios/networking/pktgen.py
index e6aa7e5fb..8ca1ca60e 100644
--- a/yardstick/benchmark/scenarios/networking/pktgen.py
+++ b/yardstick/benchmark/scenarios/networking/pktgen.py
@@ -9,6 +9,7 @@
from __future__ import absolute_import
from __future__ import print_function
+import os
import logging
import pkg_resources
@@ -19,6 +20,9 @@ from yardstick.benchmark.scenarios import base
LOG = logging.getLogger(__name__)
+VNIC_TYPE_LIST = ["ovs", "sriov"]
+SRIOV_DRIVER_LIST = ["ixgbevf", "i40evf"]
+
class Pktgen(base.Scenario):
"""Execute pktgen between two hosts
@@ -44,7 +48,11 @@ class Pktgen(base.Scenario):
def __init__(self, scenario_cfg, context_cfg):
self.scenario_cfg = scenario_cfg
self.context_cfg = context_cfg
+ self.vnic_name = "eth0"
+ self.vnic_type = "ovs"
+ self.queue_number = 1
self.setup_done = False
+ self.multiqueue_setup_done = False
def setup(self):
"""scenario setup"""
@@ -67,6 +75,212 @@ class Pktgen(base.Scenario):
self.setup_done = True
+ def multiqueue_setup(self):
+ # one time setup stuff
+ cmd = "sudo sysctl -w net.core.netdev_budget=3000"
+ self.server.send_command(cmd)
+ self.client.send_command(cmd)
+
+ cmd = "sudo sysctl -w net.core.netdev_max_backlog=100000"
+ self.server.send_command(cmd)
+ self.client.send_command(cmd)
+
+ """multiqueue setup"""
+ if not self._is_irqbalance_disabled():
+ self._disable_irqbalance()
+
+ vnic_driver_name = self._get_vnic_driver_name()
+ if vnic_driver_name in SRIOV_DRIVER_LIST:
+ self.vnic_type = "sriov"
+
+ # one time setup stuff
+ cmd = "sudo ethtool -G %s rx 4096 tx 4096" % self.vnic_name
+ self.server.send_command(cmd)
+ self.client.send_command(cmd)
+
+ self.queue_number = self._get_sriov_queue_number()
+ self._setup_irqmapping_sriov(self.queue_number)
+ else:
+ self.vnic_type = "ovs"
+ self.queue_number = self._enable_ovs_multiqueue()
+ self._setup_irqmapping_ovs(self.queue_number)
+
+ self.multiqueue_setup_done = True
+
+ def _get_vnic_driver_name(self):
+ cmd = "readlink /sys/class/net/%s/device/driver" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return os.path.basename(stdout.strip())
+
+ def _is_irqbalance_disabled(self):
+ """Did we disable irqbalance already in the guest?"""
+ is_disabled = False
+ cmd = "grep ENABLED /etc/default/irqbalance"
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ if "0" in stdout:
+ is_disabled = True
+
+ return is_disabled
+
+ def _disable_irqbalance(self):
+ cmd = "sudo sed -i -e 's/ENABLED=\"1\"/ENABLED=\"0\"/g' " \
+ "/etc/default/irqbalance"
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "sudo service irqbalance stop"
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "sudo service irqbalance disable"
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ def _setup_irqmapping_ovs(self, queue_number):
+ cmd = "grep 'virtio0-input.0' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'"
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "grep 'virtio0-output.0' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'"
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ if queue_number == 1:
+ return
+
+ for i in range(1, queue_number):
+ cmd = "grep 'virtio0-input.%s' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % (i)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
+ % (1 << i, int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "grep 'virtio0-output.%s' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % (i)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
+ % (1 << i, int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ def _setup_irqmapping_sriov(self, queue_number):
+ cmd = "grep '%s-TxRx-0' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % self.vnic_name
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ if queue_number == 1:
+ return
+
+ for i in range(1, queue_number):
+ cmd = "grep '%s-TxRx-%s' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % (self.vnic_name, i)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
+ % (1 << i, int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ def _get_sriov_queue_number(self):
+ """Get queue number from server as both VMs are the same"""
+ cmd = "grep %s-TxRx- /proc/interrupts | wc -l" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return int(stdout)
+
+ def _get_available_queue_number(self):
+ """Get queue number from client as both VMs are the same"""
+ cmd = "sudo ethtool -l %s | grep Combined | head -1 |" \
+ "awk '{printf $2}'" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return int(stdout)
+
+ def _get_usable_queue_number(self):
+ """Get queue number from client as both VMs are the same"""
+ cmd = "sudo ethtool -l %s | grep Combined | tail -1 |" \
+ "awk '{printf $2}'" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return int(stdout)
+
+ def _enable_ovs_multiqueue(self):
+ available_queue_number = self._get_available_queue_number()
+ usable_queue_number = self._get_usable_queue_number()
+ if available_queue_number > 1 and \
+ available_queue_number != usable_queue_number:
+ cmd = "sudo ethtool -L %s combined %s" % \
+ (self.vnic_name, available_queue_number)
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return available_queue_number
+
def _iptables_setup(self):
"""Setup iptables on server to monitor for received packets"""
cmd = "sudo iptables -F; " \
@@ -99,6 +313,14 @@ class Pktgen(base.Scenario):
options = self.scenario_cfg['options']
packetsize = options.get("packetsize", 60)
self.number_of_ports = options.get("number_of_ports", 10)
+ self.vnic_name = options.get("vnic_name", "eth0")
+ ovs_dpdk = options.get("ovs_dpdk", False)
+ pps = options.get("pps", 1000000)
+ multiqueue = options.get("multiqueue", False)
+
+ if multiqueue and not self.multiqueue_setup_done:
+ self.multiqueue_setup()
+
# if run by a duration runner
duration_time = self.scenario_cfg["runner"].get("duration", None) \
if "runner" in self.scenario_cfg else None
@@ -114,8 +336,18 @@ class Pktgen(base.Scenario):
self._iptables_setup()
- cmd = "sudo bash pktgen.sh %s %s %s %s" \
- % (ipaddr, self.number_of_ports, packetsize, duration)
+ queue_number = self.queue_number
+
+ # For native OVS, half of vCPUs are used by vhost kernel threads
+ # hence set the queue_number to half number of vCPUs
+ # e.g. set queue_number to 2 if there are 4 vCPUs
+ if self.vnic_type == "ovs" and not ovs_dpdk and self.queue_number > 1:
+ queue_number = self.queue_number / 2
+
+ cmd = "sudo bash pktgen.sh %s %s %s %s %s %s" \
+ % (ipaddr, self.number_of_ports, packetsize,
+ duration, queue_number, pps)
+
LOG.debug("Executing command: %s", cmd)
status, stdout, stderr = self.client.execute(cmd)
@@ -131,12 +363,15 @@ class Pktgen(base.Scenario):
sent = result['packets_sent']
received = result['packets_received']
ppm = 1000000 * (sent - received) / sent
+ # if ppm is 1, then 11 out of 10 million is no pass
+ ppm += (sent - received) % sent > 0
+ LOG.debug("Lost packets %d - Lost ppm %d", (sent - received), ppm)
sla_max_ppm = int(self.scenario_cfg["sla"]["max_ppm"])
assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " \
% (ppm, sla_max_ppm)
-def _test():
+def _test(): # pragma: no cover
"""internal test function"""
key_filename = pkg_resources.resource_filename('yardstick.resources',
'files/yardstick_key')
@@ -165,6 +400,5 @@ def _test():
p.run(result)
print(result)
-
if __name__ == '__main__':
_test()
diff --git a/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash b/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
index 4224c5abf..e338a1b09 100644
--- a/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
+++ b/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
@@ -16,6 +16,8 @@ DST_IP=$1 # destination IP address
NUM_PORTS=$2 # number of source ports
PKT_SIZE=$3 # packet size
DURATION=$4 # test duration (seconds)
+TRXQUEUE=$5 # number of RX/TX queues to use
+PPS=$6 # packets per second to send
# Configuration
UDP_SRC_MIN=1000 # UDP source port min
@@ -37,62 +39,100 @@ pgset()
fi
}
+# remove all devices from thread
+pgclean()
+{
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ #
+ # Thread commands
+ #
+
+ PGDEV=/proc/net/pktgen/kpktgend_${COUNTER}
+
+ # Remove all devices from this thread
+ pgset "rem_device_all"
+ let COUNTER=COUNTER+1
+ done
+}
+
# configure pktgen (see pktgen doc for details)
pgconfig()
{
- #
- # Thread commands
- #
+ pps=$(( PPS / TRXQUEUE ))
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ #
+ # Thread commands
+ #
- PGDEV=/proc/net/pktgen/kpktgend_0
+ PGDEV=/proc/net/pktgen/kpktgend_${COUNTER}
- # Remove all devices from this thread
- pgset "rem_device_all"
+ # Add device to thread
+ pgset "add_device $DEV@${COUNTER}"
- # Add device to thread
- pgset "add_device $DEV"
+ #
+ # Device commands
+ #
- #
- # Device commands
- #
+ PGDEV=/proc/net/pktgen/$DEV@${COUNTER}
- PGDEV=/proc/net/pktgen/$DEV
+ # 0 means continious sends untill explicitly stopped
+ pgset "count 0"
- # 0 means continious sends untill explicitly stopped
- pgset "count 0"
+ # set pps count to test with an explicit number. if 0 will try with bandwidth
+ if [ ${pps} -gt 0 ]
+ then
+ pgset "ratep ${pps}"
+ fi
- # use single SKB for all transmits
- pgset "clone_skb 0"
+ pgset "clone_skb 10"
- # packet size, NIC adds 4 bytes CRC
- pgset "pkt_size $PKT_SIZE"
+ # use different queue per thread
+ pgset "queue_map_min ${COUNTER}"
+ pgset "queue_map_max ${COUNTER}"
- # random address within the min-max range
- pgset "flag IPDST_RND UDPSRC_RND UDPDST_RND"
+ # packet size, NIC adds 4 bytes CRC
+ pgset "pkt_size $PKT_SIZE"
- # destination IP
- pgset "dst_min $DST_IP"
- pgset "dst_max $DST_IP"
+ # random address within the min-max range
+ pgset "flag UDPDST_RND"
+ pgset "flag UDPSRC_RND"
+ pgset "flag IPDST_RND"
- # destination MAC address
- pgset "dst_mac $MAC"
+ # destination IP
+ pgset "dst_min $DST_IP"
+ pgset "dst_max $DST_IP"
+
+ # destination MAC address
+ pgset "dst_mac $MAC"
+
+ # source UDP port range
+ pgset "udp_src_min $UDP_SRC_MIN"
+ pgset "udp_src_max $UDP_SRC_MAX"
- # source UDP port range
- pgset "udp_src_min $UDP_SRC_MIN"
- pgset "udp_src_max $UDP_SRC_MAX"
+ # destination UDP port range
+ pgset "udp_dst_min $UDP_DST_MIN"
+ pgset "udp_dst_max $UDP_DST_MAX"
- # destination UDP port range
- pgset "udp_dst_min $UDP_DST_MIN"
- pgset "udp_dst_max $UDP_DST_MAX"
+ let COUNTER=COUNTER+1
+
+ done
}
# run pktgen
pgrun()
{
- # Time to run, result can be vieved in /proc/net/pktgen/$DEV
+ # Time to run, result can be viewed in /proc/net/pktgen/$DEV
PGDEV=/proc/net/pktgen/pgctrl
# Will hang, Ctrl-C or SIGINT to stop
pgset "start" start
+
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ taskset -c ${COUNTER} kpktgend_${COUNTER}
+ let COUNTER=COUNTER+1
+ done
}
# run pktgen for ${DURATION} seconds
@@ -111,19 +151,28 @@ run_test()
# write the result to stdout in json format
output_json()
{
- sent=$(awk '/^Result:/{print $5}' <$PGDEV)
- pps=$(awk 'match($0,/'\([0-9]+\)pps'/, a) {print a[1]}' <$PGDEV)
- errors=$(awk '/errors:/{print $5}' <$PGDEV)
+ sent=0
+ result_pps=0
+ errors=0
+ PGDEV=/proc/net/pktgen/$DEV@
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ sent=$(($sent + $(awk '/^Result:/{print $5}' <$PGDEV${COUNTER})))
+ result_pps=$(($result_pps + $(awk 'match($0,/'\([0-9]+\)pps'/, a) {print a[1]}' <$PGDEV${COUNTER})))
+ errors=$(($errors + $(awk '/errors:/{print $5}' <$PGDEV${COUNTER})))
+ let COUNTER=COUNTER+1
+ done
flows=$(( NUM_PORTS * (NUM_PORTS + 1) ))
- echo { '"packets_sent"':$sent , '"packets_per_second"':$pps, '"flows"':$flows, '"errors"':$errors }
+ echo '{ "packets_sent"':${sent} , '"packets_per_second"':${result_pps}, '"flows"':${flows}, '"errors"':${errors} '}'
}
# main entry
main()
{
modprobe pktgen
+ pgclean
ping -c 3 $DST_IP >/dev/null
@@ -137,16 +186,20 @@ main()
pgconfig
# run the test
- run_test >/dev/null
+ run_test
- PGDEV=/proc/net/pktgen/$DEV
+ PGDEV=/proc/net/pktgen/$DEV@
# check result
- result=$(cat $PGDEV | fgrep "Result: OK:")
- if [ "$result" = "" ]; then
- cat $PGDEV | fgrep Result: >/dev/stderr
- exit 1
- fi
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ result=$(cat $PGDEV${COUNTER} | fgrep "Result: OK:")
+ if [ "$result" = "" ]; then
+ cat $PGDEV${COUNTER} | fgrep Result: >/dev/stderr
+ exit 1
+ fi
+ let COUNTER=COUNTER+1
+ done
# output result
output_json
diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py
index 594edeaa8..9607e3005 100644
--- a/yardstick/benchmark/scenarios/networking/vnf_generic.py
+++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py
@@ -164,38 +164,60 @@ class NetworkServiceTestCase(base.Scenario):
for vnfd in topology["constituent-vnfd"]
if vnf_id == vnfd["member-vnf-index"]), None)
+ @staticmethod
+ def get_vld_networks(networks):
+ return {n['vld_id']: n for n in networks.values()}
+
def _resolve_topology(self, context_cfg, topology):
for vld in topology["vld"]:
- if len(vld["vnfd-connection-point-ref"]) > 2:
+ try:
+ node_0, node_1 = vld["vnfd-connection-point-ref"]
+ except (TypeError, ValueError):
raise IncorrectConfig("Topology file corrupted, "
- "too many endpoint for connection")
-
- node_0, node_1 = vld["vnfd-connection-point-ref"]
+ "wrong number of endpoints for connection")
- node0 = self._find_vnf_name_from_id(topology,
- node_0["member-vnf-index-ref"])
- node1 = self._find_vnf_name_from_id(topology,
- node_1["member-vnf-index-ref"])
+ node_0_name = self._find_vnf_name_from_id(topology,
+ node_0["member-vnf-index-ref"])
+ node_1_name = self._find_vnf_name_from_id(topology,
+ node_1["member-vnf-index-ref"])
- if0 = node_0["vnfd-connection-point-ref"]
- if1 = node_1["vnfd-connection-point-ref"]
+ node_0_ifname = node_0["vnfd-connection-point-ref"]
+ node_1_ifname = node_1["vnfd-connection-point-ref"]
+ node_0_if = context_cfg["nodes"][node_0_name]["interfaces"][node_0_ifname]
+ node_1_if = context_cfg["nodes"][node_1_name]["interfaces"][node_1_ifname]
try:
- nodes = context_cfg["nodes"]
- nodes[node0]["interfaces"][if0]["vld_id"] = vld["id"]
- nodes[node1]["interfaces"][if1]["vld_id"] = vld["id"]
-
- nodes[node0]["interfaces"][if0]["dst_mac"] = \
- nodes[node1]["interfaces"][if1]["local_mac"]
- nodes[node0]["interfaces"][if0]["dst_ip"] = \
- nodes[node1]["interfaces"][if1]["local_ip"]
-
- nodes[node1]["interfaces"][if1]["dst_mac"] = \
- nodes[node0]["interfaces"][if0]["local_mac"]
- nodes[node1]["interfaces"][if1]["dst_ip"] = \
- nodes[node0]["interfaces"][if0]["local_ip"]
+ vld_networks = self.get_vld_networks(context_cfg["networks"])
+
+ node_0_if["vld_id"] = vld["id"]
+ node_1_if["vld_id"] = vld["id"]
+
+ # set peer name
+ node_0_if["peer_name"] = node_1_name
+ node_1_if["peer_name"] = node_0_name
+
+ # set peer interface name
+ node_0_if["peer_ifname"] = node_1_ifname
+ node_1_if["peer_ifname"] = node_0_ifname
+
+ # just load the whole network dict
+ node_0_if["network"] = vld_networks.get(vld["id"], {})
+ node_1_if["network"] = vld_networks.get(vld["id"], {})
+
+ node_0_if["dst_mac"] = node_1_if["local_mac"]
+ node_0_if["dst_ip"] = node_1_if["local_ip"]
+
+ node_1_if["dst_mac"] = node_0_if["local_mac"]
+ node_1_if["dst_ip"] = node_0_if["local_ip"]
+
+ # add peer interface dict, but remove circular link
+ # TODO: don't waste memory
+ node_0_copy = node_0_if.copy()
+ node_1_copy = node_1_if.copy()
+ node_0_if["peer_intf"] = node_1_copy
+ node_1_if["peer_intf"] = node_0_copy
except KeyError:
- raise IncorrectConfig("Required interface not found,"
+ raise IncorrectConfig("Required interface not found, "
"topology file corrupted")
@classmethod
@@ -308,21 +330,36 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
return dict(network_devices)
@classmethod
- def get_vnf_impl(cls, vnf_model):
+ def get_vnf_impl(cls, vnf_model_id):
""" Find the implementing class from vnf_model["vnf"]["name"] field
- :param vnf_model: dictionary containing a parsed vnfd
+ :param vnf_model_id: parsed vnfd model ID field
:return: subclass of GenericVNF
"""
import_modules_from_package(
"yardstick.network_services.vnf_generic.vnf")
- expected_name = vnf_model['id']
- impl = (c for c in itersubclasses(GenericVNF)
- if c.__name__ == expected_name)
+ expected_name = vnf_model_id
+ classes_found = []
+
+ def impl():
+ for name, class_ in ((c.__name__, c) for c in itersubclasses(GenericVNF)):
+ if name == expected_name:
+ yield class_
+ classes_found.append(name)
+
try:
- return next(impl)
+ return next(impl())
except StopIteration:
- raise IncorrectConfig("No implementation for %s", expected_name)
+ pass
+
+ raise IncorrectConfig("No implementation for %s found in %s" %
+ (expected_name, classes_found))
+
+ @staticmethod
+ def update_interfaces_from_node(vnfd, node):
+ for intf in vnfd["vdu"][0]["external-interface"]:
+ node_intf = node['interfaces'][intf['name']]
+ intf['virtual-interface'].update(node_intf)
def load_vnf_models(self, scenario_cfg, context_cfg):
""" Create VNF objects based on YAML descriptors
@@ -339,8 +376,11 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
scenario_cfg['task_path']) as stream:
vnf_model = stream.read()
vnfd = vnfdgen.generate_vnfd(vnf_model, node)
- vnf_impl = self.get_vnf_impl(vnfd["vnfd:vnfd-catalog"]["vnfd"][0])
- vnf_instance = vnf_impl(vnfd["vnfd:vnfd-catalog"]["vnfd"][0])
+ # TODO: here add extra context_cfg["nodes"] regardless of template
+ vnfd = vnfd["vnfd:vnfd-catalog"]["vnfd"][0]
+ self.update_interfaces_from_node(vnfd, node)
+ vnf_impl = self.get_vnf_impl(vnfd['id'])
+ vnf_instance = vnf_impl(vnfd)
vnf_instance.name = node_name
vnfs.append(vnf_instance)
diff --git a/yardstick/benchmark/scenarios/storage/fio.py b/yardstick/benchmark/scenarios/storage/fio.py
index ad34817a7..b99e34270 100644
--- a/yardstick/benchmark/scenarios/storage/fio.py
+++ b/yardstick/benchmark/scenarios/storage/fio.py
@@ -40,10 +40,26 @@ class Fio(base.Scenario):
type: string
unit: na
default: write
+ rwmixwrite - percentage of a mixed workload that should be writes
+ type: int
+ unit: percentage
+ default: 50
ramp_time - run time before logging any performance
type: int
unit: seconds
default: 20
+ direct - whether use non-buffered I/O or not
+ type: boolean
+ unit: na
+ default: 1
+ size - total size of I/O for this job.
+ type: string
+ unit: na
+ default: 1g
+ numjobs - number of clones (processes/threads performing the same workload) of this job
+ type: int
+ unit: na
+ default: 1
Read link below for more fio args description:
http://www.bluestop.org/fio/HOWTO.txt
@@ -74,8 +90,8 @@ class Fio(base.Scenario):
def run(self, result):
"""execute the benchmark"""
- default_args = "-ioengine=libaio -direct=1 -group_reporting " \
- "-numjobs=1 -time_based --output-format=json"
+ default_args = "-ioengine=libaio -group_reporting -time_based -time_based " \
+ "--output-format=json"
if not self.setup_done:
self.setup()
@@ -86,6 +102,10 @@ class Fio(base.Scenario):
iodepth = options.get("iodepth", "1")
rw = options.get("rw", "write")
ramp_time = options.get("ramp_time", 20)
+ size = options.get("size", "1g")
+ direct = options.get("direct", "1")
+ numjobs = options.get("numjobs", "1")
+ rwmixwrite = options.get("rwmixwrite", 50)
name = "yardstick-fio"
# if run by a duration runner
duration_time = self.scenario_cfg["runner"].get("duration", None) \
@@ -99,10 +119,10 @@ class Fio(base.Scenario):
else:
runtime = 30
- cmd_args = "-filename=%s -bs=%s -iodepth=%s -rw=%s -ramp_time=%s " \
- "-runtime=%s -name=%s %s" \
- % (filename, bs, iodepth, rw, ramp_time, runtime, name,
- default_args)
+ cmd_args = "-filename=%s -direct=%s -bs=%s -iodepth=%s -rw=%s -rwmixwrite=%s " \
+ "-size=%s -ramp_time=%s -numjobs=%s -runtime=%s -name=%s %s" \
+ % (filename, direct, bs, iodepth, rw, rwmixwrite, size, ramp_time, numjobs,
+ runtime, name, default_args)
cmd = "sudo bash fio.sh %s %s" % (filename, cmd_args)
LOG.debug("Executing command: %s", cmd)
# Set timeout, so that the cmd execution does not exit incorrectly
diff --git a/yardstick/benchmark/scenarios/storage/storperf.py b/yardstick/benchmark/scenarios/storage/storperf.py
index c10118ad1..f0b2361d6 100644
--- a/yardstick/benchmark/scenarios/storage/storperf.py
+++ b/yardstick/benchmark/scenarios/storage/storperf.py
@@ -87,8 +87,9 @@ class StorPerf(base.Scenario):
def setup(self):
"""Set the configuration."""
env_args = {}
- env_args_payload_list = ["agent_count", "public_network",
- "agent_image", "volume_size"]
+ env_args_payload_list = ["agent_count", "agent_flavor",
+ "public_network", "agent_image",
+ "volume_size"]
for env_argument in env_args_payload_list:
try:
@@ -206,7 +207,7 @@ class StorPerf(base.Scenario):
# terminate_res = requests.delete('http://%s:5000/api/v1.0
# /jobs' % self.target)
# else:
- # time.sleep(int(est_time)/2)
+ # time.sleep(int(esti_time)/2)
result_res = requests.get('http://%s:5000/api/v1.0/jobs?id=%s' %
(self.target, job_id))