...
- A relatively modern Linux system. This has been tried on Fedora 29 and Ubuntu 18.04, and Ubuntu 16.04 (However on 16.04 you need updated python packages, details below). This has been shown to work in VM based install.
- root/sudo access on host system. Root access is needed to add udev rules, install a few utilities, and run the udev-forward.py script.
- FRDM-K64F board with relatively fresh DAPLink firmware. A rule of thumb is that if when connecting via USB, the boards mounts a USB drive without DETAILS.TXT file, you should upgrade. We try to standardize on version 0246 of the DAPink. See corresponding section for more information.
Setup Host System
Install Docker
Use the following link for instructions on how to install docker: https://docs.docker.com/install
On distributions like Fedora & Ubuntu its recommend to add your local user to the docker group as this will prevent you from having to use sudo to run the docker commands. You can use the following command to add your user to the docker group:
Code Block language bash sudo usermod -aG docker <USERNAME>
- Note: The instructions that follow assume you are in the docker group and don't need
sudo
to run docker. If you don't add yourself you will need to explicitly addsudo
in front of the docker commands. - (OPTIONAL) Proxy Setup - If you are behind an http proxy, follow these instructions:
Install Docker Compose
Use the following link for instructions on how to install Docker Compose: https://docs.docker.com/compose/install/Install python packages
( Note: These need to be installed such that they are able to run as root - either use systems packages or install in root user (
sudo pip3 install --user
):
Major distributions have packages for pydev >= 0.18 and docker >= 2.0
For Ubuntu 18.04:Code Block language bash sudo apt-get install python3-pyudev python3-docker
For Ubuntu 16.04:
Specific action is required because the distro package versions are too old.
Code Block sudo pip3 install -U --user pyudev docker
If this doesn't work, you need to run the command in "sudo su -" shell.
Code Block pip3 install -U --user pyudev docker
NOTE: It might require to first export proxy settings in the shell.
For Fedora:
Code Block language bash sudo dnf install python3-pyudev python3-docker
NOTE: Use only if you aren't able to find distro packages (or they're very old) for
pyudev
anddocker
python packages.Code Block language bash sudo pip3 install -U --user pyudev docker
Install
lavacli
Code Block language bash pip3 install --user lavacli
Determine Serial Number for board
Code Block language bash udevadm monitor -e | grep -i ID_SERIAL_SHORT
Plug in board, should see some output like:
Code Block language bash ID_SERIAL_SHORT=0240000031754e45001c0019948500046461000097969900 ID_SERIAL_SHORT=0240000031754e45001c0019948500046461000097969900 ID_SERIAL_SHORT=0240000031754e45001c0019948500046461000097969900 ID_SERIAL_SHORT=0240000031754e45001c0019948500046461000097969900
Clone Git Repo
Code Block language bash git clone -b lite https://github.com/Linaro/lite-lava-docker-compose
Install
usb-passthrough
in/usr/local/bin
Code Block language bash sudo cp lite-lava-docker-compose/contrib/usb-passthrough /usr/local/bin
Modify
lite-lava-docker-compose/contrib/LAVA.rules
Replace
MYSERIALNUM
with serial number from step 4.Code Block language bash linenumbers true # Example LAVA.rules for USB passthrough to container # # Assumes that usb-passthrough script is installed in # /usr/local/bin/passthrough # Pass all usb devices (TTY, block, CDC) to lava-dispatcher container # FRDM-K64F ACTION=="add", ENV{ID_SERIAL_SHORT}=="MYSERIALNUM", RUN+="/usr/local/bin/usb-passthrough -a -d %E{ID_SERIAL_SHORT} -i lava-dispatcher" # Pass TTY through to lava-ser2net container ACTION=="add", SUBSYSTEM=="tty", ENV{ID_SERIAL_SHORT}=="MYSERIALNUM", RUN+="/usr/local/bin/usb-passthrough -a -d %E{ID_SERIAL_SHORT} -i lava-ser2net"
Change line #8 and #10 to look like:
Code Block language bash linenumbers true # Example LAVA.rules for USB passthrough to container # # Assumes that usb-passthrough script is installed in # /usr/local/bin/passthrough # Pass all usb devices (TTY, block, CDC) to lava-dispatcher container # FRDM-K64F ACTION=="add", ENV{ID_SERIAL_SHORT}=="0240000031754e45001c0019948500046461000097969900", RUN+="/usr/local/bin/usb-passthrough -a -d %E{ID_SERIAL_SHORT} -i lava-dispatcher" # Pass TTY through to lava-ser2net container ACTION=="add", SUBSYSTEM=="tty", ENV{ID_SERIAL_SHORT}=="0240000031754e45001c0019948500046461000097969900", RUN+="/usr/local/bin/usb-passthrough -a -d %E{ID_SERIAL_SHORT} -i lava-ser2net"
install
udev
rule fileCode Block language bash sudo cp lite-lava-docker-compose/contrib/LAVA.rules /etc/udev/rules.d/
...
Optional: Setup access for local IP/host
If you are running lava on a machine with a fixed IP (eg: a dedicated computer on your local network) you will want to modify the
overlays/lava-server/etc/lava-server/settings.conf
file to allow access. You'll want to modify theALLOWED_HOSTS
line to add the ip or hostname of the machine. In the example below, the ip192.168.1.14
was added, you'll want to keep127.0.0.1
andlocalhost
.Code Block language yml linenumbers true { "HTTPS_XML_RPC": false, "MOUNT_POINT": "/", "STATIC_URL": "/static/", "ALLOWED_HOSTS": ["192.168.1.14", "127.0.0.1", "localhost"], "CSRF_COOKIE_SECURE": false, "SESSION_COOKIE_SECURE": false, "EVENT_NOTIFICATION": true, "EVENT_TOPIC": "lava-server", "INTERNAL_EVENT_SOCKET": "tcp://lava-publisher:5557" }
- Optional: Add the proxy settings in lite-lava-dispatcher and ser2net images
It might be required to define proxy setting in lite-lava-dispatcher/Dockerfile and ser2net/Dockerfile
Code Block language bash ENV http_proxy=http://<user>:<pwd>@<proxy>:<port> ENV https_proxy=http://<user>:<pwd>@<proxy>:<port>
- Optional: Configure DNS in /etc/docker/daemon.json
Do this only if you are sure you need this. Otherwise, hardcoding a particular (local) DNS server may lead to issues when using another network connection, etc.
Get host DNS:
Code Block language bash nmcli dev show | grep 'IP4.DNS'
Set reported value in /etc/docker/daemon.json:
Code Block language yml { "dns": ["w.x.y.z"] }
Run commands to build docker images and startup lava
Code Block language bash docker-compose build make
You'll see output of docker fetching and building the images, and then all LAVA containers starting up, followed by a fair amount of logging from LAVA itself as it starts up. This may take a few minutes to complete.
Here are some examples of the output one can expect during this phase:
Docker Compose/Build Phase
Code Block language bash galak@ubuntu:~/lite-lava-docker-compose$ make docker-compose up Creating volume "lava-server-pgdata" with default driver Creating volume "lava-server-devices" with default driver Creating volume "lava-server-health-checks" with default driver Creating volume "lava-server-joboutput" with default driver Pulling db (postgres:11.2-alpine)... 11.2-alpine: Pulling from library/postgres bdf0201b3a05: Pull complete 365f27dc05d7: Pull complete bf541d40dfbc: Pull complete 823ce70c3252: Extracting [========> ] 4.194MB/25.04MB a92a31ecd32a: Download complete 83cc8c6d8282: Download complete 7995b9edc9bf: Download complete 7616119153d9: Download complete b3f69561e369: Download complete
Lava containers being created
Code Block language bash Creating lava-server-db ... done Creating lava-dispatcher ... done Creating lava-ser2net ... done Creating lava-publisher ... done Creating lava-master ... done Creating lava-logs ... done Creating lava-server ... done Creating apache2 ...
Lava starting up
Code Block language bash lava-master | Applying lava_results_app.0012_namedtestattribute_metadata... OK lava-server | . lava-master | Applying lava_results_app.0013_buglinks... OK lava-master | Applying lava_results_app.0014_xaxis_maxlength_increase... OK lava-master | Applying dashboard_app.0002_auto_20140917_1935... OK lava-logs | . lava-master | Applying dashboard_app.0003_auto_20140926_1208... OK lava-master | Applying dashboard_app.0004_imagereportchart_is_delta... OK lava-dispatcher | 2019-05-09 19:01:08,522 DEBUG [BTSP] Checking master [lava-master:5556] to create socket for lava-dispatcher lava-dispatcher | 2019-05-09 19:01:08,524 DEBUG [BTSP] socket IPv4 address: 172.18.0.6 lava-dispatcher | 2019-05-09 19:01:08,525 INFO [BTSP] Greeting master => 'HELLO_RETRY' (using the same version?) lava-master | Applying dashboard_app.0005_imagereportchart_chart_height... OK lava-master | Applying dashboard_app.0006_auto_20141028_1146... OK lava-master | Applying dashboard_app.0007_imagereportchart_chart_visibility... OK lava-server | . lava-master | Applying dashboard_app.0008_imagechartfilter_is_all_tests_included... OK
Lava idle
Code Block language bash lava-dispatcher | 2019-05-09 19:03:21,510 DEBUG PING => master (last message 20s ago) lava-master | 2019-05-09 19:03:21,513 DEBUG lava-dispatcher => PING(20) lava-dispatcher | 2019-05-09 19:03:21,519 DEBUG master => PONG(20) lava-master | 2019-05-09 19:03:36,201 INFO scheduling health checks: lava-master | 2019-05-09 19:03:36,205 INFO scheduling jobs: lava-master | 2019-05-09 19:03:38,651 DEBUG lava-logs => PING(20) lava-logs | 2019-05-09 19:03:38,648 DEBUG PING => master lava-logs | 2019-05-09 19:03:38,657 DEBUG master => PONG(20) lava-master | 2019-05-09 19:03:41,549 DEBUG lava-dispatcher => PING(20) lava-dispatcher | 2019-05-09 19:03:41,546 DEBUG PING => master (last message 20s ago) lava-dispatcher | 2019-05-09 19:03:41,555 DEBUG master => PONG(20) lava-master | 2019-05-09 19:03:56,221 INFO scheduling health checks: lava-master | 2019-05-09 19:03:56,225 INFO scheduling jobs: lava-logs | 2019-05-09 19:03:58,681 DEBUG PING => master lava-master | 2019-05-09 19:03:58,684 DEBUG lava-logs => PING(20) lava-logs | 2019-05-09 19:03:58,690 DEBUG master => PONG(20) lava-master | 2019-05-09 19:04:01,579 DEBUG lava-dispatcher => PING(20) lava-dispatcher | 2019-05-09 19:04:01,577 DEBUG PING => master (last message 20s ago) lava-dispatcher | 2019-05-09 19:04:01,584 DEBUG master => PONG(20)
Verify lava is running
You can verify that lava has completed startup by trying to connect to the LAVA webserver in a web browser by going to localhost.
Here's what the startup webpage should look like in your web browser:
...
Setup the device type
(Note how we use the
-i dispatcher
identity we created in the previous steps).Code Block language bash lavacli -i dispatcher device-types add frdm-k64f
Add a board instance
Now that the device-type is registered, we need to create a device instance. In the example below we are creating a device instance called
frdm-k64f-01 (the naming follows the Cambridge lab setup: https://lite.validation.linaro.org/scheduler/alldevices)
.Code Block language bash lavacli -i dispatcher devices add --type frdm-k64f --worker lava-dispatcher frdm-k64f-01
Note: the
--worker lava-dispatcher
argument in this command is used to specify the name of the Lava dispatcher that the board is physically connected to. The Lava architecture allows multiple dispatchers to be connected to a single server. The docker solution we are utilizing is configured for a single dispatcher called lava-dispatcher.Connect the board
Back in the Building & Starting up the LAVA Docker images section we mentioned to disconnect the board. Please connect the board back to your computer. If you didn't disconnect the board in the Building stage that's ok, please disconnect and reconnect the board. The reason we wanted the board disconnect until this point is that we wanted the docker container for the lava-dispatcher up and running before the board was connected. If you remember we added someudev
rules back in the host setup stage. Those udev rules invoke theusb-passthrough
utility. The purpose of that utility is to "setup" the various usb devices (serial, usb mass storage, debug) in the lava-dispatch container. The udev rules rely on the hotplug event associated with the board being plugged in. Thus if we plugged in the board before the docker containers were running the containers wouldn't know about the board.Generate the parameters for the board instance
Now that the board is connected we need to let lava know some details specific to this board. In the case of the FRDM-K64F board we need to let Lava know what the serial number of the board is, the device file for the mass storage device, and how to connect to the serial port. These parameters are specified in a jinja2 template format. There is a helper script that given the device type and serial number of the board will create or report information associated with setting up the board. Thecontrib/board-setup-helper.py
at a minimum needs the-d
(serial number) and-t
(device type - matches the lava device type) flags. We also specify the -u flag in our example to report the udev rules. Finally there are a-s
and-b
options to specify the ser2net config filename and board jinja filename. By default the script will look to modifyser2net/ser2net.conf
if the-s
options is not specified and will create board.jinja2 if the-b
option is not specified.contrib/board-setup-helper.py
helpCode Block language bash contrib/board-setup-helper.py -h usage: board-setup-helper.py -d DEVICE_SERIAL_NUM -t DEVICE_TYPE [-s SER2NET_CONF] [-u] [-b BOARD_FILE] contrib/board-setup-helper.py -d <DEVICE_SERIAL_NUM> -t <DEVICE_TYPE>
command to run
Here we use the serial number (0240000031754e45001c0019948500046461000097969900
) and device type (frdm-k64f
) from beforeCode Block language bash contrib/board-setup-helper.py -d 0240000031754e45001c0019948500046461000097969900 -t frdm-k64f -u
output from command
Here we see that the -u option reports back the udev rules that we would need to add for this board. These rules match the ones we specified back in the host setup stage.Code Block language bash ACTION=="add", ENV{ID_SERIAL_SHORT}=="0240000031754e45001c0019948500046461000097969900", RUN+="/usr/local/bin/usb-passthrough -a -d %E{ID_SERIAL_SHORT} -i lava-dispatcher" ACTION=="add", SUBSYSTEM=="tty", ENV{ID_SERIAL_SHORT}=="0240000031754e45001c0019948500046461000097969900", RUN+="/usr/local/bin/usb-passthrough -a -d %E{ID_SERIAL_SHORT} -i lava-ser2net"
ser2net/ser2net.conf file
ser2net is a utility that allows exposing a serial port device as a network connection. We generateCode Block language bash 5001:telnet:0:/dev/serial/by-id/usb-ARM_DAPLink_CMSIS-DAP_0240000031754e45001c0019948500046461000097969900-if01:115200 8DATABITS NONE 1STOPBIT LOCAL max-connections=10
board.jinja2 file
As mentioned before the board.jinja2 file provides unique details about the specific boardboard_id
: serial numberusb_mass_device
: device file for USB mass storage device that one would mount. We use the /dev/disk/by-id so that the name is persistent for the boardconnection_command
: command to connect to serial port, the port number here matches theser2net.conf
file.resets_after_flash
: Not used/generated - some all newer daplink firmware firmwares on the FRDM-K64F does do not reset after the board is flashed. So, we set this option to "false". If you have such a board you'll need to clear this flag. The best way to determine if you need this is to try the directions without it set and see if they succeed or notvery old DAPLink firmware and want to postpone upgrading it (not recommended), you can set this option to "true".Code Block language yml linenumbers true {% extends 'frdm-k64f.jinja2' %} {% set board_id = '0240000031754e45001c0019948500046461000097969900' %} {% set usb_mass_device = '/dev/disk/by-id/usb-MBED_VFS_0240000031754e45001c0019948500046461000097969900-0:0' %} {% set connection_command = 'telnet ser2net 5001' %} {% set resets_after_flash = false %}
Set the device dictionary
Because of the client/server nature of Lava we need to tell the server to update the device dictionary for our specific board with the parameters for the board. We utilize
lavacli
for this purpose. The device dictionary is kept by the lava server and a full dictionary that is composed of the device-type template + the board specific dictionary are sent to the lava dispatcher on every job that is submitted. Thus any updates to the dictionary for a given board will take effect for any future job submissions.Code Block language bash lavacli -i dispatcher devices dict set frdm-k64f-01 board.jinja2
Restart ser2net
Since we updated the ser2net.conf file we need to send a SIGHUP (-1) signal to the ser2net daemon to cause it to re-read the config file.
Code Block language bash docker exec -it lava-ser2net sh -c 'kill -1 `cat /var/run/ser2net.pid`'
...
You then need to bind your host certificates to container by adding following line in lite-lava-docker-compose/docker-compose.yaml:
Code Block | ||
---|---|---|
| ||
lava-master: container_name: lava-master image: ${DC_SERVER_IMAGE} volumes: ... - /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro |
Then, run the following command in the container and go back to job start step.
Code Block |
---|
update-ca-certificates |
...
This is version David and Paul originally had. Generally works well with LAVA, but requires "set resets_after_flash = false
" in the board template. Later, Paul found that this board with this version has LAVA deployment issues when used on another host computer, documented at https://github.com/pfalcon/lava-docker-compose/issues/3 .
Version 0246
Available at:
Version 0246
Available at: https://github.com/ARMmbed/DAPLink/releases/tag/0246 . .. Download and extract the .zip file and copy file 0246_k20dx_frdmk64f_0x5000.bin to a board in bootloader upgrade mode (plug into USB with Reset button held).
Contents of DETAILS.TXT:
Code Block | ||
---|---|---|
| ||
# DAPLink Firmware - see https://mbed.com/daplink Unique ID: 0240000048824e45000b700bdd8900418761000097969900 HIC ID: 97969900 Auto Reset: 0 Automation allowed: 0 Overflow detection: 0 Daplink Mode: Interface Interface Version: 0246 Git SHA: 0beabef8aa4b382809d79e98321ecf6a28936812 Local Mods: 0 USB Interfaces: MSD, CDC, HID Interface CRC: 0x434eddd1 Remount count: 0 |
Enabled auto reset mode by creating a `auto_rst.cfg` file while holding the reset button down (Useful link: MSD command documentation for 0246). Post reset, Details.txt reports "Auto Reset: 1."When adding a new job, however, the job stalls waiting for USB CDC to appear (60s timeout) and the only way for the test to pass is to manually remove and reconnect the USB cable within the 60 second delay. The CDC device is being passed through to the two docker images, as evidenced by the following commands:.
Adding multiple boards of the same type
In case you use the same board with a different debugger, or you just want to add a new board to your Lava-Docker setup you need to do the following steps:
Add a new physical board
This step assumes you have aleardy added the board's device type.
Code Block | ||
---|---|---|
| ||
$ sudo docker exec -it lava-dispatcher ls -l /dev/ crw-r--r-- 1 root root 166, 0 Jun 19 17:18 ttyACM0 $ sudo docker exec -it lava-ser2net ls -l /dev/ crw-r--r-- 1 root root 166, 0 Jun 19 17:18 ttyACM0lavacli -i dispatcher devices add --type frdm-k64f --worker lava-dispatcher frdm-k64f-02 |
2. Create a
Reset udev-forward script
Please stop udev-forward script (Ctr+C) and run the command:
Code Block | ||
---|---|---|
| ||
sudo contrib/udev-forward.py -i lava-dispatcher |