.. This work is licensed under a Creative Commons Attribution 3.0 Unported License. http://creativecommons.org/licenses/by/3.0/legalcode ======================= New Plugins Type - Hook ======================= Problem description =================== Rally lacks a plugin type that would run some code on specified iteration. New plugin type is required for reliability testing of OpenStack. This type of plugin would give an ability to activate factors on some iteration and provide timestamps and some info about executed actions to rally report. Proposed change =============== Add a new section to task config: Schema of hook section allows to specify number of iteration and a list of hook plugins that should be executed on this iteration. .. code:: json { "KeystoneBasic.create_delete_user": [ { "args": {}, "runner": { "type": "constant", "times": 100, "concurrency": 10 }, "hook": [ # new section { "name": "example_hook", "args": { "cmd": "bash enable_factor_1" }, "trigger": { "name": "event", "args": { "unit": "time", "at": [1, 50, 100] # seconds since start } } }, { "name": "example_hook", "args": { "cmd": "bash enable_factor_2" }, "trigger": { "name": "event", "args": { "unit": "iteration", "at": [35, 40, 45] # iteration numbers } } }, { "name": "example_hook", "args": { "cmd": "bash enable_factor_3" }, "trigger": { "name": "periodic", "args": { "unit": "iteration", "step": 20, # execute hook each 20 iterations "start": 0, "end": 1000 } } }, { "name": "example_hook", "args": { "cmd": "bash enable_factor_4" }, "trigger": { "name": "periodic", "args": { "unit": "time", "step": 15, # execute hook each 15 seconds "start": 100, "end": 200 } } } ] } ] } Add a new base class for such plugins, that should: - contain common logic for schema validation - save timestamps when "run" method started/finished - provide abstract method 'run' which should be implemented in plugins this method should be called after specified iteration has been executed Add new classes for trigger plugins, that should: - contain validation schema for its configuration - contain "get_listening_event" and "on_event" methods Trigger plugin classes should: - implement "get_listening_event" methods that return events to listen - implement "on_event" methods that check event type and value; launch hook if needed Add HookExecuter class to run hook plugins, that should: - control when to run a hook specified in config - receive result of hook execution from hook plugin - return a full result of hook execution in the following format: .. code:: json [{ # this is config of specific hook; it should not be empty! "config": {...}, "results":[ { # value is time in seconds "triggered_by": {"event_type": "iteration", "value": 20}, "started_at": 1470331269.134323, "finished_at": 1470331319.761103, "status": "success", # same output format as in scenarios; this key can be missed # if no output was added "output": {} } ], "summary": {"success": 1} }] Modify ResultConsumer, that should: - control HookExecuter and provide info about iterations - add a full result to TaskResult Example code of base class: .. code:: python @plugin.base() @six.add_metaclass(abc.ABCMeta) class Hook(plugin.Plugin): @classmethod def validate(cls, config): # schema validation pass def __init__(self, config): self.config = config @abc.abstractmethod def run(self): pass example_hook class: .. code:: python @hook.configure(name="example_hook") class ExampleHook(hook.Hook): CONFIG_SCHEMA = { "type": "object", "$schema": consts.JSON_SCHEMA, "properties": { "cmd": { "type": "string" }, "required": [ "cmd", ], "additionalProperties": False, } def __init__(self, config): super(ExampleHook, self).__init__(config) self.cmd = self.config["cmd"] def run(self): # do some action rc = os.system(self.cmd) Example of hook result that goes to TaskResult (list of dicts): .. code:: python [{ # this is config of specific hook; it should not be empty! "config": {...}, "results":[ { "triggered_by": {"event_type": "iteration", "value": 20}, "started_at": 1470331269.134323, "finished_at": 1470331319.761103, "status": "success", # same output format as in scenarios; this key can be missed # if no output was added "output": {} }, { # value is time in seconds "triggered_by": {"event_type": "time", "value": 150.0}, "started_at": 1470331270.352342, "finished_at": 1470331333.623303, "status": "failed", "error": { "etype": "Exception", # type of exception "msg": "exception message", # additional information to help (for example, traceback) "details": "" } } ], "summary": {"success": 1, "failed": 1} }] Alternatives ------------ Use sla section for such plugins, but this looks weird Implementation ============== Assignee(s) ----------- Primary assignee: - astudenov - ylobankov - amaretskiy Work Items ---------- - Implement new section in task config - Add example of hook plugin that runs specified command as subprocess - Add trigger plugins for iterations - Add trigger plugins for time - Add hooks results into HTML report Dependencies ============ None