This is used to generate measurements by interacting with devices that are not reachable as a node, and avoid target-specific support.
Each device.conf file can define a host command or script used when entering a lava_command_run and leaving a lava_command_run, In the style of the PDU power cycling commands.
host_hook_enter_command = <enter_hook> (command line to pass to host) host_hook_exit_command = <exit_hook>
Hooks calling abi:
ENTRER: arg0 = <enter_hook> arg1 = "output-file-fullpath" & EXIT: arg0 = <exit_hook> arg1 = "output-file-fullpath" &
The MO is close to lava_test_shell:
the LAVA_SIGNAL_TESTCASE search pattern will be applied to the output of the exit hook and if a measurement is found, a test_case will be added to the bundle stream of the job. Any file found in the logdir will be attached, starting with stdout.log. If a {output-file-fullpath}.minetype is found, its content is used as 'mime_type' for the attached file (as with lava_shell_test)
example, see Job http://lava.baylibre.com:10080/dashboard/streams/anonymous/lab-health/bundle... as an example of unit-test power statistics record and display as test_cases.
Signed-off-by: Marc Titinger mtitinger@baylibre.com ---
v2: expect LAVA_SIGNAL_TESTCASE patterns like with lava_test_shell
--- lava_dispatcher/actions/lava_command.py | 46 +++++++++++++++++++++++++++++++-- lava_dispatcher/config.py | 5 ++++ 2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/lava_dispatcher/actions/lava_command.py b/lava_dispatcher/actions/lava_command.py index 7bf787a..0748b51 100644 --- a/lava_dispatcher/actions/lava_command.py +++ b/lava_dispatcher/actions/lava_command.py @@ -33,6 +33,8 @@ from lava_dispatcher.test_data import create_attachment from lava_dispatcher.utils import read_content from datetime import datetime
+from lava_dispatcher.actions import lava_test_shell +from lava_dispatcher.lava_test_shell import parse_testcase_result
class cmd_lava_command_run(BaseAction):
@@ -54,16 +56,30 @@ class cmd_lava_command_run(BaseAction): _parser = None _fixupdict = {} _results_from_log_file = [] + _cur_record = None + _record_index = 0 + _uuid = None
def run(self, commands, parser=None, iterations=1, fixupdict=None, timeout=-1): target = self.client.target_device + context = self.context log_dir = tempfile.mkdtemp(dir=target.scratch_dir) self._logfile = os.path.join(log_dir, 'stdout.log') + self._uuid = str(uuid4()) if parser is not None: self._parser = parser if fixupdict is not None: self._fixupdict = fixupdict logging.info("lava_command logfile: %s" % self._logfile) + + #if there is a host-side hook to call: + host_enter_hook = context.device_config.host_hook_enter_command + if host_enter_hook: + self._cur_record = os.path.join(log_dir, self._uuid.split('-')[0]) + host_enter_hook = host_enter_hook.rstrip('&') + " " + self._cur_record + " &" + logging.warning('Running enter hook on host %s' % host_enter_hook) + context.run_command(host_enter_hook) + with self.client.tester_session() as session: for count in range(iterations): logging.info("Executing lava_command_run iteration: %s" % count) @@ -81,6 +97,27 @@ class cmd_lava_command_run(BaseAction): self._results_from_log_file.append(res) logging.error(e)
+ #if there is a host-side hook to call: + host_exit_hook = context.device_config.host_hook_exit_command + if host_exit_hook: + host_exit_hook = host_exit_hook.rstrip('&') + " " + self._cur_record + " &" + logging.warning('Running EXIT hook on dispatcher host %s' % host_exit_hook) + output = context.run_command_get_output(host_exit_hook) + + # See https://github.com/BayLibre/iio-capture as an instance of an + # app that will produce compatible output when called from the host + # Hook. + test_pattern = r"<LAVA_SIGNAL_TESTCASE TEST_CASE_ID=(?P<test_case_id>.*)\s+"\ + "RESULT=(?P<result>(PASS|pass|FAIL|fail|SKIP|skip|UNKNOWN|unknown))\s+"\ + "UNITS=(?P<units>.*)\s+MEASUREMENT=(?P<measurement>.*)>" + test_case_pattern = re.compile(test_pattern) + + for line in output.split(os.linesep): + match = test_case_pattern.match(line.strip()) + if match: + res = parse_testcase_result(match.groupdict()) + self._results_from_log_file.append(res) + bundle = self._get_bundle() self._write_results_bundle(bundle)
@@ -126,12 +163,17 @@ class cmd_lava_command_run(BaseAction):
def _get_test_runs(self): now = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') - attachment = [create_attachment(os.path.basename(self._logfile), read_content(self._logfile))] + attachment_dir = os.path.dirname(self._logfile) + attachment = lava_test_shell._attachments_from_dir(os.path.dirname(self._logfile)) + # fixup default mimetypes, for stdout.log mainly + for entry in attachment: + if entry['pathname'].endswith(".log"): + entry['mime_type'] = "text/plain" results = self._get_test_results() return { 'test_id': 'lava-command', 'analyzer_assigned_date': now, - 'analyzer_assigned_uuid': str(uuid4()), + 'analyzer_assigned_uuid': self._uuid, 'time_check_performed': False, 'test_results': results, 'attachments': attachment diff --git a/lava_dispatcher/config.py b/lava_dispatcher/config.py index 63aa3c6..10bccc8 100644 --- a/lava_dispatcher/config.py +++ b/lava_dispatcher/config.py @@ -29,6 +29,11 @@ from configglue import parser, schema
class DeviceSchema(schema.Schema): + + # Host-side hook for lava_command_run + host_hook_enter_command = schema.StringOption() + host_hook_exit_command = schema.StringOption() + master_testboot_dir = schema.StringOption() master_testboot_label = schema.StringOption() master_testrootfs_dir = schema.StringOption()
Thanks for the patch, I've created an initial review: https://review.linaro.org/#/c/10595/
There are PEP8 issues with the review, so it cannot be merged or tested further: https://ci.linaro.org/job/lava-dispatcher/808//console
Updates for the review are best done using git review, if you register as a community contributor.
The current patch does some things which appear unnecessary: context = self.context
I've also put some comments into the review itself.
Also, examples of how to use the change would need to go into the documentation for lava-server and that would need a separate review.
On 16 February 2016 at 11:22, Marc Titinger mtitinger@baylibre.com wrote:
This is used to generate measurements by interacting with devices that are not reachable as a node, and avoid target-specific support.
Each device.conf file can define a host command or script used when entering a lava_command_run and leaving a lava_command_run, In the style of the PDU power cycling commands.
host_hook_enter_command = <enter_hook> (command line to pass to host) host_hook_exit_command = <exit_hook>
Hooks calling abi:
ENTRER: arg0 = <enter_hook> arg1 = "output-file-fullpath" & EXIT: arg0 = <exit_hook> arg1 = "output-file-fullpath" &
The MO is close to lava_test_shell:
the LAVA_SIGNAL_TESTCASE search pattern will be applied to the output of the exit hook and if a measurement is found, a test_case will be added to the bundle stream of the job. Any file found in the logdir will be attached, starting with stdout.log. If a {output-file-fullpath}.minetype is found, its content is used as 'mime_type' for the attached file (as with lava_shell_test)
example, see Job http://lava.baylibre.com:10080/dashboard/streams/anonymous/lab-health/bundle... as an example of unit-test power statistics record and display as test_cases.
Signed-off-by: Marc Titinger mtitinger@baylibre.com
v2: expect LAVA_SIGNAL_TESTCASE patterns like with lava_test_shell
lava_dispatcher/actions/lava_command.py | 46 +++++++++++++++++++++++++++++++-- lava_dispatcher/config.py | 5 ++++ 2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/lava_dispatcher/actions/lava_command.py b/lava_dispatcher/actions/lava_command.py index 7bf787a..0748b51 100644 --- a/lava_dispatcher/actions/lava_command.py +++ b/lava_dispatcher/actions/lava_command.py @@ -33,6 +33,8 @@ from lava_dispatcher.test_data import create_attachment from lava_dispatcher.utils import read_content from datetime import datetime
+from lava_dispatcher.actions import lava_test_shell +from lava_dispatcher.lava_test_shell import parse_testcase_result
class cmd_lava_command_run(BaseAction):
@@ -54,16 +56,30 @@ class cmd_lava_command_run(BaseAction): _parser = None _fixupdict = {} _results_from_log_file = []
_cur_record = None
_record_index = 0
_uuid = None
def run(self, commands, parser=None, iterations=1, fixupdict=None, timeout=-1): target = self.client.target_device
context = self.context log_dir = tempfile.mkdtemp(dir=target.scratch_dir) self._logfile = os.path.join(log_dir, 'stdout.log')
self._uuid = str(uuid4()) if parser is not None: self._parser = parser if fixupdict is not None: self._fixupdict = fixupdict logging.info("lava_command logfile: %s" % self._logfile)
#if there is a host-side hook to call:
host_enter_hook = context.device_config.host_hook_enter_command
if host_enter_hook:
self._cur_record = os.path.join(log_dir, self._uuid.split('-')[0])
host_enter_hook = host_enter_hook.rstrip('&') + " " + self._cur_record + " &"
logging.warning('Running enter hook on host %s' % host_enter_hook)
context.run_command(host_enter_hook)
with self.client.tester_session() as session: for count in range(iterations): logging.info("Executing lava_command_run iteration: %s" % count)
@@ -81,6 +97,27 @@ class cmd_lava_command_run(BaseAction): self._results_from_log_file.append(res) logging.error(e)
#if there is a host-side hook to call:
host_exit_hook = context.device_config.host_hook_exit_command
if host_exit_hook:
host_exit_hook = host_exit_hook.rstrip('&') + " " + self._cur_record + " &"
logging.warning('Running EXIT hook on dispatcher host %s' % host_exit_hook)
output = context.run_command_get_output(host_exit_hook)
# See https://github.com/BayLibre/iio-capture as an instance of an
# app that will produce compatible output when called from the host
# Hook.
test_pattern = r"<LAVA_SIGNAL_TESTCASE TEST_CASE_ID=(?P<test_case_id>.*)\s+"\
"RESULT=(?P<result>(PASS|pass|FAIL|fail|SKIP|skip|UNKNOWN|unknown))\s+"\
"UNITS=(?P<units>.*)\s+MEASUREMENT=(?P<measurement>.*)>"
test_case_pattern = re.compile(test_pattern)
for line in output.split(os.linesep):
match = test_case_pattern.match(line.strip())
if match:
res = parse_testcase_result(match.groupdict())
self._results_from_log_file.append(res)
bundle = self._get_bundle() self._write_results_bundle(bundle)
@@ -126,12 +163,17 @@ class cmd_lava_command_run(BaseAction):
def _get_test_runs(self): now = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
attachment = [create_attachment(os.path.basename(self._logfile), read_content(self._logfile))]
attachment_dir = os.path.dirname(self._logfile)
attachment = lava_test_shell._attachments_from_dir(os.path.dirname(self._logfile))
# fixup default mimetypes, for stdout.log mainly
for entry in attachment:
if entry['pathname'].endswith(".log"):
entry['mime_type'] = "text/plain" results = self._get_test_results() return { 'test_id': 'lava-command', 'analyzer_assigned_date': now,
'analyzer_assigned_uuid': str(uuid4()),
'analyzer_assigned_uuid': self._uuid, 'time_check_performed': False, 'test_results': results, 'attachments': attachment
diff --git a/lava_dispatcher/config.py b/lava_dispatcher/config.py index 63aa3c6..10bccc8 100644 --- a/lava_dispatcher/config.py +++ b/lava_dispatcher/config.py @@ -29,6 +29,11 @@ from configglue import parser, schema
class DeviceSchema(schema.Schema):
- # Host-side hook for lava_command_run
- host_hook_enter_command = schema.StringOption()
- host_hook_exit_command = schema.StringOption()
- master_testboot_dir = schema.StringOption() master_testboot_label = schema.StringOption() master_testrootfs_dir = schema.StringOption()
-- 2.5.0
Lava-users mailing list Lava-users@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lava-users