Table of Contents:

This document describes how to execute automated LAVA tests controlling resources external to the DUT across a network implementing a LAVA parallel pipeline job.

Test Cases

The approach proposed in this document will help to address test cases like:

  • Executing a test in the DUT where certain power states are simulated (for example a power loss) during specific test actions using a programmable PSU external to the DUT.

  • Executing a test in the DUT simulating SD card insertion and removal using an external device.

The only assumption, in both scenario, proposed in this document is that the external device (either a programmable PSU or SD-card simulator) can be accessed through the network using SSH.

LAVA Features

LAVA offers the following features that can be combined to implement a solution for the test cases mentioned in this document:

  • LXC to deploy required software and tools to access the external device.
  • MultiNode to communicate data between jobs actions.
  • Secondary connections for executing tests through SSH.

LXC

LAVA supports LXC containers both as a standalone device type and as dynamic transparent environments in order to interact with external devices. In either case the LXC Protocol is used.

MultiNode

The MultiNode Protocol allows data to be shared between actions, including data generated in one test shell definition being made available over the protocol to a deploy or boot action of jobs with a different role.

Synchronisation is done using the MultiNode API, specifically the lava-send and lava-wait calls.

Secondary Connections

LAVA allows Secondary Connections to open network connections to external devices using MultiNode submissions.

Approach Overview

The main idea is to create a LXC container device associated to the DUT responsible to execute the automated test, then opens a SSH connection to an external device, and use the MultiNode API in order to synchronize both devices and pass data between them with the LXC container serving like a coordinator of the different LAVA tests actions.

In this way, a server-client layout is setup that will help to execute tests in a board attached to LAVA (server side) with intervention of external devices (client side).

LAVA Job Connection Layout

The LXC container is deployed directly from the LAVA dispatcher and coordinate the execution of the parallel pipeline between the DUT and the external device (secondary connection) from there.

The layout model would be something like:

           ------------- DUT
          / MultiNode
LAVA (LXC)
          \
           ------------- Secondary Connection (PSU, SD-Card HW)
            MultiNode

Test Job

This section shows the basics proposed in this document using a LAVA job file example.

The following steps describe the main flow of the job:

1 - Create two types of roles host and guest. The host role will contain the LXC container and the DUT, the guest role will label the SSH connection for the external device. This creates two groups (host and guest) that can communicate using the MultiNode API, so messages can be sent between the LXC and Device as the server and the secondary connection as the client.

2 - Label both types of roles in the protocols section of the job.

3 - Deploy and boot the LXC container (host).

4 - Execute a test in the LXC container using the MultiNode API to send the lava_start message, so the deploy action for the external device can start, and waits for remaining clients to start using the lava-sync call.

5 - Deploy the DUT (host).

6 - Deploy the external device (guest) , which is waiting for the LXC lava_start message to start deployment. Once this message is recevied, the guest device is deployed.

7 - Boot DUT.

8 - Boot external device.

9 - Execute a test in the DUT sending the lava-sync call.

10 - Execute a test in the external device sending the lava-sync call.

11 - Once all clients are synchronized (the LXC, DUT and external device), start executing tests.

12 - Tests executed in the DUT and external device needs to use the MultiNodeAPI in order to pass data between them.

As the LXC is deployed and booted first, the LXC can run a test shell before deploying the device, before booting the device, before the test shell action on the device which starts the secondary connection guests or at any later point (AddingTestsActions).

Job File Example

job_name: LXC and Secondary connection with a Device

timeouts:
  job:
    minutes: 30
  action:
    minutes: 3
  connection:
    minutes: 5
priority: medium
visibility: public

protocols:
  lava-lxc:
    host:
      name: lxc-ssh-test
      template: debian
      distribution: debian
      release: stretch
  lava-multinode:
    # expect_role is used by the dispatcher and is part of delay_start
    # host_role is used by the scheduler, unrelated to delay_start.
    roles:
      host:
        device_type: beaglebone-black
	# This makes this role essential in order to execute the test.
	essential: True
        count: 1
        timeout:
          minutes: 10
      guest:
        # protocol API call to make during protocol setup
        request: lava-start
        # set the role for which this role will wait
        expect_role: host
        timeout:
          minutes: 15
        # no device_type, just a connection
        connection: ssh
        count: 3
        # each ssh connection will attempt to connect to the device of role 'host'
        host_role: host

actions:
- deploy:
    role:
    - host
    namespace: probe
    timeout:
      minutes: 5
    to: lxc
    # authorize for ssh adds the ssh public key to authorized_keys
    authorize: ssh
    packages:
    - usbutils
    - procps
    - lsb-release
    - util-linux
    - ntpdate
    - openssh-server
    - net-tools

- boot:
    role:
    - host
    namespace: probe
    prompts:
    - 'root@(.*):/#'
    timeout:
      minutes: 5
    method: lxc

