summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Feldt <hans.feldt@ericsson.com>2015-06-29 15:27:55 +0200
committerHans Feldt <hans.feldt@ericsson.com>2015-07-08 07:02:45 +0000
commitd71e101ac1420ed03fa2dbecb76fc8156a16761a (patch)
treef6d62c25ac79268626a6a5d3d6e2c14b153e5abf
parent6b667910909b332e78105ccdf17e39e4b286ed39 (diff)
Add support for action hooks in runner config
pre-start and post-stop intention is to be used to gather information about the target system. single-shot and periodic-action intention is to perform actions on the infrastructure or cloud resources. For example server live migration or network interface down. Example of what can be added in the runner section: pre-start-action: command: "heat stack-show demo" periodic-action: interval: 10 command: "ifconfig vboxnet1" single-shot-action: after: 30 command: "nova show goofy.demo" post-stop-action: command: "nova list" pre-start and post-stop data are added into the output file. periodic and single-shot are not because that would interfere with the actual sampled data. Besides the intention is not to log statistics but do things with the infrastructure such as server live migration. TODO: add sections to the output file, something like pre, data & post JIRA: YARDSTICK-46 Change-Id: Ia059813fb74733f86368aea9c7a20e5afb71d228 Signed-off-by: Hans Feldt <hans.feldt@ericsson.com>
-rw-r--r--samples/ping-ext-stimuli.yaml49
-rw-r--r--yardstick/benchmark/runners/base.py75
2 files changed, 123 insertions, 1 deletions
diff --git a/samples/ping-ext-stimuli.yaml b/samples/ping-ext-stimuli.yaml
new file mode 100644
index 000000000..cfe791567
--- /dev/null
+++ b/samples/ping-ext-stimuli.yaml
@@ -0,0 +1,49 @@
+---
+# Sample benchmark task config file
+# Measure network latency using ping, destination is an external server
+# Make sure servers have internet access before running this test.
+# For example using virtual MOS do something this on the host:
+# sudo iptables -t nat -A POSTROUTING -s 172.16.0.0/24 \! -d 172.16.0.0/24 -j MASQUERADE
+#
+# This sample demonstrates the use of runner actions - hooks inserted in
+# diffrent places of the runner execution.
+#
+
+schema: "yardstick:task:0.1"
+
+scenarios:
+-
+ type: Ping
+ host: goofy.demo
+ target: 8.8.8.8
+ runner:
+ type: Duration
+ duration: 60
+ interval: 1
+ pre-start-action:
+ command: "heat stack-show demo"
+ periodic-action:
+ interval: 10
+ command: "ifconfig vboxnet1"
+ single-shot-action:
+ after: 30
+ command: "nova show goofy.demo"
+ post-stop-action:
+ command: "nova list"
+ sla:
+ max_rtt: 10
+ action: monitor
+
+context:
+ name: demo
+ image: cirros-0.3.3
+ flavor: m1.tiny
+ user: cirros
+ servers:
+ goofy:
+ floating_ip: true
+ networks:
+ test:
+ cidr: '10.0.1.0/24'
+ external_network: "net04_ext"
+
diff --git a/yardstick/benchmark/runners/base.py b/yardstick/benchmark/runners/base.py
index 08117c625..badc33565 100644
--- a/yardstick/benchmark/runners/base.py
+++ b/yardstick/benchmark/runners/base.py
@@ -8,9 +8,11 @@
##############################################################################
import importlib
-import multiprocessing
import json
import logging
+import multiprocessing
+import subprocess
+import time
log = logging.getLogger(__name__)
@@ -35,6 +37,27 @@ def _output_serializer_main(filename, queue):
outfile.write('\n')
+def _single_action(seconds, command, queue):
+ '''entrypoint for the single action process'''
+ log.debug("single action, fires after %d seconds (from now)", seconds)
+ time.sleep(seconds)
+ log.debug("single action: executing command: '%s'", command)
+ data = subprocess.check_output(command, shell=True)
+ log.debug("\n%s" % data)
+
+
+def _periodic_action(interval, command, queue):
+ '''entrypoint for the periodic action process'''
+ log.debug("periodic action, fires every: %d seconds", interval)
+ time_spent = 0
+ while True:
+ time.sleep(interval)
+ time_spent += interval
+ log.debug("periodic action, executing command: '%s'", command)
+ data = subprocess.check_output(command, shell=True)
+ log.debug("\n%s" % data)
+
+
class Runner(object):
queue = None
dump_process = None
@@ -88,6 +111,10 @@ class Runner(object):
'''Terminate all runners (subprocesses)'''
log.debug("Terminating all runners")
for runner in Runner.runners:
+ if runner.periodic_action_process:
+ log.debug("Terminating periodic action process")
+ runner.periodic_action_process.terminate()
+ runner.periodic_action_process = None
runner.process.terminate()
runner.process.join()
Runner.release(runner)
@@ -95,9 +122,30 @@ class Runner(object):
def __init__(self, config, queue):
self.context = {}
self.config = config
+ self.periodic_action_process = None
self.result_queue = queue
Runner.runners.append(self)
+ def run_pre_start_action(self):
+ '''run a potentially configured pre-start action'''
+ if "pre-start-action" in self.config:
+ command = self.config["pre-start-action"]["command"]
+ log.debug("pre start action: command: '%s'" % command)
+ data = subprocess.check_output(command, shell=True)
+ log.debug("pre-start data: \n%s" % data)
+ output = "{'pre-start-action-data': %s}" % data
+ self.result_queue.put(output)
+
+ def run_post_stop_action(self):
+ '''run a potentially configured post-stop action'''
+ if "post-stop-action" in self.config:
+ command = self.config["post-stop-action"]["command"]
+ log.debug("post stop action: command: '%s'" % command)
+ data = subprocess.check_output(command, shell=True)
+ log.debug("post-stop data: \n%s" % data)
+ output = "{'post-stop-action-data': %s}" % data
+ self.result_queue.put(output)
+
def run(self, scenario_type, scenario_args):
class_name = base_scenario.Scenario.get(scenario_type)
path_split = class_name.split(".")
@@ -106,8 +154,33 @@ class Runner(object):
cls = getattr(module, path_split[-1])
self.config['object'] = class_name
+
+ self.run_pre_start_action()
+
+ if "single-shot-action" in self.config:
+ single_action_process = multiprocessing.Process(
+ target=_single_action,
+ name="single-shot-action",
+ args=(self.config["single-shot-action"]["after"],
+ self.config["single-shot-action"]["command"],
+ self.result_queue))
+ single_action_process.start()
+
+ if "periodic-action" in self.config:
+ self.periodic_action_process = multiprocessing.Process(
+ target=_periodic_action,
+ name="periodic-action",
+ args=(self.config["periodic-action"]["interval"],
+ self.config["periodic-action"]["command"],
+ self.result_queue))
+ self.periodic_action_process.start()
+
self._run_benchmark(cls, "run", scenario_args)
def join(self):
self.process.join()
+ if self.periodic_action_process:
+ self.periodic_action_process.terminate()
+ self.periodic_action_process = None
+ self.run_post_stop_action()
return self.process.exitcode