[smart_switch][dhcp_server] Add smart_switch support in dhcpservd (#17576)

* [smart_switch][dhcp_server] Add related checker for smart_switch in dhcp_db_monitor
* [smart_switch][dhcp_server] Add smart_switch support in dhcpservd
This commit is contained in:
Yaqiang Zhu 2024-01-10 07:40:11 +08:00 committed by GitHub
parent e30782b0fe
commit b2ca36aa1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 32 deletions

View File

@ -163,3 +163,14 @@ def get_target_process_cmds(process_name):
if proc.name() == process_name: if proc.name() == process_name:
res.append(proc.cmdline()) res.append(proc.cmdline())
return res return res
def is_smart_switch(device_metadata):
"""
Check in device metadata whether subtype is smartswitch
Args:
device_metadata: DEVICE_METADATA table
Returns:
If subtype is "SmartSwitch", return True. Else, return False
"""
return device_metadata.get("localhost", {}).get("subtype", "") == "SmartSwitch"

View File

@ -5,7 +5,7 @@ import os
import syslog import syslog
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from dhcp_utilities.common.utils import merge_intervals, validate_str_type from dhcp_utilities.common.utils import merge_intervals, validate_str_type, is_smart_switch
PORT_MAP_PATH = "/tmp/port-name-alias-map.txt" PORT_MAP_PATH = "/tmp/port-name-alias-map.txt"
UNICODE_TYPE = str UNICODE_TYPE = str
@ -15,9 +15,12 @@ DHCP_SERVER_IPV4_RANGE = "DHCP_SERVER_IPV4_RANGE"
DHCP_SERVER_IPV4_PORT = "DHCP_SERVER_IPV4_PORT" DHCP_SERVER_IPV4_PORT = "DHCP_SERVER_IPV4_PORT"
VLAN_INTERFACE = "VLAN_INTERFACE" VLAN_INTERFACE = "VLAN_INTERFACE"
VLAN_MEMBER = "VLAN_MEMBER" VLAN_MEMBER = "VLAN_MEMBER"
DPUS = "DPUS"
MID_PLANE_BRIDGE = "MID_PLANE_BRIDGE"
PORT_MODE_CHECKER = ["DhcpServerTableCfgChangeEventChecker", "DhcpPortTableEventChecker", "DhcpRangeTableEventChecker", PORT_MODE_CHECKER = ["DhcpServerTableCfgChangeEventChecker", "DhcpPortTableEventChecker", "DhcpRangeTableEventChecker",
"DhcpOptionTableEventChecker", "VlanTableEventChecker", "VlanIntfTableEventChecker", "DhcpOptionTableEventChecker", "VlanTableEventChecker", "VlanIntfTableEventChecker",
"VlanMemberTableEventChecker"] "VlanMemberTableEventChecker"]
SMART_SWITCH_CHECKER = ["DpusTableEventChecker", "MidPlaneTableEventChecker"]
LEASE_UPDATE_SCRIPT_PATH = "/etc/kea/lease_update.sh" LEASE_UPDATE_SCRIPT_PATH = "/etc/kea/lease_update.sh"
DEFAULT_LEASE_TIME = 900 DEFAULT_LEASE_TIME = 900
DEFAULT_LEASE_PATH = "/tmp/kea-lease.csv" DEFAULT_LEASE_PATH = "/tmp/kea-lease.csv"
@ -58,21 +61,62 @@ class DhcpServCfgGenerator(object):
# Get host name # Get host name
device_metadata = self.db_connector.get_config_db_table("DEVICE_METADATA") device_metadata = self.db_connector.get_config_db_table("DEVICE_METADATA")
hostname = self._parse_hostname(device_metadata) hostname = self._parse_hostname(device_metadata)
smart_switch = is_smart_switch(device_metadata)
# Get ip information of vlan # Get ip information of vlan
vlan_interface = self.db_connector.get_config_db_table(VLAN_INTERFACE) vlan_interface = self.db_connector.get_config_db_table(VLAN_INTERFACE)
vlan_member_table = self.db_connector.get_config_db_table(VLAN_MEMBER) vlan_member_table = self.db_connector.get_config_db_table(VLAN_MEMBER)
vlan_interfaces, vlan_members = self._parse_vlan(vlan_interface, vlan_member_table) vlan_interfaces, vlan_members = self._parse_vlan(vlan_interface, vlan_member_table)
# Parse dpu
dpus_table = self.db_connector.get_config_db_table(DPUS)
mid_plane_table = self.db_connector.get_config_db_table(MID_PLANE_BRIDGE)
mid_plane, dpus = self._parse_dpu(dpus_table, mid_plane_table) if smart_switch else {}, {}
dhcp_server_ipv4, customized_options_ipv4, range_ipv4, port_ipv4 = self._get_dhcp_ipv4_tables_from_db() dhcp_server_ipv4, customized_options_ipv4, range_ipv4, port_ipv4 = self._get_dhcp_ipv4_tables_from_db()
# Parse range table # Parse range table
ranges = self._parse_range(range_ipv4) ranges = self._parse_range(range_ipv4)
# Parse port table # Parse port table
port_ips, used_ranges = self._parse_port(port_ipv4, vlan_interfaces, vlan_members, ranges) dhcp_interfaces = vlan_interfaces
if smart_switch and "bridge" in mid_plane and "ip_prefix" in mid_plane:
mid_plane_name = mid_plane["bridge"]
dhcp_interfaces[mid_plane_name] = [{
"network": ipaddress.ip_network(mid_plane["ip_prefix"], strict=False),
"ip": mid_plane["ip_prefix"]
}]
dpus = ["{}|{}".format(mid_plane_name, dpu) for dpu in dpus]
dhcp_members = vlan_members | set(dpus)
port_ips, used_ranges = self._parse_port(port_ipv4, dhcp_interfaces, dhcp_members, ranges)
customized_options = self._parse_customized_options(customized_options_ipv4) customized_options = self._parse_customized_options(customized_options_ipv4)
render_obj, enabled_dhcp_interfaces, used_options, subscribe_table = \ render_obj, enabled_dhcp_interfaces, used_options, subscribe_table = \
self._construct_obj_for_template(dhcp_server_ipv4, port_ips, hostname, customized_options) self._construct_obj_for_template(dhcp_server_ipv4, port_ips, hostname, customized_options)
if smart_switch:
subscribe_table |= set(SMART_SWITCH_CHECKER)
return self._render_config(render_obj), used_ranges, enabled_dhcp_interfaces, used_options, subscribe_table return self._render_config(render_obj), used_ranges, enabled_dhcp_interfaces, used_options, subscribe_table
def _parse_dpu(self, dpus_table, mid_plane_table):
"""
Parse dpu related tables
Args:
dpus_table: DPU table dict
mid_plane_table: mid_plane table dict
Returns:
Parsed obj, sample:
mid_plane = {
"bridge": "bridge_midplane",
"address": "169.254.200.254/24"
}
dpus = {
"dpu0"
}
"""
mid_plane = mid_plane_table.get("GLOBAL", {})
dpus = set([dpu_value["midplane_interface"] for dpu_value in dpus_table.values()
if "midplane_interface" in dpu_value])
return mid_plane, dpus
def _parse_customized_options(self, customized_options_ipv4): def _parse_customized_options(self, customized_options_ipv4):
customized_options = {} customized_options = {}
for option_name, config in customized_options_ipv4.items(): for option_name, config in customized_options_ipv4.items():
@ -107,7 +151,7 @@ class DhcpServCfgGenerator(object):
def _parse_vlan(self, vlan_interface, vlan_member): def _parse_vlan(self, vlan_interface, vlan_member):
vlan_interfaces = self._get_vlan_ipv4_interface(vlan_interface.keys()) vlan_interfaces = self._get_vlan_ipv4_interface(vlan_interface.keys())
vlan_members = vlan_member.keys() vlan_members = set(vlan_member.keys())
return vlan_interfaces, vlan_members return vlan_interfaces, vlan_members
def _parse_hostname(self, device_metadata): def _parse_hostname(self, device_metadata):
@ -306,19 +350,19 @@ class DhcpServCfgGenerator(object):
port_ips[dhcp_interface_name][dhcp_interface_ip_str][port].append([range[0], range[1]]) port_ips[dhcp_interface_name][dhcp_interface_ip_str][port].append([range[0], range[1]])
break break
def _parse_port(self, port_ipv4, vlan_interfaces, vlan_members, ranges): def _parse_port(self, port_ipv4, dhcp_interfaces, dhcp_members, ranges):
""" """
Parse content in DHCP_SERVER_IPV4_PORT table to below format, which indicate ip ranges assign to interface. Parse content in DHCP_SERVER_IPV4_PORT table to below format, which indicate ip ranges assign to interface.
Args: Args:
port_ipv4: Table object. port_ipv4: Table object.
vlan_interfaces: Vlan information, sample: dhcp_interfaces: DHCP interfaces information, sample:
{ {
'Vlan1000': [{ 'Vlan1000': [{
'network': IPv4Network('192.168.0.0/24'), 'network': IPv4Network('192.168.0.0/24'),
'ip': '192.168.0.1/24' 'ip': '192.168.0.1/24'
}] }]
} }
vlan_members: List of vlan members dhcp_members: List of DHCP members
ranges: Dict of ranges ranges: Dict of ranges
Returns: Returns:
Dict of dhcp conf, sample: Dict of dhcp conf, sample:
@ -349,23 +393,21 @@ class DhcpServCfgGenerator(object):
continue continue
splits = port_key.split("|") splits = port_key.split("|")
# Skip port not in correct vlan # Skip port not in correct vlan
if port_key not in vlan_members: if port_key not in dhcp_members:
syslog.syslog(syslog.LOG_WARNING, f"Port {splits[1]} is not in {splits[0]}") syslog.syslog(syslog.LOG_WARNING, f"Port {splits[1]} is not in {splits[0]}")
continue continue
# Get dhcp interface name like Vlan1000 # Get dhcp interface name like Vlan1000
dhcp_interface_name = splits[0] dhcp_interface_name = splits[0]
# Get dhcp member interface name like etp1 # Get dhcp member interface name like etp1, be consistent with dhcp_relay, if alias doesn't exist,
if splits[1] not in self.port_alias_map: # use port name directly
syslog.syslog(syslog.LOG_WARNING, f"Cannot find {splits[1]} in port_alias_map") port = self.port_alias_map[splits[1]] if splits[1] in self.port_alias_map else splits[1]
continue if dhcp_interface_name not in dhcp_interfaces:
port = self.port_alias_map[splits[1]]
if dhcp_interface_name not in vlan_interfaces:
syslog.syslog(syslog.LOG_WARNING, f"Interface {dhcp_interface_name} doesn't have IPv4 address") syslog.syslog(syslog.LOG_WARNING, f"Interface {dhcp_interface_name} doesn't have IPv4 address")
continue continue
if dhcp_interface_name not in port_ips: if dhcp_interface_name not in port_ips:
port_ips[dhcp_interface_name] = {} port_ips[dhcp_interface_name] = {}
# Get ip information of Vlan # Get ip information of Vlan
dhcp_interface = vlan_interfaces[dhcp_interface_name] dhcp_interface = dhcp_interfaces[dhcp_interface_name]
for dhcp_interface_ip in dhcp_interface: for dhcp_interface_ip in dhcp_interface:
ip_ports[str(dhcp_interface_ip["network"])] = dhcp_interface_name ip_ports[str(dhcp_interface_ip["network"])] = dhcp_interface_name

View File

@ -9,7 +9,7 @@ from .dhcp_lease import LeaseManager
from dhcp_utilities.common.utils import DhcpDbConnector from dhcp_utilities.common.utils import DhcpDbConnector
from dhcp_utilities.common.dhcp_db_monitor import DhcpServdDbMonitor, DhcpServerTableCfgChangeEventChecker, \ from dhcp_utilities.common.dhcp_db_monitor import DhcpServdDbMonitor, DhcpServerTableCfgChangeEventChecker, \
DhcpOptionTableEventChecker, DhcpRangeTableEventChecker, DhcpPortTableEventChecker, VlanIntfTableEventChecker, \ DhcpOptionTableEventChecker, DhcpRangeTableEventChecker, DhcpPortTableEventChecker, VlanIntfTableEventChecker, \
VlanMemberTableEventChecker, VlanTableEventChecker VlanMemberTableEventChecker, VlanTableEventChecker, MidPlaneTableEventChecker, DpusTableEventChecker
from swsscommon import swsscommon from swsscommon import swsscommon
KEA_DHCP4_CONFIG = "/etc/kea/kea-dhcp4.conf" KEA_DHCP4_CONFIG = "/etc/kea/kea-dhcp4.conf"
@ -110,6 +110,8 @@ def main():
checkers.append(VlanTableEventChecker(sel, dhcp_db_connector.config_db)) checkers.append(VlanTableEventChecker(sel, dhcp_db_connector.config_db))
checkers.append(VlanIntfTableEventChecker(sel, dhcp_db_connector.config_db)) checkers.append(VlanIntfTableEventChecker(sel, dhcp_db_connector.config_db))
checkers.append(VlanMemberTableEventChecker(sel, dhcp_db_connector.config_db)) checkers.append(VlanMemberTableEventChecker(sel, dhcp_db_connector.config_db))
checkers.append(DpusTableEventChecker(sel, dhcp_db_connector.config_db))
checkers.append(MidPlaneTableEventChecker(sel, dhcp_db_connector.config_db))
dhcp_servd_monitor = DhcpServdDbMonitor(dhcp_db_connector, sel, checkers, DEFAULT_SELECT_TIMEOUT) dhcp_servd_monitor = DhcpServdDbMonitor(dhcp_db_connector, sel, checkers, DEFAULT_SELECT_TIMEOUT)
dhcpservd = DhcpServd(dhcp_cfg_generator, dhcp_db_connector, dhcp_servd_monitor) dhcpservd = DhcpServd(dhcp_cfg_generator, dhcp_db_connector, dhcp_servd_monitor)
dhcpservd.start() dhcpservd.start()

View File

@ -14,6 +14,7 @@ VLAN_MEMBER = "VLAN_MEMBER"
PORT_MODE_CHECKER = ["DhcpServerTableCfgChangeEventChecker", "DhcpPortTableEventChecker", "DhcpRangeTableEventChecker", PORT_MODE_CHECKER = ["DhcpServerTableCfgChangeEventChecker", "DhcpPortTableEventChecker", "DhcpRangeTableEventChecker",
"DhcpOptionTableEventChecker", "VlanTableEventChecker", "VlanIntfTableEventChecker", "DhcpOptionTableEventChecker", "VlanTableEventChecker", "VlanIntfTableEventChecker",
"VlanMemberTableEventChecker"] "VlanMemberTableEventChecker"]
SMART_SWITCH_CHECKER = ["DpusTableEventChecker", "MidPlaneTableEventChecker"]
class MockConfigDb(object): class MockConfigDb(object):

View File

@ -2,10 +2,10 @@ import copy
import ipaddress import ipaddress
import json import json
import pytest import pytest
from common_utils import MockConfigDb, mock_get_config_db_table, PORT_MODE_CHECKER from common_utils import MockConfigDb, mock_get_config_db_table, PORT_MODE_CHECKER, SMART_SWITCH_CHECKER
from dhcp_utilities.common.utils import DhcpDbConnector from dhcp_utilities.common.utils import DhcpDbConnector
from dhcp_utilities.dhcpservd.dhcp_cfggen import DhcpServCfgGenerator from dhcp_utilities.dhcpservd.dhcp_cfggen import DhcpServCfgGenerator
from unittest.mock import patch from unittest.mock import patch, MagicMock
expected_dhcp_config = { expected_dhcp_config = {
"Dhcp4": { "Dhcp4": {
@ -165,7 +165,8 @@ expected_parsed_port = {
"Vlan1000": { "Vlan1000": {
"192.168.0.1/21": { "192.168.0.1/21": {
"etp8": [["192.168.0.2", "192.168.0.5"], ["192.168.0.10", "192.168.0.10"]], "etp8": [["192.168.0.2", "192.168.0.5"], ["192.168.0.10", "192.168.0.10"]],
"etp7": [["192.168.0.7", "192.168.0.7"]] "etp7": [["192.168.0.7", "192.168.0.7"]],
"Ethernet40": [["192.168.0.10", "192.168.0.10"]]
} }
} }
} }
@ -302,8 +303,8 @@ def test_parse_vlan(mock_swsscommon_dbconnector_init, mock_parse_port_map_alias,
vlan_interfaces, vlan_members = dhcp_cfg_generator._parse_vlan(mock_config_db.config_db.get("VLAN_INTERFACE"), vlan_interfaces, vlan_members = dhcp_cfg_generator._parse_vlan(mock_config_db.config_db.get("VLAN_INTERFACE"),
mock_config_db.config_db.get("VLAN_MEMBER")) mock_config_db.config_db.get("VLAN_MEMBER"))
assert vlan_interfaces == expected_vlan_ipv4_interface assert vlan_interfaces == expected_vlan_ipv4_interface
expeceted_members = ["Vlan1000|Ethernet24", "Vlan1000|Ethernet28", "Vlan1000|Ethernet40", "Vlan3000|Ethernet44"] assert vlan_members == set(["Vlan1000|Ethernet24", "Vlan1000|Ethernet28", "Vlan1000|Ethernet40",
assert list(vlan_members) == expeceted_members "Vlan3000|Ethernet44"])
@pytest.mark.parametrize("test_config_db", ["mock_config_db.json", "mock_config_db_without_port_config.json"]) @pytest.mark.parametrize("test_config_db", ["mock_config_db.json", "mock_config_db_without_port_config.json"])
@ -323,17 +324,22 @@ def test_parse_port(test_config_db, mock_swsscommon_dbconnector_init, mock_get_r
if test_config_db == "mock_config_db.json" else set()) if test_config_db == "mock_config_db.json" else set())
def test_generate(mock_swsscommon_dbconnector_init, mock_parse_port_map_alias, mock_get_render_template): @pytest.mark.parametrize("mid_plane", [{}, {"bridge": "mid_plane", "ip_prefix": "192.168.0.1/24"}])
@pytest.mark.parametrize("is_smart_switch", [True, False])
def test_generate(mock_swsscommon_dbconnector_init, mock_parse_port_map_alias, mock_get_render_template, mid_plane,
is_smart_switch):
with patch.object(DhcpServCfgGenerator, "_parse_hostname"), \ with patch.object(DhcpServCfgGenerator, "_parse_hostname"), \
patch.object(DhcpServCfgGenerator, "_parse_vlan", return_value=(None, None)), \ patch.object(DhcpServCfgGenerator, "_parse_vlan", return_value=({}, set(["Ethernet0"]))), \
patch.object(DhcpServCfgGenerator, "_get_dhcp_ipv4_tables_from_db", return_value=(None, None, None, None)), \ patch.object(DhcpServCfgGenerator, "_get_dhcp_ipv4_tables_from_db", return_value=(None, None, None, None)), \
patch.object(DhcpServCfgGenerator, "_parse_range"), \ patch.object(DhcpServCfgGenerator, "_parse_range"), \
patch.object(DhcpServCfgGenerator, "_parse_port", return_value=(None, set(["range1"]))), \ patch.object(DhcpServCfgGenerator, "_parse_port", return_value=(None, set(["range1"]))), \
patch.object(DhcpServCfgGenerator, "_parse_customized_options"), \ patch.object(DhcpServCfgGenerator, "_parse_customized_options"), \
patch.object(DhcpServCfgGenerator, "_parse_dpu", side_effect=[mid_plane, set()]), \
patch.object(DhcpServCfgGenerator, "_construct_obj_for_template", patch.object(DhcpServCfgGenerator, "_construct_obj_for_template",
return_value=(None, set(["Vlan1000"]), set(["option1"]), set(["dummy"]))), \ return_value=(None, set(["Vlan1000"]), set(["option1"]), set(["dummy"]))), \
patch.object(DhcpServCfgGenerator, "_render_config", return_value="dummy_config"), \ patch.object(DhcpServCfgGenerator, "_render_config", return_value="dummy_config"), \
patch.object(DhcpDbConnector, "get_config_db_table", side_effect=mock_get_config_db_table): patch.object(DhcpDbConnector, "get_config_db_table", side_effect=mock_get_config_db_table), \
patch("dhcp_utilities.dhcpservd.dhcp_cfggen.is_smart_switch", return_value=is_smart_switch):
dhcp_db_connector = DhcpDbConnector() dhcp_db_connector = DhcpDbConnector()
dhcp_cfg_generator = DhcpServCfgGenerator(dhcp_db_connector) dhcp_cfg_generator = DhcpServCfgGenerator(dhcp_db_connector)
kea_dhcp4_config, used_ranges, enabled_dhcp_interfaces, used_options, subscribe_table = \ kea_dhcp4_config, used_ranges, enabled_dhcp_interfaces, used_options, subscribe_table = \
@ -342,7 +348,11 @@ def test_generate(mock_swsscommon_dbconnector_init, mock_parse_port_map_alias, m
assert used_ranges == set(["range1"]) assert used_ranges == set(["range1"])
assert enabled_dhcp_interfaces == set(["Vlan1000"]) assert enabled_dhcp_interfaces == set(["Vlan1000"])
assert used_options == set(["option1"]) assert used_options == set(["option1"])
assert subscribe_table == set(["dummy"]) expected_tables = set(["dummy"])
if is_smart_switch:
expected_tables |= set(["DpusTableEventChecker", "MidPlaneTableEventChecker"])
assert subscribe_table == expected_tables
def test_construct_obj_for_template(mock_swsscommon_dbconnector_init, mock_parse_port_map_alias, def test_construct_obj_for_template(mock_swsscommon_dbconnector_init, mock_parse_port_map_alias,
@ -414,3 +424,13 @@ def test_parse_customized_options(mock_swsscommon_dbconnector_init, mock_get_ren
} }
else: else:
assert customized_options == {} assert customized_options == {}
def test_parse_dpus(mock_swsscommon_dbconnector_init, mock_get_render_template, mock_parse_port_map_alias):
dhcp_db_connector = DhcpDbConnector()
dhcp_cfg_generator = DhcpServCfgGenerator(dhcp_db_connector)
dpus_table = {"dpu0": {"midplane_interface": "dpu0"}}
mid_plane_table = {"GLOBAL": {"bridge": "bridge_midplane", "ip_prefix": "169.254.200.254/24"}}
mid_plane, dpus = dhcp_cfg_generator._parse_dpu(dpus_table, mid_plane_table)
assert mid_plane == {"bridge": "bridge_midplane", "ip_prefix": "169.254.200.254/24"}
assert dpus == set(["dpu0"])

View File

@ -369,7 +369,7 @@ def test_feature_table_checker(mock_swsscommon_dbconnector_init, tested_data, te
assert expected_res == check_res assert expected_res == check_res
@pytest.mark.parametrize("tested_db_snapshot", [{"enabled_dhcp_interfaces": {"bridge_midplane": ["dpu0"]}}, {}]) @pytest.mark.parametrize("tested_db_snapshot", [{"enabled_dhcp_interfaces": {"bridge_midplane"}}, {}])
@pytest.mark.parametrize("tested_data", get_subscribe_table_tested_data("test_mid_plane_update")) @pytest.mark.parametrize("tested_data", get_subscribe_table_tested_data("test_mid_plane_update"))
def test_mid_plane_table_checker(mock_swsscommon_dbconnector_init, tested_data, tested_db_snapshot): def test_mid_plane_table_checker(mock_swsscommon_dbconnector_init, tested_data, tested_db_snapshot):
with patch.object(ConfigDbEventChecker, "enable"), \ with patch.object(ConfigDbEventChecker, "enable"), \
@ -386,9 +386,8 @@ def test_mid_plane_table_checker(mock_swsscommon_dbconnector_init, tested_data,
assert expected_res == check_res assert expected_res == check_res
@pytest.mark.parametrize("tested_db_snapshot", [{"enabled_dhcp_interfaces": {"bridge_midplane": ["dpu0"]}}, {}])
@pytest.mark.parametrize("tested_data", get_subscribe_table_tested_data("test_dpus_update")) @pytest.mark.parametrize("tested_data", get_subscribe_table_tested_data("test_dpus_update"))
def test_dpus_table_checker(mock_swsscommon_dbconnector_init, tested_data, tested_db_snapshot): def test_dpus_table_checker(mock_swsscommon_dbconnector_init, tested_data):
with patch.object(ConfigDbEventChecker, "enable"), \ with patch.object(ConfigDbEventChecker, "enable"), \
patch.object(ConfigDbEventChecker, "subscriber_state_table", patch.object(ConfigDbEventChecker, "subscriber_state_table",
return_value=MockSubscribeTable(tested_data["table"]), new_callable=PropertyMock), \ return_value=MockSubscribeTable(tested_data["table"]), new_callable=PropertyMock), \
@ -396,8 +395,5 @@ def test_dpus_table_checker(mock_swsscommon_dbconnector_init, tested_data, teste
sel = swsscommon.Select() sel = swsscommon.Select()
db_event_checker = DpusTableEventChecker(sel, MagicMock()) db_event_checker = DpusTableEventChecker(sel, MagicMock())
expected_res = tested_data["exp_res"] expected_res = tested_data["exp_res"]
check_res = db_event_checker.check_update_event(tested_db_snapshot) check_res = db_event_checker.check_update_event({})
if "enabled_dhcp_interfaces" not in tested_db_snapshot: assert expected_res == check_res
assert check_res
else:
assert expected_res == check_res

View File

@ -152,3 +152,9 @@ def test_get_target_process_cmds():
] ]
] ]
assert res == expected_res assert res == expected_res
@pytest.mark.parametrize("is_smart_switch", [True, False])
def test_is_smart_switch(is_smart_switch):
device_metadata = {"localhost": {"subtype": "SmartSwitch"}} if is_smart_switch else {"localhost": {}}
assert utils.is_smart_switch(device_metadata) == is_smart_switch