summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/service_dhcp-server.xml.in21
-rw-r--r--python/vyos/template.py15
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcp-server.py65
-rwxr-xr-xsrc/conf_mode/service_dhcp-server.py8
-rwxr-xr-xsrc/op_mode/generate_tech-support_archive.py2
5 files changed, 104 insertions, 7 deletions
diff --git a/interface-definitions/service_dhcp-server.xml.in b/interface-definitions/service_dhcp-server.xml.in
index 2afa05a8a..cb5f9a804 100644
--- a/interface-definitions/service_dhcp-server.xml.in
+++ b/interface-definitions/service_dhcp-server.xml.in
@@ -22,6 +22,27 @@
</properties>
<children>
#include <include/source-address-ipv4.xml.i>
+ <leafNode name="mode">
+ <properties>
+ <help>Configure high availability mode</help>
+ <completionHelp>
+ <list>active-active active-passive</list>
+ </completionHelp>
+ <valueHelp>
+ <format>active-active</format>
+ <description>Both server attend DHCP requests</description>
+ </valueHelp>
+ <valueHelp>
+ <format>active-passive</format>
+ <description>Only primary server attends DHCP requests</description>
+ </valueHelp>
+ <constraint>
+ <regex>(active-active|active-passive)</regex>
+ </constraint>
+ <constraintErrorMessage>Invalid DHCP high availability mode</constraintErrorMessage>
+ </properties>
+ <defaultValue>active-active</defaultValue>
+ </leafNode>
<leafNode name="remote">
<properties>
<help>IPv4 remote address used for connection</help>
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 3e468eb82..ac77e8a3d 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -823,10 +823,19 @@ def kea_high_availability_json(config):
source_addr = config['source_address']
remote_addr = config['remote']
+ ha_mode = 'hot-standby' if config['mode'] == 'active-passive' else 'load-balancing'
+ ha_role = config['status']
+
+ if ha_role == 'primary':
+ peer1_role = 'primary'
+ peer2_role = 'standby' if ha_mode == 'hot-standby' else 'secondary'
+ else:
+ peer1_role = 'standby' if ha_mode == 'hot-standby' else 'secondary'
+ peer2_role = 'primary'
data = {
'this-server-name': os.uname()[1],
- 'mode': 'hot-standby',
+ 'mode': ha_mode,
'heartbeat-delay': 10000,
'max-response-delay': 10000,
'max-ack-delay': 5000,
@@ -835,13 +844,13 @@ def kea_high_availability_json(config):
{
'name': os.uname()[1],
'url': f'http://{source_addr}:647/',
- 'role': 'standby' if config['status'] == 'secondary' else 'primary',
+ 'role': peer1_role,
'auto-failover': True
},
{
'name': config['name'],
'url': f'http://{remote_addr}:647/',
- 'role': 'primary' if config['status'] == 'secondary' else 'standby',
+ 'role': peer2_role,
'auto-failover': True
}]
}
diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py
index abf40cd3b..46c4e25a1 100755
--- a/smoketest/scripts/cli/test_service_dhcp-server.py
+++ b/smoketest/scripts/cli/test_service_dhcp-server.py
@@ -699,6 +699,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ['high-availability', 'name', failover_name])
self.cli_set(base_path + ['high-availability', 'remote', failover_remote])
self.cli_set(base_path + ['high-availability', 'status', 'primary'])
+ ## No mode defined -> its active-active mode by default
# commit changes
self.cli_commit()
@@ -717,7 +718,69 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
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})
+ {'name': failover_name, 'url': f'http://{failover_remote}:647/', 'role': 'secondary', '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))
+
+ def test_dhcp_high_availability_standby(self):
+ shared_net_name = 'FAILOVER'
+ failover_name = 'VyOS-Failover'
+
+ range_0_start = inc_ip(subnet, 10)
+ range_0_stop = inc_ip(subnet, 20)
+
+ pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
+ self.cli_set(pool + ['subnet-id', '1'])
+ # we use the first subnet IP address as default gateway
+ self.cli_set(pool + ['option', 'default-router', router])
+ self.cli_set(pool + ['range', '0', 'start', range_0_start])
+ self.cli_set(pool + ['range', '0', 'stop', range_0_stop])
+
+ # failover
+ failover_local = router
+ failover_remote = inc_ip(router, 1)
+
+ self.cli_set(base_path + ['high-availability', 'source-address', failover_local])
+ self.cli_set(base_path + ['high-availability', 'name', failover_name])
+ self.cli_set(base_path + ['high-availability', 'remote', failover_remote])
+ self.cli_set(base_path + ['high-availability', 'status', 'secondary'])
+ self.cli_set(base_path + ['high-availability', 'mode', 'active-passive'])
+
+ # commit changes
+ self.cli_commit()
+
+ 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': 'standby', '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': 'primary', '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)
diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py
index bf4454fda..f4fb78f57 100755
--- a/src/conf_mode/service_dhcp-server.py
+++ b/src/conf_mode/service_dhcp-server.py
@@ -143,8 +143,12 @@ def get_config(config=None):
dhcp['shared_network_name'][network]['subnet'][subnet].update(
{'range' : new_range_dict})
- if dict_search('high_availability.certificate', dhcp):
- dhcp['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True)
+ if len(dhcp['high_availability']) == 1:
+ ## only default value for mode is set, need to remove ha node
+ del dhcp['high_availability']
+ else:
+ if dict_search('high_availability.certificate', dhcp):
+ dhcp['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True)
return dhcp
diff --git a/src/op_mode/generate_tech-support_archive.py b/src/op_mode/generate_tech-support_archive.py
index c490b0137..41b53cd15 100755
--- a/src/op_mode/generate_tech-support_archive.py
+++ b/src/op_mode/generate_tech-support_archive.py
@@ -120,7 +120,7 @@ if __name__ == '__main__':
# Temporary directory creation
tmp_dir_path = f'{tmp_path}/drops-debug_{time_now}'
tmp_dir: Path = Path(tmp_dir_path)
- tmp_dir.mkdir()
+ tmp_dir.mkdir(parents=True)
report_file: Path = Path(f'{tmp_dir_path}/show_tech-support_report.txt')
report_file.touch()