Skip to content

Commit

Permalink
Update unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexrallen committed Feb 24, 2022
1 parent ec10c3f commit f860ca1
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 117 deletions.
72 changes: 44 additions & 28 deletions src/sonic-host-services/scripts/hostcfgd
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import signal

import jinja2
from sonic_py_common import device_info
from swsscommon.swsscommon import SubscriberStateTable, DBConnector, Select
from swsscommon.swsscommon import ConfigDBConnector, TableConsumable

# FILE
Expand Down Expand Up @@ -195,6 +194,20 @@ class FeatureHandler(object):
else:
self.resync_feature_state(self._cached_config[feature_name])

def update_all_features_config(self, feature_table):
for feature_name in feature_table.keys():
if not feature_name:
syslog.syslog(syslog.LOG_WARNING, "Feature is None")
continue

feature = Feature(feature_name, feature_table[feature_name], self._device_config)
self._cached_config.setdefault(feature_name, feature)

self.update_feature_auto_restart(feature)

self.update_feature_state(feature)
self.resync_feature_state(feature)

def sync_state_field(self):
"""
Summary:
Expand Down Expand Up @@ -956,14 +969,8 @@ class HostConfigDaemon:
# before moving forward
self.config_db = ConfigDBConnector()
self.config_db.connect(wait_for_init=True, retry_on=True)
self.dbconn = DBConnector(CFG_DB, 0)
self.selector = Select()
syslog.syslog(syslog.LOG_INFO, 'ConfigDB connect success')

self.select = Select()
self.callbacks = dict()
self.subscriber_map = dict()

# Load DEVICE metadata configurations
self.device_config = {}
self.device_config['DEVICE_METADATA'] = self.config_db.get_table('DEVICE_METADATA')
Expand Down Expand Up @@ -993,6 +1000,9 @@ class HostConfigDaemon:


def load(self):
features = self.config_db.get_table('FEATURE')
self.feature_handler.update_all_features_config(features)

aaa = self.config_db.get_table('AAA')
tacacs_global = self.config_db.get_table('TACPLUS')
tacacs_server = self.config_db.get_table('TACPLUS_SERVER')
Expand All @@ -1002,6 +1012,14 @@ class HostConfigDaemon:
'RADIUS': radius_global, 'RADIUS_SERVER': radius_server}
self.aaacfg.load(aaa, tacacs_global, tacacs_server, radius_global, radius_server)

lpbk_table = self.config_db.get_table('LOOPBACK_INTERFACE')
self.iptables.load(lpbk_table)

# Load NTP configurations
ntp_server = self.config_db.get_table('NTP_SERVER')
ntp_global = self.config_db.get_table('NTP')
self.ntpcfg.load(ntp_global, ntp_server)

try:
dev_meta = self.config_db.get_table('DEVICE_METADATA')
if 'localhost' in dev_meta:
Expand Down Expand Up @@ -1105,36 +1123,34 @@ class HostConfigDaemon:
def register_callbacks(self):

def make_callback(func):
if data is None:
op = "DEL"
else:
op = "SET"

def callback(table, key, data):
if data is None:
op = "DEL"
else:
op = "SET"
return func(key, op, data)

return callback

self.config_db.subscribe('KDUMP', make_callback(self.config_db.kdump_handler), init=True)
self.config_db.subscribe('KDUMP', make_callback(self.kdump_handler))
# Handle FEATURE updates before other tables
self.config_db.subscribe('FEATURE', make_callback(self.config_db.feature_handler.handle), init=True)
self.config_db.subscribe('FEATURE', make_callback(self.feature_handler.handle))
# Handle AAA, TACACS and RADIUS related tables
self.config_db.subscribe('AAA', make_callback(self.config_db.aaa_handler), init=True)
self.config_db.subscribe('TACPLUS', make_callback(self.config_db.tacacs_global_handler), init=True)
self.config_db.subscribe('TACPLUS_SERVER', make_callback(self.config_db.tacacs_server_handler, init=True)
self.config_db.subscribe('RADIUS', make_callback(self.config_db.radius_global_handler), init=True)
self.config_db.subscribe('RADIUS_SERVER', make_callback(self.config_db.radius_server_handler), init=True)
self.config_db.subscribe('AAA', make_callback(self.aaa_handler))
self.config_db.subscribe('TACPLUS', make_callback(self.tacacs_global_handler))
self.config_db.subscribe('TACPLUS_SERVER', make_callback(self.tacacs_server_handler))
self.config_db.subscribe('RADIUS', make_callback(self.radius_global_handler))
self.config_db.subscribe('RADIUS_SERVER', make_callback(self.radius_server_handler))
# Handle IPTables configuration
self.config_db.subscribe('LOOPBACK_INTERFACE', make_callback(self.config_db.lpbk_handler), init=True)
self.config_db.subscribe('LOOPBACK_INTERFACE', make_callback(self.lpbk_handler))
# Handle NTP & NTP_SERVER updates
self.config_db.subscribe('NTP', make_callback(self.config_db.ntp_global_handler), init=True)
self.config_db.subscribe('NTP_SERVER', make_callback(self.config_db.ntp_server_handler), init=True)
self.config_db.subscribe('NTP', make_callback(self.ntp_global_handler))
self.config_db.subscribe('NTP_SERVER', make_callback(self.ntp_server_handler))
# Handle updates to src intf changes in radius
self.config_db.subscribe('MGMT_INTERFACE', make_callback(self.config_db.mgmt_intf_handler), init=True)
self.config_db.subscribe('VLAN_INTERFACE', make_callback(self.config_db.vlan_intf_handler), init=True)
self.config_db.subscribe('VLAN_SUB_INTERFACE', make_callback(self.config_db.vlan_sub_intf_handler), init=True)
self.config_db.subscribe('PORTCHANNEL_INTERFACE', make_callback(self.config_db.portchannel_intf_handler), init=True)
self.config_db.subscribe('INTERFACE', make_callback(self.config_db.phy_intf_handler), init=True)
self.config_db.subscribe('MGMT_INTERFACE', make_callback(self.mgmt_intf_handler))
self.config_db.subscribe('VLAN_INTERFACE', make_callback(self.vlan_intf_handler))
self.config_db.subscribe('VLAN_SUB_INTERFACE', make_callback(self.vlan_sub_intf_handler))
self.config_db.subscribe('PORTCHANNEL_INTERFACE', make_callback(self.portchannel_intf_handler))
self.config_db.subscribe('INTERFACE', make_callback(self.phy_intf_handler))

syslog.syslog(syslog.LOG_INFO,
"Waiting for systemctl to finish initialization")
Expand Down
79 changes: 9 additions & 70 deletions src/sonic-host-services/tests/common/mock_configdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ class MockConfigDb(object):
"""
STATE_DB = None
CONFIG_DB = None
event_queue = []

