1
0
mirror of https://github.com/ARM-software/devlib.git synced 2024-10-05 18:30:50 +01:00
Commit Graph

1146 Commits

Author SHA1 Message Date
Douglas Raillard
f5f06122f3 target: Provide context manager API for Target
Allow cleanly disconnecting the Target object, so that we don't get
garbage output from __del__ later on when half of the namespace has
already disappeared.
2024-06-12 16:32:21 -05:00
Sebastian Goscik
c9b539f722 Validate cgroups_run_into has taken effect
On some systems this seems to have no effect, leaving the executed shell in the root cgroup. Before, this function would still execute and the end user would think the desired process was run in the cgroup when infact it had not.
2024-06-12 16:23:35 -05:00
Douglas Raillard
a28c6d7ce0 utils/android: Use subprocess.DEVNULL where appropriate 2024-06-12 16:03:19 -05:00
Douglas Raillard
b8292b1f2b utils/android: Log error in _ping()
Log any error happening in adb command ran by _ping() so it can be diagnosed.
Also fix possible deadlock by not using subprocess.PIPE along
subprocess.call(), as the documentation recommends against it.
2024-06-12 16:03:19 -05:00
Stephen Paulger
94f1812ab2 Create LICENSE 2024-06-12 15:59:29 -05:00
Metin Kaya
71d1663b2d tools/android: Address review comments on PR#668
PR#668: https://github.com/ARM-software/devlib/pull/668

- Fix mixed tab-space white-spacing issues
- s/CMDLINE_VERSION/ANDROID_CMDLINE_VERSION/ to be more precise
- s/set_host_arch/get_android_sdk_host_arch/ because the global variable
  for Android host architecture is removed now

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-05-28 19:08:40 -05:00
Metin Kaya
492d42dddb target: tests: Address review comments on PR#667
PR#667: https://github.com/ARM-software/devlib/pull/667

- Implement a test module initializer with a tear down method in
  test/test_target.py
- Make various cleanups in test/test_target.py
- Improve structure of test/test_config.yml (previously
  target_configs.yaml)
- Make docstrings Sphinx compatible
- Make ``TargetRunner`` and its subclasses private
- Cleanup tests/test_target.py
- Replace print()'s with appropriate logging calls
- Implement ``NOPTargetRunner`` class for simplifying tests
- Improve Python v3.7 compatibility
- Relax host machine type checking
- Escape user input strings

and more..

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-05-28 19:08:05 -05:00
Douglas Raillard
7276097d4e target: Make default modules list empty
Default modules are a recurrent source of errors as they fail to
initialize (cgroups particularly) on any recent target. This leads to
error in basically any workload-automation setup on Android 12 and
above targets.

Since modules can now be lazily loaded upon Target attribute access,
there is no reason to preload those anymore.
2024-04-24 10:04:09 -05:00
Douglas Raillard
6939e5660e target: Cleanup and lazily initialize modules
Cleanup the module loading code and enable lazy initialization of modules:

* Target.modules is now a read-only property, that is a list of strings
  (always, not either strings or dict with mod name as key and params dict as
  value).
  Target._modules dict stores parameters for each module that was asked
  for.

* Target.__init__() now makes thorough validation of the modules list it
  is given:
    * Specifying the same module mulitple time is only allowed if they
      are specified with the same parameters. If a module is specified
      both with and without parameters, the parameters take precedence
      and the conflict is resolved.
    * Only one module of each "kind" can be present in the list.

* Module subclasses gained a class attribute "attr_name" that computes
  their "attribute name", i.e. the name under which they are expected to
  be lookedup on a Target instance.

* Modules are now automatically registered by simple virtue of
  inheriting from Module and defining a name, wherever the source
  resides. They do not have to be located in devlib.modules anymore.
  This allows 3rd party module providers to very easily add new ones.

* Modules are accessible as Target attribute as:
    * Their "kind" if they specified one
    * Their "name" (always)

    This allows the consumer to either rely on a generic API (via the
    "kind") or to expect a specific module (via the "name").

* Accessing a module on Target will lazily load it even if was not
  selected using Target(modules=...):
    * If the module parameters were specified in Target(modules=...) or
      via platform modules, they will be applied automatically.
    * Otherwise, no parameter is passed.
    * If no module can be found with that name, the list of
      Target.modules will be searched for a module matching the given
      kind. The first one to be found will be used.

* Modules specified in Target(modules=...) are still loaded eagerly when
  their stage is reached just like it used to. We could easily make
  those lazily loaded though if we wanted.

