diff --git a/libs/utils/env.py b/libs/utils/env.py index 2857f35a2c3d517315e18471641fb72930d28587..19b1bec6e720b9a002a2eb53d5a9fa43d9045031 100644 --- a/libs/utils/env.py +++ b/libs/utils/env.py @@ -520,7 +520,8 @@ class TestEnv(ShareState): self.target = devlib.LocalLinuxTarget( platform = platform, load_default_modules = False, - modules = self.__modules) + modules = self.__modules, + connection_settings = {'unrooted': True}) else: raise ValueError('Config error: not supported [platform] type {}'\ .format(platform_type)) @@ -763,24 +764,17 @@ class TestEnv(ShareState): force=False and we have not installed rt-app. """ - if not force and self._calib: - return self._calib - - required = force or 'rt-app' in self.__installed_tools - - if not required: - self._log.debug('No RT-App workloads, skipping calibration') - return - - if not force and 'rtapp-calib' in self.conf: - self._log.warning('Using configuration provided RTApp calibration') - self._calib = { + if not force and 'rt-app' not in self.__installed_tools: + if not self._calib and 'rtapp-calib' in self.conf: + self._log.warning('Using configuration provided RTApp calibration') + self._calib = { int(key): int(value) for key, value in self.conf['rtapp-calib'].items() } - else: - self._log.info('Calibrating RTApp...') - self._calib = RTA.calibrate(self.target) + return self._calib + + self._log.info('Calibrating RTApp...') + self._calib = RTA.calibrate(self.target) self._log.info('Using RT-App calibration values:') self._log.info(' %s', diff --git a/libs/utils/executor.py b/libs/utils/executor.py index 7c7060b22fed9703c23816b4fd1155d0055d7a78..529ce87bf6522784fdcab272a3996fd14daa6e0a 100644 --- a/libs/utils/executor.py +++ b/libs/utils/executor.py @@ -188,6 +188,7 @@ class Executor(): # Initialize globals self._default_cgroup = None self._cgroup = None + self._old_selinux_mode = None # Setup logging self._log = logging.getLogger('Executor') @@ -242,10 +243,6 @@ class Executor(): self._log.info('Results will be collected under:') self._log.info(' %s', self.te.res_dir) - if any(wl['type'] == 'rt-app' - for wl in self._experiments_conf['wloads'].values()): - self._log.info('rt-app workloads found, installing tool on target') - self.te.install_tools(['rt-app']) def run(self): self._print_section('Experiments execution') @@ -328,26 +325,30 @@ class Executor(): self._log.debug('Setup RT-App run folder [%s]...', self.te.run_dir) self.target.execute('[ -d {0} ] || mkdir {0}'\ .format(self.te.run_dir)) - self.target.execute( + + if self.target.is_rooted: + self.target.execute( 'grep schedtest /proc/mounts || '\ ' mount -t tmpfs -o size=1024m {} {}'\ .format('schedtest', self.te.run_dir), as_root=True) - # tmpfs mounts have an SELinux context with "tmpfs" as the type (while - # other files we create have "shell_data_file"). That prevents non-root - # users from creating files in tmpfs mounts. For now, just put SELinux - # in permissive mode to get around that. - try: - # First, save the old SELinux mode - self._old_selinux_mode = self.target.execute('getenforce') - self._log.warning('Setting target SELinux in permissive mode') - self.target.execute('setenforce 0', as_root=True) - except TargetError: - # Probably the target doesn't have SELinux, or there are no - # contexts set up. No problem. - self._log.warning("Couldn't set SELinux in permissive mode. " - "This is probably fine.") - self._old_selinux_mode = None + + # tmpfs mounts have an SELinux context with "tmpfs" as the type + # (while other files we create have "shell_data_file"). That + # prevents non-root users from creating files in tmpfs mounts. For + # now, just put SELinux in permissive mode to get around that. + try: + # First, save the old SELinux mode + self._old_selinux_mode = self.target.execute('getenforce') + except TargetError: + # Probably the target doesn't have SELinux. No problem. + pass + else: + + self._log.warning('Setting target SELinux in permissive mode') + self.target.execute('setenforce 0', as_root=True) + else: + self._log.warning('Not mounting tempfs because no root') def _setup_cpufreq(self, tc): if 'cpufreq' not in tc: @@ -636,7 +637,12 @@ class Executor(): # Configure the test workload wlspec = self._experiments_conf['wloads'][wl_idx] - wload = self._wload_conf(wl_idx, wlspec) + if type(wlspec) == dict: + wload = self._wload_conf(wl_idx, wlspec) + else: + wload = wlspec + + self.te.install_tools([wload.executor]) # Keep track of platform configuration test_dir = '{}/{}:{}:{}'\ diff --git a/libs/wlgen/wlgen/rta.py b/libs/wlgen/wlgen/rta.py index 496435e0f6c3db5f0cfc0dd34f6c38481a1ae904..04ce176b0e5ac7933ccc54f4c75cda2600df37f4 100644 --- a/libs/wlgen/wlgen/rta.py +++ b/libs/wlgen/wlgen/rta.py @@ -50,7 +50,8 @@ class RTA(Workload): def __init__(self, target, name, - calibration=None): + calibration=None, + *args, **kwargs): """ :param target: Devlib target to run workload on. :param name: Human-readable name for the workload. @@ -67,8 +68,6 @@ class RTA(Workload): # TODO: Assume rt-app is pre-installed on target # self.target.setup('rt-app') - super(RTA, self).__init__(target, name) - # rt-app executor self.wtype = 'rtapp' self.executor = 'rt-app' @@ -81,6 +80,8 @@ class RTA(Workload): self.rta_conf = None self.test_label = None + super(RTA, self).__init__(target, name, *args, **kwargs) + # Setup RTA callbacks self.setCallback('postrun', self.__postrun) @@ -385,6 +386,9 @@ class RTA(Workload): for tid in sorted(self.params['profile'].keys()): task = self.params['profile'][tid] + if isinstance(task, RTATask): + task = task.get() + # Initialize task configuration task_conf = {} diff --git a/libs/wlgen/wlgen/workload.py b/libs/wlgen/wlgen/workload.py index 5e3cb6c04cc45f570c478ae37dbb4e2dc0ffbbba..33330b8c14cc70c339df12d8290db8fdbeb21ad1 100644 --- a/libs/wlgen/wlgen/workload.py +++ b/libs/wlgen/wlgen/workload.py @@ -41,7 +41,13 @@ class Workload(object): def __init__(self, target, - name): + name, + profile=None, + custom_conf=None, + *args, **kwargs): + + if custom_conf and profile_conf: + raise ValueError('Provide only one of custom_conf and profile_conf') # Target device confguration self.target = target @@ -96,6 +102,11 @@ class Workload(object): self._log.info('Setup new workload %s', self.name) + if profile: + self.conf('profile', profile, *args, **kwargs) + elif custom_conf: + self.conf('custom', custom_conf, *args, **kwargs) + def __callback(self, step, **kwords): if step not in self.steps.keys(): raise ValueError('Callbacks for [%s] step not supported', step) diff --git a/tests/lisa/test_executor.py b/tests/lisa/test_executor.py new file mode 100644 index 0000000000000000000000000000000000000000..c675c89d77164923f7e987167b2c9b257e7f0fbd --- /dev/null +++ b/tests/lisa/test_executor.py @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2017, ARM Limited and contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import logging +import shutil +import os +from unittest import TestCase + +from env import TestEnv +from executor import Executor +from wlgen import RTA, Periodic + +class SetUpTarget(TestCase): + @classmethod + def setUpClass(cls): + cls._log = logging.getLogger('TestExecutor') + + def setUp(self): + self.res_dir='test_{}'.format(self.__class__.__name__) + self.te = TestEnv( + target_conf={'platform': 'host'}, + test_conf={'results_dir': self.res_dir}, + force_new=True) + +class TestMagicSmoke(SetUpTarget): + def test_files_created(self): + """Test that we can run experiments and get output files""" + conf_name = 'myconf' + wl_name = 'mywl' + + results_dir = os.path.join(self.te.LISA_HOME, 'results', self.res_dir, + 'rtapp:{}:{}'.format(conf_name, wl_name)) + if os.path.isdir(results_dir): + shutil.rmtree(results_dir) + + experiments_conf = { + 'confs': [{ + 'tag': conf_name + }], + "wloads" : { + wl_name : { + "type" : "rt-app", + "conf" : { + "class" : "profile", + "params" : { + "mytask" : { + "kind" : "Periodic", + "params" : { + "duty_cycle_pct": 10, + "duration_s": 0.2, + }, + }, + }, + }, + }, + }, + } + + executor = Executor(self.te, experiments_conf) + executor.run() + + self.assertTrue( + os.path.isdir(results_dir), + 'Expected to find a directory at {}'.format(results_dir)) + + result_1_dir = os.path.join(results_dir, '1') + self.assertTrue( + os.path.isdir(result_1_dir), + 'Expected to find a directory at {}'.format(result_1_dir)) + +class TestDirectObject(SetUpTarget): + """Test that Executor can be configured directly using Workload objects""" + def test_files_created(self): + """Test that we can run experiments and get output files""" + conf_name = 'myconf' + wl_name = 'mywl' + + results_dir = os.path.join(self.te.LISA_HOME, 'results', self.res_dir, + 'rtapp:{}:{}'.format(conf_name, wl_name)) + if os.path.isdir(results_dir): + shutil.rmtree(results_dir) + + wload = RTA(self.te.target, wl_name) + wload.conf('profile', {'mytask': Periodic().get()}) + + experiments_conf = { + 'confs': [{ + 'tag': conf_name + }], + "wloads" : { + wl_name : wload + } + } + + executor = Executor(self.te, experiments_conf) + executor.run() + + self.assertTrue( + os.path.isdir(results_dir), + 'Expected to find a directory at {}'.format(results_dir)) + + result_1_dir = os.path.join(results_dir, '1') + self.assertTrue( + os.path.isdir(result_1_dir), + 'Expected to find a directory at {}'.format(result_1_dir))