mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
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:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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,
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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}"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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"
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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}" }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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"
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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]
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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"])
|
||||
|
||||
|
||||
@@ -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,
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user