* Specifying Target(modules={'foo': None}) will make the "foo" module
  unloadable. This can be used to prevent lazy loading a specific
  module.
2024-04-24 10:04:09 -05:00
Brendan Jackman
ce02f8695f Add missing import 2024-04-18 14:01:11 -05:00
Metin Kaya
b5f311feff tools/docker: Add Docker image support for devlib
Introduce a Dockerfile in order to create Docker image for devlib and
``run_tests.sh`` script to test Android, Linux, LocalLinux, and QEMU
targets on the Docker image.

The Dockerfile forks from ``Ubuntu-22.04``, installs required system
packages, checks out ``master`` branch of devlib, installs devlib,
creates Android virtual devices via ``tools/android/install_base.sh``,
and QEMU images for aarch64 and x86_84 architectures.

Note that Android command line tools version, buildroot and devlib
branches can be customized via environment variables.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-04-01 14:02:38 -05:00
Metin Kaya
233f76d03a test_target.py: Allow specifying connection timeout for Android targets
Default connection timeout (30 secs) may be insufficient for some test
setups or in some conditions. Thus, support specifying timeout parameter
in target configuration file.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-04-01 14:02:38 -05:00
Metin Kaya
ac4f581f4b target: tests: Add support for testing ChromeOS targets
We can mimic ChromeOS target by combining a QEMU guest (for Linux
bindings of ``ChromeOsTarget`` class) with a Android virtual desktop
(for Android bits of ``ChromeOsTarget``).

Note that Android bindings of ``ChromeOsTarget`` class also requires
existence of ``/opt/google/containers/android`` folder on the Linux
guest.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-04-01 14:02:38 -05:00
Metin Kaya
c6bd736c82 target: Address pylint issues in ChromeOsTarget class
Also clean a mutable default value (``modules=[]`` in ``ChromeOsTarget``
class).

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-04-01 14:02:38 -05:00
Douglas Raillard
28b30649f1 utils/ssh: Fix atexit.register() SshConnection leak
SshConnection registers an atexit handler so the connection is closed
upon exiting the process if it has not been done before. However, the
handler keeps a reference on the connection, which means it _will_ stay
alive. If lots of short-lived connections are created (which can happen
when using e.g. ThreadPoolExecutor), they will simply stay around and
leak.

Fix that by using a weak reference (WeakMethod) to register in the
atexit handler, with a callback to unregister it when the object is
deallocated.
2024-03-28 20:04:38 -05:00
Sebastian Goscik
5817866ad0 Fixed issue where non-consecutive list resulted in incorrect ranges
For example if `[3,1,2]` was provided, it would result in `3,1-2`, but after writing this to a sysfs file, it would read back as `1-3`
2024-03-28 20:04:12 -05:00
Ola Olsson
8247ac91e7 Add option not to validate PMU counters.
The validation call can take a long for targets where PLL:s have
been clocked down, such as FPGAs.
2024-03-28 20:03:53 -05:00
Metin Kaya
228baeb317 target: Implement target runner classes
Add support for launching emulated targets on QEMU. The base class
``TargetRunner`` has groundwork for target runners like
``QEMUTargetRunner``.

``TargetRunner`` is a contextmanager which starts runner process (e.g.,
QEMU), makes sure the target is accessible over SSH (if
``connect=True``), and terminates the runner process once it's done.

The other newly introduced ``QEMUTargetRunner`` class:
- performs sanity checks to ensure QEMU executable, kernel, and initrd
  images exist,
- builds QEMU parameters properly,
- creates ``Target`` object,
- and lets ``TargetRunner`` manage the QEMU instance.

Also add a new test case in ``tests/test_target.py`` to ensure devlib
can run a QEMU target and execute some basic commands on it.

While we are in neighborhood, fix a typo in ``Target.setup()``.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-03-20 12:16:12 +00:00
Metin Kaya
1431bebd80 tools/buildroot: Add support for generating Linux target system images
Integrate buildroot into devlib in order to ease building kernel and
root filesystem images via 'generate-kernel-initrd.sh' helper script.

As its name suggests, the script builds kernel image which also includes
an initial RAM disk per default config files located under
configs/<arch>/.

Provide config files for buildroot and Linux kernel as well as a
post-build.sh script which tweaks (e.g., allowing root login on SSH)
target's root filesystem.

