diff --git a/ansible/roles/vm_set/library/vm_topology.py b/ansible/roles/vm_set/library/vm_topology.py index 00f6799fae7..ee3ee2a87cf 100644 --- a/ansible/roles/vm_set/library/vm_topology.py +++ b/ansible/roles/vm_set/library/vm_topology.py @@ -116,7 +116,6 @@ cmd_debug_fname = None - class HostInterfaces(object): """Data descriptor that supports multi-DUTs interface definition.""" diff --git a/ansible/roles/vm_set/tasks/add_topo.yml b/ansible/roles/vm_set/tasks/add_topo.yml index 441e96a39f6..e2b9b5ae4e0 100644 --- a/ansible/roles/vm_set/tasks/add_topo.yml +++ b/ansible/roles/vm_set/tasks/add_topo.yml @@ -19,6 +19,11 @@ container_type: "API-SERVER" when: ptf_imagename is defined and ptf_imagename == "docker-keysight-api-server" +- name: set "IxANVL-CONF-TESTER" container type if Keysight IxANVL is used + set_fact: + container_type: "IxANVL-CONF-TESTER" + when: ptf_imagename is defined and ptf_imagename == "docker-ptf-anvl" + - name: Try to login into docker registry docker_login: registry_url: "{{ docker_registry_host }}" @@ -54,6 +59,56 @@ become: yes when: container_type == "API-SERVER" +- name: Start Keysight IxANVL container + block: + - name: Pull and start Keysight IxANVL container + docker_container: + name: ptf_anvl + image: "{{ docker_registry_host }}/{{ ptf_imagename }}:{{ ptf_imagetag }}" + pull: yes + state: started + restart: no + detach: True + network_mode: none + capabilities: + - net_admin + privileged: yes + become: yes + + - name: Get dut ports + include_tasks: get_dut_port.yml + loop: "{{ duts_name.split(',') }}" + loop_control: + loop_var: dut_name + + - name: Create vlan ports for dut + include_tasks: create_dut_port.yml + when: external_port is defined + loop: "{{ duts_name.split(',') }}" + loop_control: + loop_var: dut_name + + - name: Bind topology {{ topo }} to VMs. base vm = {{ VM_base }} + vm_topology: + cmd: "bind" + vm_names: "" + vm_set_name: "{{ vm_set_name }}" + topo: "{{ topology }}" + ptf_mgmt_ip_addr: "{{ ptf_ip }}" + ptf_mgmt_ipv6_addr: "{{ ptf_ipv6 }}" + ptf_mgmt_ip_gw: "{{ mgmt_gw }}" + ptf_mgmt_ipv6_gw: "{{ mgmt_gw_v6 | default(None) }}" + ptf_bp_ip_addr: "{{ ptf_bp_ip }}" + ptf_bp_ipv6_addr: "{{ ptf_bp_ipv6 }}" + mgmt_bridge: "{{ mgmt_bridge }}" + duts_fp_ports: "{{ duts_fp_ports }}" + duts_mgmt_port: "{{ duts_mgmt_port }}" + duts_name: "{{ duts_name.split(',') }}" + fp_mtu: "{{ fp_mtu_size }}" + max_fp_num: "{{ max_fp_num }}" + become: yes + + when: container_type == "IxANVL-CONF-TESTER" - name: Start PTF container block: diff --git a/ansible/roles/vm_set/tasks/main.yml b/ansible/roles/vm_set/tasks/main.yml index fe137207de2..8ad204fb04f 100644 --- a/ansible/roles/vm_set/tasks/main.yml +++ b/ansible/roles/vm_set/tasks/main.yml @@ -183,6 +183,13 @@ - ptf_imagename is defined - ptf_imagename == "docker-keysight-api-server" +- name: VMs not needed in case of Keysight IxANVL + set_fact: + veos_vm_required: false + when: + - ptf_imagename is defined + - ptf_imagename == "docker-ptf-anvl" + - name: Retrieve a list of the defined VMs virt: command=list_vms uri=qemu:///system diff --git a/ansible/roles/vm_set/tasks/remove_topo.yml b/ansible/roles/vm_set/tasks/remove_topo.yml index 1f2088822ae..56259aae71a 100644 --- a/ansible/roles/vm_set/tasks/remove_topo.yml +++ b/ansible/roles/vm_set/tasks/remove_topo.yml @@ -7,6 +7,11 @@ container_type: "API-SERVER" when: ptf_imagename is defined and ptf_imagename == "docker-keysight-api-server" +- name: set "IxANVL-CONF-TESTER" container type if Keysight IxANVL is used + set_fact: + container_type: "IxANVL-CONF-TESTER" + when: ptf_imagename is defined and ptf_imagename == "docker-ptf-anvl" + - block: - name: Stop mux simulator @@ -61,3 +66,36 @@ become: yes when: container_type == "API-SERVER" +- block: + - name: Get dut ports + include_tasks: get_dut_port.yml + loop: "{{ duts_name.split(',') }}" + loop_control: + loop_var: dut_name + + - name: Unbind topology {{ topo }} for Keysight IxANVL. + vm_topology: + cmd: "unbind" + vm_names: "" + vm_set_name: "{{ vm_set_name }}" + topo: "{{ topology }}" + duts_fp_ports: "{{ duts_fp_ports }}" + duts_mgmt_port: "{{ duts_mgmt_port }}" + duts_name: "{{ duts_name.split(',') }}" + max_fp_num: "{{ max_fp_num }}" + become: yes + + - name: Remove duts ports + include_tasks: remove_dut_port.yml + when: external_port is defined + loop: "{{ duts_name.split(',') }}" + loop_control: + loop_var: dut_name + + - name: Remove Keysight IxANVL container + docker_container: + name: ptf_anvl + state: absent + become: yes + + when: container_type == "IxANVL-CONF-TESTER" diff --git a/ansible/testbed.csv b/ansible/testbed.csv index 53723f7746d..2a9dcf27e55 100644 --- a/ansible/testbed.csv +++ b/ansible/testbed.csv @@ -11,3 +11,4 @@ vms-s6100-t1,vms4-1,t1-64,docker-ptf,ptf-unknown,10.255.0.182/24,,server_1,VM010 vms-s6100-t1-lag,vms5-1,t1-64-lag,docker-ptf,ptf-unknown,10.255.0.183/24,,server_1,VM0100,lab-s6100-01,lab,True,ests Dell S6100 vms vms-multi-dut,vms1-duts,ptf64,docker-ptf,ptf-unknown,10.255.0.184/24,,server_1,VM0100,[dut-host1;dut-host2],lab,True,Example Multi DUTs testbed vms-example-ixia-1,vms6-1,t0-64,docker-ptf-ixia,example-ixia-ptf-1,10.0.0.30/32,,server_6,VM0600,example-s6100-dut-1,lab,True,superman +ixanvl-vs-conf,anvl,ptf32,docker-ptf-anvl,ptf-unknown,10.250.0.100/24,,server_1,,vlab-01,lab,True,Test ptf ANVL SONIC VM diff --git a/ansible/testbed.yaml b/ansible/testbed.yaml index 4670834ec5e..c6278a07ec6 100644 --- a/ansible/testbed.yaml +++ b/ansible/testbed.yaml @@ -156,3 +156,16 @@ dut: - example-s6100-dut-1 comment: superman + +- conf-name: ixanvl-vs-conf + group-name: anvl + topo: ptf32 + ptf_image_name: docker-ptf-anvl + ptf: ptf-unknown + ptf_ip: 10.250.0.100/24 + ptf_ipv6: + server: server_1 + vm_base: + dut: + - vlab-01 + comment: Test ptf ANVL SONIC VM diff --git a/docs/testbed/README.testbed.IxANVL.VsSetup.md b/docs/testbed/README.testbed.IxANVL.VsSetup.md new file mode 100644 index 00000000000..6d69143df57 --- /dev/null +++ b/docs/testbed/README.testbed.IxANVL.VsSetup.md @@ -0,0 +1,170 @@ +# Testbed Setup with Keysight IxANVL container and SONIC Virtual DUT + + This document describes the steps to setup a testbed with Keysight IxANVL container and SONIC Virtual DUT to run BGP conformance test cases. + + ### Testbed server + The schematic diagram below provides an overview of the setup. + ![](img\keysight_ixanvl_testbed_topology.png) + + ### Network connections + - The testbed server has 1 network port: + - A management port to manage the server, IxANVL container, sonic-mgmt container running on the server. + + ### Prepare testbed server + + - If the testbed host is a VM, then it must support nested virtualization + - [Instructions for Hyper-V based VMs](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization#configure-nested-virtualization) + - Python version should be atleast `2.7.17`. + - Install docker as below. The docker here is needed to run the sonic-mgmt container. + + ```shell + $ wget -O get-docker.sh https://get.docker.com/ + + $ sudo ./get-docker.sh + ``` + - [Install Docker CE](https://docs.docker.com/install/linux/docker-ce/ubuntu/). + - Be sure to follow the [post-install instructions](https://docs.docker.com/install/linux/linux-postinstall/) so that you don't need sudo privileges to run docker commands. + - Run the host setup script to install required packages and initialize the management bridge network + + ``` + git clone https://github.com/Azure/sonic-mgmt + cd sonic-mgmt/ansible + sudo ./setup-management-network.sh + ``` + + **NOTE** setup-management-network.sh can fail on a check of br1 exists or not. In that case you can modify the script and comment out if checks of line 45 and line 49 until the issue is fixed. + + This step creates a bridge interface called 'br1' in your host. It is the management bridge of the topology that is to be deployed. + To access outside networks other than management network run the below script. The access to the outside network may be needed in case any host outside the testbed is used to activate the licenses needed to run IxANVL. That host will then become the License Server for the IxANVL application. + + ``` + cd sonic-mgmt/ansible + sudo ./setup-br1-nat.sh (external-iface-host can be any interface which connects to other networks. Mostly this is the LAN interface of the host.) + ``` + + - Download Keysight IxANVL container image from the below location + - [IxANVL](https://downloads.ixiacom.com/support/downloads_and_updates/eb/1558879/anvl_docker_image.tar). The path is not of ixia webserver as IxANVL container is not released yet. Once released the path will be properly updated. + + Downloaded files would be like below - + - `anvl_docker_image.tar` + + - Place the downloaded file in a folder say `~/keysight_images`. + Setup a local docker registry for IxANVL container image. + > **Note** If you load the *IxANVL* docker image in your docker registry then you need not place `anvl_container.tar` inside the `~/keysight_images` folder. In that case you need to consider the `docker_registry_host` in `ansible/vars/docker_registry.yml` file. If local file is used it will not pull from the docker registry. + > **Note** For setting up local docker registry please follow the instructions from the link: (https://docs.docker.com/registry/deploying/) + To setup local docker registry in docker host below are the commands that need to be run: + + ``` + $ docker image load < anvl_docker_image.tar + $ docker run -d -p 5000:5000 --restart=always --name registry registry:2 + $ docker tag anvl_container:latest localhost:5000/docker-ptf-anvl + $ docker push localhost:5000/docker-ptf-anvl + + ``` + docker-ptf-anvl is the ptf-imagename in testbed.csv in sonic-mgmt/ansible + + - Download the sonic-vs image + To run the tests with a virtual SONiC device, we need a virtual SONiC image. The simplest way to do so is to download a public build from Jenkins. + + - Download the sonic-vs image from [here](https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-image/lastSuccessfulBuild/artifact/target/sonic-vs.img.gz) + + ``` + $ wget https://sonic-jenkins.westus2.cloudapp.azure.com/job/vs/job/buildimage-vs-image/lastSuccessfulBuild/artifact/target/sonic-vs.img.gz + ``` + + - Unzip the image and move it into `~/sonic-vm/images/` + + ``` + $ gzip -d sonic-vs.img.gz + $ mkdir -p ~/sonic-vm/images + $ mv sonic-vs.img ~/sonic-vm/images + ``` + - Setup sonic-mgmt docker + All testbed configuration steps and tests are run from a `sonic-mgmt` docker container. This container has all the necessary packages and tools for SONiC testing so that test behavior is consistent between different developers and lab setups. + + Run the `setup-container.sh` in the root directory of the sonic-mgmt repository: + + ``` + $ cd sonic-mgmt + $ ./setup-container.sh -n -d /data + ``` + + From now on, **all steps are running inside the sonic-mgmt docker**, unless otherwise specified. + + + You can enter your sonic-mgmt container with the following command: + + ``` + $ docker exec -it bash + ``` + + You will find your sonic-mgmt directory mounted at `/data/sonic-mgmt`: + + ``` + $ ls /data/sonic-mgmt/ + LICENSE README.md __pycache__ ansible docs lgtm.yml setup-container.sh spytest test_reporting tests + ``` + + - Setup host public key in sonic-mgmt docker + In order to configure the testbed on your host automatically, Ansible needs to be able to SSH into it without a password prompt. The `setup-container` script from the previous step will setup all the necessary SSH keys for you, but there are a few more modifications needed to make Ansible work: + + Modify `veos_vtb` to use the user name and password (e.g. `foo`) you want to use to login to the host machine (this can be your username on the host) + + ``` + foo@sonic:/data/sonic-mgmt/ansible$ git diff + diff --git a/ansible/veos_vtb b/ansible/veos_vtb + index 3e7b3c4e..edabfc40 100644 + --- a/ansible/veos_vtb + +++ b/ansible/veos_vtb + @@ -73,7 +73,7 @@ vm_host_1: + hosts: + STR-ACS-VSERV-01: + ansible_host: 172.17.0.1 + - ansible_user: use_own_value + + ansible_user: foo + + ansible_password: foo + + vms_1: + hosts: + ``` + + Create a dummy `password.txt` file under `/data/sonic-mgmt/ansible` + - **Note**: Here, `password.txt` is the Ansible Vault password file. Ansible allows users to use Ansible Vault to encrypt password files. + + By default, the testbed scripts require a password file. If you are not using Ansible Vault, you can create a file with a dummy password (e.g. `abc`) and pass the filename to the command line. The file name and location is created and maintained by the user. + + **On the host,** after doing ssh from sonic-mgmt container, run `sudo visudo` and add the following line at the end: + + ``` + foo ALL=(ALL) NOPASSWD:ALL + ``` + + Verify that you can login into the host (e.g. `ssh foo@172.17.0.1`) from the `sonic-mgmt` container without any password prompt. + + Verify that you can use `sudo` without a password prompt inside the host (e.g. `sudo bash`). + + - Deploy PTF32 topology + Now we're finally ready to deploy the topology for our testbed! Run the following command: + + ``` + $ cd /data/sonic-mgmt/ansible + $ ./testbed-cli.sh -t testbed.csv -m veos_vtb add-topo ixanvl-vs-conf password.txt + ``` + - Verify that you can login to the SONiC KVM using Mgmt IP = 10.250.0.101 and admin:password. + + ### Run a Pytest + Now that the testbed has been fully setup and configured, let's run a simple test to make sure everything is functioning as expected. + + - Switch over to the `tests` directory: + + ``` + cd sonic-mgmt/tests + ``` + + - Run the following command to execute the `bgp_fact` test (including the pre/post setup steps): + + ``` + ./run_tests.sh -n ixanvl-vs-conf -d vlab01 -c ixia/ixanvl/test_anvl_run.py -f ../ansible/testbed.csv -i veos_vtb + ``` + + You should see 1 set of tests run and pass. You're now set up and ready to use the IxANVL testbed! diff --git a/docs/testbed/img/keysight_ixanvl_testbed_topology.png b/docs/testbed/img/keysight_ixanvl_testbed_topology.png new file mode 100644 index 00000000000..f5f8160b3bb Binary files /dev/null and b/docs/testbed/img/keysight_ixanvl_testbed_topology.png differ diff --git a/tests/conftest.py b/tests/conftest.py index 55f959c1169..afd2c7c4245 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -93,6 +93,10 @@ def pytest_addoption(parser): help="Deep clean DUT before tests (remove old logs, cores, dumps)") parser.addoption("--py_saithrift_url", action="store", default=None, type=str, help="Specify the url of the saithrift package to be installed on the ptf (should be http:///path/python-saithrift_0.9.4_amd64.deb") + ############################ + # keysight ixanvl options # + ############################ + parser.addoption("--testnum", action="store", default=None, type=str) @pytest.fixture(scope="session", autouse=True) diff --git a/tests/ixia/ixanvl/__init__.py b/tests/ixia/ixanvl/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ixia/ixanvl/test_bgp_conformance.py b/tests/ixia/ixanvl/test_bgp_conformance.py new file mode 100644 index 00000000000..32b620af03a --- /dev/null +++ b/tests/ixia/ixanvl/test_bgp_conformance.py @@ -0,0 +1,68 @@ +import logging +import time +import paramiko +import sys +import pytest +import re + +from tests.common.reboot import logger +from tests.common.fixtures.conn_graph_facts import conn_graph_facts + +from tests.common.helpers.assertions import pytest_assert + +from scp import SCPClient, SCPException + +from tests.common.utilities import wait_tcp_connection + +pytestmark = [pytest.mark.disable_loganalyzer] + +@pytest.fixture() +def testnum(pytestconfig): + return pytestconfig.getoption("testnum") + +def test_anvl_bgp_run(duthost, + ptfhost, + testnum): + """ + 1. ANVL run. + """ + + + ptfip = ptfhost.host.options['inventory_manager'].get_host(ptfhost.hostname).vars['ansible_host'] + + ptfuser = ptfhost.host.options['inventory_manager'].get_host(ptfhost.hostname).vars['ansible_user'] + ptfpass = ptfhost.host.options['inventory_manager'].get_host(ptfhost.hostname).vars['ansible_password'] + + logging.info("ixanvl container ip=%s" % ptfip) + logging.info("ixanvl container ip=%s" % ptfuser) + logging.info("ixanvl container ip=%s" % ptfpass) + + testnumber = testnum + logging.info("run anvl with static configuration") + ixanvl_tester=paramiko.SSHClient() + ##Add missing client key + ixanvl_tester.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ##connect to ptf + ixanvl_tester.connect(ptfip,username=ptfuser,password=ptfpass) + logging.info("SSH connection to %s established" % ptfip) + + + scp = SCPClient(ixanvl_tester.get_transport()) + + ##Gather commands and read the output from stdout + if not testnumber: + logging.info("================= Running ANVL BGP Full Suite ===============\n") + command_str = "cd /opt/Ixia/IxANVL && ./anvl -l l -f DocUser/anvlbgp4 bgp4 | tee bgp4.log\n" + else: + logging.info("================= Running ANVL BGP Test Case %s ===============\n" % testnumber) + command_str = "cd /opt/Ixia/IxANVL && ./anvl -l l -f DocUser/anvlbgp4 bgp4 " + testnumber + " | tee bgp4.log\n" + + stdin, stdout, stderr = ixanvl_tester.exec_command(command_str) + + for line in stdout: + logging.info(line) + + stdout.channel.recv_exit_status() + scp.get('/opt/Ixia/IxANVL/bgp4.log') + + ixanvl_tester.close()