From 5f9ef0f2da44a7158b4f9b4868fa01e45e54285a Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Wed, 25 Mar 2020 08:59:12 +0000 Subject: [PATCH] Convert vxlan-decap testing to pytest Signed-off-by: Xin Wang --- ansible/roles/test/tasks/vxlan-decap.yml | 119 +------------- .../test/templates/vxlan_db.maps.json.j2 | 9 -- .../test/templates/vxlan_db.tunnel.json.j2 | 8 - .../roles/test/templates/vxlan_decap.json.j2 | 9 -- tests/test_vxlan_decap.py | 149 ++++++++++++++++++ 5 files changed, 153 insertions(+), 141 deletions(-) delete mode 100644 ansible/roles/test/templates/vxlan_db.maps.json.j2 delete mode 100644 ansible/roles/test/templates/vxlan_db.tunnel.json.j2 delete mode 100644 ansible/roles/test/templates/vxlan_decap.json.j2 create mode 100644 tests/test_vxlan_decap.py diff --git a/ansible/roles/test/tasks/vxlan-decap.yml b/ansible/roles/test/tasks/vxlan-decap.yml index 937182aa51..532dd23cab 100644 --- a/ansible/roles/test/tasks/vxlan-decap.yml +++ b/ansible/roles/test/tasks/vxlan-decap.yml @@ -1,115 +1,4 @@ -# example - -- block: - - fail: msg="Please set ptf_host variable" - when: ptf_host is not defined - - - name: Remove existing ip from ptf host - script: roles/test/files/helpers/remove_ip.sh - delegate_to: "{{ ptf_host }}" - - - name: Make all mac addresses in ptf unique - should be done in vm_set - script: roles/test/files/helpers/change_mac.sh - delegate_to: "{{ ptf_host }}" - - - name: Copy tests to the PTF container - copy: src=roles/test/files/ptftests dest=/root - delegate_to: "{{ ptf_host }}" - - - name: Copy arp responder to the PTF container - copy: src=roles/test/files/helpers/arp_responder.py dest=/opt - delegate_to: "{{ ptf_host }}" - - - name: Copy arp responder supervisor configuration to the PTF container - template: src=arp_responder.conf.j2 dest=/etc/supervisor/conf.d/arp_responder.conf - vars: - - arp_responder_args: '--conf /tmp/vxlan_arpresponder.conf' - delegate_to: "{{ ptf_host }}" - - - name: Update supervisor configuration - include_tasks: "roles/test/tasks/common_tasks/update_supervisor.yml" - vars: - supervisor_host: "{{ ptf_host }}" - - - name: Restart DUT. Wait 240 seconds after SONiC started ssh - include_tasks: reboot.yml - vars: - ready_timeout: 240 - - - name: Render DUT parameters to json file for the test - template: src=vxlan_decap.json.j2 dest=/tmp/vxlan_decap.json - delegate_to: "{{ ptf_host }}" - - - name: Render DUT vxlan configuration. Tunnel - template: src=vxlan_db.tunnel.json.j2 dest=/tmp/vxlan_db.tunnel.json - - - name: Render DUT vxlan configuration. Tunnel Maps - template: src=vxlan_db.maps.json.j2 dest=/tmp/vxlan_db.maps.{{ item }}.json - with_items: "{{ minigraph_vlans }}" - - - set_fact: - send_packet_count: 10 - when: send_packet_count is not defined - - - include_tasks: ptf_runner.yml - vars: - ptf_test_name: Vxlan decap test - No vxlan configuration - ptf_test_dir: ptftests - ptf_test_path: vxlan-decap.Vxlan - ptf_platform: remote - ptf_platform_dir: ptftests - ptf_qlen: 1000 - ptf_test_params: - - vxlan_enabled=False - - config_file='/tmp/vxlan_decap.json' - - count={{ send_packet_count }} - - - name: Configure vxlan decap tunnel - shell: sonic-cfggen -j /tmp/vxlan_db.tunnel.json --write-to-db - - - name: Configure vxlan decap tunnel maps - shell: sonic-cfggen -j /tmp/vxlan_db.maps.{{ item }}.json --write-to-db - with_items: "{{ minigraph_vlans }}" - - - include_tasks: ptf_runner.yml - vars: - ptf_test_name: Vxlan decap test - vxlan configuration applied - ptf_test_dir: ptftests - ptf_test_path: vxlan-decap.Vxlan - ptf_platform: remote - ptf_platform_dir: ptftests - ptf_qlen: 1000 - ptf_test_params: - - vxlan_enabled=True - - config_file='/tmp/vxlan_decap.json' - - count={{ send_packet_count }} - - - name: Remove vxlan tunnel maps configuration - shell: docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL_MAP|tunnelVxlan|map{{ item }}" - with_items: "{{ minigraph_vlans }}" - - - name: Remove vxlan tunnel configuration - shell: docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL|tunnelVxlan" - - - include_tasks: ptf_runner.yml - vars: - ptf_test_name: Vxlan decap test - vxlan configuration removed - ptf_test_dir: ptftests - ptf_test_path: vxlan-decap.Vxlan - ptf_platform: remote - ptf_platform_dir: ptftests - ptf_qlen: 1000 - ptf_test_params: - - vxlan_enabled=False - - config_file='/tmp/vxlan_decap.json' - - count={{ send_packet_count }} - -- block: - - name: Remove vxlan tunnel maps configuration - shell: docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL_MAP|tunnelVxlan|map{{ item }}" - with_items: "{{ minigraph_vlans }}" - - - name: Remove vxlan tunnel configuration - shell: docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL|tunnelVxlan" - tags: - - always +- name: run test + include_tasks: roles/test/tasks/pytest_runner.yml + vars: + test_node: test_vxlan_decap.py diff --git a/ansible/roles/test/templates/vxlan_db.maps.json.j2 b/ansible/roles/test/templates/vxlan_db.maps.json.j2 deleted file mode 100644 index 1be0cf7c6e..0000000000 --- a/ansible/roles/test/templates/vxlan_db.maps.json.j2 +++ /dev/null @@ -1,9 +0,0 @@ -{ - "VXLAN_TUNNEL_MAP": { - "tunnelVxlan|map{{ item }}": { - "vni": "{{ item | replace("Vlan", "") | int + 336 }}", - "vlan": "{{ item }}" - } - } -} - diff --git a/ansible/roles/test/templates/vxlan_db.tunnel.json.j2 b/ansible/roles/test/templates/vxlan_db.tunnel.json.j2 deleted file mode 100644 index f4671fe6e2..0000000000 --- a/ansible/roles/test/templates/vxlan_db.tunnel.json.j2 +++ /dev/null @@ -1,8 +0,0 @@ -{ - "VXLAN_TUNNEL": { - "tunnelVxlan": { - "src_ip": "{{ minigraph_lo_interfaces[0]['addr'] }}", - "dst_ip": "8.8.8.8" - } - } -} diff --git a/ansible/roles/test/templates/vxlan_decap.json.j2 b/ansible/roles/test/templates/vxlan_decap.json.j2 deleted file mode 100644 index ab68c860c3..0000000000 --- a/ansible/roles/test/templates/vxlan_decap.json.j2 +++ /dev/null @@ -1,9 +0,0 @@ -{ - "minigraph_port_indices": {{ minigraph_port_indices | to_nice_json }}, - "minigraph_portchannel_interfaces": {{ minigraph_portchannel_interfaces | to_nice_json }}, - "minigraph_portchannels": {{ minigraph_portchannels | to_nice_json }}, - "minigraph_lo_interfaces": {{ minigraph_lo_interfaces | to_nice_json }}, - "minigraph_vlans": {{ minigraph_vlans | to_nice_json }}, - "minigraph_vlan_interfaces": {{ minigraph_vlan_interfaces | to_nice_json }}, - "dut_mac": {{ ansible_Ethernet0['macaddress'] | to_nice_json }} -} diff --git a/tests/test_vxlan_decap.py b/tests/test_vxlan_decap.py new file mode 100644 index 0000000000..7a486cc7ef --- /dev/null +++ b/tests/test_vxlan_decap.py @@ -0,0 +1,149 @@ +import json +import logging +from datetime import datetime + +import pytest +from jinja2 import Template +from netaddr import IPAddress + +from ptf_runner import ptf_runner + +logger = logging.getLogger(__name__) + +VTEP2_IP = "8.8.8.8" +VNI_BASE = 336 +COUNT = 10 + + +def prepare_ptf(ptfhost, mg_facts, dut_facts): + """ + @summary: Prepare the PTF docker container for testing + @param mg_facts: Minigraph facts + @param dut_facts: Host facts of DUT + """ + logger.info("Remove IP and change MAC") + ptfhost.script("./scripts/remove_ip.sh") + ptfhost.script("./scripts/change_mac.sh") + + logger.info("Prepare arp_responder") + ptfhost.copy(src="../ansible/roles/test/files/helpers/arp_responder.py", dest="/opt") + + arp_responder_conf = Template(open("../ansible/roles/test/templates/arp_responder.conf.j2").read()) + ptfhost.copy(content=arp_responder_conf.render(arp_responder_args="--conf /tmp/vxlan_arpresponder.conf"), + dest="/etc/supervisor/conf.d/arp_responder.conf") + + ptfhost.shell("supervisorctl reread") + ptfhost.shell("supervisorctl update") + + logger.info("Put information needed by the PTF script to the PTF container.") + vxlan_decap = { + "minigraph_port_indices": mg_facts["minigraph_port_indices"], + "minigraph_portchannel_interfaces": mg_facts["minigraph_portchannel_interfaces"], + "minigraph_portchannels": mg_facts["minigraph_portchannels"], + "minigraph_lo_interfaces": mg_facts["minigraph_lo_interfaces"], + "minigraph_vlans": mg_facts["minigraph_vlans"], + "minigraph_vlan_interfaces": mg_facts["minigraph_vlan_interfaces"], + "dut_mac": dut_facts["ansible_Ethernet0"]["macaddress"] + } + ptfhost.copy(content=json.dumps(vxlan_decap, indent=2), dest="/tmp/vxlan_decap.json") + + logger.info("Copy PTF scripts to PTF container") + ptfhost.copy(src="ptftests", dest="/root") + + +def generate_vxlan_config_files(duthost, mg_facts): + """ + @summary: Generate VXLAN tunnel and VXLAN map configuration files to DUT. + @param duthost: DUT host object + @mg_facts: Minigraph facts + """ + loopback_ip = None + for intf in mg_facts["minigraph_lo_interfaces"]: + if IPAddress(intf["addr"]).version == 4: + loopback_ip = intf["addr"] + break + if not loopback_ip: + pytest.fail("ipv4 lo interface not found") + + # Generate vxlan tunnel config json file on DUT + vxlan_tunnel_cfg = { + "VXLAN_TUNNEL": { + "tunnelVxlan": { + "src_ip": loopback_ip, + "dst_ip": VTEP2_IP + } + } + } + duthost.copy(content=json.dumps(vxlan_tunnel_cfg, indent=2), dest="/tmp/vxlan_db.tunnel.json") + + # Generate vxlan maps config json file on DUT + vxlan_maps_cfg = { + "VXLAN_TUNNEL_MAP": {} + } + for vlan in mg_facts["minigraph_vlans"]: + vxlan_maps_cfg["VXLAN_TUNNEL_MAP"]["tunnelVxlan|map%s" % vlan] = { + "vni": int(vlan.replace("Vlan", "")) + VNI_BASE, + "vlan": vlan + } + duthost.copy(content=json.dumps(vxlan_maps_cfg, indent=2), dest="/tmp/vxlan_db.maps.json") + + +@pytest.fixture(scope="module") +def setup(duthost, ptfhost): + + logger.info("Gather some facts") + mg_facts = duthost.minigraph_facts(host=duthost.hostname)["ansible_facts"] + dut_facts = duthost.setup(gather_subset="!all,!any,network", filter="ansible_Ethernet*")["ansible_facts"] + ptf_facts = ptfhost.setup(gather_subset="!all,!any,network")["ansible_facts"] + + logger.info("Prepare PTF") + prepare_ptf(ptfhost, mg_facts, dut_facts) + + logger.info("Generate VxLAN config files") + generate_vxlan_config_files(duthost, mg_facts) + + setup_info = { + "mg_facts": mg_facts + } + + yield setup_info + + logger.info("Stop arp_responder on PTF") + ptfhost.shell("supervisorctl stop arp_responder") + + logger.info("Always try to remove any possible VxLAN tunnel and map configuration") + for vlan in mg_facts["minigraph_vlans"]: + duthost.shell('docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL_MAP|tunnelVxlan|map%s"' % vlan) + duthost.shell('docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL|tunnelVxlan"') + + +@pytest.fixture(params=["NoVxLAN", "Enabled", "Removed"]) +def vxlan_status(setup, request, duthost): + if request.param == "Enabled": + duthost.shell("sonic-cfggen -j /tmp/vxlan_db.tunnel.json --write-to-db") + duthost.shell("sonic-cfggen -j /tmp/vxlan_db.maps.json --write-to-db") + return True, request.param + elif request.param == "Removed": + for vlan in setup["mg_facts"]["minigraph_vlans"]: + duthost.shell('docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL_MAP|tunnelVxlan|map%s"' % vlan) + duthost.shell('docker exec -i database redis-cli -n 4 -c DEL "VXLAN_TUNNEL|tunnelVxlan"') + return False, request.param + else: + return False, request.param + + +def test_vxlan_decap(setup, vxlan_status, duthost, ptfhost): + + vxlan_enabled, scenario = vxlan_status + + logger.info("vxlan_enabled=%s, scenario=%s" % (vxlan_enabled, scenario)) + log_file = "/tmp/vxlan-decap.Vxlan.{}.{}.log".format(scenario, datetime.now().strftime('%Y-%m-%d-%H:%M:%S')) + ptf_runner(ptfhost, + "ptftests", + "vxlan-decap.Vxlan", + platform_dir="ptftests", + params={"vxlan_enabled": vxlan_enabled, + "config_file": '/tmp/vxlan_decap.json', + "count": COUNT}, + qlen=1000, + log_file=log_file)