diff options
Diffstat (limited to 'yardstick/benchmark/scenarios')
70 files changed, 1945 insertions, 1184 deletions
diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py index 979e3ab14..4c79a4931 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py @@ -23,7 +23,7 @@ def _execute_shell_command(command, stdin=None): output = [] try: output = subprocess.check_output(command, stdin=stdin, shell=True) - except Exception: + except Exception: # pylint: disable=broad-except exitcode = -1 LOG.error("exec command '%s' error:\n ", command, exc_info=True) @@ -34,6 +34,8 @@ class BaremetalAttacker(BaseAttacker): __attacker_type__ = 'bare-metal-down' def setup(self): + # baremetal down need to recover even sla pass + self.mandatory = True LOG.debug("config:%s context:%s", self._config, self._context) host = self._context.get(self._config['host'], None) @@ -49,8 +51,7 @@ class BaremetalAttacker(BaseAttacker): LOG.debug("jump_host ip:%s user:%s", jump_host['ip'], jump_host['user']) self.jump_connection = ssh.SSH.from_node( jump_host, - # why do we allow pwd for password? - defaults={"user": "root", "password": jump_host.get("pwd")} + defaults={"user": "root", "password": jump_host.get("password")} ) self.jump_connection.wait(timeout=600) LOG.debug("ssh jump host success!") @@ -59,7 +60,7 @@ class BaremetalAttacker(BaseAttacker): self.ipmi_ip = host.get("ipmi_ip", None) self.ipmi_user = host.get("ipmi_user", "root") - self.ipmi_pwd = host.get("ipmi_pwd", None) + self.ipmi_pwd = host.get("ipmi_password", None) self.fault_cfg = BaseAttacker.attacker_cfgs.get('bare-metal-down') self.check_script = self.get_script_fullpath( @@ -107,26 +108,3 @@ class BaremetalAttacker(BaseAttacker): else: _execute_shell_command(cmd, stdin=stdin_file) LOG.info("Recover fault END") - - -def _test(): # pragma: no cover - host = { - "ipmi_ip": "10.20.0.5", - "ipmi_user": "root", - "ipmi_pwd": "123456", - "ip": "10.20.0.5", - "user": "root", - "key_filename": "/root/.ssh/id_rsa" - } - context = {"node1": host} - attacker_cfg = { - 'fault_type': 'bear-metal-down', - 'host': 'node1', - } - ins = BaremetalAttacker(attacker_cfg, context) - ins.setup() - ins.inject_fault() - - -if __name__ == '__main__': # pragma: no cover - _test() diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py index cb171eafa..7f1136c08 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py @@ -42,29 +42,28 @@ class ProcessAttacker(BaseAttacker): def check(self): with open(self.check_script, "r") as stdin_file: - exit_status, stdout, stderr = self.connection.execute( + _, stdout, stderr = self.connection.execute( "sudo /bin/sh -s {0}".format(self.service_name), stdin=stdin_file) if stdout: - LOG.info("check the environment success!") + LOG.info("Check the environment success!") return int(stdout.strip('\n')) else: - LOG.error( - "the host environment is error, stdout:%s, stderr:%s", - stdout, stderr) + LOG.error("Error checking the host environment, " + "stdout:%s, stderr:%s", stdout, stderr) return False def inject_fault(self): with open(self.inject_script, "r") as stdin_file: - exit_status, stdout, stderr = self.connection.execute( + self.connection.execute( "sudo /bin/sh -s {0}".format(self.service_name), stdin=stdin_file) def recover(self): with open(self.recovery_script, "r") as stdin_file: - exit_status, stdout, stderr = self.connection.execute( + exit_status, _, _ = self.connection.execute( "sudo /bin/bash -s {0} ".format(self.service_name), stdin=stdin_file) if exit_status: - LOG.info("Fail to restart service!") + LOG.info("Failed to restart service: %s", self.recovery_script) diff --git a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py index d03d04420..7871cc918 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py +++ b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py @@ -63,6 +63,7 @@ class BaseAttacker(object): self.data = {} self.setup_done = False self.intermediate_variables = {} + self.mandatory = False @staticmethod def get_attacker_cls(attacker_cfg): @@ -71,7 +72,7 @@ class BaseAttacker(object): for attacker_cls in utils.itersubclasses(BaseAttacker): if attacker_type == attacker_cls.__attacker_type__: return attacker_cls - raise RuntimeError("No such runner_type %s" % attacker_type) + raise RuntimeError("No such runner_type: %s" % attacker_type) def get_script_fullpath(self, path): base_path = os.path.dirname(attacker_conf_path) diff --git a/yardstick/benchmark/scenarios/availability/director.py b/yardstick/benchmark/scenarios/availability/director.py index 71690c135..6cc0cb286 100644 --- a/yardstick/benchmark/scenarios/availability/director.py +++ b/yardstick/benchmark/scenarios/availability/director.py @@ -40,7 +40,7 @@ class Director(object): nodes = self.context_cfg.get("nodes", None) # setup attackers if "attackers" in self.scenario_cfg["options"]: - LOG.debug("start init attackers...") + LOG.debug("Start init attackers...") attacker_cfgs = self.scenario_cfg["options"]["attackers"] self.attackerMgr = baseattacker.AttackerMgr() self.data = self.attackerMgr.init_attackers(attacker_cfgs, @@ -48,19 +48,19 @@ class Director(object): # setup monitors if "monitors" in self.scenario_cfg["options"]: - LOG.debug("start init monitors...") + LOG.debug("Start init monitors...") monitor_cfgs = self.scenario_cfg["options"]["monitors"] self.monitorMgr = basemonitor.MonitorMgr(self.data) self.monitorMgr.init_monitors(monitor_cfgs, nodes) # setup operations if "operations" in self.scenario_cfg["options"]: - LOG.debug("start init operations...") + LOG.debug("Start init operations...") operation_cfgs = self.scenario_cfg["options"]["operations"] self.operationMgr = baseoperation.OperationMgr() self.operationMgr.init_operations(operation_cfgs, nodes) # setup result checker if "resultCheckers" in self.scenario_cfg["options"]: - LOG.debug("start init resultCheckers...") + LOG.debug("Start init resultCheckers...") result_check_cfgs = self.scenario_cfg["options"]["resultCheckers"] self.resultCheckerMgr = baseresultchecker.ResultCheckerMgr() self.resultCheckerMgr.init_ResultChecker(result_check_cfgs, nodes) @@ -69,7 +69,7 @@ class Director(object): if intermediate_variables is None: intermediate_variables = {} LOG.debug( - "the type of current action is %s, the key is %s", type, key) + "The type of current action is %s, the key is %s", type, key) if type == ActionType.ATTACKER: return actionplayers.AttackerPlayer(self.attackerMgr[key], intermediate_variables) if type == ActionType.MONITOR: @@ -80,17 +80,17 @@ class Director(object): if type == ActionType.OPERATION: return actionplayers.OperationPlayer(self.operationMgr[key], intermediate_variables) - LOG.debug("something run when creatactionplayer") + LOG.debug("The type is not recognized by createActionPlayer") def createActionRollbacker(self, type, key): LOG.debug( - "the type of current action is %s, the key is %s", type, key) + "The type of current action is %s, the key is %s", type, key) if type == ActionType.ATTACKER: return actionrollbackers.AttackerRollbacker(self.attackerMgr[key]) if type == ActionType.OPERATION: return actionrollbackers.OperationRollbacker( self.operationMgr[key]) - LOG.debug("no rollbacker created for %s", key) + LOG.debug("No rollbacker created for key: %s", key) def verify(self): result = True @@ -99,7 +99,7 @@ class Director(object): if hasattr(self, 'resultCheckerMgr'): result &= self.resultCheckerMgr.verify() if result: - LOG.debug("monitors are passed") + LOG.debug("Monitor results are passed") return result def stopMonitors(self): @@ -107,12 +107,12 @@ class Director(object): self.monitorMgr.wait_monitors() def knockoff(self): - LOG.debug("knock off ....") + LOG.debug("Knock off ....") while self.executionSteps: singleStep = self.executionSteps.pop() singleStep.rollback() def store_result(self, result): - LOG.debug("store result ....") + LOG.debug("Store result ....") if hasattr(self, 'monitorMgr'): self.monitorMgr.store_result(result) diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash b/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash index d34ce9338..cda469cf9 100755 --- a/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash +++ b/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash @@ -16,7 +16,7 @@ set -e process_name=$1 if [ "$process_name" = "keystone" ]; then - for pid in $(ps aux | grep "keystone" | grep -iv heartbeat | grep -iv monitor | grep -v grep | grep -v /bin/sh | awk '{print $2}'); \ + for pid in $(ps aux | grep "keystone" | grep -iv monitor | grep -v grep | grep -v /bin/sh | awk '{print $2}'); \ do kill -9 "${pid}" done @@ -26,7 +26,7 @@ elif [ "$process_name" = "haproxy" ]; then kill -9 "${pid}" done else - for pid in $(pgrep -fa [^-_a-zA-Z0-9]${process_name} | grep -iv heartbeat | awk '{print $1}'); + for pid in $(pgrep -fa [^-_a-zA-Z0-9]${process_name} | awk '{print $1}'); do kill -9 "${pid}" done diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/add_server_to_existing_secgroup.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/add_server_to_existing_secgroup.bash new file mode 100644 index 000000000..3a50626f5 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/add_server_to_existing_secgroup.bash @@ -0,0 +1,26 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2018 Intracom Telecom 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 +############################################################################## + +# add server to existing security group +# parameters: $1 - server name, $2 - security group name + +set -e + +if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then + SECURE="--insecure" +else + SECURE="" +fi + +SECGROUPNAME="$(openstack ${SECURE} security group list -f value -c Name | grep $2)" + +openstack ${SECURE} server add security group $1 ${SECGROUPNAME} + diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_instance_from_image.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_instance_from_image.bash new file mode 100644 index 000000000..5e0b1ccf1 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_instance_from_image.bash @@ -0,0 +1,26 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2018 Intracom Telecom 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 +############################################################################## + +# create nova server +# parameters: $1 - server name, $2 - image name, $3 - flavor name, $4 - network name + +set -e + +if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then + SECURE="--insecure" +else + SECURE="" +fi + +NETNAME="$(openstack ${SECURE} network list -f value -c Name | grep $4)" + +openstack ${SECURE} server create $1 --image $2 --flavor $3 --network ${NETNAME} + diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_instance.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_instance.bash new file mode 100644 index 000000000..008e7f5ff --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_instance.bash @@ -0,0 +1,24 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2018 Intracom Telecom 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 +############################################################################## + +# delete nova server +# parameters: $1 - server name + +set -e + +if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then + SECURE="--insecure" +else + SECURE="" +fi + +openstack ${SECURE} server delete $1 + diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/get_server_privateip.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/get_server_privateip.bash new file mode 100644 index 000000000..7f2bad540 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/get_server_privateip.bash @@ -0,0 +1,24 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2018 Intracom Telecom 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 +############################################################################## + +# get private ip of a server +# parameter: $1 - server name + +set -e + +if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then + SECURE="--insecure" +else + SECURE="" +fi + +openstack ${SECURE} server list -f value -c Name -c Networks | grep $1 | awk '{print $2}' | sed -r 's/.*=([0-9\.\:]+)[;,]*/\1/' + diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/remove_server_from_secgroup.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/remove_server_from_secgroup.bash new file mode 100644 index 000000000..61d0a2b49 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/remove_server_from_secgroup.bash @@ -0,0 +1,25 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2018 Intracom Telecom 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 +############################################################################## + +# remove server from existing security group +# parameters: $1 - server name, $2 - security group name + +set -e + +if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then + SECURE="--insecure" +else + SECURE="" +fi + +SECGROUPNAME="$(openstack ${SECURE} security group list -f value -c Name | grep $2)" + +openstack ${SECURE} server remove security group $1 ${SECGROUPNAME} diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/start_service.bash b/yardstick/benchmark/scenarios/availability/ha_tools/start_service.bash index 858d86ca0..2388507d7 100755 --- a/yardstick/benchmark/scenarios/availability/ha_tools/start_service.bash +++ b/yardstick/benchmark/scenarios/availability/ha_tools/start_service.bash @@ -9,24 +9,23 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -# Start a service and check the service is started +# Start or restart a service and check the service is started set -e service_name=$1 +operation=${2-start} # values are "start" or "restart" -Distributor=$(lsb_release -a | grep "Distributor ID" | awk '{print $3}') - -if [ "$Distributor" != "Ubuntu" -a "$service_name" != "keystone" -a "$service_name" != "neutron-server" -a "$service_name" != "haproxy" ]; then +if [ -f /usr/bin/yum -a "$service_name" != "keystone" -a "$service_name" != "neutron-server" -a "$service_name" != "haproxy" -a "$service_name" != "openvswitch" ]; then service_name="openstack-"${service_name} -elif [ "$Distributor" = "Ubuntu" -a "$service_name" = "keystone" ]; then +elif [ -f /usr/bin/apt -a "$service_name" = "keystone" ]; then service_name="apache2" elif [ "$service_name" = "keystone" ]; then service_name="httpd" fi if which systemctl 2>/dev/null; then - systemctl start $service_name + systemctl $operation $service_name else - service $service_name start + service $service_name $operation fi diff --git a/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py b/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py index 50a63f53d..f6004c774 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py +++ b/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py @@ -103,7 +103,7 @@ class BaseMonitor(multiprocessing.Process): for monitor in utils.itersubclasses(BaseMonitor): if monitor_type == monitor.__monitor_type__: return monitor - raise RuntimeError("No such monitor_type %s" % monitor_type) + raise RuntimeError("No such monitor_type: %s" % monitor_type) def get_script_fullpath(self, path): base_path = os.path.dirname(monitor_conf_path) diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py index d0551bf03..3b36c762d 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py @@ -24,7 +24,7 @@ def _execute_shell_command(command): output = [] try: output = subprocess.check_output(command, shell=True) - except Exception: + except Exception: # pylint: disable=broad-except exitcode = -1 LOG.error("exec command '%s' error:\n ", command, exc_info=True) @@ -45,7 +45,7 @@ class MonitorOpenstackCmd(basemonitor.BaseMonitor): self.connection = ssh.SSH.from_node(host, defaults={"user": "root"}) self.connection.wait(timeout=600) - LOG.debug("ssh host success!") + LOG.debug("ssh host (%s) success!", str(host)) self.check_script = self.get_script_fullpath( "ha_tools/check_openstack_cmd.bash") @@ -61,22 +61,20 @@ class MonitorOpenstackCmd(basemonitor.BaseMonitor): self.cmd = self.cmd + " --insecure" def monitor_func(self): - exit_status = 0 exit_status, stdout = _execute_shell_command(self.cmd) - LOG.debug("Execute command '%s' and the stdout is:\n%s", self.cmd, stdout) + LOG.debug("Executed command '%s'. " + "The stdout is:\n%s", self.cmd, stdout) if exit_status: return False return True def verify_SLA(self): outage_time = self._result.get('outage_time', None) - LOG.debug("the _result:%s", self._result) max_outage_time = self._config["sla"]["max_outage_time"] if outage_time > max_outage_time: LOG.info("SLA failure: %f > %f", outage_time, max_outage_time) return False else: - LOG.info("the sla is passed") return True @@ -97,7 +95,7 @@ def _test(): # pragma: no cover } monitor_configs.append(config) - p = basemonitor.MonitorMgr() + p = basemonitor.MonitorMgr({}) p.init_monitors(monitor_configs, context) p.start_monitors() p.wait_monitors() diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py index dce69f45f..8f1f53cde 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py @@ -29,7 +29,7 @@ class MultiMonitor(basemonitor.BaseMonitor): monitor_cls = basemonitor.BaseMonitor.get_monitor_cls(monitor_type) monitor_number = self._config.get("monitor_number", 1) - for i in range(monitor_number): + for _ in range(monitor_number): monitor_ins = monitor_cls(self._config, self._context, self.monitor_data) self.monitors.append(monitor_ins) @@ -62,19 +62,19 @@ class MultiMonitor(basemonitor.BaseMonitor): outage_time = ( last_outage - first_outage if last_outage > first_outage else 0 ) + self._result = {"outage_time": outage_time} LOG.debug("outage_time is: %f", outage_time) max_outage_time = 0 - if "max_outage_time" in self._config["sla"]: - max_outage_time = self._config["sla"]["max_outage_time"] - elif "max_recover_time" in self._config["sla"]: - max_outage_time = self._config["sla"]["max_recover_time"] - else: - raise RuntimeError("monitor max_outage_time config is not found") - self._result = {"outage_time": outage_time} - - if outage_time > max_outage_time: - LOG.error("SLA failure: %f > %f", outage_time, max_outage_time) - return False - else: - return True + if self._config.get("sla"): + if "max_outage_time" in self._config["sla"]: + max_outage_time = self._config["sla"]["max_outage_time"] + elif "max_recover_time" in self._config["sla"]: + max_outage_time = self._config["sla"]["max_recover_time"] + else: + raise RuntimeError("'max_outage_time' or 'max_recover_time' " + "config is not found") + if outage_time > max_outage_time: + LOG.error("SLA failure: %f > %f", outage_time, max_outage_time) + return False + return True diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py index b0f6f8e9d..280e5811d 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py @@ -25,14 +25,14 @@ class MonitorProcess(basemonitor.BaseMonitor): self.connection = ssh.SSH.from_node(host, defaults={"user": "root"}) self.connection.wait(timeout=600) - LOG.debug("ssh host success!") + LOG.debug("ssh host (%s) success!", str(host)) self.check_script = self.get_script_fullpath( "ha_tools/check_process_python.bash") self.process_name = self._config["process_name"] def monitor_func(self): with open(self.check_script, "r") as stdin_file: - exit_status, stdout, stderr = self.connection.execute( + _, stdout, _ = self.connection.execute( "sudo /bin/sh -s {0}".format(self.process_name), stdin=stdin_file) @@ -45,15 +45,13 @@ class MonitorProcess(basemonitor.BaseMonitor): return True def verify_SLA(self): - LOG.debug("the _result:%s", self._result) outage_time = self._result.get('outage_time', None) - max_outage_time = self._config["sla"]["max_recover_time"] - if outage_time > max_outage_time: - LOG.error("SLA failure: %f > %f", outage_time, max_outage_time) - return False - else: - LOG.info("the sla is passed") - return True + if self._config.get("sla"): + max_outage_time = self._config["sla"]["max_recover_time"] + if outage_time > max_outage_time: + LOG.info("SLA failure: %f > %f", outage_time, max_outage_time) + return False + return True def _test(): # pragma: no cover @@ -73,7 +71,7 @@ def _test(): # pragma: no cover } monitor_configs.append(config) - p = basemonitor.MonitorMgr() + p = basemonitor.MonitorMgr({}) p.init_monitors(monitor_configs, context) p.start_monitors() p.wait_monitors() diff --git a/yardstick/benchmark/scenarios/availability/operation_conf.yaml b/yardstick/benchmark/scenarios/availability/operation_conf.yaml index dc5169196..5f3f6c91e 100644 --- a/yardstick/benchmark/scenarios/availability/operation_conf.yaml +++ b/yardstick/benchmark/scenarios/availability/operation_conf.yaml @@ -35,3 +35,14 @@ get-vip-host: action_script: ha_tools/pacemaker/get_vip_host.bash rollback_script: ha_tools/pacemaker/get_resource_status.bash +start-service: + action_script: ha_tools/start_service.bash + rollback_script: ha_tools/check_process_python.bash + +add-server-to-secgroup: + action_script: ha_tools/nova/add_server_to_existing_secgroup.bash + rollback_script: ha_tools/nova/remove_server_from_secgroup.bash + +get-privateip: + action_script: ha_tools/nova/get_server_privateip.bash + rollback_script: ha_tools/nova/list_servers.bash diff --git a/yardstick/benchmark/scenarios/availability/scenario_general.py b/yardstick/benchmark/scenarios/availability/scenario_general.py index 9ac55471d..e2db03a70 100644 --- a/yardstick/benchmark/scenarios/availability/scenario_general.py +++ b/yardstick/benchmark/scenarios/availability/scenario_general.py @@ -26,7 +26,6 @@ class ScenarioGeneral(base.Scenario): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg self.intermediate_variables = {} - self.pass_flag = True def setup(self): self.director = Director(self.scenario_cfg, self.context_cfg) @@ -47,7 +46,7 @@ class ScenarioGeneral(base.Scenario): step['actionType'], step['actionKey']) if actionRollbacker: self.director.executionSteps.append(actionRollbacker) - except Exception: + except Exception: # pylint: disable=broad-except LOG.exception("Exception") LOG.debug( "\033[91m exception when running step: %s .... \033[0m", @@ -59,31 +58,20 @@ class ScenarioGeneral(base.Scenario): self.director.stopMonitors() verify_result = self.director.verify() - - self.director.store_result(result) - + service_not_found = False for k, v in self.director.data.items(): if v == 0: - result['sla_pass'] = 0 verify_result = False - self.pass_flag = False - LOG.info( - "\033[92m The service process not found in the host \ -envrioment, the HA test case NOT pass") + service_not_found = True + LOG.info("\033[92m The service process (%s) not found in the host environment", k) - if verify_result: - result['sla_pass'] = 1 - LOG.info( - "\033[92m Congratulations, " - "the HA test case PASS! \033[0m") - else: - result['sla_pass'] = 0 - self.pass_flag = False - LOG.info( - "\033[91m Aoh, the HA test case FAIL," - "please check the detail debug information! \033[0m") + result['sla_pass'] = 1 if verify_result else 0 + self.director.store_result(result) + + self.verify_SLA( + verify_result, ("a service process was not found in the host " + "environment" if service_not_found + else "Director.verify() failed")) def teardown(self): self.director.knockoff() - - assert self.pass_flag, "The HA test case NOT passed" diff --git a/yardstick/benchmark/scenarios/availability/serviceha.py b/yardstick/benchmark/scenarios/availability/serviceha.py index 6d0d812af..fdfe7cbbe 100755 --- a/yardstick/benchmark/scenarios/availability/serviceha.py +++ b/yardstick/benchmark/scenarios/availability/serviceha.py @@ -29,13 +29,13 @@ class ServiceHA(base.Scenario): self.context_cfg = context_cfg self.setup_done = False self.data = {} - self.pass_flag = True + self.sla_pass = False def setup(self): """scenario setup""" nodes = self.context_cfg.get("nodes", None) if nodes is None: - LOG.error("the nodes info is none") + LOG.error("The nodes info is none") return self.attackers = [] @@ -58,43 +58,40 @@ class ServiceHA(base.Scenario): def run(self, result): """execute the benchmark""" if not self.setup_done: - LOG.error("The setup not finished!") + LOG.error("The setup is not finished!") return self.monitorMgr.start_monitors() - LOG.info("HA monitor start!") + LOG.info("Monitor '%s' start!", self.__scenario_type__) for attacker in self.attackers: attacker.inject_fault() self.monitorMgr.wait_monitors() - LOG.info("HA monitor stop!") + LOG.info("Monitor '%s' stop!", self.__scenario_type__) - sla_pass = self.monitorMgr.verify_SLA() + self.sla_pass = self.monitorMgr.verify_SLA() + service_not_found = False for k, v in self.data.items(): if v == 0: - result['sla_pass'] = 0 - self.pass_flag = False - LOG.info("The service process not found in the host envrioment, \ -the HA test case NOT pass") - return + self.sla_pass = False + service_not_found = True + LOG.info("The service process (%s) not found in the host envrioment", k) + + result['sla_pass'] = 1 if self.sla_pass else 0 self.monitorMgr.store_result(result) - if sla_pass: - result['sla_pass'] = 1 - LOG.info("The HA test case PASS the SLA") - else: - result['sla_pass'] = 0 - self.pass_flag = False - assert sla_pass is True, "The HA test case NOT pass the SLA" - return + self.verify_SLA( + self.sla_pass, ("a service process was not found in the host " + "environment" if service_not_found + else "MonitorMgr.verify_SLA() failed")) def teardown(self): """scenario teardown""" + # recover when mandatory or sla not pass for attacker in self.attackers: - attacker.recover() - - assert self.pass_flag, "The HA test case NOT passed" + if attacker.mandatory or not self.sla_pass: + attacker.recover() def _test(): # pragma: no cover diff --git a/yardstick/benchmark/scenarios/base.py b/yardstick/benchmark/scenarios/base.py index 7af85834c..ae8bfad71 100644 --- a/yardstick/benchmark/scenarios/base.py +++ b/yardstick/benchmark/scenarios/base.py @@ -13,44 +13,76 @@ # License for the specific language governing permissions and limitations # under the License. -# yardstick comment: this is a modified copy of -# rally/rally/benchmark/scenarios/base.py +import abc +import time -""" Scenario base class -""" +import six +from stevedore import extension -from __future__ import absolute_import import yardstick.common.utils as utils +from yardstick.common import exceptions as y_exc +def _iter_scenario_classes(scenario_type=None): + """Generator over all 'Scenario' subclasses + + This function will iterate over all 'Scenario' subclasses defined in this + project and will load any class introduced by any installed plugin project, + defined in 'entry_points' section, under 'yardstick.scenarios' subsection. + """ + extension.ExtensionManager(namespace='yardstick.scenarios', + invoke_on_load=False) + for scenario in utils.itersubclasses(Scenario): + if not scenario_type: + yield scenario + elif getattr(scenario, '__scenario_type__', None) == scenario_type: + yield scenario + + +@six.add_metaclass(abc.ABCMeta) class Scenario(object): def setup(self): - """ default impl for scenario setup """ + """Default setup implementation for Scenario classes""" pass - def run(self, args): - """ catcher for not implemented run methods in subclasses """ - raise RuntimeError("run method not implemented") + @abc.abstractmethod + def run(self, *args): + """Entry point for scenario classes, called from runner worker""" + + def is_ended(self): + return False def teardown(self): - """ default impl for scenario teardown """ + """Default teardown implementation for Scenario classes""" + pass + + def pre_run_wait_time(self, time_seconds): + """Time waited before executing the run method""" pass + def post_run_wait_time(self, time_seconds): + """Time waited after executing the run method""" + time.sleep(time_seconds) + + def verify_SLA(self, condition, error_msg): + if not condition: + raise y_exc.SLAValidationError( + case_name=self.__scenario_type__, error_msg=error_msg) + @staticmethod def get_types(): """return a list of known runner type (class) names""" scenarios = [] - for scenario in utils.itersubclasses(Scenario): + for scenario in _iter_scenario_classes(): scenarios.append(scenario) return scenarios @staticmethod def get_cls(scenario_type): """return class of specified type""" - for scenario in utils.itersubclasses(Scenario): - if scenario_type == scenario.__scenario_type__: - return scenario + for scenario in _iter_scenario_classes(scenario_type): + return scenario raise RuntimeError("No such scenario type %s" % scenario_type) @@ -58,11 +90,8 @@ class Scenario(object): def get(scenario_type): """Returns instance of a scenario runner for execution type. """ - for scenario in utils.itersubclasses(Scenario): - if scenario_type == scenario.__scenario_type__: - return scenario.__module__ + "." + scenario.__name__ - - raise RuntimeError("No such scenario type %s" % scenario_type) + scenario = Scenario.get_cls(scenario_type) + return scenario.__module__ + "." + scenario.__name__ @classmethod def get_scenario_type(cls): @@ -78,10 +107,14 @@ class Scenario(object): """ return cls.__doc__.splitlines()[0] if cls.__doc__ else str(None) - def _push_to_outputs(self, keys, values): + @staticmethod + def _push_to_outputs(keys, values): + """Return a dictionary given the keys and the values""" return dict(zip(keys, values)) - def _change_obj_to_dict(self, obj): + @staticmethod + def _change_obj_to_dict(obj): + """Return a dictionary from the __dict__ attribute of an object""" dic = {} for k, v in vars(obj).items(): try: diff --git a/yardstick/benchmark/scenarios/compute/cyclictest.py b/yardstick/benchmark/scenarios/compute/cyclictest.py index 998463ef6..413709f3b 100644 --- a/yardstick/benchmark/scenarios/compute/cyclictest.py +++ b/yardstick/benchmark/scenarios/compute/cyclictest.py @@ -100,7 +100,7 @@ class Cyclictest(base.Scenario): def _run_setup_cmd(self, client, cmd): LOG.debug("Run cmd: %s", cmd) - status, stdout, stderr = client.execute(cmd) + status, _, stderr = client.execute(cmd) if status: if re.search(self.REBOOT_CMD_PATTERN, cmd): LOG.debug("Error on reboot") @@ -195,7 +195,7 @@ class Cyclictest(base.Scenario): if latency > sla_latency: sla_error += "%s latency %d > sla:max_%s_latency(%d); " % \ (t, latency, t, sla_latency) - assert sla_error == "", sla_error + self.verify_SLA(sla_error == "", sla_error) def _test(): # pragma: no cover diff --git a/yardstick/benchmark/scenarios/compute/lmbench.py b/yardstick/benchmark/scenarios/compute/lmbench.py index 801f7fa80..2237e49e0 100644 --- a/yardstick/benchmark/scenarios/compute/lmbench.py +++ b/yardstick/benchmark/scenarios/compute/lmbench.py @@ -119,8 +119,8 @@ class Lmbench(base.Scenario): cmd = "sudo bash lmbench_latency_for_cache.sh %d %d" % \ (repetition, warmup) else: - raise RuntimeError("No such test_type: %s for Lmbench scenario", - test_type) + raise RuntimeError("No such test_type: %s for Lmbench scenario" + % test_type) LOG.debug("Executing command: %s", cmd) status, stdout, stderr = self.client.execute(cmd) @@ -157,7 +157,7 @@ class Lmbench(base.Scenario): if sla_latency < cache_latency: sla_error += "latency %f > sla:max_latency(%f); " \ % (cache_latency, sla_latency) - assert sla_error == "", sla_error + self.verify_SLA(sla_error == "", sla_error) def _test(): diff --git a/yardstick/benchmark/scenarios/compute/perf.py b/yardstick/benchmark/scenarios/compute/perf.py index 0b8ed9b28..b973211f1 100644 --- a/yardstick/benchmark/scenarios/compute/perf.py +++ b/yardstick/benchmark/scenarios/compute/perf.py @@ -93,7 +93,7 @@ class Perf(base.Scenario): % (load, duration, events_string) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) + status, stdout, _ = self.client.execute(cmd) if status: raise RuntimeError(stdout) @@ -105,16 +105,14 @@ class Perf(base.Scenario): exp_val = self.scenario_cfg['sla']['expected_value'] smaller_than_exp = 'smaller_than_expected' \ in self.scenario_cfg['sla'] - - if metric not in result: - assert False, "Metric (%s) not found." % metric - else: - if smaller_than_exp: - assert result[metric] < exp_val, "%s %d >= %d (sla); " \ - % (metric, result[metric], exp_val) - else: - assert result[metric] >= exp_val, "%s %d < %d (sla); " \ - % (metric, result[metric], exp_val) + self.verify_SLA(metric in result, + "Metric (%s) not found." % metric) + self.verify_SLA( + not smaller_than_exp, + "%s %d >= %d (sla); " % (metric, result[metric], exp_val)) + self.verify_SLA( + result[metric] >= exp_val, + "%s %d < %d (sla); " % (metric, result[metric], exp_val)) def _test(): diff --git a/yardstick/benchmark/scenarios/compute/qemu_migrate.py b/yardstick/benchmark/scenarios/compute/qemu_migrate.py index 2de1270ef..975c90b22 100644 --- a/yardstick/benchmark/scenarios/compute/qemu_migrate.py +++ b/yardstick/benchmark/scenarios/compute/qemu_migrate.py @@ -56,7 +56,7 @@ class QemuMigrate(base.Scenario): def _run_setup_cmd(self, client, cmd): LOG.debug("Run cmd: %s", cmd) - status, stdout, stderr = client.execute(cmd) + status, _, stderr = client.execute(cmd) if status: if re.search(self.REBOOT_CMD_PATTERN, cmd): LOG.debug("Error on reboot") @@ -127,7 +127,7 @@ class QemuMigrate(base.Scenario): if timevalue > sla_time: sla_error += "%s timevalue %d > sla:max_%s(%d); " % \ (t, timevalue, t, sla_time) - assert sla_error == "", sla_error + self.verify_SLA(sla_error == "", sla_error) def _test(): # pragma: no cover diff --git a/yardstick/benchmark/scenarios/compute/ramspeed.py b/yardstick/benchmark/scenarios/compute/ramspeed.py index ca64935dd..4daf776ff 100644 --- a/yardstick/benchmark/scenarios/compute/ramspeed.py +++ b/yardstick/benchmark/scenarios/compute/ramspeed.py @@ -121,8 +121,8 @@ class Ramspeed(base.Scenario): (test_id, load, block_size) # only the test_id 1-6 will be used in this scenario else: - raise RuntimeError("No such type_id: %s for Ramspeed scenario", - test_id) + raise RuntimeError("No such type_id: %s for Ramspeed scenario" + % test_id) LOG.debug("Executing command: %s", cmd) status, stdout, stderr = self.client.execute(cmd) @@ -140,4 +140,4 @@ class Ramspeed(base.Scenario): if bw < sla_min_bw: sla_error += "Bandwidth %f < " \ "sla:min_bandwidth(%f)" % (bw, sla_min_bw) - assert sla_error == "", sla_error + self.verify_SLA(sla_error == "", sla_error) diff --git a/yardstick/benchmark/scenarios/compute/unixbench.py b/yardstick/benchmark/scenarios/compute/unixbench.py index cdb345717..3cea31694 100644 --- a/yardstick/benchmark/scenarios/compute/unixbench.py +++ b/yardstick/benchmark/scenarios/compute/unixbench.py @@ -125,7 +125,7 @@ class Unixbench(base.Scenario): if score < sla_score: sla_error += "%s score %f < sla:%s_score(%f); " % \ (t, score, t, sla_score) - assert sla_error == "", sla_error + self.verify_SLA(sla_error == "", sla_error) def _test(): # pragma: no cover diff --git a/yardstick/benchmark/scenarios/compute/unixbench_benchmark.bash b/yardstick/benchmark/scenarios/compute/unixbench_benchmark.bash index 5a5dbc394..0f0122e51 100644 --- a/yardstick/benchmark/scenarios/compute/unixbench_benchmark.bash +++ b/yardstick/benchmark/scenarios/compute/unixbench_benchmark.bash @@ -18,15 +18,15 @@ OUTPUT_FILE=/tmp/unixbench-out.log # run unixbench test run_unixbench() { - cd /opt/tempT/UnixBench/ + cd /opt/tempT/UnixBench/UnixBench/ ./Run $OPTIONS > $OUTPUT_FILE } # write the result to stdout in json format output_json() { - single_score=$(awk '/Score/{print $7}' $OUTPUT_FILE | head -1 ) - parallel_score=$(awk '/Score/{print $7}' $OUTPUT_FILE | tail -1 ) + single_score=$(awk '/Score/{print $NF}' $OUTPUT_FILE | head -1 ) + parallel_score=$(awk '/Score/{print $NF}' $OUTPUT_FILE | tail -1 ) echo -e "{ \ \"single_score\":\"$single_score\", \ \"parallel_score\":\"$parallel_score\" \ diff --git a/yardstick/benchmark/scenarios/energy/__init__.py b/yardstick/benchmark/scenarios/energy/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/benchmark/scenarios/energy/__init__.py diff --git a/yardstick/benchmark/scenarios/energy/energy.py b/yardstick/benchmark/scenarios/energy/energy.py new file mode 100644 index 000000000..7440835be --- /dev/null +++ b/yardstick/benchmark/scenarios/energy/energy.py @@ -0,0 +1,139 @@ +############################################################################## +# Copyright (c) 2019 Lenovo Group Limited 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 requests +import json +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) +logging.captureWarnings(True) + + +class Energy(base.Scenario): + """Get current energy consumption of target host + + This scenario sends a REDFISH request to a host BMC + to request current energy consumption. + The response returns a number of Watts. + Usually this is an average of a rolling windows + taken from server internal sensor. + This is dependant of the server provider. + + This scenario should be used with node context + + As this scenario usually run background with other scenarios, + error of api query or data parse will not terminate task runner. + If any error occured, energy consumption will be set to -1. + + Parameters + None + """ + + __scenario_type__ = "Energy" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.target = self.context_cfg['target'] + self.setup_done = False + self.get_response = False + + def _send_request(self, url): + LOG.info("Send request to %s", url) + pod_auth = (self.target["redfish_user"], self.target["redfish_pwd"]) + response = requests.get(url, auth=pod_auth, verify=False) + return response + + def setup(self): + url = "https://{}/redfish/v1/".format(self.target["redfish_ip"]) + response = self._send_request(url) + if response.status_code != 200: + LOG.info("Don't get right response from %s", url) + self.get_response = False + else: + LOG.info("Get response from %s", url) + self.get_response = True + + self.setup_done = True + + def load_chassis_list(self): + chassis_list = [] + + # Get Chassis list + request_url = "https://" + self.target["redfish_ip"] + request_url += "/redfish/v1/Chassis/" + response = self._send_request(request_url) + if response.status_code != 200: + LOG.info("Do not get proper response from %s", request_url) + return chassis_list + + try: + chassis_data = json.loads(response.text) + except(TypeError, ValueError) as e: + LOG.info("Invalid response data, %s", e) + return chassis_list + + try: + for chassis in chassis_data['Members']: + chassis_list.append(chassis["@odata.id"]) + except KeyError as e: + LOG.info("Error data format of chassis data or invalid key.") + + return chassis_list + + def get_power(self, chassis_uri): + """Get PowerMetter values from Redfish API.""" + if chassis_uri[-1:] != '/': + chassis_uri += '/' + request_url = "https://" + self.target['redfish_ip'] + request_url += chassis_uri + request_url += "Power/" + response = self._send_request(request_url) + if response.status_code != 200: + LOG.info("Do not get proper response from %s", request_url) + power = -1 + return power + + try: + power_metrics = json.loads(response.text) + except(TypeError, ValueError) as e: + LOG.info("Invalid response data, %s", e) + power = -1 + return power + + try: + power = power_metrics["PowerControl"][0]["PowerConsumedWatts"] + except KeyError as e: + LOG.info("Error data format of power metrics or invalid key.") + power = -1 + + return power + + def run(self, result): + """execute the benchmark""" + if not self.setup_done: + self.setup() + chassis_list = self.load_chassis_list() + if not self.get_response or not chassis_list: + power = -1 + data = { + "power": power, + } + result.update(data) + else: + power = 0 + for chassis in chassis_list: + power += self.get_power(chassis) + data = { + "power": power, + } + result.update(data) diff --git a/yardstick/benchmark/scenarios/lib/attach_volume.py b/yardstick/benchmark/scenarios/lib/attach_volume.py index 88124964b..96dd130b1 100644 --- a/yardstick/benchmark/scenarios/lib/attach_volume.py +++ b/yardstick/benchmark/scenarios/lib/attach_volume.py @@ -6,30 +6,31 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) class AttachVolume(base.Scenario): - """Attach a volmeu to an instance""" + """Attach a volume to an instance""" __scenario_type__ = "AttachVolume" def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.server_id = self.options.get("server_id", "TestServer") - self.volume_id = self.options.get("volume_id", None) + self.server_name_or_id = self.options["server_name_or_id"] + self.volume_name_or_id = self.options["volume_name_or_id"] + self.device = self.options.get("device") + self.wait = self.options.get("wait", True) + self.timeout = self.options.get("timeout") + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -44,10 +45,14 @@ class AttachVolume(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.attach_server_volume(self.server_id, - self.volume_id) + status = openstack_utils.attach_volume_to_server( + self.shade_client, self.server_name_or_id, self.volume_name_or_id, + device=self.device, wait=self.wait, timeout=self.timeout) + + if not status: + result.update({"attach_volume": 0}) + LOG.error("Attach volume to server failed!") + raise exceptions.ScenarioAttachVolumeError - if status: - LOG.info("Attach volume to server successful!") - else: - LOG.info("Attach volume to server failed!") + result.update({"attach_volume": 1}) + LOG.info("Attach volume to server successful!") diff --git a/yardstick/benchmark/scenarios/lib/check_value.py b/yardstick/benchmark/scenarios/lib/check_value.py index 759076068..4c9b27df4 100644 --- a/yardstick/benchmark/scenarios/lib/check_value.py +++ b/yardstick/benchmark/scenarios/lib/check_value.py @@ -13,6 +13,7 @@ from __future__ import absolute_import import logging from yardstick.benchmark.scenarios import base +from yardstick.common import exceptions as y_exc LOG = logging.getLogger(__name__) @@ -34,24 +35,18 @@ class CheckValue(base.Scenario): self.context_cfg = context_cfg self.options = self.scenario_cfg['options'] - def run(self, result): + def run(self, _): """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")) + if (op == "eq" and value1 != value2) or (op == "ne" and + value1 == value2): + raise y_exc.ValueCheckError( + value1=value1, operator=op, value2=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] diff --git a/yardstick/benchmark/scenarios/lib/create_floating_ip.py b/yardstick/benchmark/scenarios/lib/create_floating_ip.py index 328566d48..e29f9d1fc 100644 --- a/yardstick/benchmark/scenarios/lib/create_floating_ip.py +++ b/yardstick/benchmark/scenarios/lib/create_floating_ip.py @@ -7,14 +7,13 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -from __future__ import print_function -from __future__ import absolute_import - import logging import os from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils +from yardstick.common import openstack_utils +from yardstick.common import exceptions + LOG = logging.getLogger(__name__) @@ -28,8 +27,18 @@ class CreateFloatingIp(base.Scenario): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg self.ext_net_id = os.getenv("EXTERNAL_NETWORK", "external") + self.options = self.scenario_cfg["options"] + + self.network_name_or_id = self.options.get("network_name_or_id", self.ext_net_id) + self.server = self.options.get("server") + self.fixed_address = self.options.get("fixed_address") + self.nat_destination = self.options.get("nat_destination") + self.port = self.options.get("port") + self.wait = self.options.get("wait", False) + self.timeout = self.options.get("timeout", 60) + + self.shade_client = openstack_utils.get_shade_client() - self.neutron_client = op_utils.get_neutron_client() self.setup_done = False def setup(self): @@ -43,18 +52,19 @@ class CreateFloatingIp(base.Scenario): if not self.setup_done: self.setup() - net_id = op_utils.get_network_id(self.neutron_client, self.ext_net_id) - floating_info = op_utils.create_floating_ip(self.neutron_client, - extnet_id=net_id) - if floating_info: - LOG.info("Creating floating ip successful!") - else: + floating_info = openstack_utils.create_floating_ip( + self.shade_client, network_name_or_id=self.network_name_or_id, + server=self.server, fixed_address=self.fixed_address, + nat_destination=self.nat_destination, port=self.port, + wait=self.wait, timeout=self.timeout) + + if not floating_info: + result.update({"floating_ip_create": 0}) LOG.error("Creating floating ip failed!") + raise exceptions.ScenarioCreateFloatingIPError - try: - keys = self.scenario_cfg.get('output', '').split() - except KeyError: - pass - else: - values = [floating_info["fip_id"], floating_info["fip_addr"]] - return self._push_to_outputs(keys, values) + result.update({"floating_ip_create": 1}) + LOG.info("Creating floating ip successful!") + keys = self.scenario_cfg.get("output", '').split() + values = [floating_info["fip_id"], floating_info["fip_addr"]] + return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_image.py b/yardstick/benchmark/scenarios/lib/create_image.py index bcffc7452..d057894a9 100644 --- a/yardstick/benchmark/scenarios/lib/create_image.py +++ b/yardstick/benchmark/scenarios/lib/create_image.py @@ -6,14 +6,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -26,20 +23,23 @@ class CreateImage(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] - - self.image_name = self.options.get("image_name", "TestImage") - self.file_path = self.options.get("file_path", None) - self.disk_format = self.options.get("disk_format", "qcow2") - self.container_format = self.options.get("container_format", "bare") - self.min_disk = self.options.get("min_disk", 0) - self.min_ram = self.options.get("min_ram", 0) - self.protected = self.options.get("protected", False) - self.public = self.options.get("public", "public") - self.tags = self.options.get("tags", []) - self.custom_property = self.options.get("property", {}) - - self.glance_client = op_utils.get_glance_client() + self.options = self.scenario_cfg["options"] + + self.name = self.options["image_name"] + self.file_name = self.options.get("file_name") + self.container = self.options.get("container", 'images') + self.md5 = self.options.get("md5") + self.sha256 = self.options.get("sha256") + self.disk_format = self.options.get("disk_format") + self.container_format = self.options.get("container_format",) + self.disable_vendor_agent = self.options.get("disable_vendor_agent", True) + self.wait = self.options.get("wait", True) + self.timeout = self.options.get("timeout", 3600) + self.allow_duplicates = self.options.get("allow_duplicates", False) + self.meta = self.options.get("meta") + self.volume = self.options.get("volume") + + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -54,19 +54,22 @@ class CreateImage(base.Scenario): if not self.setup_done: self.setup() - image_id = op_utils.create_image(self.glance_client, self.image_name, - self.file_path, self.disk_format, - self.container_format, self.min_disk, - self.min_ram, self.protected, self.tags, - self.public, **self.custom_property) - - if image_id: - LOG.info("Create image successful!") - values = [image_id] - - else: - LOG.info("Create image failed!") - values = [] - - keys = self.scenario_cfg.get('output', '').split() + image_id = openstack_utils.create_image( + self.shade_client, self.name, filename=self.file_name, + container=self.container, md5=self.md5, sha256=self.sha256, + disk_format=self.disk_format, + container_format=self.container_format, + disable_vendor_agent=self.disable_vendor_agent, wait=self.wait, + timeout=self.timeout, allow_duplicates=self.allow_duplicates, + meta=self.meta, volume=self.volume) + + if not image_id: + result.update({"image_create": 0}) + LOG.error("Create image failed!") + raise exceptions.ScenarioCreateImageError + + result.update({"image_create": 1}) + LOG.info("Create image successful!") + keys = self.scenario_cfg.get("output", '').split() + values = [image_id] return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_keypair.py b/yardstick/benchmark/scenarios/lib/create_keypair.py index f5b1fff7a..ee9bc440a 100644 --- a/yardstick/benchmark/scenarios/lib/create_keypair.py +++ b/yardstick/benchmark/scenarios/lib/create_keypair.py @@ -6,15 +6,11 @@ # 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 paramiko from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -27,10 +23,11 @@ class CreateKeypair(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.key_name = self.options.get("key_name", "yardstick_key") - self.key_filename = self.options.get("key_path", "/tmp/yardstick_key") + self.name = self.options["key_name"] + self.public_key = self.options.get("public_key") + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,27 +42,17 @@ class CreateKeypair(base.Scenario): if not self.setup_done: self.setup() - rsa_key = paramiko.RSAKey.generate(bits=2048, progress_func=None) - rsa_key.write_private_key_file(self.key_filename) - LOG.info("Writing key_file %s ...", self.key_filename) - with open(self.key_filename + ".pub", "w") as pubkey_file: - pubkey_file.write( - "%s %s\n" % (rsa_key.get_name(), rsa_key.get_base64())) - del rsa_key - - keypair = op_utils.create_keypair(self.key_name, - self.key_filename + ".pub") + keypair = openstack_utils.create_keypair( + self.shade_client, self.name, public_key=self.public_key) - if keypair: - result.update({"keypair_create": 1}) - LOG.info("Create keypair successful!") - else: + if not keypair: result.update({"keypair_create": 0}) - LOG.info("Create keypair failed!") - try: - keys = self.scenario_cfg.get('output', '').split() - except KeyError: - pass - else: - values = [keypair.id] - return self._push_to_outputs(keys, values) + LOG.error("Create keypair failed!") + raise exceptions.ScenarioCreateKeypairError + + result.update({"keypair_create": 1}) + LOG.info("Create keypair successful!") + keys = self.scenario_cfg.get("output", '').split() + keypair_id = keypair["id"] + values = [keypair_id] + return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_network.py b/yardstick/benchmark/scenarios/lib/create_network.py index cffff132a..734820519 100644 --- a/yardstick/benchmark/scenarios/lib/create_network.py +++ b/yardstick/benchmark/scenarios/lib/create_network.py @@ -7,13 +7,12 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions + LOG = logging.getLogger(__name__) @@ -28,9 +27,14 @@ class CreateNetwork(base.Scenario): self.context_cfg = context_cfg self.options = self.scenario_cfg['options'] - self.openstack = self.options.get("openstack_paras", None) + self.network_name = self.options["network_name"] + self.shared = self.options.get("shared", False) + self.admin_state_up = self.options.get("admin_state_up", True) + self.external = self.options.get("external", False) + self.provider = self.options.get("provider") + self.project_id = self.options.get("project_id") - self.neutron_client = op_utils.get_neutron_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,20 +49,17 @@ class CreateNetwork(base.Scenario): if not self.setup_done: self.setup() - openstack_paras = {'network': self.openstack} - network_id = op_utils.create_neutron_net(self.neutron_client, - openstack_paras) - if network_id: - result.update({"network_create": 1}) - LOG.info("Create network successful!") - else: + network_id = openstack_utils.create_neutron_net( + self.shade_client, self.network_name, shared=self.shared, + admin_state_up=self.admin_state_up, external=self.external, + provider=self.provider, project_id=self.project_id) + if not network_id: result.update({"network_create": 0}) LOG.error("Create network failed!") + raise exceptions.ScenarioCreateNetworkError - try: - keys = self.scenario_cfg.get('output', '').split() - except KeyError: - pass - else: - values = [network_id] - return self._push_to_outputs(keys, values) + result.update({"network_create": 1}) + LOG.info("Create network successful!") + keys = self.scenario_cfg.get('output', '').split() + values = [network_id] + return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_router.py b/yardstick/benchmark/scenarios/lib/create_router.py index 9aa57ebb2..34252f603 100644 --- a/yardstick/benchmark/scenarios/lib/create_router.py +++ b/yardstick/benchmark/scenarios/lib/create_router.py @@ -7,13 +7,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -28,9 +26,14 @@ class CreateRouter(base.Scenario): self.context_cfg = context_cfg self.options = self.scenario_cfg['options'] - self.openstack = self.options.get("openstack_paras", None) + self.name = self.options.get('name') + self.admin_state_up = self.options.get('admin_state_up', True) + self.ext_gateway_net_id = self.options.get('ext_gateway_net_id') + self.enable_snat = self.options.get('enable_snat') + self.ext_fixed_ips = self.options.get('ext_fixed_ips') + self.project_id = self.options.get('project_id') - self.neutron_client = op_utils.get_neutron_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,22 +48,19 @@ class CreateRouter(base.Scenario): if not self.setup_done: self.setup() - openstack_paras = {'router': self.openstack} - router_id = op_utils.create_neutron_router(self.neutron_client, - openstack_paras) - if router_id: - result.update({"network_create": 1}) - LOG.info("Create router successful!") - else: - result.update({"network_create": 0}) + router_id = openstack_utils.create_neutron_router( + self.shade_client, name=self.name, + admin_state_up=self.admin_state_up, + ext_gateway_net_id=self.ext_gateway_net_id, + enable_snat=self.enable_snat, ext_fixed_ips=self.ext_fixed_ips, + project_id=self.project_id) + if not router_id: + result.update({"router_create": 0}) LOG.error("Create router failed!") + raise exceptions.ScenarioCreateRouterError - check_result = router_id - - try: - keys = self.scenario_cfg.get('output', '').split() - except KeyError: - pass - else: - values = [check_result] - return self._push_to_outputs(keys, values) + result.update({"router_create": 1}) + LOG.info("Create router successful!") + keys = self.scenario_cfg.get('output', '').split() + values = [router_id] + return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_sec_group.py b/yardstick/benchmark/scenarios/lib/create_sec_group.py index 3d1aec9e8..1d2e36488 100644 --- a/yardstick/benchmark/scenarios/lib/create_sec_group.py +++ b/yardstick/benchmark/scenarios/lib/create_sec_group.py @@ -7,13 +7,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -26,11 +24,12 @@ class CreateSecgroup(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.sg_name = self.options.get("sg_name", "yardstick_sec_group") - self.description = self.options.get("description", None) - self.neutron_client = op_utils.get_neutron_client() + self.sg_name = self.options["sg_name"] + self.description = self.options.get("description", "") + self.project_id = self.options.get("project_id") + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,21 +44,16 @@ class CreateSecgroup(base.Scenario): if not self.setup_done: self.setup() - sg_id = op_utils.create_security_group_full(self.neutron_client, - sg_name=self.sg_name, - sg_description=self.description) - - if sg_id: - result.update({"sg_create": 1}) - LOG.info("Create security group successful!") - else: + sg_id = openstack_utils.create_security_group_full( + self.shade_client, self.sg_name, sg_description=self.description, + project_id=self.project_id) + if not sg_id: result.update({"sg_create": 0}) LOG.error("Create security group failed!") + raise exceptions.ScenarioCreateSecurityGroupError - try: - keys = self.scenario_cfg.get('output', '').split() - except KeyError: - pass - else: - values = [sg_id] - return self._push_to_outputs(keys, values) + result.update({"sg_create": 1}) + LOG.info("Create security group successful!") + keys = self.scenario_cfg.get("output", '').split() + values = [sg_id] + return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_server.py b/yardstick/benchmark/scenarios/lib/create_server.py index 31ba18ed4..e2748aecf 100644 --- a/yardstick/benchmark/scenarios/lib/create_server.py +++ b/yardstick/benchmark/scenarios/lib/create_server.py @@ -6,14 +6,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -26,15 +23,27 @@ class CreateServer(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] - - self.image_name = self.options.get("image_name", None) - self.flavor_name = self.options.get("flavor_name", None) - self.openstack = self.options.get("openstack_paras", None) - - self.glance_client = op_utils.get_glance_client() - self.neutron_client = op_utils.get_neutron_client() - self.nova_client = op_utils.get_nova_client() + self.options = self.scenario_cfg["options"] + + self.name = self.options["name"] + self.image = self.options["image"] + self.flavor = self.options["flavor"] + self.auto_ip = self.options.get("auto_ip", True) + self.ips = self.options.get("ips") + self.ip_pool = self.options.get("ip_pool") + self.root_volume = self.options.get("root_volume") + self.terminate_volume = self.options.get("terminate_volume", False) + self.wait = self.options.get("wait", True) + self.timeout = self.options.get("timeout", 180) + self.reuse_ips = self.options.get("reuse_ips", True) + self.network = self.options.get("network") + self.boot_from_volume = self.options.get("boot_from_volume", False) + self.volume_size = self.options.get("volume_size", "20") + self.boot_volume = self.options.get("boot_volume") + self.volumes = self.options.get("volumes") + self.nat_destination = self.options.get("nat_destination") + + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -49,26 +58,23 @@ class CreateServer(base.Scenario): if not self.setup_done: self.setup() - if self.image_name is not None: - self.openstack['image'] = op_utils.get_image_id(self.glance_client, - self.image_name) - if self.flavor_name is not None: - self.openstack['flavor'] = op_utils.get_flavor_id(self.nova_client, - self.flavor_name) - - vm = op_utils.create_instance_and_wait_for_active(self.openstack) - - if vm: - result.update({"instance_create": 1}) - LOG.info("Create server successful!") - else: + server = openstack_utils.create_instance_and_wait_for_active( + self.shade_client, self.name, self.image, + self.flavor, auto_ip=self.auto_ip, ips=self.ips, + ip_pool=self.ip_pool, root_volume=self.root_volume, + terminate_volume=self.terminate_volume, wait=self.wait, + timeout=self.timeout, reuse_ips=self.reuse_ips, + network=self.network, boot_from_volume=self.boot_from_volume, + volume_size=self.volume_size, boot_volume=self.boot_volume, + volumes=self.volumes, nat_destination=self.nat_destination) + + if not server: result.update({"instance_create": 0}) LOG.error("Create server failed!") + raise exceptions.ScenarioCreateServerError - try: - keys = self.scenario_cfg.get('output', '').split() - except KeyError: - pass - else: - values = [vm.id] - return self._push_to_outputs(keys, values) + result.update({"instance_create": 1}) + LOG.info("Create instance successful!") + keys = self.scenario_cfg.get("output", '').split() + values = [server["id"]] + return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_subnet.py b/yardstick/benchmark/scenarios/lib/create_subnet.py index c34af8a9e..e383c99de 100644 --- a/yardstick/benchmark/scenarios/lib/create_subnet.py +++ b/yardstick/benchmark/scenarios/lib/create_subnet.py @@ -7,13 +7,12 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions + LOG = logging.getLogger(__name__) @@ -28,9 +27,23 @@ class CreateSubnet(base.Scenario): self.context_cfg = context_cfg self.options = self.scenario_cfg['options'] - self.openstack = self.options.get("openstack_paras", None) - - self.neutron_client = op_utils.get_neutron_client() + self.network_name_or_id = self.options['network_name_or_id'] + self.cidr = self.options.get('cidr') + self.ip_version = self.options.get('ip_version', 4) + self.enable_dhcp = self.options.get('enable_dhcp', False) + self.subnet_name = self.options.get('subnet_name') + self.tenant_id = self.options.get('tenant_id') + self.allocation_pools = self.options.get('allocation_pools') + self.gateway_ip = self.options.get('gateway_ip') + self.disable_gateway_ip = self.options.get('disable_gateway_ip', False) + self.dns_nameservers = self.options.get('dns_nameservers') + self.host_routes = self.options.get('host_routes') + self.ipv6_ra_mode = self.options.get('ipv6_ra_mode') + self.ipv6_address_mode = self.options.get('ipv6_address_mode') + self.use_default_subnetpool = self.options.get( + 'use_default_subnetpool', False) + + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,22 +58,23 @@ class CreateSubnet(base.Scenario): if not self.setup_done: self.setup() - openstack_paras = {'subnets': [self.openstack]} - subnet_id = op_utils.create_neutron_subnet(self.neutron_client, - openstack_paras) - if subnet_id: - result.update({"subnet_create": 1}) - LOG.info("Create subnet successful!") - else: + subnet_id = openstack_utils.create_neutron_subnet( + self.shade_client, self.network_name_or_id, cidr=self.cidr, + ip_version=self.ip_version, enable_dhcp=self.enable_dhcp, + subnet_name=self.subnet_name, tenant_id=self.tenant_id, + allocation_pools=self.allocation_pools, gateway_ip=self.gateway_ip, + disable_gateway_ip=self.disable_gateway_ip, + dns_nameservers=self.dns_nameservers, host_routes=self.host_routes, + ipv6_ra_mode=self.ipv6_ra_mode, + ipv6_address_mode=self.ipv6_address_mode, + use_default_subnetpool=self.use_default_subnetpool) + if not subnet_id: result.update({"subnet_create": 0}) LOG.error("Create subnet failed!") + raise exceptions.ScenarioCreateSubnetError - check_result = subnet_id - - try: - keys = self.scenario_cfg.get('output', '').split() - except KeyError: - pass - else: - values = [check_result] - return self._push_to_outputs(keys, values) + result.update({"subnet_create": 1}) + LOG.info("Create subnet successful!") + keys = self.scenario_cfg.get('output', '').split() + values = [subnet_id] + return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/create_volume.py b/yardstick/benchmark/scenarios/lib/create_volume.py index c7086d0ef..b66749026 100644 --- a/yardstick/benchmark/scenarios/lib/create_volume.py +++ b/yardstick/benchmark/scenarios/lib/create_volume.py @@ -7,14 +7,12 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -from __future__ import print_function -from __future__ import absolute_import - import time import logging from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -27,15 +25,16 @@ class CreateVolume(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.volume_name = self.options.get("volume_name", "TestVolume") - self.volume_size = self.options.get("size", 100) - self.image_name = self.options.get("image", None) - self.image_id = None + self.size = self.options["size_gb"] + self.wait = self.options.get("wait", True) + self.timeout = self.options.get("timeout") + self.image = self.options.get("image") + self.name = self.options.get("name") + self.description = self.options.get("description") - self.glance_client = op_utils.get_glance_client() - self.cinder_client = op_utils.get_cinder_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -50,22 +49,23 @@ class CreateVolume(base.Scenario): if not self.setup_done: self.setup() - if self.image_name: - self.image_id = op_utils.get_image_id(self.glance_client, - self.image_name) + volume = openstack_utils.create_volume( + self.shade_client, self.size, wait=self.wait, timeout=self.timeout, + image=self.image, name=self.name, description=self.description) - volume = op_utils.create_volume(self.cinder_client, self.volume_name, - self.volume_size, self.image_id) + if not volume: + result.update({"volume_create": 0}) + LOG.error("Create volume failed!") + raise exceptions.ScenarioCreateVolumeError - status = volume.status - while(status == 'creating' or status == 'downloading'): - LOG.info("Volume status is: %s" % status) + status = volume["status"] + while status == "creating" or status == "downloading": + LOG.info("Volume status is: %s", status) time.sleep(5) - volume = op_utils.get_volume_by_name(self.volume_name) - status = volume.status - + volume = openstack_utils.get_volume(self.shade_client, self.name) + status = volume["status"] + result.update({"volume_create": 1}) LOG.info("Create volume successful!") - - values = [volume.id] - keys = self.scenario_cfg.get('output', '').split() + values = [volume["id"]] + keys = self.scenario_cfg.get("output", '').split() return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/delete_floating_ip.py b/yardstick/benchmark/scenarios/lib/delete_floating_ip.py index 4314952fb..a35445f6f 100644 --- a/yardstick/benchmark/scenarios/lib/delete_floating_ip.py +++ b/yardstick/benchmark/scenarios/lib/delete_floating_ip.py @@ -7,13 +7,12 @@ # 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 import exceptions from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils + LOG = logging.getLogger(__name__) @@ -28,9 +27,10 @@ class DeleteFloatingIp(base.Scenario): self.context_cfg = context_cfg self.options = self.scenario_cfg['options'] - self.floating_ip_id = self.options.get("floating_ip_id", None) + self.floating_ip_id = self.options["floating_ip_id"] + self.retry = self.options.get("retry", 1) - self.nova_client = op_utils.get_nova_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False def setup(self): @@ -44,11 +44,13 @@ class DeleteFloatingIp(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.delete_floating_ip(nova_client=self.nova_client, - floatingip_id=self.floating_ip_id) - if status: - result.update({"delete_floating_ip": 1}) - LOG.info("Delete floating ip successful!") - else: + status = openstack_utils.delete_floating_ip( + self.shade_client, self.floating_ip_id, + retry=self.retry) + if not status: result.update({"delete_floating_ip": 0}) LOG.error("Delete floating ip failed!") + raise exceptions.ScenarioDeleteFloatingIPError + + result.update({"delete_floating_ip": 1}) + LOG.info("Delete floating ip successful!") diff --git a/yardstick/benchmark/scenarios/lib/delete_image.py b/yardstick/benchmark/scenarios/lib/delete_image.py index 0e3a853e5..008f104b2 100644 --- a/yardstick/benchmark/scenarios/lib/delete_image.py +++ b/yardstick/benchmark/scenarios/lib/delete_image.py @@ -7,13 +7,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -26,12 +24,14 @@ class DeleteImage(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.image_name = self.options.get("image_name", "TestImage") - self.image_id = None + self.image_name_or_id = self.options["name_or_id"] + self.wait = self.options.get("wait", False) + self.timeout = self.options.get("timeout", 3600) + self.delete_objects = self.options.get("delete_objects", True) - self.glance_client = op_utils.get_glance_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -46,16 +46,14 @@ class DeleteImage(base.Scenario): if not self.setup_done: self.setup() - self.image_id = op_utils.get_image_id(self.glance_client, self.image_name) - LOG.info("Deleting image: %s", self.image_name) - status = op_utils.delete_image(self.glance_client, self.image_id) + status = openstack_utils.delete_image( + self.shade_client, self.image_name_or_id, wait=self.wait, + timeout=self.timeout, delete_objects=self.delete_objects) - if status: - LOG.info("Delete image successful!") - values = [status] - else: - LOG.info("Delete image failed!") - values = [] + if not status: + result.update({"delete_image": 0}) + LOG.error("Delete image failed!") + raise exceptions.ScenarioDeleteImageError - keys = self.scenario_cfg.get('output', '').split() - return self._push_to_outputs(keys, values) + result.update({"delete_image": 1}) + LOG.info("Delete image successful!") diff --git a/yardstick/benchmark/scenarios/lib/delete_keypair.py b/yardstick/benchmark/scenarios/lib/delete_keypair.py index 135139959..a52a38567 100644 --- a/yardstick/benchmark/scenarios/lib/delete_keypair.py +++ b/yardstick/benchmark/scenarios/lib/delete_keypair.py @@ -6,14 +6,12 @@ # 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 import exceptions from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils + LOG = logging.getLogger(__name__) @@ -26,11 +24,11 @@ class DeleteKeypair(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.key_name = self.options.get("key_name", "yardstick_key") + self.key_name = self.options["key_name"] - self.nova_client = op_utils.get_nova_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,12 +43,13 @@ class DeleteKeypair(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.delete_keypair(self.nova_client, - self.key_name) + status = openstack_utils.delete_keypair(self.shade_client, + self.key_name) - if status: - result.update({"delete_keypair": 1}) - LOG.info("Delete keypair successful!") - else: + if not status: result.update({"delete_keypair": 0}) - LOG.info("Delete keypair failed!") + LOG.error("Delete keypair failed!") + raise exceptions.ScenarioDeleteKeypairError + + result.update({"delete_keypair": 1}) + LOG.info("Delete keypair successful!") diff --git a/yardstick/benchmark/scenarios/lib/delete_network.py b/yardstick/benchmark/scenarios/lib/delete_network.py index e8796bf82..8874e8b1e 100644 --- a/yardstick/benchmark/scenarios/lib/delete_network.py +++ b/yardstick/benchmark/scenarios/lib/delete_network.py @@ -7,13 +7,12 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions + LOG = logging.getLogger(__name__) @@ -26,11 +25,11 @@ class DeleteNetwork(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.network_id = self.options.get("network_id", None) + self.network_name_or_id = self.options["network_name_or_id"] - self.neutron_client = op_utils.get_neutron_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,11 +44,13 @@ class DeleteNetwork(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.delete_neutron_net(self.neutron_client, - network_id=self.network_id) - if status: - result.update({"delete_network": 1}) - LOG.info("Delete network successful!") - else: + status = openstack_utils.delete_neutron_net(self.shade_client, + self.network_name_or_id) + + if not status: result.update({"delete_network": 0}) LOG.error("Delete network failed!") + raise exceptions.ScenarioDeleteNetworkError + + result.update({"delete_network": 1}) + LOG.info("Delete network successful!") diff --git a/yardstick/benchmark/scenarios/lib/delete_router.py b/yardstick/benchmark/scenarios/lib/delete_router.py index 358fd40cf..5e7467b2c 100644 --- a/yardstick/benchmark/scenarios/lib/delete_router.py +++ b/yardstick/benchmark/scenarios/lib/delete_router.py @@ -7,13 +7,12 @@ # 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 import exceptions from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils + LOG = logging.getLogger(__name__) @@ -28,9 +27,9 @@ class DeleteRouter(base.Scenario): self.context_cfg = context_cfg self.options = self.scenario_cfg['options'] - self.router_id = self.options.get("router_id", None) + self.router_id = self.options["router_id"] - self.neutron_client = op_utils.get_neutron_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,11 +44,12 @@ class DeleteRouter(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.delete_neutron_router(self.neutron_client, - router_id=self.router_id) - if status: - result.update({"delete_router": 1}) - LOG.info("Delete router successful!") - else: + status = openstack_utils.delete_neutron_router(self.shade_client, + self.router_id) + if not status: result.update({"delete_router": 0}) LOG.error("Delete router failed!") + raise exceptions.ScenarioDeleteRouterError + + result.update({"delete_router": 1}) + LOG.info("Delete router successful!") diff --git a/yardstick/benchmark/scenarios/lib/delete_router_interface.py b/yardstick/benchmark/scenarios/lib/delete_router_interface.py index 117c80811..e71aed3ef 100644 --- a/yardstick/benchmark/scenarios/lib/delete_router_interface.py +++ b/yardstick/benchmark/scenarios/lib/delete_router_interface.py @@ -7,13 +7,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -28,10 +26,11 @@ class DeleteRouterInterface(base.Scenario): self.context_cfg = context_cfg self.options = self.scenario_cfg['options'] - self.subnet_id = self.options.get("subnet_id", None) - self.router_id = self.options.get("router_id", None) + self.router = self.options["router"] + self.subnet_id = self.options.get("subnet_id") + self.port_id = self.options.get("port_id") - self.neutron_client = op_utils.get_neutron_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -46,12 +45,13 @@ class DeleteRouterInterface(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.remove_interface_router(self.neutron_client, - router_id=self.router_id, - subnet_id=self.subnet_id) - if status: - result.update({"delete_router_interface": 1}) - LOG.info("Delete router interface successful!") - else: + status = openstack_utils.remove_router_interface( + self.shade_client, self.router, subnet_id=self.subnet_id, + port_id=self.port_id) + if not status: result.update({"delete_router_interface": 0}) LOG.error("Delete router interface failed!") + raise exceptions.ScenarioRemoveRouterIntError + + result.update({"delete_router_interface": 1}) + LOG.info("Delete router interface successful!") diff --git a/yardstick/benchmark/scenarios/lib/delete_server.py b/yardstick/benchmark/scenarios/lib/delete_server.py index bcd8faba7..46229ff04 100644 --- a/yardstick/benchmark/scenarios/lib/delete_server.py +++ b/yardstick/benchmark/scenarios/lib/delete_server.py @@ -6,14 +6,11 @@ # 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 import exceptions from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils LOG = logging.getLogger(__name__) @@ -26,9 +23,13 @@ class DeleteServer(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] - self.server_id = self.options.get("server_id", None) - self.nova_client = op_utils.get_nova_client() + self.options = self.scenario_cfg["options"] + self.server_name_or_id = self.options["name_or_id"] + self.wait = self.options.get("wait", False) + self.timeout = self.options.get("timeout", 180) + self.delete_ips = self.options.get("delete_ips", False) + self.delete_ip_retry = self.options.get("delete_ip_retry", 1) + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -43,9 +44,15 @@ class DeleteServer(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.delete_instance(self.nova_client, - instance_id=self.server_id) - if status: - LOG.info("Delete server successful!") - else: + status = openstack_utils.delete_instance( + self.shade_client, self.server_name_or_id, wait=self.wait, + timeout=self.timeout, delete_ips=self.delete_ips, + delete_ip_retry=self.delete_ip_retry) + + if not status: + result.update({"delete_server": 0}) LOG.error("Delete server failed!") + raise exceptions.ScenarioDeleteServerError + + result.update({"delete_server": 1}) + LOG.info("Delete server successful!") diff --git a/yardstick/benchmark/scenarios/lib/delete_volume.py b/yardstick/benchmark/scenarios/lib/delete_volume.py index ea2b85812..59e19dfdf 100644 --- a/yardstick/benchmark/scenarios/lib/delete_volume.py +++ b/yardstick/benchmark/scenarios/lib/delete_volume.py @@ -6,14 +6,11 @@ # 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 import exceptions from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils LOG = logging.getLogger(__name__) @@ -26,11 +23,13 @@ class DeleteVolume(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.volume_id = self.options.get("volume_id", None) + self.volume_name_or_id = self.options.get("name_or_id") + self.wait = self.options.get("wait", True) + self.timeout = self.options.get("timeout") - self.cinder_client = op_utils.get_cinder_client() + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -45,11 +44,14 @@ class DeleteVolume(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.delete_volume(self.cinder_client, self.volume_id) + status = openstack_utils.delete_volume( + self.shade_client, name_or_id=self.volume_name_or_id, + wait=self.wait, timeout=self.timeout) - if status: - result.update({"delete_volume": 1}) - LOG.info("Delete volume successful!") - else: + if not status: result.update({"delete_volume": 0}) - LOG.info("Delete volume failed!") + LOG.error("Delete volume failed!") + raise exceptions.ScenarioDeleteVolumeError + + result.update({"delete_volume": 1}) + LOG.info("Delete volume successful!") diff --git a/yardstick/benchmark/scenarios/lib/detach_volume.py b/yardstick/benchmark/scenarios/lib/detach_volume.py index 0b02a3a81..76c0167bd 100644 --- a/yardstick/benchmark/scenarios/lib/detach_volume.py +++ b/yardstick/benchmark/scenarios/lib/detach_volume.py @@ -6,14 +6,12 @@ # 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 import exceptions from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils + LOG = logging.getLogger(__name__) @@ -26,10 +24,14 @@ class DetachVolume(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.server_id = self.options.get("server_id", "TestServer") - self.volume_id = self.options.get("volume_id", None) + self.server = self.options["server_name_or_id"] + self.volume = self.options["volume_name_or_id"] + self.wait = self.options.get("wait", True) + self.timeout = self.options.get("timeout") + + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -44,11 +46,14 @@ class DetachVolume(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.detach_volume(self.server_id, self.volume_id) + status = openstack_utils.detach_volume( + self.shade_client, self.server, self.volume, + wait=self.wait, timeout=self.timeout) - if status: - result.update({"detach_volume": 1}) - LOG.info("Detach volume from server successful!") - else: + if not status: result.update({"detach_volume": 0}) - LOG.info("Detach volume from server failed!") + LOG.error("Detach volume from server failed!") + raise exceptions.ScenarioDetachVolumeError + + result.update({"detach_volume": 1}) + LOG.info("Detach volume from server successful!") diff --git a/yardstick/benchmark/scenarios/lib/get_flavor.py b/yardstick/benchmark/scenarios/lib/get_flavor.py index d5e33947e..6727a7343 100644 --- a/yardstick/benchmark/scenarios/lib/get_flavor.py +++ b/yardstick/benchmark/scenarios/lib/get_flavor.py @@ -6,14 +6,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -26,8 +23,12 @@ class GetFlavor(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] - self.flavor_name = self.options.get("flavor_name", "TestFlavor") + self.options = self.scenario_cfg["options"] + self.name_or_id = self.options["name_or_id"] + self.filters = self.options.get("filters") + self.get_extra = self.options.get("get_extra", True) + self.shade_client = openstack_utils.get_shade_client() + self.setup_done = False def setup(self): @@ -41,14 +42,18 @@ class GetFlavor(base.Scenario): if not self.setup_done: self.setup() - LOG.info("Querying flavor: %s", self.flavor_name) - flavor = op_utils.get_flavor_by_name(self.flavor_name) - if flavor: - LOG.info("Get flavor successful!") - values = [self._change_obj_to_dict(flavor)] - else: - LOG.info("Get flavor: no flavor matched!") - values = [] + LOG.info("Querying flavor: %s", self.name_or_id) + flavor = openstack_utils.get_flavor( + self.shade_client, self.name_or_id, filters=self.filters, + get_extra=self.get_extra) + + if not flavor: + result.update({"get_flavor": 0}) + LOG.error("Get flavor failed!") + raise exceptions.ScenarioGetFlavorError - keys = self.scenario_cfg.get('output', '').split() + result.update({"get_flavor": 1}) + LOG.info("Get flavor successful!") + values = [flavor] + keys = self.scenario_cfg.get("output", '').split() return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/lib/get_server.py b/yardstick/benchmark/scenarios/lib/get_server.py index fcf47c80d..f65fa9ebf 100644 --- a/yardstick/benchmark/scenarios/lib/get_server.py +++ b/yardstick/benchmark/scenarios/lib/get_server.py @@ -6,14 +6,11 @@ # 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 +from yardstick.common import openstack_utils +from yardstick.common import exceptions LOG = logging.getLogger(__name__) @@ -21,63 +18,58 @@ 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 + Parameters: + name_or_id - Name or ID of the server + type: string + filters - meta data to use for further filtering + type: dict + detailed: Whether or not to add detailed additional information. + type: bool + bare: Whether to skip adding any additional information to the server + record. + type: bool + all_projects: Whether to get server from all projects or just the current + auth scoped project. + type: bool + + Outputs: rc - response code of getting server instance - 0 for success - 1 for failure + 1 for success + 0 for failure type: int - unit: N/A server - instance of the server type: dict - unit: N/A + """ - __scenario_type__ = "GetServer" + __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.options = self.scenario_cfg['options'] - self.server_id = self.options.get("server_id") - if self.server_id: - LOG.debug('Server id is %s', self.server_id) + self.server_name_or_id = self.options.get('name_or_id') + self.filters = self.options.get('filters') + self.detailed = self.options.get('detailed', False) + self.bare = self.options.get('bare', False) - 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() + self.shade_client = openstack_utils.get_shade_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() + server = openstack_utils.get_server( + self.shade_client, name_or_id=self.server_name_or_id, + filters=self.filters, detailed=self.detailed, bare=self.bare) - if server: - LOG.info("Get server successful!") - values = [0, self._change_obj_to_dict(server)] - else: - LOG.info("Get server failed!") - values = [1] + if not server: + result.update({'get_server': 0}) + LOG.error('Get Server failed!') + raise exceptions.ScenarioGetServerError + result.update({'get_server': 1}) + LOG.info('Get Server successful!') + keys = self.scenario_cfg.get('output', '').split() + values = [server] return self._push_to_outputs(keys, values) diff --git a/yardstick/benchmark/scenarios/networking/iperf3.py b/yardstick/benchmark/scenarios/networking/iperf3.py index 98c45990e..51e044e7b 100644 --- a/yardstick/benchmark/scenarios/networking/iperf3.py +++ b/yardstick/benchmark/scenarios/networking/iperf3.py @@ -92,7 +92,7 @@ For more info see http://software.es.net/iperf def teardown(self): LOG.debug("teardown") self.host.close() - status, stdout, stderr = self.target.execute("pkill iperf3") + status, _, stderr = self.target.execute("pkill iperf3") if status: LOG.warning(stderr) self.target.close() @@ -145,7 +145,7 @@ For more info see http://software.es.net/iperf LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.host.execute(cmd) + status, stdout, _ = self.host.execute(cmd) if status: # error cause in json dict on stdout raise RuntimeError(stdout) @@ -165,16 +165,17 @@ For more info see http://software.es.net/iperf bit_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); " % \ - (bytes_per_second, sla_bytes_per_second) + self.verify_SLA( + bytes_per_second >= sla_bytes_per_second, + "bytes_per_second %d < sla:bytes_per_second (%d); " + % (bytes_per_second, sla_bytes_per_second)) else: sla_jitter = float(sla_iperf["jitter"]) jitter_ms = float(iperf_result["end"]["sum"]["jitter_ms"]) - assert jitter_ms <= sla_jitter, \ - "jitter_ms %f > sla:jitter %f; " % \ - (jitter_ms, sla_jitter) + self.verify_SLA(jitter_ms <= sla_jitter, + "jitter_ms %f > sla:jitter %f; " + % (jitter_ms, sla_jitter)) def _test(): diff --git a/yardstick/benchmark/scenarios/networking/moongen_testpmd.bash b/yardstick/benchmark/scenarios/networking/moongen_testpmd.bash new file mode 100644 index 000000000..3e92cc900 --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/moongen_testpmd.bash @@ -0,0 +1,62 @@ +############################################################################## +# Copyright (c) 2018 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 +############################################################################## +#!/bin/bash + +set -e + +# Commandline arguments +MOONGEN_PORT1_MAC=$1 # MAC address of the peer port +MOONGEN_PORT2_MAC=$2 # MAC address of the peer port +TESTPMD_QUEUE=$3 + +BIND_ROOT='/opt/nsb_bin' +DRIVER_ROOT='/opt/tempT/dpdk-17.02/' + +load_modules() +{ + if ! lsmod | grep "uio" &> /dev/null; then + modprobe uio + fi + + if ! lsmod | grep "igb_uio" &> /dev/null; then + insmod ${DRIVER_ROOT}/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko + fi + + if ! lsmod | grep "rte_kni" &> /dev/null; then + insmod ${DRIVER_ROOT}/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko + fi +} + +change_permissions() +{ + chmod 777 /sys/bus/pci/drivers/virtio-pci/* + chmod 777 /sys/bus/pci/drivers/igb_uio/* +} + +add_interface_to_dpdk(){ + interfaces=$(lspci |grep Eth |tail -n +2 |awk '{print $1}') + ${BIND_ROOT}/dpdk_nic_bind.py --bind=igb_uio $interfaces &> /dev/null +} + +run_testpmd() +{ + blacklist=$(lspci |grep Eth |awk '{print $1}'|head -1) + cd ${DRIVER_ROOT} + sudo ./x86_64-native-linuxapp-gcc/app/testpmd -c 0x3f -n 4 -b $blacklist -- -a --nb-cores=4 --coremask=0x3c --burst=64 --txd=4096 --rxd=4096 --rxq=$TESTPMD_QUEUE --txq=$TESTPMD_QUEUE --rss-udp --eth-peer=0,$MOONGEN_PORT1_MAC --eth-peer=1,$MOONGEN_PORT2_MAC --forward-mode=mac +} + +main() +{ + load_modules + change_permissions + add_interface_to_dpdk + run_testpmd +} + +main diff --git a/yardstick/benchmark/scenarios/networking/moongen_testpmd.py b/yardstick/benchmark/scenarios/networking/moongen_testpmd.py new file mode 100644 index 000000000..e3bd7af46 --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/moongen_testpmd.py @@ -0,0 +1,379 @@ +# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" VsperfDPDK specific scenario definition """ + +from __future__ import absolute_import +import pkg_resources +import logging +import subprocess +import time +import re +from oslo_serialization import jsonutils + +import yardstick.ssh as ssh +import yardstick.common.utils as utils +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) + + +class MoongenTestPMD(base.Scenario): + """Execute vsperf with defined parameters + + Parameters: + frame_size - a frame size for which test should be executed; + Multiple frame sizes can be tested by modification of sequence runner + section inside TC YAML definition. + type: string + default: "64" + multistream - the number of simulated streams + type: string + default: 0 (disabled) + testpmd_queue - specifies how many queues you will use the VM + only useful when forward_type is true. + type: int + default: 1(one queue) + trafficgen_port1 - specifies device name of 1st interface connected to + the trafficgen + type: string + default: NA + trafficgen_port2 - specifies device name of 2nd interface connected to + the trafficgen + type: string + default: NA + moongen_host_user - specifies moongen host ssh user name + type: string + default: root + moongen_host_passwd - specifies moongen host ssh user password + type: string + default: root + moongen_host_ip - specifies moongen host ssh ip address + type: string + default NA + moongen_dir - specifies where is the moongen installtion dir + type: string + default NA + moongen_runBidirec - specifies moongen will run in one traffic + or two traffic. + type: string + default true + Package_Loss - specifies the package_Loss number in moongen server. + type: int + default 0(0%) + SearchRuntime - specifies the SearchRuntime and validation time + on moongen server. + type: int + default 60(s) + moongen_port1_mac - moongen server port1 mac address. + type: string + default NA + moongen_port2_mac - moongen server port2 mac address. + type: string + default NA + forward_type - VM forward type is l2fwd or testpmd. + type: string + default: testpmd + """ + __scenario_type__ = "MoongenTestPMD" + + TESTPMD_SCRIPT = 'moongen_testpmd.bash' + VSPERF_CONFIG = '/tmp/opnfv-vsperf-cfg.lua' + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.forward_setup_done = False + self.options = scenario_cfg.get('options', {}) + self.moongen_host_user = \ + self.options.get('moongen_host_user', "root") + self.moongen_host_passwd = \ + self.options.get('moongen_host_passwd', "r00t") + self.moongen_dir = \ + self.options.get('moongen_dir', '~/moongen.py') + self.testpmd_queue = \ + self.options.get('testpmd_queue', 1) + self.moongen_host_ip = \ + self.options.get('moongen_host_ip', "127.0.0.1") + self.moongen_port1_mac = \ + self.options.get('moongen_port1_mac', None) + self.moongen_port2_mac = \ + self.options.get('moongen_port2_mac', None) + self.tg_port1 = \ + self.options.get('trafficgen_port1', "enp2s0f0") + self.tg_port2 = \ + self.options.get('trafficgen_port2', "enp2s0f1") + self.forward_type = \ + self.options.get('forward_type', 'testpmd') + self.tgen_port1_mac = None + self.tgen_port2_mac = None + + def setup(self): + """scenario setup""" + host = self.context_cfg['host'] + + task_id = self.scenario_cfg['task_id'] + context_number = task_id.split('-')[0] + self.tg_port1_nw = 'demo' + \ + "-" + context_number + "-" + \ + self.options.get('trafficgen_port1_nw', 'test2') + self.tg_port2_nw = 'demo' + \ + "-" + context_number + "-" + \ + self.options.get('trafficgen_port2_nw', 'test3') + + # copy vsperf conf to VM + self.client = ssh.SSH.from_node(host, defaults={"user": "ubuntu"}) + # traffic generation could last long + self.client.wait(timeout=1800) + + self.server = ssh.SSH( + self.moongen_host_user, + self.moongen_host_ip, + password=self.moongen_host_passwd + ) + # traffic generation could last long + self.server.wait(timeout=1800) + + self.setup_done = True + + def forward_setup(self): + """forward tool setup""" + + # setup forward loopback in VM + self.testpmd_script = pkg_resources.resource_filename( + 'yardstick.benchmark.scenarios.networking', + self.TESTPMD_SCRIPT) + + self.client._put_file_shell(self.testpmd_script, + '~/testpmd_vsperf.sh') + + # disable Address Space Layout Randomization (ASLR) + cmd = "echo 0 | sudo tee /proc/sys/kernel/randomize_va_space" + self.client.send_command(cmd) + + if not self._is_forward_setup(): + self.tgen_port1_ip = \ + utils.get_port_ip(self.client, self.tg_port1) + self.tgen_port1_mac = \ + utils.get_port_mac(self.client, self.tg_port1) + self.client.run("tee ~/.testpmd.ipaddr.port1 > /dev/null", + stdin=self.tgen_port1_ip) + self.client.run("tee ~/.testpmd.macaddr.port1 > /dev/null", + stdin=self.tgen_port1_mac) + self.tgen_port2_ip = \ + utils.get_port_ip(self.client, self.tg_port2) + self.tgen_port2_mac = \ + utils.get_port_mac(self.client, self.tg_port2) + self.client.run("tee ~/.testpmd.ipaddr.port2 > /dev/null", + stdin=self.tgen_port2_ip) + self.client.run("tee ~/.testpmd.macaddr.port2 > /dev/null", + stdin=self.tgen_port2_mac) + else: + cmd = "cat ~/.testpmd.macaddr.port1" + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError(stderr) + self.tgen_port1_mac = stdout + cmd = "cat ~/.testpmd.ipaddr.port1" + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError(stderr) + self.tgen_port1_ip = stdout + cmd = "cat ~/.testpmd.macaddr.port2" + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError(stderr) + self.tgen_port2_mac = stdout + cmd = "cat ~/.testpmd.ipaddr.port2" + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError(stderr) + self.tgen_port2_ip = stdout + + LOG.info("forward type is %s", self.forward_type) + if self.forward_type == 'testpmd': + cmd = "sudo ip link set %s down" % (self.tg_port1) + LOG.debug("Executing command: %s", cmd) + self.client.execute(cmd) + cmd = "sudo ip link set %s down" % (self.tg_port2) + LOG.debug("Executing command: %s", cmd) + self.client.execute(cmd) + cmd = "screen -d -m sudo -E bash ~/testpmd_vsperf.sh %s %s %d" % \ + (self.moongen_port1_mac, self.moongen_port2_mac, + self.testpmd_queue) + LOG.debug("Executing command: %s", cmd) + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError(stderr) + + elif self.forward_type == 'l2fwd': + cmd = ('sed -i "s/static char *net1 = \\\"eth1\\\";' + '/static char *net1 = \\\"%s %s %s\\\";/g" /home/l2fwd/l2fwd.c' + % (self.tg_port1, self.tgen_port1_ip, self.moongen_port1_mac)) + LOG.debug("Executing command: %s", cmd) + status, stdout, stderr = self.client.execute(cmd) + + cmd = ('sed -i "s/static char *net2 = \\\"eth2\\\";' + '/static char *net2 = \\\"%s %s %s\\\";/g" /home/l2fwd/l2fwd.c' + % (self.tg_port2, self.tgen_port2_ip, self.moongen_port2_mac)) + LOG.debug("Executing command: %s", cmd) + status, stdout, stderr = self.client.execute(cmd) + + cmd = ('cd /home/l2fwd/;make;./gen_debian_package.sh;' + 'sudo dpkg -i *.deb;' + 'sudo modprobe l2fwd') + LOG.debug("Executing command: %s", cmd) + status, stdout, stderr = self.client.execute(cmd) + + time.sleep(1) + + self.forward_setup_done = True + + def _is_forward_setup(self): + """Is forward already setup in the host?""" + if self.forward_type is 'testpmd': + is_run = True + cmd = "ip a | grep %s 2>/dev/null" % (self.tg_port1) + LOG.debug("Executing command: %s", cmd) + _, stdout, _ = self.client.execute(cmd) + if stdout: + is_run = False + return is_run + elif self.forward_type is 'l2fwd': + cmd = ('sudo lsmod |grep l2fwd') + LOG.debug("Executing command: %s", cmd) + _, stdout, _ = self.client.execute(cmd) + if stdout: + return True + else: + return False + + def generate_config_file(self, frame_size, multistream, + runBidirec, tg_port1_vlan, tg_port2_vlan, + SearchRuntime, Package_Loss): + out_text = """\ +VSPERF { +testType = 'throughput', +nrFlows = %d, +runBidirec = %s, +frameSize = %d, +srcMacs = {\'%s\', \'%s\'}, +dstMacs = {\'%s\', \'%s\'}, +vlanIds = {%d, %d}, +searchRunTime = %d, +validationRunTime = %d, +acceptableLossPct = %d, +ports = {0,1}, +} +""" % (multistream, runBidirec, frame_size, self.moongen_port1_mac, + self.moongen_port2_mac, self.tgen_port1_mac, self.tgen_port2_mac, + tg_port1_vlan, tg_port2_vlan, SearchRuntime, SearchRuntime, Package_Loss) + with open(self.VSPERF_CONFIG, "wt") as out_file: + out_file.write(out_text) + self.CONFIG_FILE = True + + def result_to_data(self, result): + search_pattern = re.compile( + r'\[REPORT\]\s+total\:\s+' + r'Tx\s+frames\:\s+(\d+)\s+' + r'Rx\s+Frames\:\s+(\d+)\s+' + r'frame\s+loss\:\s+(\d+)\,' + r'\s+(\d+\.\d+|\d+)%\s+' + r'Tx\s+Mpps\:\s+(\d+.\d+|\d+)\s+' + r'Rx\s+Mpps\:\s+(\d+\.\d+|\d+)', + re.IGNORECASE) + results_match = search_pattern.search(result) + if results_match: + rx_mpps = float(results_match.group(6)) + tx_mpps = float(results_match.group(5)) + else: + rx_mpps = 0 + tx_mpps = 0 + test_result = {"rx_mpps": rx_mpps, "tx_mpps": tx_mpps} + self.TO_DATA = True + return test_result + + def run(self, result): + """ execute the vsperf benchmark and return test results + within result dictionary + """ + + if not self.setup_done: + self.setup() + + # get vsperf options + multistream = self.options.get("multistream", 1) + + if not self.forward_setup_done: + self.forward_setup() + + if 'frame_size' in self.options: + frame_size = self.options.get("frame_size", 64) + Package_Loss = self.options.get("Package_Loss", 0) + runBidirec = self.options.get("moongen_runBidirec", + "true") + SearchRuntime = self.options.get("SearchRuntime", 10) + + cmd = "openstack network show %s --format json -c " \ + "provider:segmentation_id" % (self.tg_port1_nw) + LOG.debug("Executing command: %s", cmd) + output = subprocess.check_output(cmd, shell=True) + try: + tg_port1_vlan = jsonutils.loads(output).get("provider:segmentation_id", 1) + except TypeError: + tg_port1_vlan = 1 + + cmd = "openstack network show %s --format json -c " \ + "provider:segmentation_id" % (self.tg_port2_nw) + LOG.debug("Executing command: %s", cmd) + output = subprocess.check_output(cmd, shell=True) + try: + tg_port2_vlan = jsonutils.loads(output).get("provider:segmentation_id", 2) + except TypeError: + tg_port2_vlan = 2 + + self.generate_config_file(frame_size, multistream, + runBidirec, tg_port1_vlan, + tg_port2_vlan, SearchRuntime, Package_Loss) + + self.server.execute("rm -f -- %s/opnfv-vsperf-cfg.lua" % + (self.moongen_dir)) + self.server._put_file_shell(self.VSPERF_CONFIG, + "%s/opnfv-vsperf-cfg.lua" + % (self.moongen_dir)) + + # execute moongen + cmd = ("cd %s;./MoonGen/build/MoonGen ./trafficgen.lua" + % (self.moongen_dir)) + status, stdout, stderr = self.server.execute(cmd) + if status: + raise RuntimeError(stderr) + + moongen_result = self.result_to_data(stdout) + LOG.info(moongen_result) + result.update(moongen_result) + + if "sla" in self.scenario_cfg: + throughput_rx_mpps = int( + self.scenario_cfg["sla"]["throughput_rx_mpps"]) + + self.verify_SLA( + throughput_rx_mpps <= moongen_result["tx_mpps"], + "sla_throughput_rx_mpps %f > throughput_rx_mpps(%f); " + % (throughput_rx_mpps, moongen_result["tx_mpps"])) + + def teardown(self): + """cleanup after the test execution""" + + # execute external setup script + self.setup_done = False diff --git a/yardstick/benchmark/scenarios/networking/netperf.py b/yardstick/benchmark/scenarios/networking/netperf.py index a8d9010ed..9f1a81413 100755 --- a/yardstick/benchmark/scenarios/networking/netperf.py +++ b/yardstick/benchmark/scenarios/networking/netperf.py @@ -104,7 +104,9 @@ class Netperf(base.Scenario): cmd_args = "-H %s -l %s -t %s" % (ipaddr, testlen, testname) # get test specific options - default_args = "-O 'THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY'" + output_opt = options.get( + "output_opt", "THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY") + default_args = "-O %s" % output_opt cmd_args += " -- %s" % default_args option_pair_list = [("send_msg_size", "-m"), ("recv_msg_size", "-M"), @@ -136,9 +138,9 @@ class Netperf(base.Scenario): sla_max_mean_latency = int( self.scenario_cfg["sla"]["mean_latency"]) - assert mean_latency <= sla_max_mean_latency, \ - "mean_latency %f > sla_max_mean_latency(%f); " % \ - (mean_latency, sla_max_mean_latency) + self.verify_SLA(mean_latency <= sla_max_mean_latency, + "mean_latency %f > sla_max_mean_latency(%f); " + % (mean_latency, sla_max_mean_latency)) def _test(): diff --git a/yardstick/benchmark/scenarios/networking/netperf_node.py b/yardstick/benchmark/scenarios/networking/netperf_node.py index d52e6b9e1..0ad2ecff5 100755 --- a/yardstick/benchmark/scenarios/networking/netperf_node.py +++ b/yardstick/benchmark/scenarios/networking/netperf_node.py @@ -156,9 +156,10 @@ class NetperfNode(base.Scenario): sla_max_mean_latency = int( self.scenario_cfg["sla"]["mean_latency"]) - assert mean_latency <= sla_max_mean_latency, \ - "mean_latency %f > sla_max_mean_latency(%f); " % \ - (mean_latency, sla_max_mean_latency) + self.verify_SLA( + mean_latency <= sla_max_mean_latency, + "mean_latency %f > sla_max_mean_latency(%f); " + % (mean_latency, sla_max_mean_latency)) def teardown(self): """remove netperf from nodes after test""" diff --git a/yardstick/benchmark/scenarios/networking/nstat.py b/yardstick/benchmark/scenarios/networking/nstat.py index 10c560769..ea067f8ab 100644 --- a/yardstick/benchmark/scenarios/networking/nstat.py +++ b/yardstick/benchmark/scenarios/networking/nstat.py @@ -121,4 +121,4 @@ class Nstat(base.Scenario): if rate > sla_rate: sla_error += "%s rate %f > sla:%s_rate(%f); " % \ (i, rate, i, sla_rate) - assert sla_error == "", sla_error + self.verify_SLA(sla_error == "", sla_error) diff --git a/yardstick/benchmark/scenarios/networking/ping.py b/yardstick/benchmark/scenarios/networking/ping.py index e7d9beea8..1c9510220 100644 --- a/yardstick/benchmark/scenarios/networking/ping.py +++ b/yardstick/benchmark/scenarios/networking/ping.py @@ -91,9 +91,10 @@ class Ping(base.Scenario): result.update(utils.flatten_dict_key(ping_result)) if sla_max_rtt is not None: sla_max_rtt = float(sla_max_rtt) - assert rtt_result[target_vm_name] <= sla_max_rtt,\ - "rtt %f > sla: max_rtt(%f); " % \ - (rtt_result[target_vm_name], sla_max_rtt) + self.verify_SLA( + rtt_result[target_vm_name] <= sla_max_rtt, + "rtt %f > sla: max_rtt(%f); " + % (rtt_result[target_vm_name], sla_max_rtt)) else: LOG.error("ping '%s' '%s' timeout", options, target_vm) # we need to specify a result to satisfy influxdb schema @@ -103,12 +104,13 @@ class Ping(base.Scenario): # store result before potential AssertionError result.update(utils.flatten_dict_key(ping_result)) if sla_max_rtt is not None: - raise AssertionError("packet dropped rtt {:f} > sla: max_rtt({:f})".format( - rtt_result[target_vm_name], sla_max_rtt)) - + self.verify_SLA(rtt_result[target_vm_name] <= sla_max_rtt, + "packet dropped rtt %f > sla: max_rtt(%f)" + % (rtt_result[target_vm_name], sla_max_rtt)) else: - raise AssertionError( - "packet dropped rtt {:f}".format(rtt_result[target_vm_name])) + self.verify_SLA(False, + "packet dropped rtt %f" + % (rtt_result[target_vm_name])) def _test(): # pragma: no cover diff --git a/yardstick/benchmark/scenarios/networking/ping6.py b/yardstick/benchmark/scenarios/networking/ping6.py index 74855a10f..377278004 100644 --- a/yardstick/benchmark/scenarios/networking/ping6.py +++ b/yardstick/benchmark/scenarios/networking/ping6.py @@ -59,8 +59,7 @@ class Ping6(base.Scenario): # pragma: no cover self._ssh_host(node_name) self.client._put_file_shell( self.pre_setup_script, '~/pre_setup.sh') - status, stdout, stderr = self.client.execute( - "sudo bash pre_setup.sh") + self.client.execute("sudo bash pre_setup.sh") def _get_controller_node(self, host_list): for host_name in host_list: @@ -122,7 +121,7 @@ class Ping6(base.Scenario): # pragma: no cover cmd = "sudo bash %s %s %s" % \ (setup_bash_file, self.openrc, self.external_network) LOG.debug("Executing setup command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) + self.client.execute(cmd) self.setup_done = True @@ -171,8 +170,9 @@ class Ping6(base.Scenario): # pragma: no cover result["rtt"] = float(stdout) if "sla" in self.scenario_cfg: sla_max_rtt = int(self.scenario_cfg["sla"]["max_rtt"]) - assert result["rtt"] <= sla_max_rtt, \ - "rtt %f > sla:max_rtt(%f); " % (result["rtt"], sla_max_rtt) + self.verify_SLA(result["rtt"] <= sla_max_rtt, + "rtt %f > sla:max_rtt(%f); " + % (result["rtt"], sla_max_rtt)) else: LOG.error("ping6 timeout!!!") self.run_done = True @@ -216,5 +216,4 @@ class Ping6(base.Scenario): # pragma: no cover self._ssh_host(node_name) self.client._put_file_shell( self.post_teardown_script, '~/post_teardown.sh') - status, stdout, stderr = self.client.execute( - "sudo bash post_teardown.sh") + self.client.execute("sudo bash post_teardown.sh") diff --git a/yardstick/benchmark/scenarios/networking/pktgen.py b/yardstick/benchmark/scenarios/networking/pktgen.py index b79b91539..c78108adb 100644 --- a/yardstick/benchmark/scenarios/networking/pktgen.py +++ b/yardstick/benchmark/scenarios/networking/pktgen.py @@ -87,7 +87,7 @@ class Pktgen(base.Scenario): self.server.send_command(cmd) self.client.send_command(cmd) - """multiqueue setup""" + # multiqueue setup if not self._is_irqbalance_disabled(): self._disable_irqbalance() @@ -112,18 +112,14 @@ class Pktgen(base.Scenario): 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) if "0" in stdout: is_disabled = True @@ -132,49 +128,35 @@ class Pktgen(base.Scenario): 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) + self.server.run(cmd) + self.client.run(cmd) cmd = "sudo service irqbalance stop" - status, stdout, stderr = self.server.execute(cmd) - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + self.server.run(cmd) + self.client.run(cmd) cmd = "sudo service irqbalance disable" - status, stdout, stderr = self.server.execute(cmd) - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + self.server.run(cmd) + self.client.run(cmd) 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) 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) + self.server.run(cmd) + self.client.run(cmd) 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) 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) + self.server.run(cmd) + self.client.run(cmd) if queue_number == 1: return @@ -186,44 +168,32 @@ class Pktgen(base.Scenario): 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \ % (smp_affinity_mask, int(stdout)) - status, stdout, stderr = self.server.execute(cmd) - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + self.server.run(cmd) + self.client.run(cmd) 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \ % (smp_affinity_mask, int(stdout)) - status, stdout, stderr = self.server.execute(cmd) - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + self.server.run(cmd) + self.client.run(cmd) 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) 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) + self.server.run(cmd) + self.client.run(cmd) if queue_number == 1: return @@ -234,24 +204,18 @@ class Pktgen(base.Scenario): 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \ % (smp_affinity_mask, int(stdout)) - status, stdout, stderr = self.server.execute(cmd) - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + self.server.run(cmd) + self.client.run(cmd) 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) return int(stdout) def _get_available_queue_number(self): @@ -259,9 +223,7 @@ class Pktgen(base.Scenario): 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) return int(stdout) def _get_usable_queue_number(self): @@ -269,9 +231,7 @@ class Pktgen(base.Scenario): 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) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) return int(stdout) def _enable_ovs_multiqueue(self): @@ -282,10 +242,8 @@ class Pktgen(base.Scenario): 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) + self.server.run(cmd) + self.client.run(cmd) return available_queue_number def _iptables_setup(self): @@ -294,9 +252,7 @@ class Pktgen(base.Scenario): "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP" \ % (1000 + self.number_of_ports) LOG.debug("Executing command: %s", cmd) - status, _, stderr = self.server.execute(cmd, timeout=SSH_TIMEOUT) - if status: - raise RuntimeError(stderr) + self.server.run(cmd, timeout=SSH_TIMEOUT) def _iptables_get_result(self): """Get packet statistics from server""" @@ -304,9 +260,7 @@ class Pktgen(base.Scenario): "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'" \ % (1000 + self.number_of_ports) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.server.execute(cmd) - if status: - raise RuntimeError(stderr) + _, stdout, _ = self.server.execute(cmd, raise_on_error=True) return int(stdout) def run(self, result): @@ -356,10 +310,8 @@ class Pktgen(base.Scenario): duration, queue_number, pps) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd, timeout=SSH_TIMEOUT) - - if status: - raise RuntimeError(stderr) + _, stdout, _ = self.client.execute(cmd, raise_on_error=True, + timeout=SSH_TIMEOUT) result.update(jsonutils.loads(stdout)) @@ -374,8 +326,8 @@ class Pktgen(base.Scenario): if "sla" in self.scenario_cfg: 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) + self.verify_SLA(ppm <= sla_max_ppm, + "ppm %d > sla_max_ppm %d; " % (ppm, sla_max_ppm)) def _test(): # pragma: no cover diff --git a/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py b/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py index ce8a7f497..efb7d8b5d 100644 --- a/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py +++ b/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py @@ -70,39 +70,42 @@ class PktgenDPDKLatency(base.Scenario): def run(self, result): """execute the benchmark""" + options = self.scenario_cfg['options'] + eth1 = options.get("eth1", "ens4") + eth2 = options.get("eth2", "ens5") if not self.setup_done: self.setup() if not self.testpmd_args: - self.testpmd_args = utils.get_port_mac(self.client, 'eth2') + self.testpmd_args = utils.get_port_mac(self.client, eth2) if not self.pktgen_args: - server_rev_mac = utils.get_port_mac(self.server, 'eth1') - server_send_mac = utils.get_port_mac(self.server, 'eth2') - client_src_ip = utils.get_port_ip(self.client, 'eth1') - client_dst_ip = utils.get_port_ip(self.client, 'eth2') + server_rev_mac = utils.get_port_mac(self.server, eth1) + server_send_mac = utils.get_port_mac(self.server, eth2) + client_src_ip = utils.get_port_ip(self.client, eth1) + client_dst_ip = utils.get_port_ip(self.client, eth2) self.pktgen_args = [client_src_ip, client_dst_ip, server_rev_mac, server_send_mac] - options = self.scenario_cfg['options'] packetsize = options.get("packetsize", 64) rate = options.get("rate", 100) - cmd = "screen sudo -E bash ~/testpmd_fwd.sh %s " % (self.testpmd_args) + cmd = "screen sudo -E bash ~/testpmd_fwd.sh %s %s %s" % \ + (self.testpmd_args, eth1, eth2) LOG.debug("Executing command: %s", cmd) self.server.send_command(cmd) time.sleep(1) - cmd = "screen sudo -E bash ~/pktgen_dpdk.sh %s %s %s %s %s %s" % \ + cmd = "screen sudo -E bash ~/pktgen_dpdk.sh %s %s %s %s %s %s %s %s" % \ (self.pktgen_args[0], self.pktgen_args[1], self.pktgen_args[2], - self.pktgen_args[3], rate, packetsize) + self.pktgen_args[3], rate, packetsize, eth1, eth2) LOG.debug("Executing command: %s", cmd) self.client.send_command(cmd) # wait for finishing test - time.sleep(1) + time.sleep(60) cmd = r"""\ cat ~/result.log -vT \ @@ -110,10 +113,7 @@ cat ~/result.log -vT \ {print substr($0,RSTART,RLENGTH)}' \ |grep -v ^$ |awk '{if ($2 != 0) print $2}'\ """ - client_status, client_stdout, client_stderr = self.client.execute(cmd) - - if client_status: - raise RuntimeError(client_stderr) + _, client_stdout, _ = self.client.execute(cmd, raise_on_error=True) avg_latency = 0 if client_stdout: @@ -132,4 +132,4 @@ cat ~/result.log -vT \ LOG.info("sla_max_latency: %d", sla_max_latency) debug_info = "avg_latency %d > sla_max_latency %d" \ % (avg_latency, sla_max_latency) - assert avg_latency <= sla_max_latency, debug_info + self.verify_SLA(avg_latency <= sla_max_latency, debug_info) diff --git a/yardstick/benchmark/scenarios/networking/pktgen_dpdk_latency_benchmark.bash b/yardstick/benchmark/scenarios/networking/pktgen_dpdk_latency_benchmark.bash index b872aa3df..dcd5a9bfb 100644 --- a/yardstick/benchmark/scenarios/networking/pktgen_dpdk_latency_benchmark.bash +++ b/yardstick/benchmark/scenarios/networking/pktgen_dpdk_latency_benchmark.bash @@ -7,7 +7,7 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -!/bin/sh +#!/bin/sh set -e @@ -18,6 +18,11 @@ FWD_REV_MAC=$3 # MAC address of forwarding receiver in VM B FWD_SEND_MAC=$4 # MAC address of forwarding sender in VM B RATE=$5 # packet rate in percentage PKT_SIZE=$6 # packet size +ETH1=$7 +ETH2=$8 + +DPDK_VERSION="dpdk-17.02" +PKTGEN_VERSION="pktgen-3.2.12" load_modules() @@ -31,13 +36,13 @@ load_modules() if lsmod | grep "igb_uio" &> /dev/null ; then echo "igb_uio module is loaded" else - insmod /dpdk/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko + insmod /opt/tempT/$DPDK_VERSION/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko fi if lsmod | grep "rte_kni" &> /dev/null ; then echo "rte_kni module is loaded" else - insmod /dpdk/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko + insmod /opt/tempT/$DPDK_VERSION/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko fi } @@ -48,8 +53,10 @@ change_permissions() } add_interface_to_dpdk(){ + ip link set $ETH1 down + ip link set $ETH2 down interfaces=$(lspci |grep Eth |tail -n +2 |awk '{print $1}') - /dpdk/tools/dpdk-devbind.py --bind=igb_uio $interfaces + /opt/tempT/$DPDK_VERSION/usertools/dpdk-devbind.py --bind=igb_uio $interfaces } @@ -106,20 +113,14 @@ spawn ./app/app/x86_64-native-linuxapp-gcc/pktgen -c 0x07 -n 4 -b $blacklist -- expect "Pktgen>" send "\n" expect "Pktgen>" -send "screen on\n" +send "on\n" expect "Pktgen>" set count 10 while { $count } { send "page latency\n" - expect { - timeout { send "\n" } - -regexp {..*} { - set result "${result}$expect_out(0,string)" - set timeout 1 - exp_continue - } - "Pktgen>" - } + expect -re "(..*)" + set result "${result}$expect_out(0,string)" + set timeout 1 set count [expr $count-1] } send "stop 0\n" @@ -136,7 +137,7 @@ EOF run_pktgen() { blacklist=$(lspci |grep Eth |awk '{print $1}'|head -1) - cd /pktgen-dpdk + cd /opt/tempT/$PKTGEN_VERSION touch /home/ubuntu/result.log result_log="/home/ubuntu/result.log" sudo expect /home/ubuntu/pktgen.exp $blacklist $result_log @@ -153,4 +154,3 @@ main() } main - diff --git a/yardstick/benchmark/scenarios/networking/pktgen_dpdk_throughput.py b/yardstick/benchmark/scenarios/networking/pktgen_dpdk_throughput.py index 497e59ee8..97b9cf73f 100644 --- a/yardstick/benchmark/scenarios/networking/pktgen_dpdk_throughput.py +++ b/yardstick/benchmark/scenarios/networking/pktgen_dpdk_throughput.py @@ -143,11 +143,11 @@ class PktgenDPDK(base.Scenario): cmd = "ip a | grep eth1 2>/dev/null" LOG.debug("Executing command: %s in %s", cmd, host) if "server" in host: - status, stdout, stderr = self.server.execute(cmd) + _, stdout, _ = self.server.execute(cmd) if stdout: is_run = False else: - status, stdout, stderr = self.client.execute(cmd) + _, stdout, _ = self.client.execute(cmd) if stdout: is_run = False @@ -222,5 +222,5 @@ class PktgenDPDK(base.Scenario): 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) + self.verify_SLA(ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " + % (ppm, sla_max_ppm)) diff --git a/yardstick/benchmark/scenarios/networking/sfc_openstack.py b/yardstick/benchmark/scenarios/networking/sfc_openstack.py index d5feabbbe..aaab2131a 100644 --- a/yardstick/benchmark/scenarios/networking/sfc_openstack.py +++ b/yardstick/benchmark/scenarios/networking/sfc_openstack.py @@ -34,11 +34,13 @@ def get_credentials(service): # pragma: no cover # The most common way to pass these info to the script is to do it through # environment variables. + # NOTE(ralonsoh): OS_TENANT_NAME is deprecated. + project_name = os.environ.get('OS_PROJECT_NAME', 'admin') creds.update({ "username": os.environ.get('OS_USERNAME', "admin"), password: os.environ.get("OS_PASSWORD", 'admin'), "auth_url": os.environ.get("OS_AUTH_URL"), - tenant: os.environ.get("OS_TENANT_NAME", "admin"), + tenant: os.environ.get("OS_TENANT_NAME", project_name), }) cacert = os.environ.get("OS_CACERT") if cacert is not None: @@ -59,7 +61,7 @@ def get_instances(nova_client): # pragma: no cover try: instances = nova_client.servers.list(search_opts={'all_tenants': 1}) return instances - except Exception as e: + except Exception as e: # pylint: disable=broad-except print("Error [get_instances(nova_client)]:", e) return None @@ -72,7 +74,7 @@ def get_SFs(nova_client): # pragma: no cover if "sfc_test" not in instance.name: SFs.append(instance) return SFs - except Exception as e: + except Exception as e: # pylint: disable=broad-except print("Error [get_SFs(nova_client)]:", e) return None @@ -93,7 +95,7 @@ def create_floating_ips(neutron_client): # pragma: no cover ip_json = neutron_client.create_floatingip({'floatingip': props}) fip_addr = ip_json['floatingip']['floating_ip_address'] ips.append(fip_addr) - except Exception as e: + except Exception as e: # pylint: disable=broad-except print("Error [create_floating_ip(neutron_client)]:", e) return None return ips @@ -106,7 +108,7 @@ def floatIPtoSFs(SFs, floatips): # pragma: no cover SF.add_floating_ip(floatips[i]) i = i + 1 return True - except Exception as e: + except Exception as e: # pylint: disable=broad-except print(("Error [add_floating_ip(nova_client, '%s', '%s')]:" % (SF, floatips[i]), e)) return False @@ -122,7 +124,3 @@ def get_an_IP(): # pragma: no cover floatips = create_floating_ips(neutron_client) floatIPtoSFs(SFs, floatips) return floatips - - -if __name__ == '__main__': # pragma: no cover - get_an_IP() diff --git a/yardstick/benchmark/scenarios/networking/testpmd_fwd.bash b/yardstick/benchmark/scenarios/networking/testpmd_fwd.bash index 247a8a833..30b63a734 100644 --- a/yardstick/benchmark/scenarios/networking/testpmd_fwd.bash +++ b/yardstick/benchmark/scenarios/networking/testpmd_fwd.bash @@ -13,6 +13,10 @@ set -e # Commandline arguments DST_MAC=$1 # MAC address of the peer port +ETH1=$2 +ETH2=$3 + +DPDK_VERSION="dpdk-17.02" load_modules() { @@ -25,13 +29,13 @@ load_modules() if lsmod | grep "igb_uio" &> /dev/null ; then echo "igb_uio module is loaded" else - insmod /dpdk/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko + insmod /opt/tempT/$DPDK_VERSION/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko fi if lsmod | grep "rte_kni" &> /dev/null ; then echo "rte_kni module is loaded" else - insmod /dpdk/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko + insmod /opt/tempT/$DPDK_VERSION/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko fi } @@ -42,15 +46,17 @@ change_permissions() } add_interface_to_dpdk(){ + ip link set $ETH1 down + ip link set $ETH2 down interfaces=$(lspci |grep Eth |tail -n +2 |awk '{print $1}') - /dpdk/tools/dpdk-devbind.py --bind=igb_uio $interfaces + /opt/tempT/$DPDK_VERSION/usertools//dpdk-devbind.py --bind=igb_uio $interfaces } run_testpmd() { blacklist=$(lspci |grep Eth |awk '{print $1}'|head -1) - cd /dpdk - sudo ./destdir/bin/testpmd -c 0x07 -n 4 -b $blacklist -- -a --eth-peer=1,$DST_MAC --forward-mode=mac + cd /opt/tempT/$DPDK_VERSION/x86_64-native-linuxapp-gcc/app + sudo ./testpmd -c 0x07 -n 4 -b $blacklist -- -a --eth-peer=1,$DST_MAC --forward-mode=mac } main() diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py index b94bfc9ab..c5e75d093 100644 --- a/yardstick/benchmark/scenarios/networking/vnf_generic.py +++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016-2017 Intel Corporation +# Copyright (c) 2016-2019 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,168 +11,116 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" NSPerf specific scenario definition """ - -from __future__ import absolute_import - -import logging -import errno - -import ipaddress import copy +import ipaddress +from itertools import chain +import logging import os import sys -import re -from itertools import chain +import time import six import yaml -from collections import defaultdict -from yardstick.benchmark.scenarios import base +from yardstick.benchmark.contexts import base as context_base +from yardstick.benchmark.scenarios import base as scenario_base from yardstick.common.constants import LOG_DIR +from yardstick.common import exceptions from yardstick.common.process import terminate_children -from yardstick.common.utils import import_modules_from_package, itersubclasses -from yardstick.common.yaml_loader import yaml_load +from yardstick.common import utils from yardstick.network_services.collector.subscriber import Collector from yardstick.network_services.vnf_generic import vnfdgen from yardstick.network_services.vnf_generic.vnf.base import GenericVNF -from yardstick.network_services.traffic_profile.base import TrafficProfile +from yardstick.network_services import traffic_profile +from yardstick.network_services.traffic_profile import base as tprofile_base from yardstick.network_services.utils import get_nsb_option from yardstick import ssh -LOG = logging.getLogger(__name__) - - -class SSHError(Exception): - """Class handles ssh connection error exception""" - pass - - -class SSHTimeout(SSHError): - """Class handles ssh connection timeout exception""" - pass +traffic_profile.register_modules() -class IncorrectConfig(Exception): - """Class handles incorrect configuration during setup""" - pass - - -class IncorrectSetup(Exception): - """Class handles incorrect setup during setup""" - pass - - -class SshManager(object): - def __init__(self, node, timeout=120): - super(SshManager, self).__init__() - self.node = node - self.conn = None - self.timeout = timeout - - def __enter__(self): - """ - args -> network device mappings - returns -> ssh connection ready to be used - """ - try: - self.conn = ssh.SSH.from_node(self.node) - self.conn.wait(timeout=self.timeout) - except SSHError as error: - LOG.info("connect failed to %s, due to %s", self.node["ip"], error) - # self.conn defaults to None - return self.conn - - def __exit__(self, exc_type, exc_val, exc_tb): - if self.conn: - self.conn.close() - - -def find_relative_file(path, task_path): - """ - Find file in one of places: in abs of path or - relative to TC scenario file. In this order. - - :param path: - :param task_path: - :return str: full path to file - """ - # fixme: create schema to validate all fields have been provided - for lookup in [os.path.abspath(path), os.path.join(task_path, path)]: - try: - with open(lookup): - return lookup - except IOError: - pass - raise IOError(errno.ENOENT, 'Unable to find {} file'.format(path)) - - -def open_relative_file(path, task_path): - try: - return open(path) - except IOError as e: - if e.errno == errno.ENOENT: - return open(os.path.join(task_path, path)) - raise +LOG = logging.getLogger(__name__) -class NetworkServiceTestCase(base.Scenario): - """Class handles Generic framework to do pre-deployment VNF & - Network service testing """ +class NetworkServiceBase(scenario_base.Scenario): + """Base class for Network service testing scenarios""" - __scenario_type__ = "NSPerf" + __scenario_type__ = "" - def __init__(self, scenario_cfg, context_cfg): # Yardstick API - super(NetworkServiceTestCase, self).__init__() + def __init__(self, scenario_cfg, context_cfg): # pragma: no cover + super(NetworkServiceBase, self).__init__() self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - # fixme: create schema to validate all fields have been provided - with open_relative_file(scenario_cfg["topology"], - scenario_cfg['task_path']) as stream: - topology_yaml = yaml_load(stream) - - self.topology = topology_yaml["nsd:nsd-catalog"]["nsd"][0] + self._render_topology() self.vnfs = [] self.collector = None self.traffic_profile = None self.node_netdevs = {} + self.bin_path = get_nsb_option('bin_path', '') + + def run(self, *args): + pass + + def teardown(self): + """ Stop the collector and terminate VNF & TG instance + + :return + """ + + try: + try: + self.collector.stop() + for vnf in self.vnfs: + LOG.info("Stopping %s", vnf.name) + vnf.terminate() + LOG.debug("all VNFs terminated: %s", ", ".join(vnf.name for vnf in self.vnfs)) + finally: + terminate_children() + except Exception: + # catch any exception in teardown and convert to simple exception + # never pass exceptions back to multiprocessing, because some exceptions can + # be unpicklable + # https://bugs.python.org/issue9400 + LOG.exception("") + raise RuntimeError("Error in teardown") + + def is_ended(self): + return self.traffic_profile is not None and self.traffic_profile.is_ended() def _get_ip_flow_range(self, ip_start_range): + """Retrieve a CIDR first and last viable IPs - # IP range is specified as 'x.x.x.x-y.y.y.y' + :param ip_start_range: could be the IP range itself or a dictionary + with the host name and the port. + :return: (str) IP range (min, max) with this format "x.x.x.x-y.y.y.y" + """ if isinstance(ip_start_range, six.string_types): return ip_start_range - node_name, range_or_interface = next(iter(ip_start_range.items()), (None, '0.0.0.0')) + node_name, range_or_interface = next(iter(ip_start_range.items()), + (None, '0.0.0.0')) if node_name is None: - # we are manually specifying the range - ip_addr_range = range_or_interface + return range_or_interface + + node = self.context_cfg['nodes'].get(node_name, {}) + interface = node.get('interfaces', {}).get(range_or_interface) + if interface: + ip = interface['local_ip'] + mask = interface['netmask'] else: - node = self.context_cfg["nodes"].get(node_name, {}) - try: - # the ip_range is the interface name - interface = node.get("interfaces", {})[range_or_interface] - except KeyError: - ip = "0.0.0.0" - mask = "255.255.255.0" - else: - ip = interface["local_ip"] - # we can't default these values, they must both exist to be valid - mask = interface["netmask"] - - ipaddr = ipaddress.ip_network(six.text_type('{}/{}'.format(ip, mask)), strict=False) - hosts = list(ipaddr.hosts()) - if len(hosts) > 2: - # skip the first host in case of gateway - ip_addr_range = "{}-{}".format(hosts[1], hosts[-1]) - else: - LOG.warning("Only single IP in range %s", ipaddr) - # fall back to single IP range - ip_addr_range = ip + ip = '0.0.0.0' + mask = '255.255.255.0' + + ipaddr = ipaddress.ip_network( + six.text_type('{}/{}'.format(ip, mask)), strict=False) + if ipaddr.prefixlen + 2 < ipaddr.max_prefixlen: + ip_addr_range = '{}-{}'.format(ipaddr[2], ipaddr[-2]) + else: + LOG.warning('Only single IP in range %s', ipaddr) + ip_addr_range = ip return ip_addr_range def _get_traffic_flow(self): @@ -196,7 +144,15 @@ class NetworkServiceTestCase(base.Scenario): for index, dst_port in enumerate(fflow.get("dst_port", [])): flow["dst_port_{}".format(index)] = dst_port - flow["count"] = fflow["count"] + if "count" in fflow: + flow["count"] = fflow["count"] + + if "srcseed" in fflow: + flow["srcseed"] = fflow["srcseed"] + + if "dstseed" in fflow: + flow["dstseed"] = fflow["dstseed"] + except KeyError: flow = {} return {"flow": flow} @@ -208,43 +164,95 @@ class NetworkServiceTestCase(base.Scenario): imix = {} return imix + def _get_ip_priority(self): + try: + priority = self.scenario_cfg['options']['priority'] + except KeyError: + priority = {} + return priority + def _get_traffic_profile(self): profile = self.scenario_cfg["traffic_profile"] path = self.scenario_cfg["task_path"] - with open_relative_file(profile, path) as infile: + with utils.open_relative_file(profile, path) as infile: return infile.read() + def _get_duration(self): + options = self.scenario_cfg.get('options', {}) + return options.get('duration', + tprofile_base.TrafficProfileConfig.DEFAULT_DURATION) + + def _key_list_to_dict(self, key, value_list): + value_dict = {} + try: + for index, count in enumerate(value_list[key]): + value_dict["{}_{}".format(key, index)] = count + except KeyError: + value_dict = {} + + return value_dict + + def _get_simulated_users(self): + users = self.scenario_cfg.get("options", {}).get("simulated_users", {}) + simulated_users = self._key_list_to_dict("uplink", users) + return {"simulated_users": simulated_users} + + def _get_page_object(self): + objects = self.scenario_cfg.get("options", {}).get("page_object", {}) + page_object = self._key_list_to_dict("uplink", objects) + return {"page_object": page_object} + def _fill_traffic_profile(self): - traffic_mapping = self._get_traffic_profile() - traffic_map_data = { + tprofile = self._get_traffic_profile() + extra_args = self.scenario_cfg.get('extra_args', {}) + tprofile_data = { 'flow': self._get_traffic_flow(), 'imix': self._get_traffic_imix(), - TrafficProfile.UPLINK: {}, - TrafficProfile.DOWNLINK: {}, - } + 'priority': self._get_ip_priority(), + tprofile_base.TrafficProfile.UPLINK: {}, + tprofile_base.TrafficProfile.DOWNLINK: {}, + 'extra_args': extra_args, + 'duration': self._get_duration(), + 'page_object': self._get_page_object(), + 'simulated_users': self._get_simulated_users()} + traffic_vnfd = vnfdgen.generate_vnfd(tprofile, tprofile_data) + + traffic_config = \ + self.scenario_cfg.get("options", {}).get("traffic_config", {}) + + traffic_vnfd.setdefault("traffic_profile", {}) + traffic_vnfd["traffic_profile"].update(traffic_config) + + self.traffic_profile = \ + tprofile_base.TrafficProfile.get(traffic_vnfd) + + def _get_topology(self): + topology = self.scenario_cfg["topology"] + path = self.scenario_cfg["task_path"] + with utils.open_relative_file(topology, path) as infile: + return infile.read() - traffic_vnfd = vnfdgen.generate_vnfd(traffic_mapping, traffic_map_data) - self.traffic_profile = TrafficProfile.get(traffic_vnfd) - return self.traffic_profile + def _render_topology(self): + topology = self._get_topology() + topology_args = self.scenario_cfg.get('extra_args', {}) + topolgy_data = { + 'extra_args': topology_args + } + topology_yaml = vnfdgen.generate_vnfd(topology, topolgy_data) + self.topology = topology_yaml["nsd:nsd-catalog"]["nsd"][0] - def _find_vnf_name_from_id(self, vnf_id): + def _find_vnf_name_from_id(self, vnf_id): # pragma: no cover return next((vnfd["vnfd-id-ref"] for vnfd in self.topology["constituent-vnfd"] if vnf_id == vnfd["member-vnf-index"]), None) - @staticmethod - def get_vld_networks(networks): - # network name is vld_id - vld_map = {} - for name, n in networks.items(): - try: - vld_map[n['vld_id']] = n - except KeyError: - vld_map[name] = n - return vld_map + def _find_vnfd_from_vnf_idx(self, vnf_id): # pragma: no cover + return next((vnfd + for vnfd in self.topology["constituent-vnfd"] + if vnf_id == vnfd["member-vnf-index"]), None) @staticmethod - def find_node_if(nodes, name, if_name, vld_id): + def find_node_if(nodes, name, if_name, vld_id): # pragma: no cover try: # check for xe0, xe1 intf = nodes[name]["interfaces"][if_name] @@ -260,8 +268,9 @@ class NetworkServiceTestCase(base.Scenario): try: node0_data, node1_data = vld["vnfd-connection-point-ref"] except (ValueError, TypeError): - raise IncorrectConfig("Topology file corrupted, " - "wrong endpoint count for connection") + raise exceptions.IncorrectConfig( + error_msg='Topology file corrupted, wrong endpoint count ' + 'for connection') node0_name = self._find_vnf_name_from_id(node0_data["member-vnf-index-ref"]) node1_name = self._find_vnf_name_from_id(node1_data["member-vnf-index-ref"]) @@ -293,7 +302,9 @@ class NetworkServiceTestCase(base.Scenario): node1_if["peer_ifname"] = node0_if_name # just load the network - vld_networks = self.get_vld_networks(self.context_cfg["networks"]) + vld_networks = {n.get('vld_id', name): n for name, n in + self.context_cfg["networks"].items()} + node0_if["network"] = vld_networks.get(vld["id"], {}) node1_if["network"] = vld_networks.get(vld["id"], {}) @@ -305,15 +316,17 @@ class NetworkServiceTestCase(base.Scenario): except KeyError: LOG.exception("") - raise IncorrectConfig("Required interface not found, " - "topology file corrupted") + raise exceptions.IncorrectConfig( + error_msg='Required interface not found, topology file ' + 'corrupted') for vld in self.topology['vld']: try: node0_data, node1_data = vld["vnfd-connection-point-ref"] except (ValueError, TypeError): - raise IncorrectConfig("Topology file corrupted, " - "wrong endpoint count for connection") + raise exceptions.IncorrectConfig( + error_msg='Topology file corrupted, wrong endpoint count ' + 'for connection') node0_name = self._find_vnf_name_from_id(node0_data["member-vnf-index-ref"]) node1_name = self._find_vnf_name_from_id(node1_data["member-vnf-index-ref"]) @@ -332,55 +345,14 @@ class NetworkServiceTestCase(base.Scenario): node0_if["peer_intf"] = node1_copy node1_if["peer_intf"] = node0_copy - def _find_vnfd_from_vnf_idx(self, vnf_idx): - return next((vnfd for vnfd in self.topology["constituent-vnfd"] - if vnf_idx == vnfd["member-vnf-index"]), None) - - def _update_context_with_topology(self): + def _update_context_with_topology(self): # pragma: no cover for vnfd in self.topology["constituent-vnfd"]: vnf_idx = vnfd["member-vnf-index"] vnf_name = self._find_vnf_name_from_id(vnf_idx) vnfd = self._find_vnfd_from_vnf_idx(vnf_idx) self.context_cfg["nodes"][vnf_name].update(vnfd) - def _probe_netdevs(self, node, node_dict, timeout=120): - try: - return self.node_netdevs[node] - except KeyError: - pass - - netdevs = {} - cmd = "PATH=$PATH:/sbin:/usr/sbin ip addr show" - - with SshManager(node_dict, timeout=timeout) as conn: - if conn: - exit_status = conn.execute(cmd)[0] - if exit_status != 0: - raise IncorrectSetup("Node's %s lacks ip tool." % node) - exit_status, stdout, _ = conn.execute( - self.FIND_NETDEVICE_STRING) - if exit_status != 0: - raise IncorrectSetup( - "Cannot find netdev info in sysfs" % node) - netdevs = node_dict['netdevs'] = self.parse_netdev_info(stdout) - - self.node_netdevs[node] = netdevs - return netdevs - - @classmethod - def _probe_missing_values(cls, netdevs, network): - - mac_lower = network['local_mac'].lower() - for netdev in netdevs.values(): - if netdev['address'].lower() != mac_lower: - continue - network.update({ - 'driver': netdev['driver'], - 'vpci': netdev['pci_bus_id'], - 'ifindex': netdev['ifindex'], - }) - - def _generate_pod_yaml(self): + def _generate_pod_yaml(self): # pragma: no cover context_yaml = os.path.join(LOG_DIR, "pod-{}.yaml".format(self.scenario_cfg['task_id'])) # convert OrderedDict to a list # pod.yaml nodes is a list @@ -394,7 +366,7 @@ class NetworkServiceTestCase(base.Scenario): explicit_start=True) @staticmethod - def _serialize_node(node): + def _serialize_node(node): # pragma: no cover new_node = copy.deepcopy(node) # name field is required # remove context suffix @@ -405,96 +377,31 @@ class NetworkServiceTestCase(base.Scenario): pass return new_node - TOPOLOGY_REQUIRED_KEYS = frozenset({ - "vpci", "local_ip", "netmask", "local_mac", "driver"}) - def map_topology_to_infrastructure(self): """ This method should verify if the available resources defined in pod.yaml match the topology.yaml file. :return: None. Side effect: context_cfg is updated """ - num_nodes = len(self.context_cfg["nodes"]) - # OpenStack instance creation time is probably proportional to the number - # of instances - timeout = 120 * num_nodes - for node, node_dict in self.context_cfg["nodes"].items(): - - for network in node_dict["interfaces"].values(): - missing = self.TOPOLOGY_REQUIRED_KEYS.difference(network) - if not missing: - continue - - # only ssh probe if there are missing values - # ssh probe won't work on Ixia, so we had better define all our values - try: - netdevs = self._probe_netdevs(node, node_dict, timeout=timeout) - except (SSHError, SSHTimeout): - raise IncorrectConfig( - "Unable to probe missing interface fields '%s', on node %s " - "SSH Error" % (', '.join(missing), node)) - try: - self._probe_missing_values(netdevs, network) - except KeyError: - pass - else: - missing = self.TOPOLOGY_REQUIRED_KEYS.difference( - network) - if missing: - raise IncorrectConfig( - "Require interface fields '%s' not found, topology file " - "corrupted" % ', '.join(missing)) - - # we have to generate pod.yaml here so we have vpci and driver - self._generate_pod_yaml() # 3. Use topology file to find connections & resolve dest address self._resolve_topology() self._update_context_with_topology() - FIND_NETDEVICE_STRING = r"""find /sys/devices/pci* -type d -name net -exec sh -c '{ grep -sH ^ \ -$1/ifindex $1/address $1/operstate $1/device/vendor $1/device/device \ -$1/device/subsystem_vendor $1/device/subsystem_device ; \ -printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ -' sh \{\}/* \; -""" - BASE_ADAPTER_RE = re.compile( - '^/sys/devices/(.*)/net/([^/]*)/([^:]*):(.*)$', re.M) - - @classmethod - def parse_netdev_info(cls, stdout): - network_devices = defaultdict(dict) - matches = cls.BASE_ADAPTER_RE.findall(stdout) - for bus_path, interface_name, name, value in matches: - dirname, bus_id = os.path.split(bus_path) - if 'virtio' in bus_id: - # for some stupid reason VMs include virtio1/ - # in PCI device path - bus_id = os.path.basename(dirname) - # remove extra 'device/' from 'device/vendor, - # device/subsystem_vendor', etc. - if 'device/' in name: - name = name.split('/')[1] - network_devices[interface_name][name] = value - network_devices[interface_name][ - 'interface_name'] = interface_name - network_devices[interface_name]['pci_bus_id'] = bus_id - # convert back to regular dict - return dict(network_devices) - @classmethod - def get_vnf_impl(cls, vnf_model_id): + def get_vnf_impl(cls, vnf_model_id): # pragma: no cover """ Find the implementing class from vnf_model["vnf"]["name"] field :param vnf_model_id: parsed vnfd model ID field :return: subclass of GenericVNF """ - import_modules_from_package( + utils.import_modules_from_package( "yardstick.network_services.vnf_generic.vnf") expected_name = vnf_model_id classes_found = [] def impl(): - for name, class_ in ((c.__name__, c) for c in itersubclasses(GenericVNF)): + for name, class_ in ((c.__name__, c) for c in + utils.itersubclasses(GenericVNF)): if name == expected_name: yield class_ classes_found.append(name) @@ -504,11 +411,12 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ except StopIteration: pass - raise IncorrectConfig("No implementation for %s found in %s" % - (expected_name, classes_found)) + message = ('No implementation for %s found in %s' + % (expected_name, classes_found)) + raise exceptions.IncorrectConfig(error_msg=message) @staticmethod - def create_interfaces_from_node(vnfd, node): + def create_interfaces_from_node(vnfd, node): # pragma: no cover ext_intfs = vnfd["vdu"][0]["external-interface"] = [] # have to sort so xe0 goes first for intf_name, intf in sorted(node['interfaces'].items()): @@ -547,7 +455,7 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ context_cfg = self.context_cfg vnfs = [] - # we assume OrderedDict for consistenct in instantiation + # we assume OrderedDict for consistency in instantiation for node_name, node in context_cfg["nodes"].items(): LOG.debug(node) try: @@ -556,7 +464,7 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ LOG.debug("no model for %s, skipping", node_name) continue file_path = scenario_cfg['task_path'] - with open_relative_file(file_name, file_path) as stream: + with utils.open_relative_file(file_name, file_path) as stream: vnf_model = stream.read() vnfd = vnfdgen.generate_vnfd(vnf_model, node) # TODO: here add extra context_cfg["nodes"] regardless of template @@ -576,11 +484,26 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ self.vnfs = vnfs return vnfs - def setup(self): - """ Setup infrastructure, provission VNFs & start traffic + def pre_run_wait_time(self, time_seconds): # pragma: no cover + """Time waited before executing the run method""" + time.sleep(time_seconds) - :return: - """ + def post_run_wait_time(self, time_seconds): # pragma: no cover + """Time waited after executing the run method""" + pass + + +class NetworkServiceTestCase(NetworkServiceBase): + """Class handles Generic framework to do pre-deployment VNF & + Network service testing """ + + __scenario_type__ = "NSPerf" + + def __init__(self, scenario_cfg, context_cfg): # pragma: no cover + super(NetworkServiceTestCase, self).__init__(scenario_cfg, context_cfg) + + def setup(self): + """Setup infrastructure, provission VNFs & start traffic""" # 1. Verify if infrastructure mapping can meet topology self.map_topology_to_infrastructure() # 1a. Load VNF models @@ -606,13 +529,16 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ vnf.terminate() raise + # we have to generate pod.yaml here after VNF has probed so we know vpci and driver + self._generate_pod_yaml() + # 3. Run experiment # Start listeners first to avoid losing packets for traffic_gen in traffic_runners: traffic_gen.listen_traffic(self.traffic_profile) # register collector with yardstick for KPI collection. - self.collector = Collector(self.vnfs, self.context_cfg["nodes"], self.traffic_profile) + self.collector = Collector(self.vnfs, context_base.Context.get_physical_nodes()) self.collector.start() # Start the actual traffic @@ -634,25 +560,125 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \ result.update(self.collector.get_kpi()) - def teardown(self): - """ Stop the collector and terminate VNF & TG instance - :return +class NetworkServiceRFC2544(NetworkServiceBase): + """Class handles RFC2544 Network service testing""" + + __scenario_type__ = "NSPerf-RFC2544" + + def __init__(self, scenario_cfg, context_cfg): # pragma: no cover + super(NetworkServiceRFC2544, self).__init__(scenario_cfg, context_cfg) + + def setup(self): + """Setup infrastructure, provision VNFs""" + self.map_topology_to_infrastructure() + self.load_vnf_models() + + traffic_runners = [vnf for vnf in self.vnfs if vnf.runs_traffic] + non_traffic_runners = [vnf for vnf in self.vnfs if not vnf.runs_traffic] + try: + for vnf in chain(traffic_runners, non_traffic_runners): + LOG.info("Instantiating %s", vnf.name) + vnf.instantiate(self.scenario_cfg, self.context_cfg) + LOG.info("Waiting for %s to instantiate", vnf.name) + vnf.wait_for_instantiate() + except: + LOG.exception("") + for vnf in self.vnfs: + vnf.terminate() + raise + + self._generate_pod_yaml() + + def run(self, output): + """ Run experiment + + :param output: scenario output to push results + :return: None """ + self._fill_traffic_profile() + + traffic_runners = [vnf for vnf in self.vnfs if vnf.runs_traffic] + + for traffic_gen in traffic_runners: + traffic_gen.listen_traffic(self.traffic_profile) + + self.collector = Collector(self.vnfs, + context_base.Context.get_physical_nodes()) + self.collector.start() + + test_completed = False + while not test_completed: + for traffic_gen in traffic_runners: + LOG.info("Run traffic on %s", traffic_gen.name) + traffic_gen.run_traffic_once(self.traffic_profile) + + test_completed = True + for traffic_gen in traffic_runners: + # wait for all tg to complete running traffic + status = traffic_gen.wait_on_traffic() + LOG.info("Run traffic on %s complete status=%s", + traffic_gen.name, status) + if status == 'CONTINUE': + # continue running if at least one tg is running + test_completed = False + + output.push(self.collector.get_kpi()) + + self.collector.stop() + +class NetworkServiceRFC3511(NetworkServiceBase): + """Class handles RFC3511 Network service testing""" + + __scenario_type__ = "NSPerf-RFC3511" + + def __init__(self, scenario_cfg, context_cfg): # pragma: no cover + super(NetworkServiceRFC3511, self).__init__(scenario_cfg, context_cfg) + + def setup(self): + """Setup infrastructure, provision VNFs""" + self.map_topology_to_infrastructure() + self.load_vnf_models() + + traffic_runners = [vnf for vnf in self.vnfs if vnf.runs_traffic] + non_traffic_runners = [vnf for vnf in self.vnfs if not vnf.runs_traffic] try: - try: - self.collector.stop() - for vnf in self.vnfs: - LOG.info("Stopping %s", vnf.name) - vnf.terminate() - LOG.debug("all VNFs terminated: %s", ", ".join(vnf.name for vnf in self.vnfs)) - finally: - terminate_children() - except Exception: - # catch any exception in teardown and convert to simple exception - # never pass exceptions back to multiprocessing, because some exceptions can - # be unpicklable - # https://bugs.python.org/issue9400 + for vnf in chain(traffic_runners, non_traffic_runners): + LOG.info("Instantiating %s", vnf.name) + vnf.instantiate(self.scenario_cfg, self.context_cfg) + LOG.info("Waiting for %s to instantiate", vnf.name) + vnf.wait_for_instantiate() + except: LOG.exception("") - raise RuntimeError("Error in teardown") + for vnf in self.vnfs: + vnf.terminate() + raise + + self._generate_pod_yaml() + + def run(self, output): + """ Run experiment + + :param output: scenario output to push results + :return: None + """ + + self._fill_traffic_profile() + + traffic_runners = [vnf for vnf in self.vnfs if vnf.runs_traffic] + + for traffic_gen in traffic_runners: + traffic_gen.listen_traffic(self.traffic_profile) + + self.collector = Collector(self.vnfs, + context_base.Context.get_physical_nodes()) + self.collector.start() + + for traffic_gen in traffic_runners: + LOG.info("Run traffic on %s", traffic_gen.name) + traffic_gen.run_traffic(self.traffic_profile) + + output.push(self.collector.get_kpi()) + + self.collector.stop() diff --git a/yardstick/benchmark/scenarios/networking/vsperf.py b/yardstick/benchmark/scenarios/networking/vsperf.py index 705544c41..8344b1595 100644 --- a/yardstick/benchmark/scenarios/networking/vsperf.py +++ b/yardstick/benchmark/scenarios/networking/vsperf.py @@ -193,37 +193,34 @@ class Vsperf(base.Scenario): cmd += "--conf-file ~/vsperf.conf " cmd += "--test-params=\"%s\"" % (';'.join(test_params)) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) - - if status: - raise RuntimeError(stderr) + self.client.run(cmd) # get test results cmd = "cat /tmp/results*/result.csv" LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) - - if status: - raise RuntimeError(stderr) + _, stdout, _ = self.client.execute(cmd, raise_on_error=True) # convert result.csv to JSON format - reader = csv.DictReader(stdout.split('\r\n')) - result.update(next(reader)) + reader = csv.DictReader(stdout.split('\r\n'), strict=True) + try: + result.update(next(reader)) + except StopIteration: + pass # sla check; go through all defined SLAs and check if values measured # by VSPERF are higher then those defined by SLAs if 'sla' in self.scenario_cfg and \ 'metrics' in self.scenario_cfg['sla']: for metric in self.scenario_cfg['sla']['metrics'].split(','): - assert metric in result, \ - '%s is not collected by VSPERF' % (metric) - assert metric in self.scenario_cfg['sla'], \ - '%s is not defined in SLA' % (metric) + self.verify_SLA(metric in result, + '%s was not collected by VSPERF' % metric) + self.verify_SLA(metric in self.scenario_cfg['sla'], + '%s is not defined in SLA' % metric) vs_res = float(result[metric]) sla_res = float(self.scenario_cfg['sla'][metric]) - assert vs_res >= sla_res, \ - 'VSPERF_%s(%f) < SLA_%s(%f)' % \ - (metric, vs_res, metric, sla_res) + self.verify_SLA(vs_res >= sla_res, + 'VSPERF_%s(%f) < SLA_%s(%f)' + % (metric, vs_res, metric, sla_res)) def teardown(self): """cleanup after the test execution""" diff --git a/yardstick/benchmark/scenarios/networking/vsperf_dpdk.py b/yardstick/benchmark/scenarios/networking/vsperf_dpdk.py index 454587829..d5c8a3bfe 100644 --- a/yardstick/benchmark/scenarios/networking/vsperf_dpdk.py +++ b/yardstick/benchmark/scenarios/networking/vsperf_dpdk.py @@ -205,22 +205,17 @@ class VsperfDPDK(base.Scenario): self.client.send_command(cmd) else: cmd = "cat ~/.testpmd.macaddr.port1" - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + _, stdout, _ = self.client.execute(cmd, raise_on_error=True) self.tgen_port1_mac = stdout + cmd = "cat ~/.testpmd.macaddr.port2" - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + _, stdout, _ = self.client.execute(cmd, raise_on_error=True) self.tgen_port2_mac = stdout cmd = "screen -d -m sudo -E bash ~/testpmd_vsperf.sh %s %s" % \ (self.moongen_port1_mac, self.moongen_port2_mac) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + self.client.run(cmd) time.sleep(1) @@ -231,7 +226,7 @@ class VsperfDPDK(base.Scenario): is_run = True cmd = "ip a | grep %s 2>/dev/null" % (self.tg_port1) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) + _, stdout, _ = self.client.execute(cmd) if stdout: is_run = False return is_run @@ -245,7 +240,7 @@ class VsperfDPDK(base.Scenario): self.setup() # remove results from previous tests - self.client.execute("rm -rf /tmp/results*") + self.client.run("rm -rf /tmp/results*", raise_on_error=False) # get vsperf options options = self.scenario_cfg['options'] @@ -291,9 +286,7 @@ class VsperfDPDK(base.Scenario): cmd = "sshpass -p yardstick ssh-copy-id -o StrictHostKeyChecking=no " \ "root@%s -p 22" % (self.moongen_host_ip) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) - if status: - raise RuntimeError(stderr) + self.client.run(cmd) # execute vsperf cmd = "source ~/vsperfenv/bin/activate ; cd vswitchperf ; " @@ -302,22 +295,19 @@ class VsperfDPDK(base.Scenario): cmd += "--conf-file ~/vsperf.conf " cmd += "--test-params=\"%s\"" % (';'.join(test_params)) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) - - if status: - raise RuntimeError(stderr) + self.client.run(cmd) # get test results cmd = "cat /tmp/results*/result.csv" LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) - - if status: - raise RuntimeError(stderr) + _, stdout, _ = self.client.execute(cmd, raise_on_error=True) # convert result.csv to JSON format reader = csv.DictReader(stdout.split('\r\n')) - result.update(next(reader)) + try: + result.update(next(reader)) + except StopIteration: + pass result['nrFlows'] = multistream # sla check; go through all defined SLAs and check if values measured @@ -325,15 +315,15 @@ class VsperfDPDK(base.Scenario): if 'sla' in self.scenario_cfg and \ 'metrics' in self.scenario_cfg['sla']: for metric in self.scenario_cfg['sla']['metrics'].split(','): - assert metric in result, \ - '%s is not collected by VSPERF' % (metric) - assert metric in self.scenario_cfg['sla'], \ - '%s is not defined in SLA' % (metric) + self.verify_SLA(metric in result, + '%s was not collected by VSPERF' % metric) + self.verify_SLA(metric in self.scenario_cfg['sla'], + '%s is not defined in SLA' % metric) vs_res = float(result[metric]) sla_res = float(self.scenario_cfg['sla'][metric]) - assert vs_res >= sla_res, \ - 'VSPERF_%s(%f) < SLA_%s(%f)' % \ - (metric, vs_res, metric, sla_res) + self.verify_SLA(vs_res >= sla_res, + 'VSPERF_%s(%f) < SLA_%s(%f)' + % (metric, vs_res, metric, sla_res)) def teardown(self): """cleanup after the test execution""" diff --git a/yardstick/benchmark/scenarios/parser/parser.py b/yardstick/benchmark/scenarios/parser/parser.py index eb16833e5..a0f8e9e72 100644 --- a/yardstick/benchmark/scenarios/parser/parser.py +++ b/yardstick/benchmark/scenarios/parser/parser.py @@ -6,13 +6,13 @@ # 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 pkg_resources import logging import subprocess from yardstick.benchmark.scenarios import base + LOG = logging.getLogger(__name__) @@ -20,7 +20,7 @@ class Parser(base.Scenario): """running Parser Yang-to-Tosca module as a tool validating output against expected outcome - more info https://wiki.opnfv.org/parser + more info https://wiki.opnfv.org/display/parser """ __scenario_type__ = "Parser" @@ -63,7 +63,7 @@ class Parser(base.Scenario): p = subprocess.Popen(cmd1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p.communicate() - print("yangtotosca finished") + LOG.info("yangtotosca finished") result['yangtotosca'] = "success" if p.returncode == 0 else "fail" diff --git a/yardstick/benchmark/scenarios/storage/fio.py b/yardstick/benchmark/scenarios/storage/fio.py index 125bc7ed4..c57c6edf2 100644 --- a/yardstick/benchmark/scenarios/storage/fio.py +++ b/yardstick/benchmark/scenarios/storage/fio.py @@ -124,12 +124,16 @@ class Fio(base.Scenario): if mount_dir: LOG.debug("Formating volume...") - self.client.execute("sudo mkfs.ext4 /dev/vdb") - cmd = "sudo mkdir %s" % mount_dir - self.client.execute(cmd) - LOG.debug("Mounting volume at: %s", mount_dir) - cmd = "sudo mount /dev/vdb %s" % mount_dir - self.client.execute(cmd) + _, stdout, _ = self.client.execute( + "lsblk -dps | grep -m 1 disk | awk '{print $1}'") + block_device = stdout.strip() + if block_device: + self.client.execute("sudo mkfs.ext4 %s" % block_device) + cmd = "sudo mkdir %s" % mount_dir + self.client.execute(cmd) + LOG.debug("Mounting volume at: %s", mount_dir) + cmd = "sudo mount %s %s" % (block_device, mount_dir) + self.client.execute(cmd) self.setup_done = True @@ -219,7 +223,7 @@ class Fio(base.Scenario): sla_error += "%s %d < " \ "sla:%s(%d); " % (k, v, k, min_v) - assert sla_error == "", sla_error + self.verify_SLA(sla_error == "", sla_error) def _test(): diff --git a/yardstick/benchmark/scenarios/storage/storperf.py b/yardstick/benchmark/scenarios/storage/storperf.py index f0b2361d6..5b8b00075 100644 --- a/yardstick/benchmark/scenarios/storage/storperf.py +++ b/yardstick/benchmark/scenarios/storage/storperf.py @@ -8,15 +8,16 @@ ############################################################################## from __future__ import absolute_import -import os import logging +import os import time -import requests from oslo_serialization import jsonutils +import requests from yardstick.benchmark.scenarios import base + LOG = logging.getLogger(__name__) @@ -43,12 +44,6 @@ class StorPerf(base.Scenario): wr: 100% Write, random access rw: 70% Read / 30% write, random access - nossd (Optional): - Do not perform SSD style preconditioning. - - nowarm (Optional): - Do not perform a warmup prior to measurements. - report = [job_id] (Optional): Query the status of the supplied job_id and report on metrics. If a workload is supplied, will report on only that subset. @@ -79,17 +74,22 @@ class StorPerf(base.Scenario): setup_query_content = jsonutils.loads( setup_query.content) - if setup_query_content["stack_created"]: - self.setup_done = True + if ("stack_created" in setup_query_content and + setup_query_content["stack_created"]): LOG.debug("stack_created: %s", setup_query_content["stack_created"]) + return True + + return False def setup(self): """Set the configuration.""" env_args = {} env_args_payload_list = ["agent_count", "agent_flavor", "public_network", "agent_image", - "volume_size"] + "volume_size", "volume_type", + "volume_count", "availability_zone", + "stack_name", "subnet_CIDR"] for env_argument in env_args_payload_list: try: @@ -102,30 +102,36 @@ class StorPerf(base.Scenario): setup_res = requests.post('http://%s:5000/api/v1.0/configurations' % self.target, json=env_args) - setup_res_content = jsonutils.loads( - setup_res.content) if setup_res.status_code != 200: - raise RuntimeError("Failed to create a stack, error message:", - setup_res_content["message"]) + LOG.error("Failed to create stack. %s: %s", + setup_res.status_code, setup_res.content) + raise RuntimeError("Failed to create stack. %s: %s" % + (setup_res.status_code, setup_res.content)) elif setup_res.status_code == 200: + setup_res_content = jsonutils.loads(setup_res.content) LOG.info("stack_id: %s", setup_res_content["stack_id"]) - while not self.setup_done: - self._query_setup_state() - time.sleep(self.query_interval) + while not self._query_setup_state(): + time.sleep(self.query_interval) + + # We do not want to load the results of the disk initialization, + # so it is not added to the results here. + self.initialize_disks() + self.setup_done = True def _query_job_state(self, job_id): """Query the status of the supplied job_id and report on metrics""" LOG.info("Fetching report for %s...", job_id) - report_res = requests.get('http://{}:5000/api/v1.0/jobs'.format - (self.target), + report_res = requests.get('http://%s:5000/api/v1.0/jobs' % self.target, params={'id': job_id, 'type': 'status'}) report_res_content = jsonutils.loads( report_res.content) if report_res.status_code != 200: + LOG.error("Failed to fetch report, error message: %s", + report_res_content["message"]) raise RuntimeError("Failed to fetch report, error message:", report_res_content["message"]) else: @@ -149,7 +155,8 @@ class StorPerf(base.Scenario): if not self.setup_done: self.setup() - metadata = {"build_tag": "latest", "test_case": "opnfv_yardstick_tc074"} + metadata = {"build_tag": "latest", + "test_case": "opnfv_yardstick_tc074"} metadata_payload_dict = {"pod_name": "NODE_NAME", "scenario_name": "DEPLOY_SCENARIO", "version": "YARDSTICK_BRANCH"} @@ -162,7 +169,9 @@ class StorPerf(base.Scenario): job_args = {"metadata": metadata} job_args_payload_list = ["block_sizes", "queue_depths", "deadline", - "target", "nossd", "nowarm", "workload"] + "target", "workload", "workloads", + "agent_count", "steady_state_samples"] + job_args["deadline"] = self.options["timeout"] for job_argument in job_args_payload_list: try: @@ -170,16 +179,24 @@ class StorPerf(base.Scenario): except KeyError: pass - LOG.info("Starting a job with parameters %s", job_args) - job_res = requests.post('http://%s:5000/api/v1.0/jobs' % self.target, - json=job_args) + api_version = "v1.0" - job_res_content = jsonutils.loads(job_res.content) + if ("workloads" in job_args and + job_args["workloads"] is not None and + len(job_args["workloads"])) > 0: + api_version = "v2.0" + + LOG.info("Starting a job with parameters %s", job_args) + job_res = requests.post('http://%s:5000/api/%s/jobs' % (self.target, + api_version), json=job_args) if job_res.status_code != 200: - raise RuntimeError("Failed to start a job, error message:", - job_res_content["message"]) + LOG.error("Failed to start job. %s: %s", + job_res.status_code, job_res.content) + raise RuntimeError("Failed to start job. %s: %s" % + (job_res.status_code, job_res.content)) elif job_res.status_code == 200: + job_res_content = jsonutils.loads(job_res.content) job_id = job_res_content["job_id"] LOG.info("Started job id: %s...", job_id) @@ -187,15 +204,6 @@ class StorPerf(base.Scenario): self._query_job_state(job_id) time.sleep(self.query_interval) - terminate_res = requests.delete('http://%s:5000/api/v1.0/jobs' % - self.target) - - if terminate_res.status_code != 200: - terminate_res_content = jsonutils.loads( - terminate_res.content) - raise RuntimeError("Failed to start a job, error message:", - terminate_res_content["message"]) - # TODO: Support using ETA to polls for completion. # Read ETA, next poll in 1/2 ETA time slot. # If ETA is greater than the maximum allowed job time, @@ -209,21 +217,65 @@ class StorPerf(base.Scenario): # else: # time.sleep(int(esti_time)/2) + result_res = requests.get('http://%s:5000/api/v1.0/jobs?type=' + 'metadata&id=%s' % (self.target, job_id)) + result_res_content = jsonutils.loads(result_res.content) + if 'report' in result_res_content and \ + 'steady_state' in result_res_content['report']['details']: + res = result_res_content['report']['details']['steady_state'] + steady_state = res.values()[0] + LOG.info("Job %s completed with steady state %s", + job_id, steady_state) + result_res = requests.get('http://%s:5000/api/v1.0/jobs?id=%s' % (self.target, job_id)) result_res_content = jsonutils.loads( result_res.content) - result.update(result_res_content) + def initialize_disks(self): + """Fills the target with random data prior to executing workloads""" + + job_args = {} + job_args_payload_list = ["target"] + + for job_argument in job_args_payload_list: + try: + job_args[job_argument] = self.options[job_argument] + except KeyError: + pass + + LOG.info("Starting initialization with parameters %s", job_args) + job_res = requests.post('http://%s:5000/api/v1.0/initializations' % + self.target, json=job_args) + + + if job_res.status_code != 200: + LOG.error("Failed to start initialization job, error message: %s: %s", + job_res.status_code, job_res.content) + raise RuntimeError("Failed to start initialization job, error message: %s: %s" % + (job_res.status_code, job_res.content)) + elif job_res.status_code == 200: + job_res_content = jsonutils.loads(job_res.content) + job_id = job_res_content["job_id"] + LOG.info("Started initialization as job id: %s...", job_id) + + while not self.job_completed: + self._query_job_state(job_id) + time.sleep(self.query_interval) + + self.job_completed = False + def teardown(self): """Deletes the agent configuration and the stack""" - teardown_res = requests.delete('http://%s:5000/api/v1.0/\ - configurations' % self.target) + teardown_res = requests.delete( + 'http://%s:5000/api/v1.0/configurations' % self.target) if teardown_res.status_code == 400: teardown_res_content = jsonutils.loads( - teardown_res.content) + teardown_res.json_data) + LOG.error("Failed to reset environment, error message: %s", + teardown_res_content['message']) raise RuntimeError("Failed to reset environment, error message:", teardown_res_content['message']) |