def __init__(self, **kwargs):
pass
self.handlers = {}

@staticmethod
def set_config_db(test_config_db):
Expand Down Expand Up @@ -44,75 +45,13 @@ def set_entry(self, key, field, data):
def get_table(self, table_name):
return MockConfigDb.CONFIG_DB[table_name]

def subscribe(self, table_name, callback):
self.handlers[table_name] = callback

class MockSelect():

event_queue = []

@staticmethod
def set_event_queue(Q):
MockSelect.event_queue = Q

@staticmethod
def get_event_queue():
return MockSelect.event_queue

@staticmethod
def reset_event_queue():
MockSelect.event_queue = []

def __init__(self):
self.sub_map = {}
self.TIMEOUT = "TIMEOUT"
self.ERROR = "ERROR"

def addSelectable(self, subscriber):
self.sub_map[subscriber.table] = subscriber

def select(self, TIMEOUT):
if not MockSelect.get_event_queue():
raise TimeoutError
table, key = MockSelect.get_event_queue().pop(0)
self.sub_map[table].nextKey(key)
return "OBJECT", self.sub_map[table]


class MockSubscriberStateTable():

FD_INIT = 0

@staticmethod
def generate_fd():
curr = MockSubscriberStateTable.FD_INIT
MockSubscriberStateTable.FD_INIT = curr + 1
return curr

@staticmethod
def reset_fd():
MockSubscriberStateTable.FD_INIT = 0

def __init__(self, conn, table, pop, pri):
self.fd = MockSubscriberStateTable.generate_fd()
self.next_key = ''
self.table = table

def getFd(self):
return self.fd

def nextKey(self, key):
self.next_key = key

def pop(self):
table = MockConfigDb.CONFIG_DB.get(self.table, {})
if self.next_key not in table:
op = "DEL"
fvs = {}
else:
op = "SET"
fvs = table.get(self.next_key, {})
return self.next_key, op, fvs
def listen(self, start):
pass

def process(self, cache):
for e in MockConfigDb.event_queue:
self.handlers[e[0]](e[0], e[1], self.get_entry(e[0], e[1]))

