-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial Arm Virtual Hardware (AVH) workflow with end to end test
- Loading branch information
1 parent
754a938
commit 5283105
Showing
10 changed files
with
805 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -116,6 +116,7 @@ autogenerated | |
automake | ||
autotools | ||
avahi | ||
AVH | ||
avL | ||
AwaitNextAction | ||
AXXXF | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Copyright (c) 2022 Project CHIP Authors | ||
# | ||
# 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. | ||
|
||
name: Arm Virtual Hardware | ||
|
||
on: | ||
push: | ||
pull_request: | ||
workflow_dispatch: | ||
|
||
concurrency: | ||
group: ${{ github.ref }}-${{ github.workflow }}-${{ (github.event_name == 'pull_request' && github.event.number) || (github.event_name == 'workflow_dispatch' && github.run_number) || github.sha }} | ||
cancel-in-progress: false | ||
|
||
jobs: | ||
arm_crosscompile: | ||
name: Linux ARM Cross compile | ||
timeout-minutes: 70 | ||
|
||
runs-on: ubuntu-latest | ||
if: github.actor != 'restyled-io[bot]' | ||
|
||
container: | ||
image: ghcr.io/project-chip/chip-build-crosscompile:1 | ||
volumes: | ||
- "/tmp/bloat_reports:/tmp/bloat_reports" | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
|
||
- name: Checkout submodules & Bootstrap | ||
uses: ./.github/actions/checkout-submodules-and-bootstrap | ||
with: | ||
platform: linux | ||
|
||
- name: Build Samples | ||
timeout-minutes: 45 | ||
run: | | ||
./scripts/run_in_build_env.sh \ | ||
"./scripts/build/build_examples.py \ | ||
--target linux-arm64-chip-tool-ipv6only-mbedtls-clang-minmdns-verbose \ | ||
--target linux-arm64-light-ipv6only-mbedtls-clang-minmdns-verbose \ | ||
build \ | ||
" | ||
- name: Upload built samples | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: arm_crosscompiled_samples | ||
path: | | ||
out/linux-arm64-chip-tool-ipv6only-mbedtls-clang-minmdns-verbose/chip-tool | ||
out/linux-arm64-light-ipv6only-mbedtls-clang-minmdns-verbose/chip-lighting-app | ||
arm_e2e_tests: | ||
name: Arm Virtual Hardware End to end tests | ||
timeout-minutes: 10 | ||
|
||
runs-on: ubuntu-latest | ||
|
||
env: | ||
AVH_API_TOKEN: ${{ secrets.AVH_API_TOKEN }} | ||
AVH_API_ENDPOINT: https://csa.app.avh.arm.com/api | ||
AVH_PROJECT_NAME: "${{ github.workflow }} #${{ github.run_number }} - End to end tests" | ||
|
||
needs: arm_crosscompile | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
|
||
- name: Downloads Cross-compiled samples | ||
uses: actions/download-artifact@v3 | ||
with: | ||
name: arm_crosscompiled_samples | ||
path: scripts/tests/avh/out | ||
|
||
- name: Install Python dependencies | ||
run: | | ||
pip3 install -r scripts/tests/avh/requirements.txt | ||
- name: Run end to end test | ||
run: | | ||
cd scripts/tests/avh | ||
python3 -u -m unittest test_lighting_app.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
avh-api | ||
paramiko |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Arm Virtual Hardware (AVH) based tests | ||
|
||
This folder contains end to end tests that use the | ||
[Arm Virtual Hardware (AVH)](https://www.arm.com/products/development-tools/simulation/virtual-hardware) | ||
service. | ||
|
||
The tests require the `AVH_API_TOKEN` environment variable is set with the value | ||
from `AVH -> Profile -> API -> API Token`. | ||
|
||
## Current tests | ||
|
||
- [`test_lighting_app.py`](test_lighting_app.py) | ||
- This test uses two virtual Raspberry Pi Model 4 boards running Ubuntu | ||
Server 22.04 and pre-built `chip-tool` and `chip-lighting-app` binaries | ||
(`linux-arm64`), and tests commissioning and control over BLE and Wi-Fi | ||
using the virtual Bluetooth and Wi-Fi network features of AVH. | ||
|
||
## Running the tests | ||
|
||
1. Install dependencies | ||
|
||
``` | ||
pip3 install -r requirements.txt | ||
``` | ||
|
||
2. Set AVH_API_TOKEN` environment variable | ||
|
||
``` | ||
export AVH_API_TOKEN=<AVH API TOKEN value> | ||
``` | ||
|
||
3. Place cross-compiled `chip-tool` and `lighting-app` binaries in `out` folder | ||
|
||
4. Run | ||
|
||
``` | ||
python3 -u -m unittest test_lighting_app.py | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# Copyright (c) 2022 Project CHIP Authors | ||
# | ||
# 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. | ||
|
||
from datetime import datetime | ||
|
||
from .avh_instance import AvhInstance | ||
|
||
APPLICATION_BINARY = "chip-tool" | ||
|
||
|
||
class AvhChiptoolInstance(AvhInstance): | ||
def __init__(self, avh_client, name, application_binary_path): | ||
super().__init__(avh_client, name) | ||
|
||
self.application_binary_path = application_binary_path | ||
|
||
def upload_application_binary(self): | ||
super().upload_application_binary( | ||
self.application_binary_path, APPLICATION_BINARY | ||
) | ||
|
||
def configure_system(self): | ||
self.log_in_to_console() | ||
|
||
# set current date and time | ||
self.console_exec_command("sudo timedatectl set-ntp false", timeout=300) | ||
self.console_exec_command( | ||
f"sudo timedatectl set-time '{datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}'", | ||
timeout=300, | ||
) | ||
self.console_exec_command("sudo timedatectl set-ntp true", timeout=300) | ||
|
||
# install network manager | ||
self.console_exec_command("sudo apt-get update", timeout=300) | ||
self.console_exec_command( | ||
"sudo apt-get -y install network-manager", timeout=300 | ||
) | ||
|
||
# connect Wi-Fi to the Arm ssid | ||
self.console_exec_command("sudo nmcli r wifi on") | ||
self.console_exec_command("sudo nmcli d wifi connect Arm password password") | ||
|
||
# disable eth0 | ||
self.console_exec_command("sudo nmcli dev set eth0 managed no") | ||
self.console_exec_command("sudo ip link set dev eth0 down") | ||
|
||
def pairing_ble_wifi(self, node_id, ssid, password, pin_code, discriminator): | ||
output = self.console_exec_command( | ||
f"./{APPLICATION_BINARY} pairing ble-wifi {node_id} {ssid} {password} {pin_code} {discriminator}", | ||
timeout=120.0, | ||
) | ||
|
||
return output | ||
|
||
def on(self, node_id): | ||
output = self.console_exec_command( | ||
f"./{APPLICATION_BINARY} onoff on {node_id} 1", timeout=30.0 | ||
) | ||
|
||
return output | ||
|
||
def off(self, node_id): | ||
output = self.console_exec_command( | ||
f"./{APPLICATION_BINARY} onoff off {node_id} 1", timeout=30.0 | ||
) | ||
|
||
return output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Copyright (c) 2022 Project CHIP Authors | ||
# | ||
# 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 uuid | ||
|
||
from avh_api import ApiClient as AvhApiClient | ||
from avh_api import Configuration as AvhApiConfiguration | ||
from avh_api.api.arm_api import ArmApi as AvhApi | ||
from avh_api.model.project_key import ProjectKey as AvhProjectKey | ||
|
||
|
||
class AvhClient: | ||
def __init__(self, api_token, api_endpoint=None): | ||
avh_api_config = AvhApiConfiguration(host=api_endpoint) | ||
self.avh_api_client = AvhApiClient(avh_api_config) | ||
|
||
self.avh_api = AvhApi(self.avh_api_client) | ||
|
||
avh_api_config.access_token = self.avh_api.v1_auth_login( | ||
{"api_token": api_token} | ||
).token | ||
|
||
self.default_project_id = self.avh_api.v1_get_projects()[0]["id"] | ||
|
||
def create_project(self, name, num_cores): | ||
return self.avh_api.v1_create_project( | ||
{ | ||
"id": str(uuid.uuid4()), | ||
"name": name, | ||
"settings": { | ||
"internet_access": True, | ||
"dhcp": True, | ||
}, | ||
"quotas": {"cores": num_cores}, | ||
} | ||
)["id"] | ||
|
||
def delete_project(self, id): | ||
self.avh_api.v1_delete_project(id) | ||
|
||
def create_instance(self, name, flavor, os, osbuild): | ||
return self.avh_api.v1_create_instance( | ||
{ | ||
"name": name, | ||
"project": self.default_project_id, | ||
"flavor": flavor, | ||
"os": os, | ||
"osbuild": osbuild, | ||
} | ||
)["id"] | ||
|
||
def instance_state(self, instance_id): | ||
return str(self.avh_api.v1_get_instance_state(instance_id)) | ||
|
||
def instance_console_log(self, instance_id): | ||
return self.avh_api.v1_get_instance_console_log(instance_id) | ||
|
||
def instance_quick_connect_command(self, instance_id): | ||
return self.avh_api.v1_get_instance_quick_connect_command(instance_id) | ||
|
||
def create_ssh_project_key(self, label, key): | ||
return self.avh_api.v1_add_project_key( | ||
self.default_project_id, | ||
AvhProjectKey(kind="ssh", key=key, label=label), | ||
)["identifier"] | ||
|
||
def instance_console_url(self, instance_id): | ||
return self.avh_api.v1_get_instance_console(instance_id).url | ||
|
||
def delete_ssh_project_key(self, key_id): | ||
self.avh_api.v1_remove_project_key(self.default_project_id, key_id) | ||
|
||
def delete_instance(self, instance_id): | ||
self.avh_api.v1_delete_instance(instance_id) | ||
|
||
def close(self): | ||
self.avh_api_client.rest_client.pool_manager.clear() | ||
self.avh_api_client.close() |
Oops, something went wrong.