Merge pull request #1525 from kernelkit/remove-put-config-dict

test: Remove function put_config_dict and convert tests to use put_config_dicts
This commit is contained in:
Mattias Walström
2026-06-03 15:05:51 +02:00
committed by GitHub
62 changed files with 964 additions and 973 deletions
+22 -18
View File
@@ -30,29 +30,33 @@ with infamy.Test() as test:
test.skip()
with test.step("Set hostname to 'container-host'"):
target.put_config_dict("ietf-system", {
"system": {
"hostname": "container-host"
target.put_config_dicts({
"ietf-system": {
"system": {
"hostname": "container-host"
}
}
})
with test.step("Create container 'web' from bundled OCI image"):
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"host": True
},
"resource-limit": {
"memory": 512, # 512 KiB
"cpu": 500 # 50% of one CPU (0.5 cores)
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"host": True
},
"resource-limit": {
"memory": 512, # 512 KiB
"cpu": 500 # 50% of one CPU (0.5 cores)
}
}
}
]
]
}
}
})
+24 -27
View File
@@ -17,14 +17,16 @@ from infamy.util import until
def set_container_enabled(target, name, enabled):
"""Helper function to set container enabled state and verify the change"""
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": name,
"enabled": enabled
}
]
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": name,
"enabled": enabled
}
]
}
}
})
@@ -39,27 +41,22 @@ with infamy.Test() as test:
if not target.has_model("infix-containers"):
test.skip()
with test.step("Set hostname to 'container-host'"):
target.put_config_dict("ietf-system", {
"system": {
"hostname": "container-host"
}
})
with test.step("Create enabled container from bundled OCI image"):
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{NAME}",
"enabled": True,
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"host": True
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": f"{NAME}",
"enabled": True,
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"host": True
}
}
}
]
]
}
}
})
+48 -42
View File
@@ -37,17 +37,19 @@ with infamy.Test() as test:
with test.step("Configure data interface with static IPv4"):
_, ifname = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [{
"name": f"{ifname}",
"ipv4": {
"address": [{
"ip": f"{DUTIP}",
"prefix-length": 24
}]
}
}]
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": f"{ifname}",
"ipv4": {
"address": [{
"ip": f"{DUTIP}",
"prefix-length": 24
}]
}
}]
}
}
})
@@ -62,31 +64,33 @@ with infamy.Test() as test:
for var in ENV_VARS:
cgi.append(f'echo "{var["key"]}=${var["key"]}"')
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 8080",
"env": ENV_VARS,
"network": {
"host": True
},
"mount": [
{
"name": "env.cgi",
"content": to_binary('\n'.join(cgi) + '\n'),
"target": "/var/www/cgi-bin/env.cgi",
"mode": "0755"
}
],
"volume": [{
"name": "www",
"target": "/var/www"
}]
}
]
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 8080",
"env": ENV_VARS,
"network": {
"host": True
},
"mount": [
{
"name": "env.cgi",
"content": to_binary('\n'.join(cgi) + '\n'),
"target": "/var/www/cgi-bin/env.cgi",
"mode": "0755"
}
],
"volume": [{
"name": "www",
"target": "/var/www"
}]
}
]
}
}
})
@@ -115,12 +119,14 @@ with infamy.Test() as test:
{"key": "PATH_WITH_SPACES", "value": "/path with spaces/test"}
]
target.put_config_dict("infix-containers", {
"containers": {
"container": [{
"name": f"{NAME}",
"env": UPDATED_ENV_VARS,
}]
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [{
"name": f"{NAME}",
"env": UPDATED_ENV_VARS,
}]
}
}
})
+84 -76
View File
@@ -52,57 +52,61 @@ with infamy.Test() as test:
test.skip()
with test.step("Set hostname to 'container-host'"):
target.put_config_dict("ietf-system", {
"system": {
"hostname": "container-host"
target.put_config_dicts({
"ietf-system": {
"system": {
"hostname": "container-host"
}
}
})
with test.step("Create VETH pair for web server container"):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": f"{ext0}",
"ipv4": {
"forwarding": True,
"address": [{
"ip": f"{EXTIP}",
"prefix-length": 24
}]
}
},
{
"name": "int0",
"type": "infix-if-type:veth",
"enabled": True,
"infix-interfaces:veth": {
"peer": f"{WEBNM}"
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": f"{ext0}",
"ipv4": {
"forwarding": True,
"address": [{
"ip": f"{EXTIP}",
"prefix-length": 24
}]
}
},
"ipv4": {
"forwarding": True,
"address": [{
"ip": f"{INTIP}",
"prefix-length": 24,
}]
}
},
{
"name": f"{WEBNM}",
"type": "infix-if-type:veth",
"enabled": True,
"infix-interfaces:veth": {
"peer": "int0"
{
"name": "int0",
"type": "infix-if-type:veth",
"enabled": True,
"infix-interfaces:veth": {
"peer": f"{WEBNM}"
},
"ipv4": {
"forwarding": True,
"address": [{
"ip": f"{INTIP}",
"prefix-length": 24,
}]
}
},
"ipv4": {
"address": [{
"ip": f"{WEBIP}",
"prefix-length": 24,
}]
{
"name": f"{WEBNM}",
"type": "infix-if-type:veth",
"enabled": True,
"infix-interfaces:veth": {
"peer": "int0"
},
"ipv4": {
"address": [{
"ip": f"{WEBIP}",
"prefix-length": 24,
}]
},
"container-network": {}
},
"container-network": {}
},
]
]
}
}
})
@@ -132,43 +136,47 @@ table ip nat {
}
""")
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{NFTNM}",
"image": f"{NFTABLES}",
"network": {
"host": True
},
"mount": [
{
"name": "nftables.conf",
"content": config,
"target": "/etc/nftables.conf"
}
],
"privileged": True
}
]
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": f"{NFTNM}",
"image": f"{NFTABLES}",
"network": {
"host": True
},
"mount": [
{
"name": "nftables.conf",
"content": config,
"target": "/etc/nftables.conf"
}
],
"privileged": True
}
]
}
}
})
with test.step("Create web server container from bundled OCI image"):
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{WEBNM}",
"image": f"{HTTPD}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"interface": [
{"name": f"{WEBNM}"}
]
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": f"{WEBNM}",
"image": f"{HTTPD}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"interface": [
{"name": f"{WEBNM}"}
]
}
}
}
]
]
}
}
})
+31 -27
View File
@@ -23,9 +23,11 @@ with infamy.Test() as test:
test.skip()
with test.step("Set initial hostname"):
target.put_config_dict("ietf-system", {
"system": {
"hostname": hostname_init
target.put_config_dicts({
"ietf-system": {
"system": {
"hostname": hostname_init
}
}
})
@@ -42,31 +44,33 @@ with infamy.Test() as test:
nsenter -m/1/ns/mnt -u/1/ns/uts -i/1/ns/ipc -n/1/ns/net hostname {hostname_new}
""")
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": cont_name,
"image": cont_image,
"network": {
"host": True
},
"mount": [
{
"name": "rc.local",
"content": commands,
"target": "/etc/rc.local",
"mode": "0755"
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": cont_name,
"image": cont_image,
"network": {
"host": True
},
{
"name": "proc1ns",
"source": "/proc/1/ns",
"target": "/1/ns",
}
],
"privileged": True
}
]
"mount": [
{
"name": "rc.local",
"content": commands,
"target": "/etc/rc.local",
"mode": "0755"
},
{
"name": "proc1ns",
"source": "/proc/1/ns",
"target": "/1/ns",
}
],
"privileged": True
}
]
}
}
})
+39 -35
View File
@@ -27,32 +27,34 @@ with infamy.Test() as test:
with test.step("Create httpd container from bundled OCI image"):
_, ifname = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [{
"name": f"{ifname}",
"ipv4": {
"address": [{
"ip": f"{DUTIP}",
"prefix-length": 24
}]
},
"container-network": {}
}]
}
})
target.put_config_dict("infix-containers", {
"containers": {
"container": [{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"interface": [
{"name": f"{ifname}"}
]
}
}]
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": f"{ifname}",
"ipv4": {
"address": [{
"ip": f"{DUTIP}",
"prefix-length": 24
}]
},
"container-network": {}
}]
}
},
"infix-containers": {
"containers": {
"container": [{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"interface": [
{"name": f"{ifname}"}
]
}
}]
}
}
})
@@ -74,16 +76,18 @@ with infamy.Test() as test:
# Verify modifying a running container takes, issue #930
data = to_binary(BODY)
target.put_config_dict("infix-containers", {
"containers": {
"container": [{
"name": f"{NAME}",
"mount": [{
"name": "index.html",
"content": f"{data}",
"target": "/var/www/index.html"
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [{
"name": f"{NAME}",
"mount": [{
"name": "index.html",
"content": f"{data}",
"target": "/var/www/index.html"
}]
}]
}]
}
}
})
+13 -11
View File
@@ -90,18 +90,20 @@ with infamy.Test() as test:
print(f"Created symlink: {latest_link} -> {old_img}")
with test.step("Create container 'web' from curios-httpd:latest (24.05.0)"):
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"http://192.168.0.1:{SRVPORT}/curios-httpd-latest.tar.gz",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"host": True
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"http://192.168.0.1:{SRVPORT}/curios-httpd-latest.tar.gz",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"host": True
}
}
}
]
]
}
}
})
+52 -50
View File
@@ -36,60 +36,62 @@ with infamy.Test() as test:
with test.step("Create 'web-br0-veth' container from bundled OCI image"):
_, ifname = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": f"{ifname}",
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "br0",
"type": "infix-if-type:bridge"
},
{
"name": f"{NAME}",
"type": "infix-if-type:veth",
"infix-interfaces:veth": {
"peer": "veth0b"
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": f"{ifname}",
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
"ipv4": {
"address": [{
"ip": f"{DUTIP}",
"prefix-length": 24
}]
{
"name": "br0",
"type": "infix-if-type:bridge"
},
"container-network": {}
},
{
"name": "veth0b",
"type": "infix-if-type:veth",
"infix-interfaces:veth": {
"peer": f"{NAME}"
{
"name": f"{NAME}",
"type": "infix-if-type:veth",
"infix-interfaces:veth": {
"peer": "veth0b"
},
"ipv4": {
"address": [{
"ip": f"{DUTIP}",
"prefix-length": 24
}]
},
"container-network": {}
},
"infix-interfaces:bridge-port": {
"bridge": "br0"
{
"name": "veth0b",
"type": "infix-if-type:veth",
"infix-interfaces:veth": {
"peer": f"{NAME}"
},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
]
}
},
"infix-containers": {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"interface": [
{ "name": f"{NAME}" }
]
}
}
},
]
}
})
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": "/usr/sbin/httpd -f -v -p 91",
"network": {
"interface": [
{ "name": f"{NAME}" }
]
}
}
]
]
}
}
})
+18 -16
View File
@@ -25,22 +25,24 @@ with infamy.Test() as test:
test.skip()
with test.step("Create container with volume from bundled OCI image"):
target.put_config_dict("infix-containers", {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": f"/usr/sbin/httpd -f -v -p {PORT}",
"network": {
"host": True
},
"volume": [{
"name": "www",
"target": "/var/www"
}]
}
]
target.put_config_dicts({
"infix-containers": {
"containers": {
"container": [
{
"name": f"{NAME}",
"image": f"oci-archive:{infamy.Container.HTTPD_IMAGE}",
"command": f"/usr/sbin/httpd -f -v -p {PORT}",
"network": {
"host": True
},
"volume": [{
"name": "www",
"target": "/var/www"
}]
}
]
}
}
})
+1 -1
View File
@@ -64,7 +64,7 @@ with infamy.Test() as test:
}]
}
}
client.put_config_dict("ietf-interfaces", config)
client.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify DHCPv6 client is running"):
until(checkrun, attempts=10)
@@ -71,7 +71,7 @@ with infamy.Test() as test:
}]
}
}
client.put_config_dict("ietf-interfaces", config)
client.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify DHCPv6 client is running"):
until(lambda: checkrun(tgtssh), attempts=20)
+1 -1
View File
@@ -80,7 +80,7 @@ with infamy.Test() as test:
}]
}
}
client.put_config_dict("ietf-interfaces", config)
client.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify DHCPv6 client is running"):
until(lambda: checkrun(tgtssh), attempts=20)
+1 -1
View File
@@ -33,7 +33,7 @@ with infamy.Test() as test:
}]
}
}
client.put_config_dict("ietf-interfaces", config)
client.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify client lease for 10.0.0.42"):
until(lambda: iface.address_exist(client, port, ADDRESS))
+1 -1
View File
@@ -39,7 +39,7 @@ with infamy.Test() as test:
}]
}
}
client.put_config_dict("ietf-interfaces", config)
client.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify DHCP client has default route via 192.168.0.254"):
until(lambda: route.ipv4_route_exist(client, "0.0.0.0/0", ROUTER), attempts=30)
+10 -4
View File
@@ -29,11 +29,11 @@ with infamy.Test() as test:
_, port = env.ltop.xlate("client", "mgmt")
with test.step("Configure static system hostname"):
client.put_config_dict("ietf-system", {
client.put_config_dicts({"ietf-system": {
"system": {
"hostname": CONF_HOSTNAME
}
})
}})
with test.step("Verify configured hostname is set"):
until(lambda: verify_hostname(client, CONF_HOSTNAME))
@@ -42,7 +42,13 @@ with infamy.Test() as test:
netns.addip("10.0.0.1")
with infamy.dhcp.Server(netns, ip="10.0.0.42", hostname=DHCP_HOSTNAME):
with test.step("Enable DHCP client requesting hostname option"):
client.put_config_dict("ietf-interfaces", {
client.put_config_dicts({
"ietf-system": {
"system": {
"hostname": CONF_HOSTNAME
}
},
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": port,
@@ -58,7 +64,7 @@ with infamy.Test() as test:
}
}]
}
})
}})
with test.step("Verify DHCP hostname takes precedence"):
until(lambda: verify_hostname(client, DHCP_HOSTNAME))
+12 -6
View File
@@ -45,16 +45,22 @@ with infamy.Test() as test:
_, port = env.ltop.xlate("client", "mgmt")
with test.step(f"Configure initial hostname '{HOSTNM_A}'"):
client.put_config_dict("ietf-system", {
client.put_config_dicts({"ietf-system": {
"system": {
"hostname": HOSTNM_A
}
})
}})
until(lambda: client.get_data("/ietf-system:system")
.get("system", {}).get("hostname") == HOSTNM_A)
with test.step("Enable DHCP client sending hostname option"):
client.put_config_dict("ietf-interfaces", {
client.put_config_dicts({
"ietf-system": {
"system": {
"hostname": HOSTNM_A
}
},
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": port,
@@ -70,17 +76,17 @@ with infamy.Test() as test:
}
}]
}
})
}})
with test.step(f"Verify running udhcpc announces hostname '{HOSTNM_A}'"):
until(lambda: running_hostname(clissh, port) == HOSTNM_A)
with test.step(f"Update system hostname to '{HOSTNM_B}'"):
client.put_config_dict("ietf-system", {
client.put_config_dicts({"ietf-system": {
"system": {
"hostname": HOSTNM_B
}
})
}})
until(lambda: client.get_data("/ietf-system:system")
.get("system", {}).get("hostname") == HOSTNM_B)
+4 -4
View File
@@ -34,7 +34,7 @@ with infamy.Test() as test:
# Install canary route to smoke out any regressions in
# how the DHCP client installs routes in the kernel FIB
client.put_config_dict("ietf-routing", {
client.put_config_dicts({"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
@@ -54,12 +54,12 @@ with infamy.Test() as test:
}]
}
}
})
}})
with test.step("Enabling DHCP client, allow option 3 and 121"):
_, port = env.ltop.xlate("client", "data")
client.put_config_dict("ietf-interfaces", {
client.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": f"{port}",
@@ -73,7 +73,7 @@ with infamy.Test() as test:
}
}]
}
})
}})
with infamy.IsolatedMacVlan(host) as netns:
netns.addip("192.168.0.1")
+48 -47
View File
@@ -28,55 +28,56 @@ with infamy.Test() as test:
HOST_IP = "192.168.1.42"
with test.step("Configure basic end-device firewall"):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": data_if,
"enabled": True,
"ipv4": {
"address": [{
"ip": TARGET_IP,
"prefix-length": 24
}]
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": data_if,
"enabled": True,
"ipv4": {
"address": [{
"ip": TARGET_IP,
"prefix-length": 24
}]
}
}
}
]
}
})
target.put_config_dict("infix-firewall", {
"firewall": {
"default": "public-untrusted-net",
"logging": "all",
"service": [{
"name": "mySSH",
"port": [{
"lower": 222,
"proto": "tcp"
]
}
},
"infix-firewall": {
"firewall": {
"default": "public-untrusted-net",
"logging": "all",
"service": [{
"name": "mySSH",
"port": [{
"lower": 222,
"proto": "tcp"
}]
}, {
"name": "http",
"port": [{
"lower": 8080,
"proto": "tcp"
}]
}],
"zone": [{
"name": "mgmt",
"description": "Management network - for test automation",
"action": "accept",
"interface": [mgmt_if],
"service": ["ssh", "netconf", "restconf"]
}, {
# 20-char name, exceeds old iptables-derived 17-char limit
# Verifies we allow long names with nftables, issue #1389
"name": "public-untrusted-net",
"description": "Public untrusted network",
"action": "drop",
"interface": [data_if],
"service": ["ssh", "dhcpv6-client", "mySSH", "http"]
}]
}, {
"name": "http",
"port": [{
"lower": 8080,
"proto": "tcp"
}]
}],
"zone": [{
"name": "mgmt",
"description": "Management network - for test automation",
"action": "accept",
"interface": [mgmt_if],
"service": ["ssh", "netconf", "restconf"]
}, {
# 20-char name, exceeds old iptables-derived 17-char limit
# Verifies we allow long names with nftables, issue #1389
"name": "public-untrusted-net",
"description": "Public untrusted network",
"action": "drop",
"interface": [data_if],
"service": ["ssh", "dhcpv6-client", "mySSH", "http"]
}]
}
}
})
@@ -192,12 +192,14 @@ with infamy.Test() as test:
with test.step("Perform dynamic zone migration"):
target.delete_xpath(f"/infix-firewall:firewall/zone[name='untrusted']/interface[.='{data1_if}']")
target.put_config_dict("infix-firewall", {
"firewall": {
"zone": [{
"name": "trusted",
"interface": [data1_if]
}]
target.put_config_dicts({
"infix-firewall": {
"firewall": {
"zone": [{
"name": "trusted",
"interface": [data1_if]
}]
}
}
})
+56 -55
View File
@@ -36,63 +36,64 @@ with infamy.Test() as test:
WAN_SERVER_IP = "203.0.113.100" # Server on WAN side
with test.step("Configure gateway with firewall and SNAT"):
gateway.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": lan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": LAN_ROUTER_IP,
"prefix-length": 24
}]
gateway.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": lan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": LAN_ROUTER_IP,
"prefix-length": 24
}]
}
},
{
"name": wan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": WAN_ROUTER_IP,
"prefix-length": 24
}]
}
}
},
{
"name": wan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": WAN_ROUTER_IP,
"prefix-length": 24
}]
]
}
},
"infix-firewall": {
"firewall": {
"default": "wan",
"logging": "all",
"zone": [
{
"name": "lan",
"description": "Internal LAN network - trusted",
"action": "accept",
"interface": [lan_if, mgmt_if],
"service": ["ssh", "dhcp", "dns"]
}, {
"name": "wan",
"description": "External WAN interface - untrusted",
"action": "drop",
"interface": [wan_if]
}
}
]
}
})
gateway.put_config_dict("infix-firewall", {
"firewall": {
"default": "wan",
"logging": "all",
"zone": [
{
"name": "lan",
"description": "Internal LAN network - trusted",
"action": "accept",
"interface": [lan_if, mgmt_if],
"service": ["ssh", "dhcp", "dns"]
}, {
"name": "wan",
"description": "External WAN interface - untrusted",
"action": "drop",
"interface": [wan_if]
}
],
"policy": [
{
"name": "lan-to-wan",
"description": "Allow LAN to WAN traffic with SNAT",
"ingress": ["lan"],
"egress": ["wan"],
"action": "accept",
"masquerade": True
}
]
],
"policy": [
{
"name": "lan-to-wan",
"description": "Allow LAN to WAN traffic with SNAT",
"ingress": ["lan"],
"egress": ["wan"],
"action": "accept",
"masquerade": True
}
]
}
}
})
+90 -89
View File
@@ -42,96 +42,97 @@ with infamy.Test() as test:
LAN_CLIENT_IP = "192.168.1.100" # Host LAN interface
with test.step("Configure gateway with multi-zone firewall and NAT"):
gateway.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": wan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": WAN_ROUTER_IP,
"prefix-length": 24
}]
}
},
{
"name": dmz_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": DMZ_ROUTER_IP,
"prefix-length": 24
}]
}
},
{
"name": lan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": LAN_ROUTER_IP,
"prefix-length": 24
}]
}
}
]
}
})
gateway.put_config_dict("infix-firewall", {
"firewall": {
"default": "wan",
"logging": "all",
"zone": [
{
"name": "wan",
"description": "External WAN interface - untrusted",
"action": "drop",
"interface": [wan_if],
"port-forward": [{
"lower": 8080,
"proto": "tcp",
"to": {
"addr": DMZ_SERVER_IP,
"port": 80
gateway.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": wan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": WAN_ROUTER_IP,
"prefix-length": 24
}]
}
}]
},
{
"name": "dmz",
"description": "DMZ network - limited trust",
"action": "reject",
"network": [DMZ_NET],
"service": ["http"]
},
{
"name": "lan",
"description": "Internal LAN network - trusted",
"action": "accept",
"interface": [lan_if, mgmt_if]
}
],
"policy": [
{
"name": "loc-to-wan",
"description": "Allow local networks to WAN with SNAT",
"ingress": ["lan", "dmz"],
"egress": ["wan"],
"action": "accept",
"masquerade": True
}, {
"name": "lan-to-dmz",
"description": "Allow LAN access to DMZ services",
"ingress": ["lan"],
"egress": ["dmz"],
"action": "accept",
"service": ["ssh", "http"]
}
]
},
{
"name": dmz_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": DMZ_ROUTER_IP,
"prefix-length": 24
}]
}
},
{
"name": lan_if,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": LAN_ROUTER_IP,
"prefix-length": 24
}]
}
}
]
}
},
"infix-firewall": {
"firewall": {
"default": "wan",
"logging": "all",
"zone": [
{
"name": "wan",
"description": "External WAN interface - untrusted",
"action": "drop",
"interface": [wan_if],
"port-forward": [{
"lower": 8080,
"proto": "tcp",
"to": {
"addr": DMZ_SERVER_IP,
"port": 80
}
}]
},
{
"name": "dmz",
"description": "DMZ network - limited trust",
"action": "reject",
"network": [DMZ_NET],
"service": ["http"]
},
{
"name": "lan",
"description": "Internal LAN network - trusted",
"action": "accept",
"interface": [lan_if, mgmt_if]
}
],
"policy": [
{
"name": "loc-to-wan",
"description": "Allow local networks to WAN with SNAT",
"ingress": ["lan", "dmz"],
"egress": ["wan"],
"action": "accept",
"masquerade": True
}, {
"name": "lan-to-dmz",
"description": "Allow LAN access to DMZ services",
"ingress": ["lan"],
"egress": ["dmz"],
"action": "accept",
"service": ["ssh", "http"]
}
]
}
}
})
+15 -9
View File
@@ -39,9 +39,11 @@ with infamy.Test() as test:
}
components.append(component)
target.put_config_dict("ietf-hardware", {
"hardware": {
"component": components
target.put_config_dicts({
"ietf-hardware": {
"hardware": {
"component": components
}
}
})
@@ -61,9 +63,11 @@ with infamy.Test() as test:
}
components.append(component)
target.put_config_dict("ietf-hardware", {
"hardware": {
"component": components
target.put_config_dicts({
"ietf-hardware": {
"hardware": {
"component": components
}
}
})
@@ -91,9 +95,11 @@ with infamy.Test() as test:
}
components.append(component)
target.put_config_dict("ietf-hardware", {
"hardware": {
"component": components
target.put_config_dicts({
"ietf-hardware": {
"hardware": {
"component": components
}
}
})
+10 -6
View File
@@ -40,9 +40,11 @@ with infamy.Test() as test:
}
components.append(component)
target.put_config_dict("ietf-hardware", {
"hardware": {
"component": components
target.put_config_dicts({
"ietf-hardware": {
"hardware": {
"component": components
}
}
})
with test.step("Verify that the correct port is locked and the correct one is unlocked"):
@@ -68,9 +70,11 @@ with infamy.Test() as test:
}
components.append(component)
target.put_config_dict("ietf-hardware", {
"hardware": {
"component": components
target.put_config_dicts({
"ietf-hardware": {
"hardware": {
"component": components
}
}
})
with test.step("Verify that the correct port is locked and the correct one is unlocked"):
+2 -2
View File
@@ -23,7 +23,7 @@ with infamy.Test() as test:
with test.step("Configure single bridge with a single physical port, bridge @ IP 10.0.0.2"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": "br0",
@@ -43,7 +43,7 @@ with infamy.Test() as test:
}
}]
}
})
}})
with test.step("Verify ping 10.0.0.2 is possible from host:data"):
_, hport = env.ltop.xlate("host", "data")
@@ -41,7 +41,7 @@ with infamy.Test() as test:
_, tport22 = env.ltop.xlate("dut2", "data2")
_, tport2_link = env.ltop.xlate("dut2", "link")
dut1.put_config_dict("ietf-interfaces", {
dut1.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -77,9 +77,9 @@ with infamy.Test() as test:
}
]
}
})
}})
dut2.put_config_dict("ietf-interfaces", {
dut2.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -123,7 +123,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with test.step("Verify ping 10.0.0.3 and 10.0.0.4 from host:data11"):
@@ -36,7 +36,7 @@ with infamy.Test() as test:
_, tport1 = env.ltop.xlate("target", "data1")
_, tport2 = env.ltop.xlate("target", "data2")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -60,7 +60,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with test.step("Verify ping from host:data1 to 10.0.0.2"):
_, hport1 = env.ltop.xlate("host", "data1")
+2 -2
View File
@@ -26,7 +26,7 @@ with infamy.Test() as test:
with test.step("Configure bridged eth port and veth pair with IP 10.0.0.2"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -70,7 +70,7 @@ with infamy.Test() as test:
},
]
}
})
}})
with test.step("Verify ping from host:data to 10.0.0.2"):
_, hport = env.ltop.xlate("host", "data")
+4 -4
View File
@@ -18,7 +18,7 @@ with infamy.Test() as test:
dut2 = env.attach("dut2", "mgmt")
with test.step("Configure DUTs"):
dut1.put_config_dict("ietf-interfaces", {
dut1.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -65,9 +65,9 @@ with infamy.Test() as test:
}
]
}
})
}})
dut2.put_config_dict("ietf-interfaces", {
dut2.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -96,7 +96,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with test.step("Verify ping from host:data to 10.0.0.2 and 10.0.0.3"):
_, hport = env.ltop.xlate("host", "data")
@@ -40,7 +40,7 @@ with infamy.Test() as test:
_, tport21 = env.ltop.xlate("dut2", "data2")
_, tport22 = env.ltop.xlate("dut2", "link")
dut1.put_config_dict("ietf-interfaces", {
dut1.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -89,9 +89,9 @@ with infamy.Test() as test:
}
]
}
})
}})
dut2.put_config_dict("ietf-interfaces", {
dut2.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -140,7 +140,7 @@ with infamy.Test() as test:
}
]
}
})
}})
_, hport10 = env.ltop.xlate("host", "data10")
+2 -2
View File
@@ -21,7 +21,7 @@ with infamy.Test() as test:
with test.step("Configure two bridges linked and a veth pair"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -73,7 +73,7 @@ with infamy.Test() as test:
},
]
}
})
}})
with test.step("Verify ping from host:data to 10.0.0.2"):
_, hport = env.ltop.xlate("host", "data")
@@ -56,11 +56,11 @@ def configure_interface(target, iface_name, iface_type=None, enabled=True, ip_ad
"bridge": bridge
}
target.put_config_dict( "ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
interface_config
]}})
]}}})
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUTs"):
@@ -102,4 +102,4 @@ with infamy.Test() as test:
send_ns.addip(host_address)
send_ns.must_reach(target_address)
test.succeed()
test.succeed()
@@ -61,7 +61,7 @@ with infamy.Test() as test:
}]
}
}
target.put_config_dict("ietf-interfaces", config)
target.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify target:data has MAC address '02:01:00:c0:ff:ee'"):
mac = iface.get_phys_address(target, tport)
@@ -85,7 +85,7 @@ with infamy.Test() as test:
}]
}
}
target.put_config_dict("ietf-interfaces", config)
target.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify target:data has chassis MAC"):
until(lambda: iface.get_phys_address(target, tport) == cmac)
@@ -104,7 +104,7 @@ with infamy.Test() as test:
}]
}
}
target.put_config_dict("ietf-interfaces", config)
target.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify target:data has chassis MAC + offset"):
BMAC = calc_mac(cmac, OFFSET)
+2 -2
View File
@@ -16,7 +16,7 @@ with infamy.Test() as test:
with test.step("Set up interface target:data with description"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -26,7 +26,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with test.step("Verify description can be read back from operational"):
text = iface.get_param(target, tport, "description")
+2 -2
View File
@@ -46,7 +46,7 @@ with infamy.Test() as test:
_, nojoin = env.ltop.xlate("target", "data3")
with test.step("Configure device"):
target.put_config_dict("ietf-interfaces",
target.put_config_dicts({"ietf-interfaces":
{
"interfaces": {
"interface": [
@@ -95,7 +95,7 @@ with infamy.Test() as test:
]
}
})
}})
_, hsend = env.ltop.xlate("host", "data1")
_, hreceive = env.ltop.xlate("host", "data2")
+1 -1
View File
@@ -37,7 +37,7 @@ with infamy.Test() as test:
}
}
target.put_config_dict("ietf-interfaces", config)
target.put_config_dicts({"ietf-interfaces": config})
with test.step("Verify '10.10.10.20/24' exists on target:mgmt"):
until(lambda: iface.address_exist(target, interface_name, new_ip_address, proto='static'))
+4 -4
View File
@@ -50,7 +50,7 @@ with infamy.Test() as test:
with test.step("Configure interface target:data with IPv4 ZeroConf IP"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -62,7 +62,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with test.step("Verify link-local address exist on target:data"):
until(lambda: has_linklocal(target, tport), attempts=30)
@@ -70,7 +70,7 @@ with infamy.Test() as test:
with test.step("Configure target:data with a specific IPv4 ZeroConf IP"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -84,7 +84,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with test.step("Verify target:data has link-local address 169.254.42.42"):
until(lambda: has_linklocal(target, tport, request="169.254.42.42"),
+2 -2
View File
@@ -17,7 +17,7 @@ with infamy.Test() as test:
with test.step("Setting up bridge with IPv6 SLAAC for global prefix on target:data"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -40,7 +40,7 @@ with infamy.Test() as test:
},
]
}
})
}})
with test.step("Verify using sysctl that 'net.ipv6.conf.br0.autoconf' is 1 on target"):
def check_autoconf():
+2 -2
View File
@@ -113,7 +113,7 @@ def dut_init(dut, mode, addr):
net = net_init(dut["mon"], addr)
lag = lag_init(mode)
dut.put_config_dict("ietf-interfaces", {
dut.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": "lag0",
@@ -130,7 +130,7 @@ def dut_init(dut, mode, addr):
"lag-port": {"lag": "lag0"}
}] + net + lag
}
})
}})
with infamy.Test() as test:
+2 -2
View File
@@ -98,7 +98,7 @@ def dut_init(dut, addr, peer):
"""Configure each DUT specific according to LAG mode and peer"""
net = net_init(dut["mon"], addr)
dut.put_config_dict("ietf-interfaces", {
dut.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": "lag0",
@@ -116,7 +116,7 @@ def dut_init(dut, addr, peer):
"lag-port": {"lag": "lag0"}
}] + net
}
})
}})
with infamy.Test() as test:
+2 -2
View File
@@ -24,7 +24,7 @@ with infamy.Test() as test:
_, tport = env.ltop.xlate("target", "data")
with test.step("Configure static IPv4 ARP and IPv6 neighbor entries on target:data"):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": tport,
@@ -42,7 +42,7 @@ with infamy.Test() as test:
}
}]
}
})
}})
with test.step("Verify static IPv4 ARP entry is visible in operational state"):
until(lambda: iface.neighbor_exist(target, tport, IPV4_NEIGH, IPV4_LLADR, "static"))
+2 -2
View File
@@ -30,14 +30,14 @@ def iface_cfg(port, subnet, enable_fwd):
def config_target(target, tport0, tport1, enable_fwd):
"""Configure forwarding and addresses for both address families."""
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
iface_cfg(tport0, SUBNETS[0], enable_fwd),
iface_cfg(tport1, SUBNETS[1], enable_fwd),
]
}
})
}})
def setup_host(ns, subnet):
"""Add IPv4 and IPv6 addresses and default routes."""
@@ -32,7 +32,7 @@ import infamy.iface as iface
from infamy.util import until
def set_static_multicast_filter(target, address, port):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -54,7 +54,7 @@ def set_static_multicast_filter(target, address, port):
}
]
}
})
}})
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUTs"):
@@ -68,7 +68,7 @@ with infamy.Test() as test:
mac_multicast_group = "01:00:00:01:02:03"
with test.step("Configure device without static filter"):
target.put_config_dict("ietf-interfaces",
target.put_config_dicts({"ietf-interfaces":
{
"interfaces": {
"interface": [
@@ -114,7 +114,7 @@ with infamy.Test() as test:
]
}
})
}})
_, hsend = env.ltop.xlate("host", "data1")
_, hreceive = env.ltop.xlate("host", "data2")
+6 -6
View File
@@ -27,7 +27,7 @@ with infamy.Test() as test:
veth0b = "veth0b"
with test.step("Create VETH pair"):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -48,7 +48,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with test.step("Verify interfaces 'veth0a' and 'veth0b' exist"):
assert iface.exist(target, veth0a), \
@@ -57,7 +57,7 @@ with infamy.Test() as test:
f"Interface <{veth0b}> does not exist."
with test.step("Set IP address on target:data1 (dummy op)"):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": f"{data1}",
@@ -69,10 +69,10 @@ with infamy.Test() as test:
}
}]
}
})
}})
with test.step("Set IP address on target:data2 (dummy op)"):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": f"{data2}",
@@ -84,7 +84,7 @@ with infamy.Test() as test:
}
}]
}
})
}})
# TODO: need target.del_config_dict() or similar for VETH _pairs_,
# because both interfaces must be removed at the same time.
+2 -2
View File
@@ -27,7 +27,7 @@ with infamy.Test() as test:
""")
with test.step("Configure VLAN 10 interface on target:data with IP 10.0.0.2"):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -52,7 +52,7 @@ with infamy.Test() as test:
},
]
}
})
}})
with test.step("Wait for links to come up"):
until(lambda: iface.get_param(target, tport, "oper-status") == "up")
+4 -4
View File
@@ -64,7 +64,7 @@ with infamy.Test() as test:
_, hd1 = env.ltop.xlate("host", "data1")
with test.step("Apply initial config without priority mapping"):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -107,7 +107,7 @@ with infamy.Test() as test:
}
]
}
})
}})
with infamy.IsolatedMacVlan(hd0) as ns0, \
infamy.IsolatedMacVlan(hd1) as ns1 :
@@ -134,7 +134,7 @@ with infamy.Test() as test:
with test.step(desc):
ns0.runsh(f"ip link set vlan10 type vlan egress-qos-map 0:{p['pcp']}")
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -155,7 +155,7 @@ with infamy.Test() as test:
},
]
}
})
}})
ns0.must_reach("192.168.11.2", id=p["id"])
+8 -6
View File
@@ -63,12 +63,14 @@ def configure_oc(iface, ip, priority1, client_only, dm="e2e"):
def set_iface_enabled(target, iface, enabled):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [{
"name": iface,
"enabled": enabled,
}]
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": iface,
"enabled": enabled,
}]
}
}
})
+107 -118
View File
@@ -20,7 +20,8 @@ from infamy.util import until, parallel
def config_target1(target, data, link):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -56,135 +57,128 @@ def config_target1(target, data, link):
}
]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": "R1"
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "192.168.33.1/32",
"next-hop": {
"special-next-hop": "blackhole"
}
}]
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "192.168.33.1/32",
"next-hop": {
"special-next-hop": "blackhole"
}
}]
}
}
}
}, {
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"redistribute": {
"redistribute": [{
"protocol": "static"
}, {
"protocol": "connected"
}]
},
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [{
"enabled": True,
"name": link,
"hello-interval": 1,
"dead-interval": 3
}]
},
}]
}, {
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"redistribute": {
"redistribute": [{
"protocol": "static"
}, {
"protocol": "connected"
}]
},
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [{
"enabled": True,
"name": link,
"hello-interval": 1,
"dead-interval": 3
}]
},
}]
}
}
}
}]
}]
}
}
}
})
def config_target2(target, link, data):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [{
"name": link,
"enabled": True,
"ipv4": {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.50.2",
"prefix-length": 24
}]
}
}, {
"name": data,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.60.1",
"prefix-length": 24
}]
}
}, {
"name": "lo",
"enabled": True,
"forwarding": True,
"address": [{
"ip": "192.168.50.2",
"prefix-length": 24
}]
}
}, {
"name": data,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.60.1",
"prefix-length": 24
}]
}
}, {
"name": "lo",
"enabled": True,
"forwarding": True,
"ipv4": {
"address": [{
"ip": "192.168.200.1",
"prefix-length": 32
}]
}
}]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": "R2"
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"redistribute": {
"redistribute": [{
"protocol": "connected"
}]
},
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [{
"enabled": True,
"name": link,
"hello-interval": 1,
"dead-interval": 3
}]
}
}]
}
"ipv4": {
"address": [{
"ip": "192.168.200.1",
"prefix-length": 32
}]
}
}]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"redistribute": {
"redistribute": [{
"protocol": "connected"
}]
},
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [{
"enabled": True,
"name": link,
"hello-interval": 1,
"dead-interval": 3
}]
}
}]
}
}
}]
}
}
}
})
def config_host(target, link):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [{
"name": link,
@@ -197,11 +191,6 @@ def config_host(target, link):
}
}]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": "HOST"
}
})
+5 -10
View File
@@ -43,7 +43,8 @@ def config(target, params):
}]}
}
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
ifconfig("lo", rid, 32),
@@ -53,15 +54,8 @@ def config(target, params):
ifconfig(sif, saddr, 30),
]
}
})
target.put_config_dict("ietf-system", {
"system": {
"hostname": name,
}
})
target.put_config_dict("ietf-routing", {
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
@@ -101,6 +95,7 @@ def config(target, params):
}]
}
}
}
})
with infamy.Test() as test:
+3 -1
View File
@@ -557,7 +557,8 @@ def config_target4(target, ring1, cross, link):
def disable_link(target, link):
target.put_config_dict("ietf-interfaces", {
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
@@ -565,6 +566,7 @@ def disable_link(target, link):
"enabled": False
}]
}
}
})
@@ -18,135 +18,137 @@ from infamy.util import until, parallel
# This test tests passive interfaces and unnumbered interfaces.
def config_target1(target, data, link):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": data,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.10.1",
"prefix-length": 24
}]}
},
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.0.1",
"prefix-length": 32
}]
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": data,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.10.1",
"prefix-length": 24
}]}
},
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.0.1",
"prefix-length": 32
}]
}
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"ip": "192.168.100.1",
"prefix-length": 32
}]
}
}
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"ip": "192.168.100.1",
"prefix-length": 32
}]
}
}
]
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces":
{
"interface": [{
"name": link,
"hello-interval": 1,
"dead-interval": 3,
"interface-type": "point-to-point"
}, {
"name": data,
"passive": True
}, {
"name": "lo",
"passive": True
}]
},
}]
}
}
}]
}
}
})
def config_target2(target, link):
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.0.2",
"prefix-length": 32
}]
}
},
{
"name": "lo",
"enabled": True,
"forwarding": True,
"ipv4": {
"address": [{
"ip": "192.168.200.1",
"prefix-length": 32
}]
}
}
]
}
})
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces": {
"interfaces":
{
"interface": [{
"name": link,
"hello-interval": 1,
"dead-interval": 3,
"interface-type": "point-to-point"
}, {
"name": data,
"passive": True
}, {
"name": "lo",
"passive": True
}]
}
},
}]
}
}
}
]
}]
}
}
}
})
def config_target2(target, link):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "10.0.0.2",
"prefix-length": 32
}]
}
},
{
"name": "lo",
"enabled": True,
"forwarding": True,
"ipv4": {
"address": [{
"ip": "192.168.200.1",
"prefix-length": 32
}]
}
}
]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces": {
"interface": [{
"name": link,
"hello-interval": 1,
"dead-interval": 3,
"interface-type": "point-to-point"
}, {
"name": "lo",
"passive": True
}]
}
}]
}
}
}
]
}
}
}
})
@@ -25,10 +25,7 @@ with infamy.Test() as test:
}
]
}
}
})
target.put_config_dicts({
},
"ieee802-dot1ab-lldp": {
"lldp": {
"enabled": False
@@ -54,7 +54,7 @@ def check(expected, allow=None, deny=None):
if deny:
mdns_config["mdns"]["interfaces"]["deny"] = deny
dut.put_config_dict("infix-services", mdns_config)
dut.put_config_dicts({"infix-services": mdns_config})
actual = mdns_scan()
if actual != tuple(expected):
@@ -34,10 +34,7 @@ with infamy.Test() as test:
}
]
}
}
})
target.put_config_dicts({
},
"infix-services": {
"mdns": {
"enabled": False
@@ -41,10 +41,12 @@ def mdns_reflect_test():
def disable_reflector():
"""Disable mDNS reflector"""
dut.put_config_dict("infix-services", {
"mdns": {
"reflector": {
"enabled": False
dut.put_config_dicts({
"infix-services": {
"mdns": {
"reflector": {
"enabled": False
}
}
}
})
@@ -52,22 +52,24 @@ with infamy.Test() as test:
# Upon attachment, target reverts to `test-config`, in which
# the SSH service is enabled, hence we do not have to
# explicitly enable it here.
target.put_config_dict("ietf-system", {
"system": {
"authentication": {
"user": [
{
"name": USER,
"authorized-key": [
{
"name":"guest-ssh-key",
"algorithm": "ssh-rsa",
"key-data": KEY["public"]
}
],
"infix-system:shell":"bash"
}
]
target.put_config_dicts({
"ietf-system": {
"system": {
"authentication": {
"user": [
{
"name": USER,
"authorized-key": [
{
"name":"guest-ssh-key",
"algorithm": "ssh-rsa",
"key-data": KEY["public"]
}
],
"infix-system:shell":"bash"
}
]
}
}
}
})
@@ -131,9 +131,11 @@ with infamy.Test() as test:
assert ns88.runsh(f"ssh-keyscan -p {SSH_PORT_1} {SSH_ADDRESS_2}").returncode == 1, "SSH is accessable on wrong interface"
with test.step("Disable SSH server"):
target.put_config_dict("infix-services", {
"ssh": {
"enabled": False
target.put_config_dicts({
"infix-services": {
"ssh": {
"enabled": False
}
}
})
assert(ns77.run(
+12 -10
View File
@@ -23,16 +23,18 @@ with infamy.Test() as test:
tgtssh = env.attach("target", "mgmt", "ssh")
with test.step("Add new user 'newuser01' with password 'newuser01password'"):
target.put_config_dict("ietf-system", {
"system": {
"authentication": {
"user": [
{
"name": username,
"password": hashed_password,
"shell": "infix-system:bash"
}
]
target.put_config_dicts({
"ietf-system": {
"system": {
"authentication": {
"user": [
{
"name": username,
"password": hashed_password,
"shell": "infix-system:bash"
}
]
}
}
}
})
+10 -6
View File
@@ -19,9 +19,11 @@ with infamy.Test() as test:
NEW = "h0stn4m3"
with test.step("Set hostname to 'h0stn4m3'"):
target.put_config_dict("ietf-system", {
"system": {
"hostname": NEW,
target.put_config_dicts({
"ietf-system": {
"system": {
"hostname": NEW,
}
}
})
@@ -30,9 +32,11 @@ with infamy.Test() as test:
assert running["system"]["hostname"] == NEW
with test.step("Set hostname to '%h-%m'"):
target.put_config_dict("ietf-system", {
"system": {
"hostname": FMT,
target.put_config_dicts({
"ietf-system": {
"system": {
"hostname": FMT,
}
}
})
+14 -12
View File
@@ -23,16 +23,18 @@ with infamy.Test() as test:
USER = "jacky"
PASS = "$1$3aR7Bq2u$G9kV.8AALtKkCnaAXFyu6/"
target.put_config_dict("ietf-system", {
"system": {
"authentication": {
"user": [
{
"name": USER,
"password": PASS,
"shell": "infix-system:bash"
}
]
target.put_config_dicts({
"ietf-system": {
"system": {
"authentication": {
"user": [
{
"name": USER,
"password": PASS,
"shell": "infix-system:bash"
}
]
}
}
}
})
@@ -60,7 +62,7 @@ with infamy.Test() as test:
if group["name"] == "admin":
if USER not in group["user-name"]:
group["user-name"].append(USER)
target.put_config_dict("ietf-netconf-acm", nacm)
target.put_config_dicts({"ietf-netconf-acm": nacm})
with test.step("Verify user jacky is now in wheel group (in Linux)"):
if not tgtssh.runsh(f"grep wheel /etc/group | grep '{USER}'"):
@@ -79,7 +81,7 @@ with infamy.Test() as test:
if user['name'] == USER:
user['password'] = "$factory$"
break
target.put_config_dict("ietf-system", running)
target.put_config_dicts({"ietf-system": running})
with test.step("Verify user jacky exists and has new password"):
operational = target.get_data("/ietf-system:system/authentication")
+11 -15
View File
@@ -330,8 +330,17 @@ class Device(Transport):
# print(f"Send new XML config: {config}")
return self.put_config(config, retries=retries)
def put_config_dict(self, modname, edit, retries=3):
"""Convert Python dictionary to XMl and send as configuration"""
def patch_config(self, modname, edit, retries=3):
"""Merge configuration for a single model to running-config
For NETCONF, edit-config already has proper NACM support, so a
single-model merge is sufficient.
Args:
modname: YANG module name
edit: Configuration dictionary
retries: Number of retry attempts on failure (default 3)
"""
try:
mod = self.ly.get_module(modname)
except libyang.util.LibyangError:
@@ -343,19 +352,6 @@ class Device(Transport):
# print(f"Send new XML config: {config}")
return self.put_config(config, retries=retries)
def patch_config(self, modname, edit, retries=3):
"""Merge configuration for a single model to running-config
For NETCONF, this is identical to put_config_dict() since
edit-config already has proper NACM support.
Args:
modname: YANG module name
edit: Configuration dictionary
retries: Number of retry attempts on failure (default 3)
"""
return self.put_config_dict(modname, edit, retries=retries)
def call(self, call):
"""Call RPC, XML version"""
return self.ncc.dispatch(call)
-55
View File
@@ -343,61 +343,6 @@ class Device(Transport):
# Copy candidate to running (acts as "commit", triggers sysrepo callbacks)
self.copy("candidate", "running")
def put_config_dict(self, xpath, edit, retries=3):
"""PATCH configuration for a single model to running-config
Uses candidate datastore + copy to running to trigger sysrepo
change callbacks, similar to how NETCONF edit-config + commit works.
Args:
xpath: YANG module name
edit: Configuration dictionary
retries: Number of retry attempts on failure (default 3)
"""
try:
mod = self.lyctx.get_module(xpath)
except libyang.util.LibyangError:
raise Exception(f"YANG model '{xpath}' not found on device. "
f"Model may not be installed or enabled. "
f"Available models can be checked with get_schema_list()") from None
# Copy running to candidate first (to preserve existing config)
self.copy("running", "candidate")
# Parse and convert to get proper structure with module prefix
lyd = mod.parse_data_dict(edit, no_state=True, validate=False)
patch_data = json.loads(lyd.print_mem("json", with_siblings=True, pretty=False))
# PATCH to candidate datastore
url = f"{self.restconf_url}/ds/ietf-datastores:candidate"
last_error = None
for attempt in range(0, retries):
try:
response = requests_workaround_patch(
url,
json=patch_data,
headers=self.headers,
auth=self.auth,
verify=False
)
response.raise_for_status()
last_error = None
break
except Exception as e:
last_error = e
if attempt < retries - 1:
print(f"Failed PATCH to {url}: {e} Retrying ...")
time.sleep(1)
else:
print(f"Failed PATCH to {url}: {e}")
continue
if last_error is not None:
raise last_error
# Copy candidate to running (acts as "commit", triggers sysrepo callbacks)
self.copy("candidate", "running")
def patch_config(self, xpath, edit, retries=3):
"""PATCH configuration directly to running datastore
-4
View File
@@ -22,10 +22,6 @@ class Transport(ABC):
def get_config_dict(self, modname):
pass
@abstractmethod
def put_config_dict(self, modname, edit):
pass
@abstractmethod
def patch_config(self, modname, edit):
pass