class MockDBConnector():
def __init__(self, db, val):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
from parameterized import parameterized
from unittest import TestCase, mock
from tests.hostcfgd.test_radius_vectors import HOSTCFGD_TEST_RADIUS_VECTOR
from tests.common.mock_configdb import MockConfigDb, MockSubscriberStateTable
from tests.common.mock_configdb import MockSelect, MockDBConnector
from tests.common.mock_configdb import MockConfigDb


test_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Expand All @@ -33,9 +32,6 @@

# Mock swsscommon classes
hostcfgd.ConfigDBConnector = MockConfigDb
hostcfgd.SubscriberStateTable = MockSubscriberStateTable
hostcfgd.Select = MockSelect
hostcfgd.DBConnector = MockDBConnector


class TestHostcfgdRADIUS(TestCase):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
from parameterized import parameterized
from unittest import TestCase, mock
from tests.hostcfgd.test_tacacs_vectors import HOSTCFGD_TEST_TACACS_VECTOR
from tests.common.mock_configdb import MockConfigDb, MockSubscriberStateTable
from tests.common.mock_configdb import MockSelect, MockDBConnector
from tests.common.mock_configdb import MockConfigDb

test_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
modules_path = os.path.dirname(test_path)
Expand All @@ -32,9 +31,6 @@

# Mock swsscommon classes
hostcfgd.ConfigDBConnector = MockConfigDb
hostcfgd.SubscriberStateTable = MockSubscriberStateTable
hostcfgd.Select = MockSelect
hostcfgd.DBConnector = MockDBConnector

class TestHostcfgdTACACS(TestCase):
"""
Expand Down
14 changes: 5 additions & 9 deletions src/sonic-host-services/tests/hostcfgd/hostcfgd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
from unittest import TestCase, mock

from .test_vectors import HOSTCFGD_TEST_VECTOR, HOSTCFG_DAEMON_CFG_DB
from tests.common.mock_configdb import MockConfigDb, MockSubscriberStateTable
from tests.common.mock_configdb import MockSelect, MockDBConnector
from tests.common.mock_configdb import MockConfigDb

from pyfakefs.fake_filesystem_unittest import patchfs
from deepdiff import DeepDiff
Expand All @@ -24,9 +23,6 @@
hostcfgd_path = os.path.join(scripts_path, 'hostcfgd')
hostcfgd = load_module_from_source('hostcfgd', hostcfgd_path)
hostcfgd.ConfigDBConnector = MockConfigDb
hostcfgd.SubscriberStateTable = MockSubscriberStateTable
hostcfgd.Select = MockSelect
hostcfgd.DBConnector = MockDBConnector


class TestHostcfgd(TestCase):
Expand Down Expand Up @@ -209,7 +205,7 @@ def tearDown(self):
@patchfs
def test_feature_events(self, fs):
fs.create_dir(hostcfgd.FeatureHandler.SYSTEMD_SYSTEM_DIR)
MockSelect.event_queue = [('FEATURE', 'dhcp_relay'),
MockConfigDb.event_queue = [('FEATURE', 'dhcp_relay'),
('FEATURE', 'mux'),
('FEATURE', 'telemetry')]
daemon = hostcfgd.HostConfigDaemon()
Expand Down Expand Up @@ -240,7 +236,7 @@ def test_feature_events(self, fs):

# Change the state to disabled
MockConfigDb.CONFIG_DB['FEATURE']['telemetry']['state'] = 'disabled'
MockSelect.event_queue = [('FEATURE', 'telemetry')]
MockConfigDb.event_queue = [('FEATURE', 'telemetry')]
try:
daemon.start()
except TimeoutError:
Expand All @@ -255,7 +251,7 @@ def test_feature_events(self, fs):

def test_loopback_events(self):
MockConfigDb.set_config_db(HOSTCFG_DAEMON_CFG_DB)
MockSelect.event_queue = [('NTP', 'global'),
MockConfigDb.event_queue = [('NTP', 'global'),
('NTP_SERVER', '0.debian.pool.ntp.org'),
('LOOPBACK_INTERFACE', 'Loopback0|10.184.8.233/32')]
daemon = hostcfgd.HostConfigDaemon()
Expand All @@ -279,7 +275,7 @@ def test_kdump_event(self):
daemon = hostcfgd.HostConfigDaemon()
daemon.register_callbacks()
assert MockConfigDb.CONFIG_DB['KDUMP']['config']
MockSelect.event_queue = [('KDUMP', 'config')]
MockConfigDb.event_queue = [('KDUMP', 'config')]
with mock.patch('hostcfgd.subprocess') as mocked_subprocess:
popen_mock = mock.Mock()
attrs = {'communicate.return_value': ('output', 'error')}
Expand Down

0 comments on commit f860ca1

Please sign in to comment.