diff options
-rw-r--r-- | .github/workflows/run-tests.yml | 179 | ||||
-rw-r--r-- | tests/accel-pppd/test_vlan_mon_driver.py | 1 | ||||
-rw-r--r-- | tests/common/iface.py | 23 | ||||
-rw-r--r-- | tests/common/veth.py | 55 |
4 files changed, 228 insertions, 30 deletions
diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index dfa637c2..f9cf1b84 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -8,7 +8,180 @@ on: - master jobs: - Build-and-Test: + Test-in-Qemu: + #if: ${{ false }} # disable for now + runs-on: ubuntu-latest + name: Test in Qemu (${{ matrix.distro }}) + strategy: + fail-fast: false + matrix: + include: + - distro: Ubuntu-22.04 + image: https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img + untar: false + format: qcow2 + + - distro: Ubuntu-20.04 + image: https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img + untar: false + format: qcow2 + + - distro: Ubuntu-18.04 + image: https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img + untar: false + format: qcow2 + + - distro: Debian12 + image: https://cloud.debian.org/images/cloud/bookworm/daily/latest/debian-12-generic-amd64-daily.tar.xz + untar: true + format: raw + + - distro: Debian11 + image: https://cdimage.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.tar.xz + untar: true + format: raw + + - distro: Debian10 + image: https://cloud.debian.org/images/cloud/buster/latest/debian-10-generic-amd64.tar.xz + untar: true + format: raw + + steps: + - name: Check out repository code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + path: "accel-ppp" + - name: Install qemu and required tools + run: > + sudo apt update && + sudo apt -y install qemu-system-x86 qemu-utils cloud-image-utils cpu-checker cloud-image-utils wget openssh-client screen + - name: Check kvm support (fail is ok) + run: sudo kvm-ok || exit 0 + - name: Prepare cloud-init image disk + run: | + ssh-keygen -t ed25519 -q -N "" -f ssh-key + echo "instance-id: $(uuidgen || echo i-abcdefg)" > init-meta + echo "#cloud-config" > init-data + echo "package_update: true" >> init-data + echo "package_upgrade: true" >> init-data + echo "package_reboot_if_required: false" >> init-data + echo "users:" >> init-data + echo " - default" >> init-data + echo " - name: user" >> init-data + echo " shell: /bin/bash" >> init-data + echo " sudo: ALL=(ALL) NOPASSWD:ALL" >> init-data + echo " ssh_authorized_keys:" >> init-data + echo " - "`cat ssh-key.pub` >> init-data + echo "power_state:">> init-data + echo " mode: poweroff">> init-data + cat init-data + cloud-localds init.img init-data init-meta + - name: Download, unpack and resize target OS cloud image + if: ${{ matrix.untar }} + run: | + wget -nv ${{ matrix.image }} + mkdir img + tar -xf *.tar.xz -C img + qemu-img resize -f ${{ matrix.format }} img/`ls -1 img` +2G + - name: Download and resize target OS cloud image + if: ${{ !matrix.untar }} + run: | + mkdir img + wget -nv ${{ matrix.image }} -O img/image + qemu-img resize -f ${{ matrix.format }} img/`ls -1 img` +2G + - name: Run target OS first time (for cloud-init actions) + run: sudo qemu-system-x86_64 -m 4096 -nographic -drive format=${{ matrix.format }},file=img/`ls -1 img` -drive format=raw,file=init.img + - name: Run target OS + run: sudo screen -dmS qemu qemu-system-x86_64 -net nic -net user,hostfwd=tcp::2222-:22 -m 4096 -nographic -drive format=${{ matrix.format }},file=img/`ls -1 img` + - name: Check that target OS is running + run: | + sleep 1 + sudo screen -ls + - name: Wait for ssh connection + timeout-minutes: 30 + run: > + while ! ssh -o StrictHostKeyChecking=accept-new -p2222 -o ConnectTimeout=5 -i ssh-key user@localhost "exit 0"; + do + echo "Trying to establish ssh connection"; + sleep 5; + done; + cat ~/.ssh/known_hosts + - name: Display free space, current dir, kernel version and test sudo + run: | + ssh -i ssh-key -p2222 user@localhost "df -h" + ssh -i ssh-key -p2222 user@localhost "pwd" + ssh -i ssh-key -p2222 user@localhost "uname -a" + ssh -i ssh-key -p2222 user@localhost "sudo cat /etc/passwd" + - name: Install build tools (on target OS) + run: > + ssh -i ssh-key -p2222 user@localhost "sudo apt -y install + git build-essential cmake gcc linux-headers-\`uname -r\` + libpcre3-dev libssl-dev liblua5.1-0-dev kmod python3-pip + iproute2 ppp pppoe isc-dhcp-client timelimit && + sudo pip3 install pytest pytest-dependency gcovr" + - name: Copy source code to target OS + run: | + tar -Jcf accel-ppp.tar.xz accel-ppp + scp -i ssh-key -P2222 accel-ppp.tar.xz user@localhost: + ssh -i ssh-key -p2222 user@localhost "tar -xf accel-ppp.tar.xz" + - name: Build accel-ppp + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp && + mkdir build && cd build && + cmake -DBUILD_IPOE_DRIVER=TRUE -DBUILD_VLAN_MON_DRIVER=TRUE -DCMAKE_INSTALL_PREFIX=/usr + -DKDIR=/usr/src/linux-headers-\`uname -r\` + -DLUA=TRUE -DSHAPER=TRUE -DRADIUS=TRUE .. && + make && sudo make install" + + - name: Run tests (not related to ipoe and vlan_mon drivers) + timeout-minutes: 5 + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp/tests && + sudo python3 -m pytest -Wall -v -m \"not ipoe_driver and not vlan_mon_driver\"" + - name: Display processes and dmesg after tests + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "ps aux | grep accel- && + sudo dmesg" + + - name: Insert ipoe kernel module + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp && + sudo insmod build/drivers/ipoe/driver/ipoe.ko && + lsmod | grep ipoe " + + - name: Run tests (not related to vlan_mon drivers) + timeout-minutes: 5 + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp/tests && + sudo python3 -m pytest -Wall -v -m \"not vlan_mon_driver\"" + - name: Display processes and dmesg after tests + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "ps aux | grep accel- && + sudo dmesg" + + - name: Insert vlan_mon kernel module + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp && + sudo insmod build/drivers/vlan_mon/driver/vlan_mon.ko && + lsmod | grep vlan_mon" + + - name: Run tests (all) + timeout-minutes: 5 + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "cd accel-ppp/tests && + sudo python3 -m pytest -Wall -v" + - name: Display processes and dmesg after tests + if: ${{ always() }} + run: > + ssh -i ssh-key -p2222 user@localhost "ps aux | grep accel- && + sudo dmesg" + + Test-in-GH: #if: ${{ false }} # disable for now strategy: fail-fast: false @@ -56,10 +229,11 @@ jobs: lsmod | grep vlan_mon - name: Run tests + timeout-minutes: 5 working-directory: ./tests run: sudo python3 -m pytest -Wall -v - Build-and-Test-With-Coverage: + Test-in-GH-Coverage: #if: ${{ false }} # disable for now strategy: fail-fast: false @@ -108,6 +282,7 @@ jobs: lsmod | grep vlan_mon - name: Run tests (for coverage report) (fail is ok) + timeout-minutes: 5 working-directory: ./tests run: sudo python3 -m pytest -Wall -v || exit 0 diff --git a/tests/accel-pppd/test_vlan_mon_driver.py b/tests/accel-pppd/test_vlan_mon_driver.py index 3e937f83..a230c7c8 100644 --- a/tests/accel-pppd/test_vlan_mon_driver.py +++ b/tests/accel-pppd/test_vlan_mon_driver.py @@ -3,5 +3,6 @@ import os # test that vlan_mon kernel module is loaded @pytest.mark.dependency(name = 'vlan_mon_driver_loaded', scope = 'session') +@pytest.mark.vlan_mon_driver def test_vlan_mon_kernel_module_loaded(): assert os.path.isdir("/sys/module/vlan_mon")
\ No newline at end of file diff --git a/tests/common/iface.py b/tests/common/iface.py new file mode 100644 index 00000000..dbd052ab --- /dev/null +++ b/tests/common/iface.py @@ -0,0 +1,23 @@ +from common import netns + +# up interface. if netns is None, then up in global rt. if ok returns 0 +def up(iface, netns_name): + command = ["ip", "link", "set", iface, "up"] + exit, out, err = netns.exec(netns_name, command) + print( + "iface.up: iface=%s netns=%s exit=%d out=%s err=%s" + % (iface, netns_name, exit, out, err) + ) + + return exit + + +# delete interface. if netns is None, then up in global rt. if ok returns 0 +def delete(iface, netns_name): + exit, out, err = netns.exec(netns_name, ["ip", "link", "delete", iface]) + print( + "iface.delete: iface=%s netns=%s exit=%d out=%s err=%s" + % (iface, netns_name, exit, out, err) + ) + + return exit diff --git a/tests/common/veth.py b/tests/common/veth.py index a31d2453..c9d3006c 100644 --- a/tests/common/veth.py +++ b/tests/common/veth.py @@ -1,4 +1,4 @@ -from common import process, netns, vlan +from common import process, netns, vlan, iface import time import math @@ -12,14 +12,6 @@ def create_pair(name_a, name_b): return veth -# deletes veth pair. if ok returns 0 -def delete_veth(name_a): - veth, out, err = process.run(["ip", "link", "delete", name_a]) - print("veth.delete: exit=%d out=%s err=%s" % (veth, out, err)) - - return veth - - # put veth to netns. if ok returns 0 def assign_netns(veth, netns): veth, out, err = process.run(["ip", "link", "set", veth, "netns", netns]) @@ -28,18 +20,6 @@ def assign_netns(veth, netns): return veth -# up interface. if netns is None, then up in global rt. if ok returns 0 -def up_interface(iface, netns_name): - command = ["ip", "link", "set", iface, "up"] - exit, out, err = netns.exec(netns_name, command) - print( - "veth.up_interface: iface=%s netns=%s exit=%d out=%s err=%s" - % (iface, str(netns_name), exit, out, err) - ) - - return exit - - # creates netns, creates veth pair and place second link to netns # creates vlans over veth interfaces according to veth_pair_vlans_config # return dict with 'netns', 'veth_a', 'veth_b' @@ -55,30 +35,49 @@ def create_veth_pair_netns(veth_pair_vlans_config): pair_status = create_pair(veth_a, veth_b) print("create_veth_pair_netns: pair_status=%d" % pair_status) - up_interface(veth_a, None) + iface.up(veth_a, None) assign_status = assign_netns(veth_b, netns_name) print("create_veth_pair_netns: assign_status=%d" % assign_status) - up_interface(veth_b, netns_name) + iface.up(veth_b, netns_name) vlans_a = veth_pair_vlans_config["vlans_a"] for vlan_num in vlans_a: vlan.create(veth_a, vlan_num, None) - up_interface(veth_a + "." + str(vlan_num), None) + iface.up(veth_a + "." + str(vlan_num), None) vlans_b = veth_pair_vlans_config["vlans_b"] for vlan_num in vlans_b: vlan.create(veth_b, vlan_num, netns_name) - up_interface(veth_b + "." + str(vlan_num), netns_name) + iface.up(veth_b + "." + str(vlan_num), netns_name) - return {"netns": netns_name, "veth_a": veth_a, "veth_b": veth_b} + return { + "netns": netns_name, + "veth_a": veth_a, + "veth_b": veth_b, + "vlans_a": vlans_a, + "vlans_b": vlans_b, + } # deletes veth pair and netns created by create_veth_pair_netns def delete_veth_pair_netns(veth_pair_netns): - veth_status = delete_veth(veth_pair_netns["veth_a"]) + + vlans_a = veth_pair_netns["vlans_a"] + veth_a = veth_pair_netns["veth_a"] + vlans_b = veth_pair_netns["vlans_b"] + veth_b = veth_pair_netns["veth_b"] + netns_name = veth_pair_netns["netns"] + + # remove vlans on top of veth interface + for vlan_num in vlans_a: + iface.delete(veth_a + "." + str(vlan_num), None) + for vlan_num in vlans_b: + iface.delete(veth_b + "." + str(vlan_num), netns_name) + + veth_status = iface.delete(veth_a, None) print("delete_veth_pair_netns: veth_status=%d" % veth_status) - netns_status = netns.delete(veth_pair_netns["netns"]) + netns_status = netns.delete(netns_name) print("delete_veth_pair_netns: netns_status=%d" % netns_status) |