doc/tools.rst talks about details of kernel and rootfs configuration.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-03-20 12:16:12 +00:00
Metin Kaya
dd84dc7e38 tests/test_target: Test more targets
Test Android and Linux targets as well in addition to LocalLinux target.
In order to keep basic verification easy, list complete list of test
targets in tests/target_configs.yaml.example and keep the default
configuration file for targets simple.

Also:
- Create a test folder on target's working directory.
- Remove all devlib artefacts after execution of the test.
- Add logs to show progress of operations.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-03-20 12:16:12 +00:00
Metin Kaya
295f1269ed target: Introduce make_temp() for creating temp file/folder on target
``Target.make_temp()`` employs ``mktemp`` command to create a temporary
file or folder.

This method will be used in unit tests.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-03-20 12:16:12 +00:00
Metin Kaya
84c0935fb2 utils/ssh: Try to free up resources during client creation
SshConnection._make_client() may throw exceptions for several reasons
(e.g., target is not ready yet). The client should be closed if that is
the case. Otherwise Python unittest like tools report resource warning
for 'unclosed socket', etc.

Signed-off-by: Douglas Raillard <douglas.raillard@arm.com>
Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-03-20 12:16:12 +00:00
Metin Kaya
598c0c1d3c tools/android: Add support for creating Android virtual devices
Introduce ``tools/android/install_base.sh`` [1] script to install
Android command line tools including necessary platforms and
system-images for Linux and create Android Virtual Devices (AVD) for
Pixel 6 with Android v12 & v14 as well as an Android virtual *desktop*
device (v13) for ChromeOS tests.

[1] Forked from https://github.com/ARM-software/lisa/blob/main/install_base.sh

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-03-20 11:56:49 +00:00
Metin Kaya
a1718c3700 tests/test_target: Read target connection settings from a YAML file
This will be useful in automating CI tests without modifying the source
code.

Replace unittest with pytest in order to make parameter passing to test
functions easier.

Move target configuration reading and generating target object outside
of the test function. Because we will run the test function for new
targets and may want to add new test functions.

While we are here, also fix pylint issues.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-02-23 12:48:44 -08:00
Metin Kaya
b5715b6560 utils/misc: Move load_struct_from_yaml() from WA to devlib
This is copied from WA (workload-automation/wa/utils/misc.py).
Hence, published another PR [1] removes the implementation from WA.

OTOH, this patch uses ``ruamel`` instead of ``yaml`` because of the
latter's design issues.

And also this patch fixes pylint issues in ``load_struct_from_yaml()``.

[1] https://github.com/ARM-software/workload-automation/pull/1248

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-02-23 12:48:44 -08:00
Metin Kaya
39dfa7ef72 utils/android: Add debug log about connection settings
While we are there, also fix a trivial pylint issue regarding string
format.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-02-23 12:48:44 -08:00
Metin Kaya
a83fe52382 test_target: Add copyright statement
Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-01-23 06:51:59 -08:00
Metin Kaya
613b4fabba ChromeOsTarget: Fix building SSH connection parameter list
'if list.get(elem, None)' like probing ignores list elements whose
values are falsy.

Here is a sample test code:
```Python
connection_settings={'host': '127.0.0.1',
                     'port': 8022,
                     'username': 'root',
                     'password': 'root',
                     'strict_host_check': False}

ssh_conn_params = ['host', 'username', 'password', 'port', 'strict_host_check']

print(f'connection_settings={connection_settings}')

ssh_connection_settings = {}
for setting in ssh_conn_params:
    if connection_settings.get(setting, None):
        print(f'1. setting "{setting}" to "{connection_settings[setting]}"...')
        ssh_connection_settings[setting] = connection_settings[setting]
    else:
        print(f'1. "{setting}" is None!')

ssh_connection_settings = {}
for setting in ssh_conn_params:
    if setting in connection_settings:
        print(f'2. setting "{setting}" to "{connection_settings[setting]}"...')
        ssh_connection_settings[setting] = connection_settings[setting]
    else:
        print(f'2. "{setting}" is None!')
```

And its output:
```
connection_settings={'host': '127.0.0.1', 'port': 8022, 'username': 'root', 'password': 'root', 'strict_host_check': False}

1. setting "host" to "127.0.0.1"...
1. setting "username" to "root"...
1. setting "password" to "root"...
1. setting "port" to "8022"...
1. "strict_host_check" is None!

2. setting "host" to "127.0.0.1"...
2. setting "username" to "root"...
2. setting "password" to "root"...
2. setting "port" to "8022"...
2. setting "strict_host_check" to "False"...
```