- test:
    role:
    - host
    namespace: probe
    timeout:
      minutes: 5
    definitions:
    - repository:
        metadata:
          format: Lava-Test Test Definition 1.0
          name: network
          description: "Send message ID"
        run:
          steps:
          - lava-test-case ntpdate --shell ntpdate-debian
          - lava-echo-ipv4 eth0
          - lava-send ipv4 ipaddr=$(lava-echo-ipv4 eth0)
          - lava-send lava_start
          - lava-sync clients
      from: inline
      name: lxc-test
      path: inline/lxc-test.yaml

# DUT actions
- deploy:
    role:
    - host
    namespace: device
    timeout:
      minutes: 5
    to: tftp

    kernel:
      url: https://files.lavasoftware.org/components/lava/standard/debian/stretch/armhf/3/vmlinuz-4.9.0-4-armmp
      sha256sum: b6043cc5a07e2cead3f7f098018e7706ea7840eece2a456ba5fcfaddaf98a21e
      type: zimage
    ramdisk:
      url: https://files.lavasoftware.org/components/lava/standard/debian/stretch/armhf/3/initrd.img-4.9.0-4-armmp
      sha256sum: 4cc25f499ae74e72b5d74c9c5e65e143de8c2e3b019f5d1781abbf519479b843
      compression: gz
    modules:
      url: https://files.lavasoftware.org/components/lava/standard/debian/stretch/armhf/3/modules.tar.gz
      sha256sum: 10e6930e9282dd44905cfd3f3a2d5a5058a1d400374afb2619412554e1067d58
      compression: gz
    nfsrootfs:
      url: https://files.lavasoftware.org/components/lava/standard/debian/stretch/armhf/3/stretch-armhf-nfs.tar.gz
      sha256sum: 46d18f339ac973359e8ac507e5258b620709add94cf5e09a858d936ace38f698
      compression: gz
    dtb:
      url: https://files.lavasoftware.org/components/lava/standard/debian/stretch/armhf/3/dtbs/am335x-boneblack.dtb
      sha256sum: c4c461712bf52af7d020e78678e20fc946f1d9b9552ef26fd07ae85c5373ece9

- deploy:
    role:
    - guest
    namespace: guest
    # Timeout for the ssh connection attempt
    timeout:
      seconds: 30
    to: ssh
    connection: ssh
    protocols:
      lava-multinode:
      - action: prepare-scp-overlay
        request: lava-wait
        messageID: ipv4
        message:
          ipaddr: $ipaddr
      timeout:  # delay_start timeout
        minutes: 5

- boot:
    role:
    - host
    namespace: device
    timeout:
      minutes: 15
    method: u-boot
    commands: nfs
    auto_login:
      login_prompt: 'login:'
      username: root
    prompts:
    - 'root@stretch:'
    parameters:
      shutdown-message: "reboot: Restarting system"

- boot:
    role:
    - guest
    namespace: guest
    timeout:
      minutes: 3
    prompts:
    - 'root@stretch:'
    parameters:
      hostID: ipv4
      host_key: ipaddr
    method: ssh
    connection: ssh

- test:
    role:
    - host
    namespace: device
    timeout:
      minutes: 30
    definitions:
    - repository:
        metadata:
          format: Lava-Test Test Definition 1.0
          name: install-ssh
          description: "install step"
        run:
          steps:
          - df -h
          - free
          - lava-sync clients
      from: inline
      name: ssh-inline
      path: inline/ssh-install.yaml
    - repository: http://git.linaro.org/lava-team/lava-functional-tests.git
      from: git
      path: lava-test-shell/smoke-tests-basic.yaml
      name: smoke-tests
    - repository: http://git.linaro.org/lava-team/lava-functional-tests.git
      from: git
      path: lava-test-shell/single-node/singlenode02.yaml
      name: singlenode-intermediate

- test:
    role:
    - guest
    namespace: guest
    timeout:
      minutes: 5
    definitions:
    - repository: http://git.linaro.org/lava-team/lava-functional-tests.git
      from: git
      path: lava-test-shell/smoke-tests-basic.yaml
      name: smoke-tests
      # run the inline last as the host is waiting for this final sync.
    - repository:
        metadata:
          format: Lava-Test Test Definition 1.0
          name: client-ssh
          description: "client complete"
        run:
          steps:
          - df -h
          - free
          - lava-sync clients
      from: inline
      name: ssh-client
      path: inline/ssh-client.yaml

#
# Tests executed in the external device and DUT can be added here.
# They all need to use the MultiNode API.
#

# Execute test in the DUT
- test:
    role:
    - host
    namespace: device
    timeout:
      minutes: 10
    definitions:
    - repository: https://gitlab.apertis.org/tests/apertis-test-cases/
      from: git
      path: lava-test-shell/single-node/singlenode03.yaml
      name: singlenode-advanced

# Execute test in the external device (PSU, SD-card device)
- test:
    role:
    - guest
    namespace: guest
    timeout:
      minutes: 10
    definitions:
    - repository: https://gitlab.apertis.org/tests/apertis-test-cases/
      from: git
      path: lava-test-shell/single-node/singlenode03.yaml
      name: singlenode-advanced

QA Report

Once tests results are available at LAVA , and the test cases are enabled for the specific images from the test case repository, the results will be available from the QA Report App automatically.