diff options
Diffstat (limited to 'yardstick/benchmark')
36 files changed, 1631 insertions, 220 deletions
diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py index 7bd430bc5..8c514d250 100644 --- a/yardstick/benchmark/contexts/heat.py +++ b/yardstick/benchmark/contexts/heat.py @@ -129,8 +129,27 @@ class HeatContext(Context): scheduler_hints = {} for pg in server.placement_groups: update_scheduler_hints(scheduler_hints, added_servers, pg) - server.add_to_template(template, self.networks, scheduler_hints) - added_servers.append(server.stack_name) + # workround for openstack nova bug, check JIRA: YARDSTICK-200 + # for details + if len(availability_servers) == 2: + if len(scheduler_hints["different_host"]) == 0: + scheduler_hints.pop("different_host", None) + server.add_to_template(template, + self.networks, + scheduler_hints) + added_servers.append(server.stack_name) + else: + scheduler_hints["different_host"] = \ + scheduler_hints["different_host"][0] + server.add_to_template(template, + self.networks, + scheduler_hints) + added_servers.append(server.stack_name) + else: + server.add_to_template(template, + self.networks, + scheduler_hints) + added_servers.append(server.stack_name) # create list of servers with affinity policy affinity_servers = [] diff --git a/yardstick/benchmark/contexts/node.py b/yardstick/benchmark/contexts/node.py index 04c8e7ca3..54ee076f4 100644 --- a/yardstick/benchmark/contexts/node.py +++ b/yardstick/benchmark/contexts/node.py @@ -83,12 +83,5 @@ class NodeContext(Context): sys.exit(-1) node = nodes[0] - - server = { - "name": attr_name, - "ip": node["ip"], - "user": node["user"], - "key_filename": node["key_filename"] - } - - return server + node["name"] = attr_name + return node diff --git a/yardstick/benchmark/runners/iteration.py b/yardstick/benchmark/runners/iteration.py index e38ed3749..c24957b1a 100755..100644 --- a/yardstick/benchmark/runners/iteration.py +++ b/yardstick/benchmark/runners/iteration.py @@ -30,12 +30,15 @@ def _worker_process(queue, cls, method_name, scenario_cfg, interval = runner_cfg.get("interval", 1) iterations = runner_cfg.get("iterations", 1) + run_step = runner_cfg.get("run_step", "setup,run,teardown") LOG.info("worker START, iterations %d times, class %s", iterations, cls) runner_cfg['runner_id'] = os.getpid() benchmark = cls(scenario_cfg, context_cfg) - benchmark.setup() + if "setup" in run_step: + benchmark.setup() + method = getattr(benchmark, method_name) queue.put({'runner_id': runner_cfg['runner_id'], @@ -45,53 +48,55 @@ def _worker_process(queue, cls, method_name, scenario_cfg, sla_action = None if "sla" in scenario_cfg: sla_action = scenario_cfg["sla"].get("action", "assert") - - while True: - - LOG.debug("runner=%(runner)s seq=%(sequence)s START" % - {"runner": runner_cfg["runner_id"], "sequence": sequence}) - - data = {} - errors = "" - - try: - method(data) - except AssertionError as assertion: - # SLA validation failed in scenario, determine what to do now - if sla_action == "assert": - raise - elif sla_action == "monitor": - LOG.warning("SLA validation failed: %s" % assertion.args) - errors = assertion.args - except Exception as e: - errors = traceback.format_exc() - LOG.exception(e) - - time.sleep(interval) - - benchmark_output = { - 'timestamp': time.time(), - 'sequence': sequence, - 'data': data, - 'errors': errors - } - - record = {'runner_id': runner_cfg['runner_id'], - 'benchmark': benchmark_output} - - queue.put(record) - - LOG.debug("runner=%(runner)s seq=%(sequence)s END" % - {"runner": runner_cfg["runner_id"], "sequence": sequence}) - - sequence += 1 - - if (errors and sla_action is None) or \ - (sequence > iterations or aborted.is_set()): - LOG.info("worker END") - break - - benchmark.teardown() + if "run" in run_step: + while True: + + LOG.debug("runner=%(runner)s seq=%(sequence)s START" % + {"runner": runner_cfg["runner_id"], + "sequence": sequence}) + + data = {} + errors = "" + + try: + method(data) + except AssertionError as assertion: + # SLA validation failed in scenario, determine what to do now + if sla_action == "assert": + raise + elif sla_action == "monitor": + LOG.warning("SLA validation failed: %s" % assertion.args) + errors = assertion.args + except Exception as e: + errors = traceback.format_exc() + LOG.exception(e) + + time.sleep(interval) + + benchmark_output = { + 'timestamp': time.time(), + 'sequence': sequence, + 'data': data, + 'errors': errors + } + + record = {'runner_id': runner_cfg['runner_id'], + 'benchmark': benchmark_output} + + queue.put(record) + + LOG.debug("runner=%(runner)s seq=%(sequence)s END" % + {"runner": runner_cfg["runner_id"], + "sequence": sequence}) + + sequence += 1 + + if (errors and sla_action is None) or \ + (sequence > iterations or aborted.is_set()): + LOG.info("worker END") + break + if "teardown" in run_step: + benchmark.teardown() class IterationRunner(base.Runner): diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py new file mode 100644 index 000000000..b35869d07 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py @@ -0,0 +1,129 @@ +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd. and others +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import logging +import traceback +import subprocess +import yardstick.ssh as ssh +from baseattacker import BaseAttacker + +LOG = logging.getLogger(__name__) + + +def _execute_shell_command(command, stdin=None): + '''execute shell script with error handling''' + exitcode = 0 + output = [] + try: + output = subprocess.check_output(command, stdin=stdin, shell=True) + except Exception: + exitcode = -1 + output = traceback.format_exc() + LOG.error("exec command '%s' error:\n " % command) + LOG.error(traceback.format_exc()) + + return exitcode, output + + +class BaremetalAttacker(BaseAttacker): + + __attacker_type__ = 'bare-metal-down' + + def setup(self): + LOG.debug("config:%s context:%s" % (self._config, self._context)) + host = self._context.get(self._config['host'], None) + ip = host.get("ip", None) + user = host.get("user", "root") + key_filename = host.get("key_filename", "~/.ssh/id_rsa") + + self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection.wait(timeout=600) + LOG.debug("ssh host success!") + self.host_ip = ip + + 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.fault_cfg = BaseAttacker.attacker_cfgs.get('bare-metal-down') + self.check_script = self.get_script_fullpath( + self.fault_cfg['check_script']) + self.recovery_script = self.get_script_fullpath( + self.fault_cfg['recovery_script']) + + if self.check(): + self.setup_done = True + + def check(self): + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0} -W 10".format(self.host_ip), + stdin=open(self.check_script, "r")) + + LOG.debug("check ret: %s out:%s err:%s" % + (exit_status, stdout, stderr)) + if not stdout or "running" not in stdout: + LOG.info("the host (ipmi_ip:%s) is not running!" % self.ipmi_ip) + return False + + return True + + def inject_fault(self): + exit_status, stdout, stderr = self.connection.execute( + "shutdown -h now") + LOG.debug("inject fault ret: %s out:%s err:%s" % + (exit_status, stdout, stderr)) + if not exit_status: + LOG.info("inject fault success") + + def recover(self): + jump_host_name = self._config.get("jump_host", None) + self.jump_connection = None + if jump_host_name is not None: + host = self._context.get(jump_host_name, None) + ip = host.get("ip", None) + user = host.get("user", "root") + pwd = host.get("pwd", None) + + LOG.debug("jump_host ip:%s user:%s" % (ip, user)) + self.jump_connection = ssh.SSH(user, ip, password=pwd) + self.jump_connection.wait(timeout=600) + LOG.debug("ssh jump host success!") + + if self.jump_connection is not None: + exit_status, stdout, stderr = self.jump_connection.execute( + "/bin/bash -s {0} {1} {2} {3}".format( + self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "on"), + stdin=open(self.recovery_script, "r")) + else: + exit_status, stdout = _execute_shell_command( + "/bin/bash -s {0} {1} {2} {3}".format( + self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "on"), + stdin=open(self.recovery_script, "r")) + + +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_conf.yaml b/yardstick/benchmark/scenarios/availability/attacker/attacker_conf.yaml deleted file mode 100644 index 44f06038b..000000000 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_conf.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -# sample config file for ha test -# -schema: "yardstick:task:0.1" - -kill-process: - inject_script: scripts/stop_service.bash - recovery_script: scripts/start_service.bash - check_script: scripts/check_service.bash diff --git a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py index ddaf09969..a1c6999e5 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py +++ b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py @@ -16,7 +16,7 @@ import yardstick.common.utils as utils LOG = logging.getLogger(__name__) attacker_conf_path = pkg_resources.resource_filename( - "yardstick.benchmark.scenarios.availability.attacker", + "yardstick.benchmark.scenarios.availability", "attacker_conf.yaml") diff --git a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml new file mode 100644 index 000000000..3f6c2aa8f --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml @@ -0,0 +1,13 @@ +--- +# sample config file for ha test +# +schema: "yardstick:task:0.1" + +kill-process: + check_script: ha_tools/check_process_python.bash + inject_script: ha_tools/fault_process_kill.bash + recovery_script: ha_tools/start_service.bash + +bare-metal-down: + check_script: ha_tools/check_host_ping.bash + recovery_script: ha_tools/ipmi_power.bash diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/check_host_ping.bash b/yardstick/benchmark/scenarios/availability/ha_tools/check_host_ping.bash new file mode 100755 index 000000000..0f160e2a8 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/check_host_ping.bash @@ -0,0 +1,27 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# check wether the host is running + +set -e + +host_ip=$1 +shift +options="$@" + +ping -c 1 $options $host_ip | grep ttl | wc -l +EXIT_CODE=$? + +if [ $EXIT_CODE -ne 0 ]; then + exit 1 +else + echo "running" +fi diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/check_openstack_cmd.bash b/yardstick/benchmark/scenarios/availability/ha_tools/check_openstack_cmd.bash new file mode 100755 index 000000000..83d7e36c1 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/check_openstack_cmd.bash @@ -0,0 +1,20 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# check the status of a openstack command + +set -e + +cmd=$1 + +source /root/openrc + +exec $cmd diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/check_process_python.bash b/yardstick/benchmark/scenarios/availability/ha_tools/check_process_python.bash new file mode 100755 index 000000000..88baed7d9 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/check_process_python.bash @@ -0,0 +1,18 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# check the status of a service + +set -e + +process_name=$1 + +ps aux | grep -e .*python.*$process_name.* | grep -v grep | wc -l diff --git a/yardstick/benchmark/scenarios/availability/attacker/scripts/check_service.bash b/yardstick/benchmark/scenarios/availability/ha_tools/check_service.bash index cc898a859..cc898a859 100755 --- a/yardstick/benchmark/scenarios/availability/attacker/scripts/check_service.bash +++ b/yardstick/benchmark/scenarios/availability/ha_tools/check_service.bash diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash b/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash new file mode 100755 index 000000000..d0e2f1683 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash @@ -0,0 +1,18 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# Stop process by process name + +set -e + +process_name=$1 + +killall -9 $process_name diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/ipmi_power.bash b/yardstick/benchmark/scenarios/availability/ha_tools/ipmi_power.bash new file mode 100755 index 000000000..ea621facd --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/ha_tools/ipmi_power.bash @@ -0,0 +1,21 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# Stop a service and check the service is stoped + +set -e + +ipmi_ip=$1 +ipmi_user=$2 +ipmi_pwd=$3 + +action=$4 +ipmitool -I lanplus -H $ipmi_ip -U $ipmi_user -P $ipmi_pwd power $action diff --git a/yardstick/benchmark/scenarios/availability/attacker/scripts/start_service.bash b/yardstick/benchmark/scenarios/availability/ha_tools/start_service.bash index c1bf8b7eb..c1bf8b7eb 100755 --- a/yardstick/benchmark/scenarios/availability/attacker/scripts/start_service.bash +++ b/yardstick/benchmark/scenarios/availability/ha_tools/start_service.bash diff --git a/yardstick/benchmark/scenarios/availability/attacker/scripts/stop_service.bash b/yardstick/benchmark/scenarios/availability/ha_tools/stop_service.bash index a8901784e..a8901784e 100755 --- a/yardstick/benchmark/scenarios/availability/attacker/scripts/stop_service.bash +++ b/yardstick/benchmark/scenarios/availability/ha_tools/stop_service.bash diff --git a/yardstick/benchmark/scenarios/availability/monitor.py b/yardstick/benchmark/scenarios/availability/monitor.py deleted file mode 100755 index 3193d3304..000000000 --- a/yardstick/benchmark/scenarios/availability/monitor.py +++ /dev/null @@ -1,114 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Huawei Technologies Co.,Ltd. and others -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## -import logging -import multiprocessing -import subprocess -import traceback -import time - -LOG = logging.getLogger(__name__) - - -def _execute_shell_command(command): - '''execute shell script with error handling''' - exitcode = 0 - output = [] - try: - output = subprocess.check_output(command, shell=True) - except Exception: - exitcode = -1 - output = traceback.format_exc() - LOG.error("exec command '%s' error:\n " % command) - LOG.error(traceback.format_exc()) - - return exitcode, output - - -def _monitor_process(config, queue, event): - - total_time = 0 - outage_time = 0 - total_count = 0 - outage_count = 0 - first_outage = 0 - last_outage = 0 - - wait_time = config.get("duration", 0) - cmd = config.get("monitor_cmd", None) - if cmd is None: - LOG.error("There are no monitor cmd!") - return - - queue.put("started") - - begin_time = time.time() - while True: - - total_count = total_count + 1 - - one_check_begin_time = time.time() - exit_status, stdout = _execute_shell_command(cmd) - one_check_end_time = time.time() - - LOG.info("the exit_status:%s stdout:%s" % (exit_status, stdout)) - if exit_status: - outage_count = outage_count + 1 - - outage_time = outage_time + ( - one_check_end_time - one_check_begin_time) - - if not first_outage: - first_outage = one_check_begin_time - - last_outage = one_check_end_time - - if event.is_set(): - LOG.debug("the monitor process stop") - break - - if wait_time > 0: - time.sleep(wait_time) - - end_time = time.time() - total_time = end_time - begin_time - - queue.put({"total_time": total_time, - "outage_time": last_outage-first_outage, - "total_count": total_count, - "outage_count": outage_count}) - - -class Monitor: - - def __init__(self): - self._result = [] - self._monitor_process = [] - - def setup(self, config): - self._config = config - - def start(self): - self._queue = multiprocessing.Queue() - self._event = multiprocessing.Event() - self._monitor_process = multiprocessing.Process( - target=_monitor_process, name="Monitor", - args=(self._config, self._queue, self._event)) - - self._monitor_process.start() - ret = self._queue.get() - if ret == "started": - LOG.debug("monitor process started!") - - def stop(self): - self._event.set() - self._result = self._queue.get() - LOG.debug("stop the monitor process. the result:%s" % self._result) - - def get_result(self): - return self._result diff --git a/yardstick/benchmark/scenarios/availability/monitor/__init__.py b/yardstick/benchmark/scenarios/availability/monitor/__init__.py new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/monitor/__init__.py diff --git a/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py b/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py new file mode 100644 index 000000000..983c3a3ac --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py @@ -0,0 +1,140 @@ +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd. and others +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import pkg_resources +import logging +import multiprocessing +import time +import os +import yardstick.common.utils as utils + +LOG = logging.getLogger(__name__) + +monitor_conf_path = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.availability", + "monitor_conf.yaml") + + +class MonitorMgr(object): + """docstring for MonitorMgr""" + def __init__(self): + self._monitor_list = [] + + def init_monitors(self, monitor_cfgs, context): + LOG.debug("monitorMgr config: %s" % monitor_cfgs) + + for monitor_cfg in monitor_cfgs: + monitor_type = monitor_cfg["monitor_type"] + monitor_cls = BaseMonitor.get_monitor_cls(monitor_type) + monitor_ins = monitor_cls(monitor_cfg, context) + + self._monitor_list.append(monitor_ins) + + def start_monitors(self): + for _monotor_instace in self._monitor_list: + _monotor_instace.start_monitor() + + def wait_monitors(self): + for monitor in self._monitor_list: + monitor.wait_monitor() + + def verify_SLA(self): + sla_pass = True + for monitor in self._monitor_list: + sla_pass = sla_pass & monitor.verify_SLA() + return sla_pass + + +class BaseMonitor(multiprocessing.Process): + """docstring for BaseMonitor""" + + def __init__(self, config, context): + multiprocessing.Process.__init__(self) + self._config = config + self._context = context + self._queue = multiprocessing.Queue() + self._event = multiprocessing.Event() + self.setup_done = False + + @staticmethod + def get_monitor_cls(monitor_type): + '''return monitor class of specified type''' + + for monitor in utils.itersubclasses(BaseMonitor): + if monitor_type == monitor.__monitor_type__: + return monitor + raise RuntimeError("No such monitor_type %s" % monitor_type) + + def get_script_fullpath(self, path): + base_path = os.path.dirname(monitor_conf_path) + return os.path.join(base_path, path) + + def run(self): + LOG.debug("config:%s context:%s" % (self._config, self._context)) + + self.setup() + monitor_time = self._config.get("monitor_time", 0) + + total_time = 0 + outage_time = 0 + total_count = 0 + outage_count = 0 + first_outage = 0 + last_outage = 0 + + begin_time = time.time() + while True: + total_count = total_count + 1 + + one_check_begin_time = time.time() + exit_status = self.monitor_func() + one_check_end_time = time.time() + + if exit_status is False: + outage_count = outage_count + 1 + + outage_time = outage_time + ( + one_check_end_time - one_check_begin_time) + + if not first_outage: + first_outage = one_check_begin_time + + last_outage = one_check_end_time + + if self._event.is_set(): + LOG.debug("the monitor process stop") + break + + if one_check_end_time - begin_time > monitor_time: + LOG.debug("the monitor max_time finished and exit!") + break + + end_time = time.time() + total_time = end_time - begin_time + + self._queue.put({"total_time": total_time, + "outage_time": last_outage-first_outage, + "total_count": total_count, + "outage_count": outage_count}) + + def start_monitor(self): + self.start() + + def wait_monitor(self): + self.join() + self._result = self._queue.get() + LOG.debug("the monitor result:%s" % self._result) + + def setup(self): # pragma: no cover + pass + + def monitor_func(self): # pragma: no cover + pass + + def verify_SLA(self): + pass diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py new file mode 100644 index 000000000..c285024e1 --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py @@ -0,0 +1,108 @@ +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd. and others +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import logging +import subprocess +import traceback +import yardstick.ssh as ssh +import basemonitor as basemonitor + +LOG = logging.getLogger(__name__) + + +def _execute_shell_command(command): + '''execute shell script with error handling''' + exitcode = 0 + output = [] + try: + output = subprocess.check_output(command, shell=True) + except Exception: + exitcode = -1 + output = traceback.format_exc() + LOG.error("exec command '%s' error:\n " % command) + LOG.error(traceback.format_exc()) + + return exitcode, output + + +class MonitorOpenstackCmd(basemonitor.BaseMonitor): + """docstring for MonitorApi""" + + __monitor_type__ = "openstack-cmd" + + def setup(self): + self.connection = None + node_name = self._config.get("host", None) + if node_name: + host = self._context[node_name] + ip = host.get("ip", None) + user = host.get("user", "root") + key_filename = host.get("key_filename", "~/.ssh/id_rsa") + + self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection.wait(timeout=600) + LOG.debug("ssh host success!") + + self.check_script = self.get_script_fullpath( + "ha_tools/check_openstack_cmd.bash") + + self.cmd = self._config["command_name"] + + def monitor_func(self): + exit_status = 0 + if self.connection: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s '{0}'".format(self.cmd), + stdin=open(self.check_script, "r")) + + LOG.debug("the ret stats: %s stdout: %s stderr: %s" % + (exit_status, stdout, stderr)) + else: + exit_status, stdout = _execute_shell_command(self.cmd) + 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 + + +def _test(): # pragma: no cover + host = { + "ip": "192.168.235.22", + "user": "root", + "key_filename": "/root/.ssh/id_rsa" + } + context = {"node1": host} + monitor_configs = [] + config = { + 'monitor_type': 'openstack-cmd', + 'command_name': 'nova image-list', + 'monitor_time': 1, + 'host': 'node1', + 'sla': {'max_outage_time': 5} + } + monitor_configs.append(config) + + p = basemonitor.MonitorMgr() + p.init_monitors(monitor_configs, context) + p.start_monitors() + p.wait_monitors() + p.verify_SLA() + + +if __name__ == '__main__': # pragma: no cover + _test() diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py new file mode 100644 index 000000000..53a6d8e4d --- /dev/null +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py @@ -0,0 +1,81 @@ +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd. and others +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import logging +import yardstick.ssh as ssh + +import basemonitor as basemonitor + +LOG = logging.getLogger(__name__) + + +class MonitorProcess(basemonitor.BaseMonitor): + """docstring for MonitorApi""" + + __monitor_type__ = "process" + + def setup(self): + host = self._context[self._config["host"]] + ip = host.get("ip", None) + user = host.get("user", "root") + key_filename = host.get("key_filename", "~/.ssh/id_rsa") + + self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection.wait(timeout=600) + LOG.debug("ssh host success!") + self.check_script = self.get_script_fullpath( + "ha_tools/check_process_python.bash") + self.process_name = self._config["process_name"] + + def monitor_func(self): + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0}".format(self.process_name), + stdin=open(self.check_script, "r")) + if not stdout or int(stdout) <= 0: + LOG.info("the process (%s) is not running!" % self.process_name) + return False + + 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: + return True + + +def _test(): # pragma: no cover + host = { + "ip": "10.20.0.5", + "user": "root", + "key_filename": "/root/.ssh/id_rsa" + } + context = {"node1": host} + monitor_configs = [] + config = { + 'monitor_type': 'process', + 'process_name': 'nova-api', + 'host': "node1", + 'monitor_time': 1, + 'sla': {'max_recover_time': 5} + } + monitor_configs.append(config) + + p = basemonitor.MonitorMgr() + p.init_monitors(monitor_configs, context) + p.start_monitors() + p.wait_monitors() + p.verify_SLA() + + +if __name__ == '__main__': # pragma: no cover + _test() diff --git a/yardstick/benchmark/scenarios/availability/serviceha.py b/yardstick/benchmark/scenarios/availability/serviceha.py index 10134ea6d..aee94ee09 100755 --- a/yardstick/benchmark/scenarios/availability/serviceha.py +++ b/yardstick/benchmark/scenarios/availability/serviceha.py @@ -7,9 +7,8 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## import logging -import time from yardstick.benchmark.scenarios import base -from yardstick.benchmark.scenarios.availability import monitor +from yardstick.benchmark.scenarios.availability.monitor import basemonitor from yardstick.benchmark.scenarios.availability.attacker import baseattacker LOG = logging.getLogger(__name__) @@ -34,6 +33,7 @@ class ServiceHA(base.Scenario): if nodes is None: LOG.error("the nodes info is none") return + self.attackers = [] attacker_cfgs = self.scenario_cfg["options"]["attackers"] for attacker_cfg in attacker_cfgs: @@ -45,9 +45,9 @@ class ServiceHA(base.Scenario): monitor_cfgs = self.scenario_cfg["options"]["monitors"] - self.monitor_ins = monitor.Monitor() - self.monitor_ins.setup(monitor_cfgs[0]) - self.monitor_ins.monitor_time = monitor_cfgs[0]["monitor_time"] + self.monitorMgr = basemonitor.MonitorMgr() + self.monitorMgr.init_monitors(monitor_cfgs, nodes) + self.setup_done = True def run(self, result): @@ -56,35 +56,24 @@ class ServiceHA(base.Scenario): LOG.error("The setup not finished!") return - self.monitor_ins.start() + self.monitorMgr.start_monitors() LOG.info("monitor start!") for attacker in self.attackers: attacker.inject_fault() - time.sleep(self.monitor_ins.monitor_time) - - self.monitor_ins.stop() + self.monitorMgr.wait_monitors() LOG.info("monitor stop!") - ret = self.monitor_ins.get_result() - LOG.info("The monitor result:%s" % ret) - outage_time = ret.get("outage_time") - result["outage_time"] = outage_time - LOG.info("the result:%s" % result) - - if "sla" in self.scenario_cfg: - sla_outage_time = int(self.scenario_cfg["sla"]["outage_time"]) - assert outage_time <= sla_outage_time, "outage_time %f > sla:outage_time(%f)" % \ - (outage_time, sla_outage_time) + sla_pass = self.monitorMgr.verify_SLA() + assert sla_pass is True, "the test cases is not pass the SLA" return def teardown(self): '''scenario teardown''' for attacker in self.attackers: - if not attacker.check(): - attacker.recover() + attacker.recover() def _test(): # pragma: no cover @@ -103,14 +92,14 @@ def _test(): # pragma: no cover attacker_cfgs = [] attacker_cfgs.append(attacker_cfg) monitor_cfg = { - "monitor_cmd": "nova image-list", - "monitor_tme": 10 + "monitor_cmd": "nova image-list" } monitor_cfgs = [] monitor_cfgs.append(monitor_cfg) options = { "attackers": attacker_cfgs, + "wait_time": 10, "monitors": monitor_cfgs } sla = {"outage_time": 5} diff --git a/yardstick/benchmark/scenarios/compute/cyclictest.py b/yardstick/benchmark/scenarios/compute/cyclictest.py index e8fc63cf7..478b0a1a2 100644 --- a/yardstick/benchmark/scenarios/compute/cyclictest.py +++ b/yardstick/benchmark/scenarios/compute/cyclictest.py @@ -9,6 +9,9 @@ import pkg_resources import logging import json +import re +import time +import os import yardstick.ssh as ssh from yardstick.benchmark.scenarios import base @@ -53,30 +56,104 @@ class Cyclictest(base.Scenario): __scenario_type__ = "Cyclictest" TARGET_SCRIPT = "cyclictest_benchmark.bash" + WORKSPACE = "/root/workspace/" + REBOOT_CMD_PATTERN = r";\s*reboot\b" def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg self.setup_done = False - def setup(self): - '''scenario setup''' - self.target_script = pkg_resources.resource_filename( - "yardstick.benchmark.scenarios.compute", - Cyclictest.TARGET_SCRIPT) + def _put_files(self, client): + setup_options = self.scenario_cfg["setup_options"] + rpm_dir = setup_options["rpm_dir"] + script_dir = setup_options["script_dir"] + image_dir = setup_options["image_dir"] + LOG.debug("Send RPMs from %s to workspace %s" % + (rpm_dir, self.WORKSPACE)) + client.put(rpm_dir, self.WORKSPACE, recursive=True) + LOG.debug("Send scripts from %s to workspace %s" % + (script_dir, self.WORKSPACE)) + client.put(script_dir, self.WORKSPACE, recursive=True) + LOG.debug("Send guest image from %s to workspace %s" % + (image_dir, self.WORKSPACE)) + client.put(image_dir, self.WORKSPACE, recursive=True) + + def _connect_host(self): + host = self.context_cfg["host"] + user = host.get("user", "root") + ip = host.get("ip", None) + key_filename = host.get("key_filename", "~/.ssh/id_rsa") + + LOG.debug("user:%s, host:%s", user, ip) + self.host = ssh.SSH(user, ip, key_filename=key_filename) + self.host.wait(timeout=600) + + def _connect_guest(self): host = self.context_cfg["host"] user = host.get("user", "root") ip = host.get("ip", None) key_filename = host.get("key_filename", "~/.ssh/id_rsa") LOG.debug("user:%s, host:%s", user, ip) - print "key_filename:" + key_filename - self.client = ssh.SSH(user, ip, key_filename=key_filename) - self.client.wait(timeout=600) + self.guest = ssh.SSH(user, ip, port=5555, key_filename=key_filename) + self.guest.wait(timeout=600) + + def _run_setup_cmd(self, client, cmd): + LOG.debug("Run cmd: %s" % cmd) + status, stdout, stderr = client.execute(cmd) + if status: + if re.search(self.REBOOT_CMD_PATTERN, cmd): + LOG.debug("Error on reboot") + else: + raise RuntimeError(stderr) + + def _run_host_setup_scripts(self, scripts): + setup_options = self.scenario_cfg["setup_options"] + script_dir = os.path.basename(setup_options["script_dir"]) + + for script in scripts: + cmd = "cd %s/%s; export PATH=./:$PATH; %s" %\ + (self.WORKSPACE, script_dir, script) + self._run_setup_cmd(self.host, cmd) + + if re.search(self.REBOOT_CMD_PATTERN, cmd): + time.sleep(3) + self._connect_host() + + def _run_guest_setup_scripts(self, scripts): + setup_options = self.scenario_cfg["setup_options"] + script_dir = os.path.basename(setup_options["script_dir"]) + + for script in scripts: + cmd = "cd %s/%s; export PATH=./:$PATH; %s" %\ + (self.WORKSPACE, script_dir, script) + self._run_setup_cmd(self.guest, cmd) + + if re.search(self.REBOOT_CMD_PATTERN, cmd): + time.sleep(3) + self._connect_guest() + + def setup(self): + '''scenario setup''' + setup_options = self.scenario_cfg["setup_options"] + host_setup_seqs = setup_options["host_setup_seqs"] + guest_setup_seqs = setup_options["guest_setup_seqs"] + + self._connect_host() + self._put_files(self.host) + self._run_host_setup_scripts(host_setup_seqs) + + self._connect_guest() + self._put_files(self.guest) + self._run_guest_setup_scripts(guest_setup_seqs) # copy script to host - self.client.run("cat > ~/cyclictest_benchmark.sh", - stdin=open(self.target_script, "rb")) + self.target_script = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.compute", + Cyclictest.TARGET_SCRIPT) + self.guest.run("cat > ~/cyclictest_benchmark.sh", + stdin=open(self.target_script, "rb")) self.setup_done = True @@ -98,9 +175,9 @@ class Cyclictest(base.Scenario): cmd_args = "-a %s -i %s -p %s -l %s -t %s -h %s %s" \ % (affinity, interval, priority, loops, threads, histogram, default_args) - cmd = "sudo bash cyclictest_benchmark.sh %s" % (cmd_args) + cmd = "bash cyclictest_benchmark.sh %s" % (cmd_args) LOG.debug("Executing command: %s", cmd) - status, stdout, stderr = self.client.execute(cmd) + status, stdout, stderr = self.guest.execute(cmd) if status: raise RuntimeError(stderr) @@ -121,7 +198,7 @@ class Cyclictest(base.Scenario): assert sla_error == "", sla_error -def _test(): +def _test(): # pragma: no cover '''internal test function''' key_filename = pkg_resources.resource_filename("yardstick.resources", "files/yardstick_key") @@ -159,5 +236,5 @@ def _test(): cyclictest.run(result) print result -if __name__ == '__main__': +if __name__ == '__main__': # pragma: no cover _test() diff --git a/yardstick/benchmark/scenarios/networking/ping6.py b/yardstick/benchmark/scenarios/networking/ping6.py new file mode 100644 index 000000000..629f62be5 --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/ping6.py @@ -0,0 +1,119 @@ +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import pkg_resources +import logging + +import yardstick.ssh as ssh +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) + + +class Ping6(base.Scenario): # pragma: no cover + """Execute ping6 between two hosts + + read link below for more ipv6 info description: + http://wiki.opnfv.org/ipv6_opnfv_project + """ + __scenario_type__ = "Ping6" + + TARGET_SCRIPT = 'ping6_benchmark.bash' + SETUP_SCRIPT = 'ping6_setup.bash' + TEARDOWN_SCRIPT = 'ping6_teardown.bash' + METADATA_SCRIPT = 'ping6_metadata.txt' + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.setup_done = False + self.run_done = False + + def _ssh_host(self): + # ssh host1 + host = self.context_cfg['host'] + host_user = host.get('user', 'ubuntu') + host_ip = host.get('ip', None) + host_pwd = host.get('password', 'root') + LOG.info("user:%s, host:%s", host_user, host_ip) + self.client = ssh.SSH(host_user, host_ip, password=host_pwd) + self.client.wait(timeout=600) + + def setup(self): + '''scenario setup''' + self.setup_script = pkg_resources.resource_filename( + 'yardstick.benchmark.scenarios.networking', + Ping6.SETUP_SCRIPT) + + self.ping6_metadata_script = pkg_resources.resource_filename( + 'yardstick.benchmark.scenarios.networking', + Ping6.METADATA_SCRIPT) + # ssh host1 + self._ssh_host() + # run script to setup ipv6 + self.client.run("cat > ~/setup.sh", + stdin=open(self.setup_script, "rb")) + self.client.run("cat > ~/metadata.txt", + stdin=open(self.ping6_metadata_script, "rb")) + cmd = "sudo bash setup.sh" + status, stdout, stderr = self.client.execute(cmd) + + self.setup_done = True + + def run(self, result): + """execute the benchmark""" + # ssh vm1 + self.ping6_script = pkg_resources.resource_filename( + 'yardstick.benchmark.scenarios.networking', + Ping6.TARGET_SCRIPT) + + if not self.setup_done: + self._ssh_host() + + self.client.run("cat > ~/ping6.sh", + stdin=open(self.ping6_script, "rb")) + cmd = "sudo bash ping6.sh" + LOG.debug("Executing command: %s", cmd) + status, stdout, stderr = self.client.execute(cmd) + print stdout + if status: + raise RuntimeError(stderr) + + if stdout: + 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) + else: + LOG.error("ping6 timeout") + self.run_done = True + + def teardown(self): + """teardown the benchmark""" + + if not self.run_done: + self._ssh_host() + + self.teardown_script = pkg_resources.resource_filename( + 'yardstick.benchmark.scenarios.networking', + Ping6.TEARDOWN_SCRIPT) + self.client.run("cat > ~/teardown.sh", + stdin=open(self.teardown_script, "rb")) + cmd = "sudo bash teardown.sh" + status, stdout, stderr = self.client.execute(cmd) + + if status: + raise RuntimeError(stderr) + + if stdout: + pass + else: + LOG.error("ping6 teardown failed") diff --git a/yardstick/benchmark/scenarios/networking/ping6_benchmark.bash b/yardstick/benchmark/scenarios/networking/ping6_benchmark.bash new file mode 100644 index 000000000..6df354a1b --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/ping6_benchmark.bash @@ -0,0 +1,20 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# Run a single ping6 command towards a ipv6 router + +set -e + +# TODO find host +sudo ip netns exec qdhcp-$(neutron net-list | grep -w ipv4-int-network1 | awk '{print $2}') bash +# TODO find VM ip +ssh -i vRouterkey fedora@20.0.0.4 +ping6 -c 1 2001:db8:0:1::1 | grep ttl | awk -F [=\ ] '{printf $10}' diff --git a/yardstick/benchmark/scenarios/networking/ping6_metadata.txt b/yardstick/benchmark/scenarios/networking/ping6_metadata.txt new file mode 100644 index 000000000..5dc08d30f --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/ping6_metadata.txt @@ -0,0 +1,82 @@ +#cloud-config +bootcmd: + - /usr/sbin/ifdown eth0 + - /usr/sbin/ifup eth0 + - /usr/sbin/ifdown eth1 + - ip link set dev eth0 mtu 1300 + - ip link set dev eth1 mtu 1300 + - /usr/sbin/ifup eth1 + - ip link set dev eth0 mtu 1300 + - ip link set dev eth1 mtu 1300 + - setenforce 0 + - /sbin/sysctl -w net.ipv6.conf.all.forwarding=1 + - /sbin/sysctl -w net.ipv6.conf.eth0.accept_ra=2 + - /sbin/sysctl -w net.ipv6.conf.eth0.accept_ra_defrtr=1 + - /sbin/sysctl -w net.ipv6.conf.eth0.router_solicitations=1 +packages: + - radvd +runcmd: + - /usr/sbin/ifdown eth1 + - /usr/sbin/ifup eth1 + - ip link set dev eth0 mtu 1300 + - ip link set dev eth1 mtu 1300 + - /usr/bin/systemctl disable NetworkManager + - /usr/bin/systemctl start radvd + - echo 'complete' >> /tmp/cloud-config.log +write_files: + - content: | + TYPE="Ethernet" + BOOTPROTO="dhcp" + DEFROUTE="yes" + PEERDNS="yes" + PEERROUTES="yes" + IPV4_FAILURE_FATAL="no" + IPV6INIT="yes" + IPV6_AUTOCONF="yes" + IPV6_DEFROUTE="yes" + IPV6_PEERROUTES="yes" + IPV6_PEERDNS="yes" + IPV6_FAILURE_FATAL="no" + NAME="eth0" + DEVICE="eth0" + ONBOOT="yes" + path: /etc/sysconfig/network-scripts/ifcfg-eth0 + permissions: '0755' + owner: root:root + - content: | + TYPE="Ethernet" + BOOTPROTO=static + IPV6INIT=yes + IPV6ADDR="2001:db8:0:2::1/64" + NAME=eth1 + DEVICE=eth1 + ONBOOT=yes + NM_CONTROLLED=no + path: /etc/sysconfig/network-scripts/ifcfg-eth1 + permissions: '0755' + owner: root:root + - content: | + interface eth1 + { + AdvSendAdvert on; + MinRtrAdvInterval 3; + MaxRtrAdvInterval 10; + AdvHomeAgentFlag off; + AdvManagedFlag on; + AdvOtherConfigFlag on; + prefix 2001:db8:0:2::/64 + { + AdvOnLink on; + ### On link tells the host that the default router is on the same "link" as it is + AdvAutonomous on; + AdvRouterAddr off; + }; + }; + path: /etc/radvd.conf + permissions: '0644' + owner: root:root + - content: | + IPV6FORWARDING=yes + path: /etc/sysconfig/network + permissions: '0644' + owner: root:root
\ No newline at end of file diff --git a/yardstick/benchmark/scenarios/networking/ping6_setup.bash b/yardstick/benchmark/scenarios/networking/ping6_setup.bash new file mode 100644 index 000000000..2a54da2ba --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/ping6_setup.bash @@ -0,0 +1,84 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +# download and create image +source /opt/admin-openrc.sh +wget https://download.fedoraproject.org/pub/fedora/linux/releases/22/Cloud/x86_64/Images/Fedora-Cloud-Base-22-20150521.x86_64.qcow2 +glance image-create --name 'Fedora22' --disk-format qcow2 \ +--container-format bare --file ./Fedora-Cloud-Base-22-20150521.x86_64.qcow2 + +# create external network +neutron net-create net04_ext --router:external --provider:physical_network physnet \ +--provider:network_type vlan --provider:segmentation_id 1411 +neutron subnet-create net04_ext 10.145.140.0/24 --name net04_ext__subnet \ +--allocation-pool start=10.145.140.13,end=10.145.140.20 --disable-dhcp --gateway 10.145.140.1 + +# create router +neutron router-create ipv4-router +neutron router-create ipv6-router + + +# create (ipv4,ipv6)router and net and subnet +neutron net-create --port_security_enabled=False ipv4-int-network1 +neutron net-create --port_security_enabled=False ipv6-int-network2 + +# Create IPv4 subnet and associate it to ipv4-router +neutron subnet-create --name ipv4-int-subnet1 \ +--dns-nameserver 8.8.8.8 ipv4-int-network1 20.0.0.0/24 +neutron router-interface-add ipv4-router ipv4-int-subnet1 + +# Associate the net04_ext to the Neutron routers +neutron router-gateway-set ipv6-router net04_ext +neutron router-gateway-set ipv4-router net04_ext + +# Create two subnets, one IPv4 subnet ipv4-int-subnet2 and +# one IPv6 subnet ipv6-int-subnet2 in ipv6-int-network2, and associate both subnets to ipv6-router +neutron subnet-create --name ipv4-int-subnet2 --dns-nameserver 8.8.8.8 ipv6-int-network2 10.0.0.0/24 +neutron subnet-create --name ipv6-int-subnet2 \ + --ip-version 6 --ipv6-ra-mode slaac --ipv6-address-mode slaac ipv6-int-network2 2001:db8:0:1::/64 + + +neutron router-interface-add ipv6-router ipv4-int-subnet2 +neutron router-interface-add ipv6-router ipv6-int-subnet2 + + +# create key +nova keypair-add vRouterKey > ~/vRouterKey + +# Create ports for vRouter +neutron port-create --name eth0-vRouter --mac-address fa:16:3e:11:11:11 ipv6-int-network2 +neutron port-create --name eth1-vRouter --mac-address fa:16:3e:22:22:22 ipv4-int-network1 + +# Create ports for VM1 and VM2. +neutron port-create --name eth0-VM1 --mac-address fa:16:3e:33:33:33 ipv4-int-network1 +neutron port-create --name eth0-VM2 --mac-address fa:16:3e:44:44:44 ipv4-int-network1 + +# Update ipv6-router with routing information to subnet 2001:db8:0:2::/64 +neutron router-update ipv6-router \ + --routes type=dict list=true destination=2001:db8:0:2::/64,nexthop=2001:db8:0:1:f816:3eff:fe11:1111 + +# vRouter boot +nova boot --image Fedora22 --flavor m1.small \ +--user-data ./metadata.txt \ +--nic port-id=$(neutron port-list | grep -w eth0-vRouter | awk '{print $2}') \ +--nic port-id=$(neutron port-list | grep -w eth1-vRouter | awk '{print $2}') \ +--key-name vRouterKey vRouter + +# VM create +nova boot --image Fedora22 --flavor m1.small \ +--nic port-id=$(neutron port-list | grep -w eth0-VM1 | awk '{print $2}') \ +--key-name vRouterKey VM1 + +nova boot --image Fedora22 --flavor m1.small \ +--nic port-id=$(neutron port-list | grep -w eth0-VM2 | awk '{print $2}') \ +--key-name vRouterKey VM2 + +nova list diff --git a/yardstick/benchmark/scenarios/networking/ping6_teardown.bash b/yardstick/benchmark/scenarios/networking/ping6_teardown.bash new file mode 100644 index 000000000..7ab145523 --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/ping6_teardown.bash @@ -0,0 +1,58 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +# delete VM +nova delete VM1 +nova delete VM2 +nova delete vRouter +#clear routes +neutron router-update ipv6-router --routes action=clear + +#VM1,VM2 port delete +neutron port-delete --name eth0-VM1 +neutron port-delete --name eth0-VM2 + +#vRouter port delete +neutron port-delete --name eth0-vRouter +neutron port-delete --name eth1-vRouter + +#delete key +nova keypair-delete vRouterKey + +#delete ipv6 router interface +neutron router-interface-delete ipv6-router ipv6-int-subnet2 +neutron router-interface-delete ipv6-router ipv4-int-subnet2 + +#delete subnet +neutron subnet-delete --name ipv6-int-subnet2 +neutron subnet-delete --name ipv4-int-subnet2 + +#clear gateway +neutron router-gateway-clear ipv4-router net04_ext +neutron router-gateway-clear ipv6-router net04_ext + +#delete ipv4 router interface +neutron router-interface-delete ipv4-router ipv4-int-subnet1 +neutron subnet-delete --name ipv4-int-subnet1 + +#delete network +neutron net-delete ipv6-int-network2 +neutron net-delete ipv4-int-network1 + +# delete router +neutron router-delete ipv4-router +neutron router-delete ipv6-router + +# delete ext net +neutron subnet-delete net04_ext__subnet +neutron net-delete net04_ext + +# delete glance image +glance --os-image-api-version 1 image-delete Fedora22
\ No newline at end of file diff --git a/yardstick/benchmark/scenarios/networking/vtc_instantiation_validation.py b/yardstick/benchmark/scenarios/networking/vtc_instantiation_validation.py new file mode 100644 index 000000000..509fa847b --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/vtc_instantiation_validation.py @@ -0,0 +1,85 @@ +############################################################################# +# Copyright (c) 2015 Ericsson AB 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 +############################################################################## + +import logging +import os + +from yardstick.benchmark.scenarios import base +import experimental_framework.api as api + +LOG = logging.getLogger(__name__) + + +class VtcInstantiationValidation(base.Scenario): + """Execute Instantiation Validation TC on the vTC + """ + __scenario_type__ = "vtc_instantiation_validation" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.options = None + self.setup_done = False + + def setup(self): + '''scenario setup''' + + self.options = self.scenario_cfg['options'] + self.setup_done = True + + def run(self, result): + """execute test""" + + if not self.setup_done: + self.setup() + + heat_template = 'vTC.yaml' + iterations = 1 + + openstack_credentials = { + 'ip_controller': '0.0.0.0', + 'heat_url': '***', + 'auth_uri': os.environ.get('OS_AUTH_URL'), + 'user': os.environ.get('OS_USERNAME'), + 'password': os.environ.get('OS_PASSWORD'), + 'project': os.environ.get('OS_TENANT_NAME') + } + heat_template_parameters = { + 'default_net': self.options['default_net_name'], + 'default_subnet': self.options['default_subnet_name'], + 'source_net': self.options['vlan_net_1_name'], + 'source_subnet': self.options['vlan_subnet_1_name'], + 'destination_net': self.options['vlan_net_2_name'], + 'destination_subnet': self.options['vlan_subnet_2_name'] + } + deployment_configuration = { + 'vnic_type': [self.options['vnic_type']], + 'vtc_flavor': [self.options['vtc_flavor']] + } + + test_case = dict() + test_case['name'] = 'instantiation_validation_benchmark.' \ + 'InstantiationValidationBenchmark' + test_case['params'] = dict() + test_case['params']['throughput'] = '1' + test_case['params']['vlan_sender'] = str(self.options['vlan_sender']) + test_case['params']['vlan_receiver'] = \ + str(self.options['vlan_receiver']) + + try: + result = api.FrameworkApi.execute_framework( + [test_case], + iterations, + heat_template, + heat_template_parameters, + deployment_configuration, + openstack_credentials) + except Exception as e: + LOG.info('Exception: {}'.format(e.message)) + LOG.info('Got output: {}'.format(result)) diff --git a/yardstick/benchmark/scenarios/networking/vtc_instantiation_validation_noisy.py b/yardstick/benchmark/scenarios/networking/vtc_instantiation_validation_noisy.py new file mode 100644 index 000000000..4834a5fc7 --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/vtc_instantiation_validation_noisy.py @@ -0,0 +1,92 @@ +############################################################################# +# Copyright (c) 2015 Ericsson AB 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 +############################################################################## + +import logging +import os + +from yardstick.benchmark.scenarios import base +import experimental_framework.api as api + +LOG = logging.getLogger(__name__) + + +class VtcInstantiationValidationNoisy(base.Scenario): + """Execute Instantiation Validation TC on the vTC + """ + __scenario_type__ = "vtc_instantiation_validation_noisy" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.options = None + self.setup_done = False + + def setup(self): + '''scenario setup''' + + self.options = self.scenario_cfg['options'] + self.setup_done = True + + def run(self, result): + """execute test""" + + if not self.setup_done: + self.setup() + + heat_template = 'vTC.yaml' + iterations = 1 + + openstack_credentials = { + 'ip_controller': '0.0.0.0', + 'heat_url': '***', + 'auth_uri': os.environ.get('OS_AUTH_URL'), + 'user': os.environ.get('OS_USERNAME'), + 'password': os.environ.get('OS_PASSWORD'), + 'project': os.environ.get('OS_TENANT_NAME') + } + heat_template_parameters = { + 'default_net': self.options['default_net_name'], + 'default_subnet': self.options['default_subnet_name'], + 'source_net': self.options['vlan_net_1_name'], + 'source_subnet': self.options['vlan_subnet_1_name'], + 'destination_net': self.options['vlan_net_2_name'], + 'destination_subnet': self.options['vlan_subnet_2_name'] + } + deployment_configuration = { + 'vnic_type': [self.options['vnic_type']], + 'vtc_flavor': [self.options['vtc_flavor']] + } + + test_case = dict() + test_case['name'] = 'instantiation_validation_noisy_neighbors_' \ + 'benchmark.' \ + 'InstantiationValidationNoisyNeighborsBenchmark' + test_case['params'] = dict() + test_case['params']['throughput'] = '1' + test_case['params']['vlan_sender'] = str(self.options['vlan_sender']) + test_case['params']['vlan_receiver'] = \ + str(self.options['vlan_receiver']) + test_case['params']['num_of_neighbours'] = \ + str(self.options['num_of_neighbours']) + test_case['params']['amount_of_ram'] = \ + str(self.options['amount_of_ram']) + test_case['params']['number_of_cores'] = \ + str(self.options['number_of_cores']) + + try: + result = api.FrameworkApi.execute_framework( + [test_case], + iterations, + heat_template, + heat_template_parameters, + deployment_configuration, + openstack_credentials) + except Exception as e: + LOG.info('Exception: {}'.format(e.message)) + LOG.info('Got output: {}'.format(result)) diff --git a/yardstick/benchmark/scenarios/networking/vtc_throughput.py b/yardstick/benchmark/scenarios/networking/vtc_throughput.py new file mode 100644 index 000000000..fe7a88470 --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/vtc_throughput.py @@ -0,0 +1,85 @@ +############################################################################# +# Copyright (c) 2015 Ericsson AB 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 +############################################################################## + +import logging +import os + +from yardstick.benchmark.scenarios import base +from experimental_framework import api as api + +LOG = logging.getLogger(__name__) + + +class VtcThroughput(base.Scenario): + """Execute Instantiation Validation TC on the vTC + """ + __scenario_type__ = "vtc_throughput" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.options = None + self.setup_done = False + + def setup(self): + '''scenario setup''' + + self.options = self.scenario_cfg['options'] + self.setup_done = True + + def run(self, result): + """execute test""" + + if not self.setup_done: + self.setup() + + heat_template = 'vTC.yaml' + iterations = 1 + + openstack_credentials = { + 'ip_controller': '0.0.0.0', + 'heat_url': '***', + 'auth_uri': os.environ.get('OS_AUTH_URL'), + 'user': os.environ.get('OS_USERNAME'), + 'password': os.environ.get('OS_PASSWORD'), + 'project': os.environ.get('OS_TENANT_NAME') + } + heat_template_parameters = { + 'default_net': self.options['default_net_name'], + 'default_subnet': self.options['default_subnet_name'], + 'source_net': self.options['vlan_net_1_name'], + 'source_subnet': self.options['vlan_subnet_1_name'], + 'destination_net': self.options['vlan_net_2_name'], + 'destination_subnet': self.options['vlan_subnet_2_name'] + } + deployment_configuration = { + 'vnic_type': [self.options['vnic_type']], + 'vtc_flavor': [self.options['vtc_flavor']] + } + + test_case = dict() + test_case['name'] = 'rfc2544_throughput_benchmark.' \ + 'RFC2544ThroughputBenchmark' + test_case['params'] = dict() + test_case['params']['packet_size'] = str(self.options['packet_size']) + test_case['params']['vlan_sender'] = str(self.options['vlan_sender']) + test_case['params']['vlan_receiver'] = \ + str(self.options['vlan_receiver']) + + try: + result = api.FrameworkApi.execute_framework( + [test_case], + iterations, + heat_template, + heat_template_parameters, + deployment_configuration, + openstack_credentials) + except Exception as e: + LOG.info('Exception: {}'.format(e.message)) + LOG.info('Got output: {}'.format(result)) diff --git a/yardstick/benchmark/scenarios/networking/vtc_throughput_noisy.py b/yardstick/benchmark/scenarios/networking/vtc_throughput_noisy.py new file mode 100644 index 000000000..ad3832fb5 --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/vtc_throughput_noisy.py @@ -0,0 +1,91 @@ +############################################################################# +# Copyright (c) 2015 Ericsson AB 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 +############################################################################## + +import logging +import os + +from yardstick.benchmark.scenarios import base +import experimental_framework.api as api + +LOG = logging.getLogger(__name__) + + +class VtcThroughputNoisy(base.Scenario): + """Execute Instantiation Validation TC on the vTC + """ + __scenario_type__ = "vtc_throughput_noisy" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.options = None + self.setup_done = False + + def setup(self): + '''scenario setup''' + + self.options = self.scenario_cfg['options'] + self.setup_done = True + + def run(self, result): + """execute test""" + + if not self.setup_done: + self.setup() + + heat_template = 'vTC.yaml' + iterations = 1 + + openstack_credentials = { + 'ip_controller': '0.0.0.0', + 'heat_url': '***', + 'auth_uri': os.environ.get('OS_AUTH_URL'), + 'user': os.environ.get('OS_USERNAME'), + 'password': os.environ.get('OS_PASSWORD'), + 'project': os.environ.get('OS_TENANT_NAME') + } + heat_template_parameters = { + 'default_net': self.options['default_net_name'], + 'default_subnet': self.options['default_subnet_name'], + 'source_net': self.options['vlan_net_1_name'], + 'source_subnet': self.options['vlan_subnet_1_name'], + 'destination_net': self.options['vlan_net_2_name'], + 'destination_subnet': self.options['vlan_subnet_2_name'] + } + deployment_configuration = { + 'vnic_type': [self.options['vnic_type']], + 'vtc_flavor': [self.options['vtc_flavor']] + } + + test_case = dict() + test_case['name'] = 'multi_tenancy_throughput_benchmark.' \ + 'MultiTenancyThroughputBenchmark' + test_case['params'] = dict() + test_case['params']['packet_size'] = str(self.options['packet_size']) + test_case['params']['vlan_sender'] = str(self.options['vlan_sender']) + test_case['params']['vlan_receiver'] = \ + str(self.options['vlan_receiver']) + test_case['params']['num_of_neighbours'] = \ + str(self.options['num_of_neighbours']) + test_case['params']['amount_of_ram'] = \ + str(self.options['amount_of_ram']) + test_case['params']['number_of_cores'] = \ + str(self.options['number_of_cores']) + + try: + result = api.FrameworkApi.execute_framework( + [test_case], + iterations, + heat_template, + heat_template_parameters, + deployment_configuration, + openstack_credentials) + except Exception as e: + LOG.info('Exception: {}'.format(e.message)) + LOG.info('Got output: {}'.format(result)) diff --git a/yardstick/benchmark/scenarios/parser/__init__.py b/yardstick/benchmark/scenarios/parser/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/benchmark/scenarios/parser/__init__.py diff --git a/yardstick/benchmark/scenarios/parser/parser.py b/yardstick/benchmark/scenarios/parser/parser.py new file mode 100644 index 000000000..006258d05 --- /dev/null +++ b/yardstick/benchmark/scenarios/parser/parser.py @@ -0,0 +1,80 @@ +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other. +# +# 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 +############################################################################## +import pkg_resources +import logging +import subprocess +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) + + +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 + """ + __scenario_type__ = "Parser" + + SETUP_SCRIPT = "parser_setup.sh" + TEARDOWN_SCRIPT = "parser_teardown.sh" + PARSER_SCRIPT = "parser.sh" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.setup_done = False + + def setup(self): + """scenario setup""" + self.setup_script = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.parser", + Parser.SETUP_SCRIPT) + cmd = "%s" % (self.setup_script) + + subprocess.call(cmd, shell=True) + + self.setup_done = True + + def run(self, result): + """execute the translation""" + options = self.scenario_cfg['options'] + yangfile = options.get("yangfile", '~/yardstick/samples/yang.yaml') + toscafile = options.get("toscafile", '~/yardstick/samples/tosca.yaml') + + self.parser_script = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.parser", + Parser.PARSER_SCRIPT) + + if not self.setup_done: + self.setup() + + cmd1 = "%s %s %s" % (self.parser_script, yangfile, toscafile) + cmd2 = "chmod 777 %s" % (self.parser_script) + subprocess.call(cmd2, shell=True) + output = subprocess.call(cmd1, shell=True, stdout=subprocess.PIPE) + print "yangtotosca finished" + + result['yangtotosca'] = "success" if output == 0 else "fail" + + def teardown(self): + ''' for scenario teardown remove parser and pyang ''' + self.teardown_script = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.parser", + Parser.TEARDOWN_SCRIPT) + subprocess.call(self.teardown_script, shell=True) + self.teardown_done = True + + +def _test(): + '''internal test function''' + pass + +if __name__ == '__main__': + _test() diff --git a/yardstick/benchmark/scenarios/parser/parser.sh b/yardstick/benchmark/scenarios/parser/parser.sh new file mode 100755 index 000000000..4408e637c --- /dev/null +++ b/yardstick/benchmark/scenarios/parser/parser.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +set -e + +# Commandline arguments +yangfile=$1 +base_dir=$(dirname $yangfile) +shift +toscafile=$1 +OUTPUT_FILE=/tmp/parser-out.log + +# run parser test +run_parser() +{ + cd /tmp/parser/yang2tosca + python tosca_translator.py --filename $yangfile> $OUTPUT_FILE +} + +# write the result to stdout in json format +check_result() +{ + + if (diff -q $toscafile ${yangfile%'.yaml'}"_tosca.yaml" >> $OUTPUT_FILE); + then + exit 0 + else + exit 1 + fi + +} + +# main entry +main() +{ + # run the test + run_parser + + # output result + check_result +} + +main diff --git a/yardstick/benchmark/scenarios/parser/parser_setup.sh b/yardstick/benchmark/scenarios/parser/parser_setup.sh new file mode 100755 index 000000000..44356447d --- /dev/null +++ b/yardstick/benchmark/scenarios/parser/parser_setup.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +git clone https://github.com/mbj4668/pyang.git /tmp/pyang +cd /tmp/pyang +python setup.py install +git clone https://gerrit.opnfv.org/gerrit/parser /tmp/parser + diff --git a/yardstick/benchmark/scenarios/parser/parser_teardown.sh b/yardstick/benchmark/scenarios/parser/parser_teardown.sh new file mode 100755 index 000000000..727e9decd --- /dev/null +++ b/yardstick/benchmark/scenarios/parser/parser_teardown.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +rm -rf /tmp/pyang +rm -rf /tmp/parser |