Also fix a typo in a log message.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-01-23 06:51:59 -08:00
Metin Kaya
be7e73db16 utils/ssh: Load host keys only if strict_host_check is true
Loading host keys breaks setting up SSH connection (paramiko throws
BadHostKeyException exception) if issuer does not want/need strict key
matching.

One use case for ignoring strict_host_check is automating virtual guests
(i.e., over QEMU). Issuer may want to skip loading host keys and start
with a blank list of known host keys for sure.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-01-23 06:51:59 -08:00
Metin Kaya
e334f8816c target: Customize as_root parameter of *write_value()
Not all command executions (or write operations in this specific case)
requires being root. So, allow write_value() and dependent
revertable_write_value() to support non-root executions by introducing
'as_root' optional parameter whose default is True to preserve current
behavior of the aforementioned methods.

Meanwhile, update the copyright year of the touched file, too.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-01-23 06:51:59 -08:00
Metin Kaya
38d8053f2f devlib: Remove unused imports
Also import 'warnings' before 'wrapt' module to address a pylint
warning.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-01-23 06:51:59 -08:00
Metin Kaya
7ccdea6b8e devlib/init: Resolve pylint issues
This is for increasing pylint score of __init__.py to 10/10.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-01-23 06:51:59 -08:00
Metin Kaya
cb36347dfe doc/connection: Fix typo Telenet
It should be *telnet* instead.

Signed-off-by: Metin Kaya <metin.kaya@arm.com>
2024-01-23 06:51:59 -08:00
Luis Machado
c60737c78e [Android] Fix use-before-initialization during initialization of ApkInfo
I noticed the following errors during invocation of uibench/uibenchjanktests:

     job:     Initializing job wk1 (uibench) [1]
  signal:         Sending before-workload-initialized from wk1 (uibench) [1]
     apk:         Resolving package on host system
