summaryrefslogtreecommitdiff
path: root/smoketest/scripts/cli
diff options
context:
space:
mode:
Diffstat (limited to 'smoketest/scripts/cli')
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py15
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_segment_routing.py70
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcp-server.py455
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcpv6-server.py156
-rwxr-xr-xsmoketest/scripts/cli/test_service_dns_dynamic.py41
-rwxr-xr-xsmoketest/scripts/cli/test_service_https.py69
6 files changed, 602 insertions, 204 deletions
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 71e2142f9..97dab255e 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -1133,5 +1133,20 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' mpls bgp forwarding', frrconfig)
self.cli_delete(['interfaces', 'ethernet', interface, 'vrf'])
+ def test_bgp_24_srv6_sid(self):
+ locator_name = 'VyOS_foo'
+ sid = 'auto'
+
+ self.cli_set(base_path + ['srv6', 'locator', locator_name])
+ self.cli_set(base_path + ['sid', 'vpn', 'per-vrf', 'export', sid])
+
+ self.cli_commit()
+
+ frrconfig = self.getFRRconfig(f'router bgp {ASN}')
+ self.assertIn(f'router bgp {ASN}', frrconfig)
+ self.assertIn(f' segment-routing srv6', frrconfig)
+ self.assertIn(f' locator {locator_name}', frrconfig)
+ self.assertIn(f' sid vpn per-vrf export {sid}', frrconfig)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_segment_routing.py b/smoketest/scripts/cli/test_protocols_segment_routing.py
new file mode 100755
index 000000000..81d42b925
--- /dev/null
+++ b/smoketest/scripts/cli/test_protocols_segment_routing.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import unittest
+
+from base_vyostest_shim import VyOSUnitTestSHIM
+
+from vyos.configsession import ConfigSessionError
+from vyos.utils.process import cmd
+from vyos.utils.process import process_named_running
+
+base_path = ['protocols', 'segment-routing']
+PROCESS_NAME = 'zebra'
+
+class TestProtocolsSegmentRouting(VyOSUnitTestSHIM.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ # call base-classes classmethod
+ super(TestProtocolsSegmentRouting, cls).setUpClass()
+ # Retrieve FRR daemon PID - it is not allowed to crash, thus PID must remain the same
+ cls.daemon_pid = process_named_running(PROCESS_NAME)
+ # ensure we can also run this test on a live system - so lets clean
+ # out the current configuration :)
+ cls.cli_delete(cls, base_path)
+
+ def tearDown(self):
+ self.cli_delete(base_path)
+ self.cli_commit()
+
+ # check process health and continuity
+ self.assertEqual(self.daemon_pid, process_named_running(PROCESS_NAME))
+
+ def test_srv6(self):
+ locators = {
+ 'foo' : { 'prefix' : '2001:a::/64' },
+ 'foo' : { 'prefix' : '2001:b::/64', 'usid' : {} },
+ }
+
+ for locator, locator_config in locators.items():
+ self.cli_set(base_path + ['srv6', 'locator', locator, 'prefix', locator_config['prefix']])
+ if 'usid' in locator_config:
+ self.cli_set(base_path + ['srv6', 'locator', locator, 'behavior-usid'])
+
+ self.cli_commit()
+
+ frrconfig = self.getFRRconfig(f'segment-routing', daemon='zebra')
+ self.assertIn(f'segment-routing', frrconfig)
+ self.assertIn(f' srv6', frrconfig)
+ self.assertIn(f' locators', frrconfig)
+ for locator, locator_config in locators.items():
+ self.assertIn(f' locator {locator}', frrconfig)
+ self.assertIn(f' prefix {locator_config["prefix"]} block-len 40 node-len 24 func-bits 16', frrconfig)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py
index 093e43494..9f6e05ff3 100755
--- a/smoketest/scripts/cli/test_service_dhcp-server.py
+++ b/smoketest/scripts/cli/test_service_dhcp-server.py
@@ -14,11 +14,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
import unittest
+from json import loads
+
from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.configsession import ConfigSessionError
+from vyos.utils.dict import dict_search_recursive
from vyos.utils.process import process_named_running
from vyos.utils.file import read_file
from vyos.template import address_from_cidr
@@ -26,8 +30,10 @@ from vyos.template import inc_ip
from vyos.template import dec_ip
from vyos.template import netmask_from_cidr
-PROCESS_NAME = 'dhcpd'
-DHCPD_CONF = '/run/dhcp-server/dhcpd.conf'
+PROCESS_NAME = 'kea-dhcp4'
+CTRL_PROCESS_NAME = 'kea-ctrl-agent'
+KEA4_CONF = '/run/kea/kea-dhcp4.conf'
+KEA4_CTRL = '/run/kea/dhcp4-ctrl-socket'
base_path = ['service', 'dhcp-server']
subnet = '192.0.2.0/25'
router = inc_ip(subnet, 1)
@@ -52,6 +58,36 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.cli_delete(base_path)
self.cli_commit()
+ def walk_path(self, obj, path):
+ current = obj
+
+ for i, key in enumerate(path):
+ if isinstance(key, str):
+ self.assertTrue(isinstance(current, dict), msg=f'Failed path: {path}')
+ self.assertTrue(key in current, msg=f'Failed path: {path}')
+ elif isinstance(key, int):
+ self.assertTrue(isinstance(current, list), msg=f'Failed path: {path}')
+ self.assertTrue(0 <= key < len(current), msg=f'Failed path: {path}')
+ else:
+ assert False, "Invalid type"
+
+ current = current[key]
+
+ return current
+
+ def verify_config_object(self, obj, path, value):
+ base_obj = self.walk_path(obj, path)
+ self.assertTrue(isinstance(base_obj, list))
+ self.assertTrue(any(True for v in base_obj if v == value))
+
+ def verify_config_value(self, obj, path, key, value):
+ base_obj = self.walk_path(obj, path)
+ if isinstance(base_obj, list):
+ self.assertTrue(any(True for v in base_obj if key in v and v[key] == value))
+ elif isinstance(base_obj, dict):
+ self.assertTrue(key in base_obj)
+ self.assertEqual(base_obj[key], value)
+
def test_dhcp_single_pool_range(self):
shared_net_name = 'SMOKE-1'
@@ -60,15 +96,12 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
range_1_start = inc_ip(subnet, 40)
range_1_stop = inc_ip(subnet, 50)
- self.cli_set(base_path + ['dynamic-dns-update'])
-
pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
# we use the first subnet IP address as default gateway
self.cli_set(pool + ['default-router', router])
self.cli_set(pool + ['name-server', dns_1])
self.cli_set(pool + ['name-server', dns_2])
self.cli_set(pool + ['domain-name', domain_name])
- self.cli_set(pool + ['ping-check'])
# check validate() - No DHCP address range or active static-mapping set
with self.assertRaises(ConfigSessionError):
@@ -81,20 +114,37 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
- self.assertIn(f'ddns-update-style interim;', config)
- self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
- self.assertIn(f'option domain-name-servers {dns_1}, {dns_2};', config)
- self.assertIn(f'option routers {router};', config)
- self.assertIn(f'option domain-name "{domain_name}";', config)
- self.assertIn(f'default-lease-time 86400;', config)
- self.assertIn(f'max-lease-time 86400;', config)
- self.assertIn(f'ping-check true;', config)
- self.assertIn(f'range {range_0_start} {range_0_stop};', config)
- self.assertIn(f'range {range_1_start} {range_1_stop};', config)
- self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
+
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'valid-lifetime', 86400)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'max-valid-lifetime', 86400)
+
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name', 'data': domain_name})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name-servers', 'data': f'{dns_1}, {dns_2}'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
+
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop}'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_1_start} - {range_1_stop}'})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
@@ -134,6 +184,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.cli_set(pool + ['static-route', '10.0.0.0/24', 'next-hop', '192.0.2.1'])
self.cli_set(pool + ['ipv6-only-preferred', ipv6_only_preferred])
+ self.cli_set(pool + ['time-zone', 'Europe/London'])
# check validate() - No DHCP address range or active static-mapping set
with self.assertRaises(ConfigSessionError):
@@ -144,38 +195,89 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
-
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
- self.assertIn(f'ddns-update-style none;', config)
- self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
- self.assertIn(f'option domain-name-servers {dns_1}, {dns_2};', config)
- self.assertIn(f'option routers {router};', config)
- self.assertIn(f'option domain-name "{domain_name}";', config)
-
- search = '"' + ('", "').join(search_domains) + '"'
- self.assertIn(f'option domain-search {search};', config)
-
- self.assertIn(f'option ip-forwarding true;', config)
- self.assertIn(f'option smtp-server {smtp_server};', config)
- self.assertIn(f'option pop-server {smtp_server};', config)
- self.assertIn(f'option time-servers {time_server};', config)
- self.assertIn(f'option wpad-url "{wpad}";', config)
- self.assertIn(f'option dhcp-server-identifier {server_identifier};', config)
- self.assertIn(f'option tftp-server-name "{tftp_server}";', config)
- self.assertIn(f'option bootfile-name "{bootfile_name}";', config)
- self.assertIn(f'filename "{bootfile_name}";', config)
- self.assertIn(f'next-server {bootfile_server};', config)
- self.assertIn(f'default-lease-time 86400;', config)
- self.assertIn(f'max-lease-time 86400;', config)
- self.assertIn(f'range {range_0_start} {range_0_stop};', config)
- self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
- self.assertIn(f'option rfc8925-ipv6-only-preferred {ipv6_only_preferred};', config)
-
- # weird syntax for those static routes
- self.assertIn(f'option rfc3442-static-route 24,10,0,0,192,0,2,1, 0,192,0,2,1;', config)
- self.assertIn(f'option windows-static-route 24,10,0,0,192,0,2,1;', config)
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
+
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'boot-file-name', bootfile_name)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'next-server', bootfile_server)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'valid-lifetime', 86400)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'max-valid-lifetime', 86400)
+
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name', 'data': domain_name})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name-servers', 'data': f'{dns_1}, {dns_2}'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'domain-search', 'data': ', '.join(search_domains)})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'pop-server', 'data': smtp_server})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'smtp-server', 'data': smtp_server})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'time-servers', 'data': time_server})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'dhcp-server-identifier', 'data': server_identifier})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'tftp-server-name', 'data': tftp_server})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'wpad-url', 'data': wpad})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'rfc3442-static-route', 'data': '24,10,0,0,192,0,2,1, 0,192,0,2,1'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'windows-static-route', 'data': '24,10,0,0,192,0,2,1'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'v6-only-preferred', 'data': ipv6_only_preferred})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'ip-forwarding', 'data': "true"})
+
+ # Time zone
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'pcode', 'data': 'GMT0BST,M3.5.0/1,M10.5.0'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'tcode', 'data': 'Europe/London'})
+
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop}'})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
@@ -205,27 +307,39 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
- self.assertIn(f'ddns-update-style none;', config)
- self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
- self.assertIn(f'option domain-name-servers {dns_1}, {dns_2};', config)
- self.assertIn(f'option routers {router};', config)
- self.assertIn(f'option domain-name "{domain_name}";', config)
- self.assertIn(f'default-lease-time 86400;', config)
- self.assertIn(f'max-lease-time 86400;', config)
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
+
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'valid-lifetime', 86400)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'max-valid-lifetime', 86400)
+
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name', 'data': domain_name})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name-servers', 'data': f'{dns_1}, {dns_2}'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
client_base = 10
for client in ['client1', 'client2', 'client3']:
mac = '00:50:00:00:00:{}'.format(client_base)
ip = inc_ip(subnet, client_base)
- self.assertIn(f'host {shared_net_name}_{client}' + ' {', config)
- self.assertIn(f'fixed-address {ip};', config)
- self.assertIn(f'hardware ethernet {mac};', config)
- client_base += 1
- self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'reservations'],
+ {'hw-address': mac, 'ip-address': ip})
+
+ client_base += 1
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
@@ -266,7 +380,9 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
+
for network in ['0', '1', '2', '3']:
shared_net_name = f'VyOS-SMOKETEST-{network}'
subnet = f'192.0.{network}.0/24'
@@ -278,27 +394,43 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
range_1_start = inc_ip(subnet, 30)
range_1_stop = inc_ip(subnet, 40)
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
-
- self.assertIn(f'ddns-update-style none;', config)
- self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
- self.assertIn(f'option domain-name-servers {dns_1};', config)
- self.assertIn(f'option routers {router};', config)
- self.assertIn(f'option domain-name "{domain_name}";', config)
- self.assertIn(f'default-lease-time {lease_time};', config)
- self.assertIn(f'max-lease-time {lease_time};', config)
- self.assertIn(f'range {range_0_start} {range_0_stop};', config)
- self.assertIn(f'range {range_1_start} {range_1_stop};', config)
- self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', int(network), 'subnet4'], 'subnet', subnet)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', int(network), 'subnet4'], 'valid-lifetime', int(lease_time))
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', int(network), 'subnet4'], 'max-valid-lifetime', int(lease_time))
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', int(network), 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name', 'data': domain_name})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', int(network), 'subnet4', 0, 'option-data'],
+ {'name': 'domain-name-servers', 'data': dns_1})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', int(network), 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', int(network), 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop}'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', int(network), 'subnet4', 0, 'pools'],
+ {'pool': f'{range_1_start} - {range_1_stop}'})
client_base = 60
for client in ['client1', 'client2', 'client3', 'client4']:
mac = '02:50:00:00:00:{}'.format(client_base)
ip = inc_ip(subnet, client_base)
- self.assertIn(f'host {shared_net_name}_{client}' + ' {', config)
- self.assertIn(f'fixed-address {ip};', config)
- self.assertIn(f'hardware ethernet {mac};', config)
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', int(network), 'subnet4', 0, 'reservations'],
+ {'hw-address': mac, 'ip-address': ip})
+
client_base += 1
# Check for running process
@@ -319,14 +451,23 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- # VErify
- config = read_file(DHCPD_CONF)
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
- self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
- self.assertIn(f'option routers {router};', config)
- self.assertIn(f'range {range_0_start} {range_0_stop};', config)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', 'EXCLUDE-TEST')
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
+
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
+
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop}'})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
@@ -352,15 +493,27 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- # Verify
- config = read_file(DHCPD_CONF)
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
+
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', 'EXCLUDE-TEST-2')
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
- self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
- self.assertIn(f'option routers {router};', config)
- self.assertIn(f'range {range_0_start} {range_0_stop_excl};', config)
- self.assertIn(f'range {range_0_start_excl} {range_0_stop};', config)
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop_excl}'})
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start_excl} - {range_0_stop}'})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
@@ -384,41 +537,23 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
- # Check the relay network
- self.assertIn(f'subnet {network} netmask {netmask}' + r' { }', config)
-
- relay_network = address_from_cidr(relay_subnet)
- relay_netmask = netmask_from_cidr(relay_subnet)
- self.assertIn(f'subnet {relay_network} netmask {relay_netmask}' + r' {', config)
- self.assertIn(f'option routers {relay_router};', config)
- self.assertIn(f'range {range_0_start} {range_0_stop};', config)
-
- # Check for running process
- self.assertTrue(process_named_running(PROCESS_NAME))
-
- def test_dhcp_invalid_raw_options(self):
- shared_net_name = 'SMOKE-5'
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
- range_0_start = inc_ip(subnet, 10)
- range_0_stop = inc_ip(subnet, 20)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', 'RELAY')
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', relay_subnet)
- pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
- # we use the first subnet IP address as default gateway
- self.cli_set(pool + ['default-router', router])
- self.cli_set(pool + ['range', '0', 'start', range_0_start])
- self.cli_set(pool + ['range', '0', 'stop', range_0_stop])
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': relay_router})
- self.cli_set(base_path + ['global-parameters', 'this-is-crap'])
- # check generate() - dhcpd should not acceot this garbage config
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
- self.cli_delete(base_path + ['global-parameters'])
-
- # commit changes
- self.cli_commit()
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop}'})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
@@ -449,41 +584,43 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ['failover', 'remote', failover_remote])
self.cli_set(base_path + ['failover', 'status', 'primary'])
- # check validate() - failover needs to be enabled for at least one subnet
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
- self.cli_set(pool + ['enable-failover'])
-
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
-
- self.assertIn(f'failover peer "{failover_name}"' + r' {', config)
- self.assertIn(f'primary;', config)
- self.assertIn(f'mclt 1800;', config)
- self.assertIn(f'mclt 1800;', config)
- self.assertIn(f'split 128;', config)
- self.assertIn(f'port 647;', config)
- self.assertIn(f'peer port 647;', config)
- self.assertIn(f'max-response-delay 30;', config)
- self.assertIn(f'max-unacked-updates 10;', config)
- self.assertIn(f'load balance max seconds 3;', config)
- self.assertIn(f'address {failover_local};', config)
- self.assertIn(f'peer address {failover_remote};', config)
-
- network = address_from_cidr(subnet)
- netmask = netmask_from_cidr(subnet)
- self.assertIn(f'ddns-update-style none;', config)
- self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
- self.assertIn(f'option routers {router};', config)
- self.assertIn(f'range {range_0_start} {range_0_stop};', config)
- self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
- self.assertIn(f'failover peer "{failover_name}";', config)
- self.assertIn(f'deny dynamic bootp clients;', config)
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
+
+ # Verify failover
+ self.verify_config_value(obj, ['Dhcp4', 'control-socket'], 'socket-name', KEA4_CTRL)
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'hooks-libraries', 0, 'parameters', 'high-availability', 0, 'peers'],
+ {'name': os.uname()[1], 'url': f'http://{failover_local}:647/', 'role': 'primary', 'auto-failover': True})
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'hooks-libraries', 0, 'parameters', 'high-availability', 0, 'peers'],
+ {'name': failover_name, 'url': f'http://{failover_remote}:647/', 'role': 'standby', 'auto-failover': True})
+
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
+
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
+
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop}'})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
+ self.assertTrue(process_named_running(CTRL_PROCESS_NAME))
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py
index 4d9dabc3f..175a67537 100755
--- a/smoketest/scripts/cli/test_service_dhcpv6-server.py
+++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2022 VyOS maintainers and contributors
+# Copyright (C) 2020-2023 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -16,6 +16,8 @@
import unittest
+from json import loads
+
from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.configsession import ConfigSessionError
@@ -23,8 +25,8 @@ from vyos.template import inc_ip
from vyos.utils.process import process_named_running
from vyos.utils.file import read_file
-PROCESS_NAME = 'dhcpd'
-DHCPD_CONF = '/run/dhcp-server/dhcpdv6.conf'
+PROCESS_NAME = 'kea-dhcp6'
+KEA6_CONF = '/run/kea/kea-dhcp6.conf'
base_path = ['service', 'dhcpv6-server']
subnet = '2001:db8:f00::/64'
@@ -52,6 +54,36 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
self.cli_delete(base_path)
self.cli_commit()
+ def walk_path(self, obj, path):
+ current = obj
+
+ for i, key in enumerate(path):
+ if isinstance(key, str):
+ self.assertTrue(isinstance(current, dict), msg=f'Failed path: {path}')
+ self.assertTrue(key in current, msg=f'Failed path: {path}')
+ elif isinstance(key, int):
+ self.assertTrue(isinstance(current, list), msg=f'Failed path: {path}')
+ self.assertTrue(0 <= key < len(current), msg=f'Failed path: {path}')
+ else:
+ assert False, "Invalid type"
+
+ current = current[key]
+
+ return current
+
+ def verify_config_object(self, obj, path, value):
+ base_obj = self.walk_path(obj, path)
+ self.assertTrue(isinstance(base_obj, list))
+ self.assertTrue(any(True for v in base_obj if v == value))
+
+ def verify_config_value(self, obj, path, key, value):
+ base_obj = self.walk_path(obj, path)
+ if isinstance(base_obj, list):
+ self.assertTrue(any(True for v in base_obj if key in v and v[key] == value))
+ elif isinstance(base_obj, dict):
+ self.assertTrue(key in base_obj)
+ self.assertEqual(base_obj[key], value)
+
def test_single_pool(self):
shared_net_name = 'SMOKE-1'
search_domains = ['foo.vyos.net', 'bar.vyos.net']
@@ -99,34 +131,66 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
- self.assertIn(f'option dhcp6.preference {preference};', config)
-
- self.assertIn(f'subnet6 {subnet}' + r' {', config)
- search = '"' + '", "'.join(search_domains) + '"'
- nissrv = ', '.join(nis_servers)
- self.assertIn(f'range6 {range_start} {range_stop};', config)
- self.assertIn(f'default-lease-time {lease_time};', config)
- self.assertIn(f'default-lease-time {lease_time};', config)
- self.assertIn(f'max-lease-time {max_lease_time};', config)
- self.assertIn(f'min-lease-time {min_lease_time};', config)
- self.assertIn(f'option dhcp6.domain-search {search};', config)
- self.assertIn(f'option dhcp6.name-servers {dns_1}, {dns_2};', config)
- self.assertIn(f'option dhcp6.nis-domain-name "{domain}";', config)
- self.assertIn(f'option dhcp6.nis-servers {nissrv};', config)
- self.assertIn(f'option dhcp6.nisp-domain-name "{domain}";', config)
- self.assertIn(f'option dhcp6.nisp-servers {nissrv};', config)
- self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+ config = read_file(KEA6_CONF)
+ obj = loads(config)
+
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'subnet', subnet)
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'valid-lifetime', int(lease_time))
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'min-valid-lifetime', int(min_lease_time))
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'max-valid-lifetime', int(max_lease_time))
+
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'dns-servers', 'data': f'{dns_1}, {dns_2}'})
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'domain-search', 'data': ", ".join(search_domains)})
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'nis-domain-name', 'data': domain})
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'nis-servers', 'data': ", ".join(nis_servers)})
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'nisp-domain-name', 'data': domain})
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'nisp-servers', 'data': ", ".join(nis_servers)})
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'sntp-servers', 'data': sntp_server})
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'option-data'],
+ {'name': 'sip-server-dns', 'data': sip_server})
+
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'pools'],
+ {'pool': f'{range_start} - {range_stop}'})
client_base = 1
for client in ['client1', 'client2', 'client3']:
cid = '00:01:00:01:12:34:56:78:aa:bb:cc:dd:ee:{}'.format(client_base)
ip = inc_ip(subnet, client_base)
prefix = inc_ip(subnet, client_base << 64) + '/64'
- self.assertIn(f'host {shared_net_name}_{client}' + ' {', config)
- self.assertIn(f'fixed-address6 {ip};', config)
- self.assertIn(f'fixed-prefix6 {prefix};', config)
- self.assertIn(f'host-identifier option dhcp6.client-id {cid};', config)
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'reservations'],
+ {'duid': cid, 'ip-addresses': [ip], 'prefixes': [prefix]})
+
client_base += 1
# Check for running process
@@ -138,22 +202,34 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
range_start = inc_ip(subnet, 256) # ::100
range_stop = inc_ip(subnet, 65535) # ::ffff
delegate_start = '2001:db8:ee::'
- delegate_stop = '2001:db8:ee:ff00::'
- delegate_len = '56'
+ delegate_len = '64'
+ prefix_len = '56'
pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
self.cli_set(pool + ['address-range', 'start', range_start, 'stop', range_stop])
- self.cli_set(pool + ['prefix-delegation', 'start', delegate_start, 'stop', delegate_stop])
- self.cli_set(pool + ['prefix-delegation', 'start', delegate_start, 'prefix-length', delegate_len])
+ self.cli_set(pool + ['prefix-delegation', 'prefix', delegate_start, 'delegated-length', delegate_len])
+ self.cli_set(pool + ['prefix-delegation', 'prefix', delegate_start, 'prefix-length', prefix_len])
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
- self.assertIn(f'subnet6 {subnet}' + r' {', config)
- self.assertIn(f'range6 {range_start} {range_stop};', config)
- self.assertIn(f'prefix6 {delegate_start} {delegate_stop} /{delegate_len};', config)
+ config = read_file(KEA6_CONF)
+ obj = loads(config)
+
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'subnet', subnet)
+
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'pools'],
+ {'pool': f'{range_start} - {range_stop}'})
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'shared-networks', 0, 'subnet6', 0, 'pd-pools'],
+ {'prefix': delegate_start, 'prefix-len': int(prefix_len), 'delegated-len': int(delegate_len)})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
@@ -170,10 +246,16 @@ class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase):
# commit changes
self.cli_commit()
- config = read_file(DHCPD_CONF)
- self.assertIn(f'option dhcp6.name-servers {ns_global_1}, {ns_global_2};', config)
- self.assertIn(f'subnet6 {subnet}' + r' {', config)
- self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+ config = read_file(KEA6_CONF)
+ obj = loads(config)
+
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp6', 'shared-networks', 0, 'subnet6'], 'subnet', subnet)
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp6', 'option-data'],
+ {'name': 'dns-servers', "code": 23, "space": "dhcp6", "csv-format": True, 'data': f'{ns_global_1}, {ns_global_2}'})
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
diff --git a/smoketest/scripts/cli/test_service_dns_dynamic.py b/smoketest/scripts/cli/test_service_dns_dynamic.py
index cb3d90593..ae46b18ba 100755
--- a/smoketest/scripts/cli/test_service_dns_dynamic.py
+++ b/smoketest/scripts/cli/test_service_dns_dynamic.py
@@ -17,8 +17,6 @@
import os
import unittest
import tempfile
-import random
-import string
from base_vyostest_shim import VyOSUnitTestSHIM
@@ -67,14 +65,12 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase):
self.cli_set(name_path + [svc, 'address', interface])
self.cli_set(name_path + [svc, 'host-name', hostname])
self.cli_set(name_path + [svc, 'password', password])
- self.cli_set(name_path + [svc, 'zone', zone])
- self.cli_set(name_path + [svc, 'ttl', ttl])
for opt, value in details.items():
self.cli_set(name_path + [svc, opt, value])
- # 'zone' option is supported and required by 'cloudfare', but not 'freedns' and 'zoneedit'
+ # 'zone' option is supported by 'cloudfare' and 'zoneedit1', but not 'freedns'
self.cli_set(name_path + [svc, 'zone', zone])
- if details['protocol'] == 'cloudflare':
+ if details['protocol'] in ['cloudflare', 'zoneedit1']:
pass
else:
# exception is raised for unsupported ones
@@ -292,9 +288,38 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase):
self.assertIn(f'password=\'{password}\'', ddclient_conf)
self.assertIn(f'{hostname}', ddclient_conf)
- def test_07_dyndns_vrf(self):
+ def test_07_dyndns_dynamic_interface(self):
+ # Check if DDNS service can be configured and runs
+ svc_path = name_path + ['namecheap']
+ proto = 'namecheap'
+ dyn_interface = 'pppoe587'
+
+ self.cli_set(svc_path + ['address', dyn_interface])
+ self.cli_set(svc_path + ['protocol', proto])
+ self.cli_set(svc_path + ['server', server])
+ self.cli_set(svc_path + ['username', username])
+ self.cli_set(svc_path + ['password', password])
+ self.cli_set(svc_path + ['host-name', hostname])
+
+ # Dynamic interface will raise a warning but still go through
+ # XXX: We should have idiomatic class "ConfigSessionWarning" wrapping
+ # "Warning" similar to "ConfigSessionError".
+ # with self.assertWarns(Warning):
+ # self.cli_commit()
+ self.cli_commit()
+
+ # Check the generating config parameters
+ ddclient_conf = cmd(f'sudo cat {DDCLIENT_CONF}')
+ self.assertIn(f'ifv4={dyn_interface}', ddclient_conf)
+ self.assertIn(f'protocol={proto}', ddclient_conf)
+ self.assertIn(f'server={server}', ddclient_conf)
+ self.assertIn(f'login={username}', ddclient_conf)
+ self.assertIn(f'password=\'{password}\'', ddclient_conf)
+ self.assertIn(f'{hostname}', ddclient_conf)
+
+ def test_08_dyndns_vrf(self):
# Table number randomized, but should be within range 100-65535
- vrf_table = "".join(random.choices(string.digits, k=4))
+ vrf_table = '58710'
vrf_name = f'vyos-test-{vrf_table}'
svc_path = name_path + ['cloudflare']
proto = 'cloudflare'
diff --git a/smoketest/scripts/cli/test_service_https.py b/smoketest/scripts/cli/test_service_https.py
index 6cb91bcf1..703e3e8c4 100755
--- a/smoketest/scripts/cli/test_service_https.py
+++ b/smoketest/scripts/cli/test_service_https.py
@@ -23,6 +23,7 @@ from urllib3.exceptions import InsecureRequestWarning
from base_vyostest_shim import VyOSUnitTestSHIM
from base_vyostest_shim import ignore_warning
from vyos.utils.file import read_file
+from vyos.utils.process import call
from vyos.utils.process import process_named_running
from vyos.configsession import ConfigSessionError
@@ -51,6 +52,23 @@ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx
u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww
"""
+# to test load config via HTTP URL
+nginx_conf_smoketest = """
+server {
+ listen 8000;
+ server_name localhost;
+
+ root /tmp;
+
+ index index.html;
+
+ location / {
+ try_files $uri $uri/ =404;
+ autoindex on;
+ }
+}
+"""
+
PROCESS_NAME = 'nginx'
class TestHTTPSService(VyOSUnitTestSHIM.TestCase):
@@ -375,6 +393,57 @@ class TestHTTPSService(VyOSUnitTestSHIM.TestCase):
r = request('POST', url, verify=False, headers=headers, data=payload)
self.assertEqual(r.status_code, 200)
+ @ignore_warning(InsecureRequestWarning)
+ def test_api_config_file_load_http(self):
+ """Test load config from HTTP URL
+ """
+ address = '127.0.0.1'
+ key = 'VyOS-key'
+ url = f'https://{address}/config-file'
+ url_config = f'https://{address}/configure'
+ headers = {}
+ tmp_file = 'tmp-config.boot'
+ nginx_tmp_site = '/etc/nginx/sites-enabled/smoketest'
+
+ self.cli_set(base_path + ['api', 'keys', 'id', 'key-01', 'key', key])
+ self.cli_commit()
+
+ # load config via HTTP requires nginx config
+ call(f'sudo touch {nginx_tmp_site}')
+ call(f'sudo chown vyos:vyattacfg {nginx_tmp_site}')
+ call(f'sudo chmod +w {nginx_tmp_site}')
+
+ with open(nginx_tmp_site, 'w') as f:
+ f.write(nginx_conf_smoketest)
+ call('sudo nginx -s reload')
+
+ # save config
+ payload = {
+ 'data': '{"op": "save", "file": "/tmp/tmp-config.boot"}',
+ 'key': f'{key}',
+ }
+ r = request('POST', url, verify=False, headers=headers, data=payload)
+ self.assertEqual(r.status_code, 200)
+
+ # change config
+ payload = {
+ 'data': '{"op": "set", "path": ["interfaces", "dummy", "dum1", "address", "192.0.2.31/32"]}',
+ 'key': f'{key}',
+ }
+ r = request('POST', url_config, verify=False, headers=headers, data=payload)
+ self.assertEqual(r.status_code, 200)
+
+ # load config from URL
+ payload = {
+ 'data': '{"op": "load", "file": "http://localhost:8000/tmp-config.boot"}',
+ 'key': f'{key}',
+ }
+ r = request('POST', url, verify=False, headers=headers, data=payload)
+ self.assertEqual(r.status_code, 200)
+
+ # cleanup tmp nginx conf
+ call(f'sudo rm -rf {nginx_tmp_site}')
+ call('sudo nginx -s reload')
if __name__ == '__main__':
unittest.main(verbosity=5)