Skip to content

Commit ad5e3b8

Browse files
authored
Add ExclusionList for telemetry/frr_bmp since they are not service in pub repo (#328)
Add whitelist for telemetry/frr_bmp since they are not service in pub repo
1 parent f71a758 commit ad5e3b8

File tree

4 files changed

+55
-142
lines changed

4 files changed

+55
-142
lines changed

host_modules/docker_service.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
"swss",
2626
"syncd",
2727
"teamd",
28-
"telemetry",
2928
}
3029

3130
# The set of allowed images that can be managed by this service.
@@ -42,7 +41,6 @@
4241
"docker-sonic-bmp",
4342
"docker-sonic-gnmi",
4443
"docker-sonic-restapi",
45-
"docker-sonic-telemetry",
4644
"docker-syncd-brcm",
4745
"docker-syncd-cisco",
4846
"docker-teamd",

scripts/featured

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class FeatureHandler(object):
132132
FEATURE_STATE_ENABLED = "enabled"
133133
FEATURE_STATE_DISABLED = "disabled"
134134
FEATURE_STATE_FAILED = "failed"
135+
FEATURE_EXCLUSION_LIST = {"telemetry", "frr_bmp"}
135136

136137
def __init__(self, config_db, feature_state_table, device_config, is_advanced_boot):
137138
self._config_db = config_db
@@ -408,7 +409,15 @@ class FeatureHandler(object):
408409
props = dict([line.split("=") for line in stdout.decode().strip().splitlines()])
409410
return props["UnitFileState"]
410411

412+
def is_exclusion_listed(self, feature_name):
413+
"""Return True if the feature is in the exclusion list."""
414+
return str(feature_name).lower() in self.FEATURE_EXCLUSION_LIST
415+
411416
def enable_feature(self, feature):
417+
if self.is_exclusion_listed(feature.name):
418+
syslog.syslog(syslog.LOG_INFO, f"ExclusionList: skip enabling '{feature.name}'")
419+
return
420+
412421
feature_names, feature_suffixes = self.get_multiasic_feature_instances(feature)
413422
for feature_name in feature_names:
414423
# Check if it is already enabled, if yes skip the system call
@@ -452,6 +461,10 @@ class FeatureHandler(object):
452461
self.set_feature_state(feature, self.FEATURE_STATE_ENABLED)
453462

454463
def disable_feature(self, feature):
464+
if self.is_exclusion_listed(feature.name):
465+
syslog.syslog(syslog.LOG_INFO, f"ExclusionList: skip disabling '{feature.name}'")
466+
return
467+
455468
feature_names, feature_suffixes = self.get_multiasic_feature_instances(feature)
456469
for feature_name in feature_names:
457470
# Check if it is already disabled, if yes skip the system call

tests/featured/featured_test.py

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,43 @@ def test_port_init_done_twice(self):
339339
feature_handler.port_listener(key='PortInitDone', op='SET', data=None)
340340
feature_handler.enable_delayed_services.assert_called_once()
341341

342+
@mock.patch("syslog.syslog", side_effect=syslog_side_effect)
343+
def test_enable_and_disable_feature_ExclusionList_skips_actions(self, mock_syslog):
344+
"""Verify that ExclusionList feature 'frr_bmp' is skipped in both enable and disable."""
345+
feature_state_table_mock = mock.Mock()
346+
device_cfg = {"DEVICE_METADATA": {"localhost": {"type": "FixedSwitch"}}}
347+
handler = featured.FeatureHandler(MockConfigDb(), feature_state_table_mock, device_cfg, False)
348+
349+
feat_cfg = {"state": "enabled", "auto_restart": "enabled"}
350+
feature = featured.Feature("frr_bmp", feat_cfg, device_cfg)
351+
352+
with mock.patch.object(handler, "get_multiasic_feature_instances",
353+
return_value=(["frr_bmp"], ["service"])), \
354+
mock.patch.object(handler, "get_systemd_unit_state", return_value="disabled"), \
355+
mock.patch("featured.run_cmd") as mocked_run_cmd, \
356+
mock.patch.object(handler, "set_feature_state") as mocked_set_state:
357+
358+
# --- enable_feature() ---
359+
handler.enable_feature(feature)
360+
361+
mocked_run_cmd.assert_not_called()
362+
mocked_set_state.assert_not_called()
363+
assert any("ExclusionList: skip enabling 'frr_bmp'" in str(c.args[1]) for c in mock_syslog.call_args_list)
364+
365+
mock_syslog.reset_mock()
366+
with mock.patch.object(handler, "get_multiasic_feature_instances",
367+
return_value=(["frr_bmp"], ["service"])), \
368+
mock.patch.object(handler, "get_systemd_unit_state", return_value="enabled"), \
369+
mock.patch("featured.run_cmd") as mocked_run_cmd, \
370+
mock.patch.object(handler, "set_feature_state") as mocked_set_state:
371+
372+
# --- disable_feature() ---
373+
handler.disable_feature(feature)
374+
375+
mocked_run_cmd.assert_not_called()
376+
mocked_set_state.assert_not_called()
377+
assert any("ExclusionList: skip disabling 'frr_bmp'" in str(c.args[1]) for c in mock_syslog.call_args_list)
378+
342379

343380
@mock.patch("syslog.syslog", side_effect=syslog_side_effect)
344381
@mock.patch('sonic_py_common.device_info.get_device_runtime_metadata')
@@ -361,8 +398,7 @@ def tearDown(self):
361398

