diff --git a/test/case/ietf_interfaces/ietf_interfaces.yaml b/test/case/ietf_interfaces/ietf_interfaces.yaml index 2141ccbf..6e72bf26 100644 --- a/test/case/ietf_interfaces/ietf_interfaces.yaml +++ b/test/case/ietf_interfaces/ietf_interfaces.yaml @@ -26,6 +26,9 @@ - name: bridge_vlan case: bridge_vlan/test.py +- name: veth_delete + case: veth_delete/test.py + - name: ipv4_autoconf case: ipv4_autoconf/test.py diff --git a/test/case/ietf_interfaces/veth_delete/Readme.adoc b/test/case/ietf_interfaces/veth_delete/Readme.adoc new file mode 100644 index 00000000..96ce39de --- /dev/null +++ b/test/case/ietf_interfaces/veth_delete/Readme.adoc @@ -0,0 +1,35 @@ +=== Verify that VETH pairs can be deleted +==== Description +``` + veth0b veth0a e1 e2 + `---------' +``` + +Each test step to create, add address, or delete an interace is distinct +from any other step. This to trigger a new configuration "generation". + +==== Topology +ifdef::topdoc[] +image::../../test/case/ietf_interfaces/veth_delete/topology.png[Verify that VETH pairs can be deleted topology] +endif::topdoc[] +ifndef::topdoc[] +ifdef::testgroup[] +image::veth_delete/topology.png[Verify that VETH pairs can be deleted topology] +endif::testgroup[] +ifndef::testgroup[] +image::topology.png[Verify that VETH pairs can be deleted topology] +endif::testgroup[] +endif::topdoc[] +==== Test sequence +. Initialize +. Create VETH pair +. Verify VETH pair exists +. Set IP address on target:eth0 (dummy op) +. Set IP address on target:eth1 (dummy op) +. Reset configuration +. Verify target:eth0 and target:eth1 still exist +. Verify VETH pair have been removed + + +<<< + diff --git a/test/case/ietf_interfaces/veth_delete/test.py b/test/case/ietf_interfaces/veth_delete/test.py new file mode 100755 index 00000000..e4f68ac9 --- /dev/null +++ b/test/case/ietf_interfaces/veth_delete/test.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Verify that VETH pairs can be deleted + +``` + veth0b veth0a e1 e2 + `---------' +``` + +Each test step to create, add address, or delete an interace is distinct +from any other step. This to trigger a new configuration "generation". + +""" + +import infamy +import infamy.iface as iface + + +with infamy.Test() as test: + with test.step("Initialize"): + env = infamy.Env() + target = env.attach("target", "mgmt") + + _, eth0 = env.ltop.xlate("target", "eth0") + _, eth1 = env.ltop.xlate("target", "eth1") + + veth0a = "veth0a" + veth0b = "veth0b" + + with test.step("Create VETH pair"): + target.put_config_dict("ietf-interfaces", { + "interfaces": { + "interface": [ + { + "name": veth0a, + "type": "infix-if-type:veth", + "enabled": True, + "infix-interfaces:veth": { + "peer": veth0b + } + }, + { + "name": veth0b, + "type": "infix-if-type:veth", + "enabled": True, + "infix-interfaces:veth": { + "peer": veth0a + } + } + ] + } + }) + + with test.step("Verify VETH pair exists"): + assert iface.interface_exist(target, veth0a), \ + f"Interface <{veth0a}> does not exist." + assert iface.interface_exist(target, veth0b), \ + f"Interface <{veth0b}> does not exist." + + with test.step("Set IP address on target:eth0 (dummy op)"): + target.put_config_dict("ietf-interfaces", { + "interfaces": { + "interface": [{ + "name": f"{eth0}", + "ipv4": { + "address": [{ + "ip": "10.0.0.1", + "prefix-length": 24 + }] + } + }] + } + }) + + with test.step("Set IP address on target:eth1 (dummy op)"): + target.put_config_dict("ietf-interfaces", { + "interfaces": { + "interface": [{ + "name": f"{eth1}", + "ipv4": { + "address": [{ + "ip": "20.0.0.1", + "prefix-length": 24 + }] + } + }] + } + }) + + # TODO: need target.del_config_dict() or similar for VETH _pairs_, + # because both interfaces must be removed at the same time. + # with test.step("Delete VETH pair"): + # xpath = f"/ietf-interfaces:interfaces/interface[name='{veth0a}']" + # target.delete_xpath(xpath) + # XXX: temporary workaround + with test.step("Reset configuration"): + # Calls target.test_reset() to apply safe-config + target = env.attach("target", "mgmt") + + with test.step("Verify target:eth0 and target:eth1 still exist"): + assert iface.interface_exist(target, eth0), \ + f"Interface {eth0} missing!" + assert iface.interface_exist(target, eth1), \ + f"Interface {eth1} missing!" + + with test.step("Verify VETH pair have been removed"): + assert not iface.interface_exist(target, veth0a), \ + f"Interface <{veth0a}> still exists!" + assert not iface.interface_exist(target, veth0b), \ + f"Interface <{veth0b}> still exists!" + + test.succeed() diff --git a/test/case/ietf_interfaces/veth_delete/topology.dot b/test/case/ietf_interfaces/veth_delete/topology.dot new file mode 100644 index 00000000..0029eb79 --- /dev/null +++ b/test/case/ietf_interfaces/veth_delete/topology.dot @@ -0,0 +1,25 @@ +graph "1x3" { + layout="neato"; + overlap="false"; + esep="+80"; + + node [shape=record, fontname="monospace"]; + edge [color="cornflowerblue", penwidth="2"]; + + host [ + label="host | { tgt | dummy0 | dummy1 }", + pos="0,12!", + kind="controller", + ]; + + target [ + label="{ mgmt | eth0 | eth1 } | target", + pos="10,12!", + + kind="infix", + ]; + + host:tgt -- target:mgmt [kind=mgmt] + host:dummy0 -- target:eth0 [color=black] + host:dummy1 -- target:eth1 [color=black] +} diff --git a/test/case/ietf_interfaces/veth_delete/topology.png b/test/case/ietf_interfaces/veth_delete/topology.png new file mode 100644 index 00000000..154cd3d0 Binary files /dev/null and b/test/case/ietf_interfaces/veth_delete/topology.png differ