resolver:         Resolving <<Workload uibench>'s apk 14>
resolver:         Trying user.get
  signal:         Sending error-logged from <ErrorSignalHandler (DEBUG)>
  signal:         Disconnecting <bound method Executor._error_signalled_callback of executor> from error-logged(<class 'louie.sender.Any'>)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/signal.py", line 324, in wrap
  signal:             yield
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/job.py", line 97, in initialize
  signal:             self.workload.initialize(context)
  signal:           File "/repos/lisa/external/workload-automation/wa/utils/exec_control.py", line 83, in wrapper
  signal:             return method(*args, **kwargs)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/workload.py", line 305, in initialize
  signal:             self.apk.initialize(context)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/workload.py", line 717, in initialize
  signal:             self.resolve_package(context)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/workload.py", line 734, in resolve_package
  signal:             self.resolve_package_from_host(context)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/workload.py", line 774, in resolve_package_from_host
  signal:             apk_file = context.get_resource(ApkFile(self.owner,
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/execution.py", line 197, in get_resource
  signal:             result = self.resolver.get(resource, strict)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/resource.py", line 268, in get
  signal:             result = source(resource)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/getters.py", line 139, in get
  signal:             return get_from_location(directory, resource)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/getters.py", line 106, in get_from_location
  signal:             return get_generic_resource(resource, files)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/getters.py", line 63, in get_generic_resource
  signal:             if resource.match(f):
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/resource.py", line 165, in match
  signal:             uiauto_matches = uiauto_test_matches(path, self.uiauto)
  signal:           File "/repos/lisa/external/workload-automation/wa/framework/resource.py", line 335, in uiauto_test_matches
  signal:             info = get_cacheable_apk_info(path)
  signal:           File "/repos/lisa/external/workload-automation/wa/utils/android.py", line 192, in get_cacheable_apk_info
  signal:             info = ApkInfo(path)
  signal:           File "/repos/lisa/external/workload-automation/wa/utils/android.py", line 116, in __init__
  signal:             super().__init__(path)
  signal:           File "/repos/lisa/external/devlib/devlib/utils/android.py", line 152, in __init__
  signal:             self.parse(path)
  signal:           File "/repos/lisa/external/devlib/devlib/utils/android.py", line 159, in parse
  signal:             output = self._run([self._aapt, 'dump', 'badging', apk_path])
  signal:
  signal:         Sending error-logged from <ErrorSignalHandler (DEBUG)>
  signal:         AttributeError('ApkInfo' object has no attribute '_aapt')
  signal:         Sending after-workload-initialized from wk1 (uibench) [1]
  signal: Sending error-logged from <ErrorSignalHandler (DEBUG)>
  runner: Skipping remaining jobs due to "'ApkInfo' object has no attribute '_aapt'".

This is due to the fact we might call self.parse in ApkInfo::__init__, if the
path variable is set to a non-empty value, but the initialization of both
self._aapt and self._aapt_version is after this call.

Fix this by moving the initialization of both variables before the call to
self.parse.
2024-01-17 09:39:43 -08:00
Douglas Raillard
f60e341d6e target: Fix read_sysctl()
Add a leading "/" so the path is absolute.
2024-01-16 13:21:10 -08:00
Douglas Raillard
46219ace04 android: Fix typo in ApkInfo
Change self.aapt into self._aapt
2024-01-16 13:20:33 -08:00
Elif Topuz
4589b4698e target: Fix typo
Changed target variable to self because it is not defined in the file.
2024-01-15 13:54:39 -08:00
Douglas Raillard
56746fdb33 ssh: Fix tools detection
Fix inadequate use of module-level __getattr__ (it is not used by the
global variable lookup path). Instead, detect all tools lazily in the
same fashion as with _AndroidEnv()
2024-01-15 13:47:23 -08:00
Douglas Raillard
c347861db4 android: Ensure we use the detected fastboot
Use fastboot as detected by _AndroidEnvironment instead of whatever
binary is in PATH.
2024-01-15 13:47:23 -08:00
Douglas Raillard
3f9ce8ba73 android: Fix tool detections
Module-level __getattr__ is not called on the global variable lookup
path, rendering it useless for what we want to do here.

Instead, use the _AndroidEnvironment class and make it lazy so that we
will not raise an exception by just importing the module.
2024-01-15 13:47:23 -08:00
Douglas Raillard
f30fb0b3fd utils/ssh: Ensure the detected sshpass is used
Since we detect the sshpass tool using which(), ensure that the code
uses that instead of just relying on PATH.
2024-01-10 11:22:54 -08:00
Douglas Raillard
c39d40c6f8 utils/ssh: Remove _check_env()
Replace _check_env() by lazily initialized global var.
2024-01-10 11:22:54 -08:00
Douglas Raillard
926aee1833 utils/android: Remove PATH manipulation
Android tools detection was manipulating os.environ['PATH'] which has
an impact beyond devlib (and even beyond the current process as it will
be inherited by any child).

Remove that hack and instead use global variables to get adb and
fastboot paths. These tools are now detected by _AndroidEnvironment()
like the others.
2024-01-10 11:22:54 -08:00
Douglas Raillard
19c51547d1 utils/android: Cleanup android tool detection
* Use lazy global var init using module-level __getattr__() and remove
  all the _check_env() calls.

* Cleanup the code by removing unnecessary statefullness. While doing so,
prune paths that can never happen.

* Encapsulate all the logic in _AndroidEnvironment() instead of mutating
it using standalone functions.

* Set "adb" and "fastboot" global variables to None as fastboot was
  always set to None, and adb was set to None on the path with
  ANDROID_HOME env var set.
2024-01-10 11:22:54 -08:00
Douglas Raillard
52485fbaa5 setup.py: Re-add "future" PyPI package
Re-add the "future" PyPI package since it actually contains the "past"
Python package that devlib still uses.
2024-01-09 12:07:57 -08:00
Douglas Raillard
416e8ac40f devlib: Remove Python 2 dead code
Remove code that was used for Python 2 only.
2024-01-09 12:07:57 -08:00
Douglas Raillard
ea4eccf95d setup.py: Remove use of "imp" module
Python 3.12 removed the "imp" module, so replace its use in devlib.
2024-01-09 12:07:57 -08:00
Marc Bonnici
b8bf2abf3b AndroidTarget: Skip ungrantable Android permission
Don't throw an error if attempting to grant a permission that
is not manageable.
2024-01-09 12:06:59 -08:00
Douglas Raillard
9f71c818c4 android: Add adb_port connection setting
Allow specifying the port of the adb server in use.
2024-01-09 12:06:26 -08:00
Douglas Raillard
0579a814f1 android: Add a retry logic for background command PID detection
PID detection can sometimes fail for unknown reason. Maybe there is a
latency between the process being started and "ps" being able to see it
that can sometimes be high enough that we look for the process before
it's exposed.

In order to remedy that, add a retry logic to avoid plain failures.
2024-01-09 12:06:26 -08:00