362399
def test_feature_events(self, mock_syslog, get_runtime):
363400
MockSelect.set_event_queue([('FEATURE', 'dhcp_relay'),
364-
('FEATURE', 'mux'),
365-
('FEATURE', 'telemetry')])
401+
('FEATURE', 'mux')])
366402
with mock.patch('featured.subprocess') as mocked_subprocess:
367403
popen_mock = mock.Mock()
368404
attrs = {'communicate.return_value': ('output', 'error')}
@@ -401,7 +437,6 @@ def test_feature_events(self, mock_syslog, get_runtime):
401437
def test_delayed_service(self, mock_syslog, get_runtime):
402438
MockSelect.set_event_queue([('FEATURE', 'dhcp_relay'),
403439
('FEATURE', 'mux'),
404-
('FEATURE', 'telemetry'),
405440
('PORT_TABLE', 'PortInitDone')])
406441
# Note: To simplify testing, subscriberstatetable only read from CONFIG_DB
407442
MockConfigDb.CONFIG_DB['PORT_TABLE'] = {'PortInitDone': {'lanes': '0'}, 'PortConfigDone': {'val': 'true'}}
@@ -424,11 +459,7 @@ def test_delayed_service(self, mock_syslog, get_runtime):
424459
call(['sudo', 'systemctl', 'daemon-reload'], capture_output=True, check=True, text=True),
425460
call(['sudo', 'systemctl', 'unmask', 'mux.service'], capture_output=True, check=True, text=True),
426461
call(['sudo', 'systemctl', 'enable', 'mux.service'], capture_output=True, check=True, text=True),
427-
call(['sudo', 'systemctl', 'start', 'mux.service'], capture_output=True, check=True, text=True),
428-
call(['sudo', 'systemctl', 'daemon-reload'], capture_output=True, check=True, text=True),
429-
call(['sudo', 'systemctl', 'unmask', 'telemetry.service'], capture_output=True, check=True, text=True),
430-
call(['sudo', 'systemctl', 'enable', 'telemetry.service'], capture_output=True, check=True, text=True),
431-
call(['sudo', 'systemctl', 'start', 'telemetry.service'], capture_output=True, check=True, text=True)]
462+
call(['sudo', 'systemctl', 'start', 'mux.service'], capture_output=True, check=True, text=True)]
432463

433464
mocked_subprocess.run.assert_has_calls(expected, any_order=True)
434465

@@ -454,20 +485,15 @@ def test_advanced_reboot(self, mock_syslog, get_runtime):
454485
call(['sudo', 'systemctl', 'daemon-reload'], capture_output=True, check=True, text=True),
455486
call(['sudo', 'systemctl', 'unmask', 'mux.service'], capture_output=True, check=True, text=True),
456487
call(['sudo', 'systemctl', 'enable', 'mux.service'], capture_output=True, check=True, text=True),
457-
call(['sudo', 'systemctl', 'start', 'mux.service'], capture_output=True, check=True, text=True),
458-
call(['sudo', 'systemctl', 'daemon-reload'], capture_output=True, check=True, text=True),
459-
call(['sudo', 'systemctl', 'unmask', 'telemetry.service'], capture_output=True, check=True, text=True),
460-
call(['sudo', 'systemctl', 'enable', 'telemetry.service'], capture_output=True, check=True, text=True),
461-
call(['sudo', 'systemctl', 'start', 'telemetry.service'], capture_output=True, check=True, text=True)]
488+
call(['sudo', 'systemctl', 'start', 'mux.service'], capture_output=True, check=True, text=True)]
462489

463490
mocked_subprocess.run.assert_has_calls(expected, any_order=True)
464491

465492
def test_portinit_timeout(self, mock_syslog, get_runtime):
466493
print(MockConfigDb.CONFIG_DB)
467494
MockSelect.NUM_TIMEOUT_TRIES = 1
468495
MockSelect.set_event_queue([('FEATURE', 'dhcp_relay'),
469-
('FEATURE', 'mux'),
470-
('FEATURE', 'telemetry')])
496+
('FEATURE', 'mux')])
471497
with mock.patch('featured.subprocess') as mocked_subprocess:
472498
popen_mock = mock.Mock()
473499
attrs = {'communicate.return_value': ('output', 'error')}
@@ -487,9 +513,5 @@ def test_portinit_timeout(self, mock_syslog, get_runtime):
487513
call(['sudo', 'systemctl', 'daemon-reload'], capture_output=True, check=True, text=True),
488514
call(['sudo', 'systemctl', 'unmask', 'mux.service'], capture_output=True, check=True, text=True),
489515
call(['sudo', 'systemctl', 'enable', 'mux.service'], capture_output=True, check=True, text=True),
490-
call(['sudo', 'systemctl', 'start', 'mux.service'], capture_output=True, check=True, text=True),
491-
call(['sudo', 'systemctl', 'daemon-reload'], capture_output=True, check=True, text=True),
492-
call(['sudo', 'systemctl', 'unmask', 'telemetry.service'], capture_output=True, check=True, text=True),
493-
call(['sudo', 'systemctl', 'enable', 'telemetry.service'], capture_output=True, check=True, text=True),
494-
call(['sudo', 'systemctl', 'start', 'telemetry.service'], capture_output=True, check=True, text=True)]
516+
call(['sudo', 'systemctl', 'start', 'mux.service'], capture_output=True, check=True, text=True)]
495517
mocked_subprocess.run.assert_has_calls(expected, any_order=True)

0 commit comments

Comments
 (0)