Skip to content

Commit 20b4500

Browse files
committed
[config reload]Config Reload Enhancement (sonic-net#2693)
Code changes for HLD: sonic-net/SONiC#1203 Removed the timer based checks for config reload Added db_migrator to migrate from "has_timer" to "delayed" Modified package-manager to migrate from "has_timer" to "delayed" Modified relevant files Added UT to verify
1 parent 984983e commit 20b4500

10 files changed

Lines changed: 70 additions & 157 deletions

File tree

config/main.py

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -869,23 +869,8 @@ def _get_sonic_services():
869869
return (unit.strip() for unit in out.splitlines())
870870

871871

872-
def _get_delayed_sonic_units(get_timers=False):
873-
rc1, _ = clicommon.run_command("systemctl list-dependencies --plain sonic-delayed.target | sed '1d'", return_cmd=True)
874-
rc2, _ = clicommon.run_command("systemctl is-enabled {}".format(rc1.replace("\n", " ")), return_cmd=True)
875-
timer = [line.strip() for line in rc1.splitlines()]
876-
state = [line.strip() for line in rc2.splitlines()]
877-
services = []
878-
for unit in timer:
879-
if state[timer.index(unit)] == "enabled":
880-
if not get_timers:
881-
services.append(re.sub('\.timer$', '', unit, 1))
882-
else:
883-
services.append(unit)
884-
return services
885-
886-
887872
def _reset_failed_services():
888-
for service in itertools.chain(_get_sonic_services(), _get_delayed_sonic_units()):
873+
for service in _get_sonic_services():
889874
clicommon.run_command("systemctl reset-failed {}".format(service))
890875

891876

@@ -904,12 +889,6 @@ def _restart_services():
904889
click.echo("Reloading Monit configuration ...")
905890
clicommon.run_command("sudo monit reload")
906891

907-
def _delay_timers_elapsed():
908-
for timer in _get_delayed_sonic_units(get_timers=True):
909-
out, _ = clicommon.run_command("systemctl show {} --property=LastTriggerUSecMonotonic --value".format(timer), return_cmd=True)
910-
if out.strip() == "0":
911-
return False
912-
return True
913892

914893
def _per_namespace_swss_ready(service_name):
915894
out, _ = clicommon.run_command("systemctl show {} --property ActiveState --value".format(service_name), return_cmd=True)
@@ -1526,10 +1505,6 @@ def reload(db, filename, yes, load_sysinfo, no_service_restart, force, file_form
15261505
click.echo("System is not up. Retry later or use -f to avoid system checks")
15271506
sys.exit(CONFIG_RELOAD_NOT_READY)
15281507

1529-
if not _delay_timers_elapsed():
1530-
click.echo("Relevant services are not up. Retry later or use -f to avoid system checks")
1531-
sys.exit(CONFIG_RELOAD_NOT_READY)
1532-
15331508
if not _swss_ready():
15341509
click.echo("SwSS container is not ready. Retry later or use -f to avoid system checks")
15351510
sys.exit(CONFIG_RELOAD_NOT_READY)

scripts/db_migrator.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def __init__(self, namespace, socket=None):
4545
none-zero values.
4646
build: sequentially increase within a minor version domain.
4747
"""
48-
self.CURRENT_VERSION = 'version_4_0_1'
48+
self.CURRENT_VERSION = 'version_4_0_2'
4949

5050
self.TABLE_NAME = 'VERSIONS'
5151
self.TABLE_KEY = 'DATABASE'
@@ -575,6 +575,18 @@ def migrate_port_qos_map_global(self):
575575
self.configDB.set_entry('PORT_QOS_MAP', 'global', {"dscp_to_tc_map": dscp_to_tc_map_table_names[0]})
576576
log.log_info("Created entry for global DSCP_TO_TC_MAP {}".format(dscp_to_tc_map_table_names[0]))
577577

578+
def migrate_feature_timer(self):
579+
'''
580+
Migrate feature 'has_timer' field to 'delayed'
581+
'''
582+
feature_table = self.configDB.get_table('FEATURE')
583+
for feature, config in feature_table.items():
584+
state = config.get('has_timer')
585+
if state is not None:
586+
config['delayed'] = state
587+
config.pop('has_timer')
588+
self.configDB.set_entry('FEATURE', feature, config)
589+
578590
def update_edgezone_aggregator_config(self):
579591
"""
580592
Update cable length configuration in ConfigDB for T0 neighbor interfaces
@@ -909,9 +921,17 @@ def version_4_0_0(self):
909921
def version_4_0_1(self):
910922
"""
911923
Version 4_0_1.
924+
"""
925+
self.migrate_feature_timer()
926+
self.set_version('version_4_0_2')
927+
return 'version_4_0_2'
928+
929+
def version_4_0_2(self):
930+
"""
931+
Version 4_0_2.
912932
This is the latest version for master branch
913933
"""
914-
log.log_info('Handling version_4_0_1')
934+
log.log_info('Handling version_4_0_2')
915935
return None
916936

917937
def get_version(self):

sonic_package_manager/service_creator/feature.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def update(self,
105105
old_manifest: Manifest,
106106
new_manifest: Manifest):
107107
""" Migrate feature configuration. It can be that non-configurable
108-
feature entries have to be updated. e.g: "has_timer" for example if
108+
feature entries have to be updated. e.g: "delayed" for example if
109109
the new feature introduces a service timer or name of the service has
110110
changed, but user configurable entries are not changed).
111111
@@ -227,12 +227,12 @@ def get_default_feature_entries(state=None, owner=None) -> Dict[str, str]:
227227

228228
@staticmethod
229229
def get_non_configurable_feature_entries(manifest) -> Dict[str, str]:
230-
""" Get non-configurable feature table entries: e.g. 'has_timer' """
230+
""" Get non-configurable feature table entries: e.g. 'delayed' """
231231

232232
return {
233233
'has_per_asic_scope': str(manifest['service']['asic-service']),
234234
'has_global_scope': str(manifest['service']['host-service']),
235-
'has_timer': str(manifest['service']['delayed']),
235+
'delayed': str(manifest['service']['delayed']),
236236
'check_up_status': str(manifest['service']['check_up_status']),
237237
'support_syslog_rate_limit': str(manifest['service']['syslog']['support-rate-limit']),
238238
}

tests/config_test.py

Lines changed: 1 addition & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,6 @@
114114
Reloading Monit configuration ...
115115
"""
116116

117-
reload_config_with_untriggered_timer_output="""\
118-
Relevant services are not up. Retry later or use -f to avoid system checks
119-
"""
120-
121117
def mock_run_command_side_effect(*args, **kwargs):
122118
command = args[0]
123119

@@ -154,41 +150,6 @@ def mock_run_command_side_effect_disabled_timer(*args, **kwargs):
154150
else:
155151
return '', 0
156152

157-
def mock_run_command_side_effect_untriggered_timer(*args, **kwargs):
158-
command = args[0]
159-
160-
if kwargs.get('display_cmd'):
161-
click.echo(click.style("Running command: ", fg='cyan') + click.style(command, fg='green'))
162-
163-
if kwargs.get('return_cmd'):
164-
if command == "systemctl list-dependencies --plain sonic-delayed.target | sed '1d'":
165-
return 'snmp.timer', 0
166-
elif command == "systemctl list-dependencies --plain sonic.target | sed '1d'":
167-
return 'swss', 0
168-
elif command == "systemctl is-enabled snmp.timer":
169-
return 'enabled', 0
170-
elif command == "systemctl show snmp.timer --property=LastTriggerUSecMonotonic --value":
171-
return '0', 0
172-
else:
173-
return '', 0
174-
175-
def mock_run_command_side_effect_gnmi(*args, **kwargs):
176-
command = args[0]
177-
178-
if kwargs.get('display_cmd'):
179-
click.echo(click.style("Running command: ", fg='cyan') + click.style(command, fg='green'))
180-
181-
if kwargs.get('return_cmd'):
182-
if command == "systemctl list-dependencies --plain sonic-delayed.target | sed '1d'":
183-
return 'gnmi.timer', 0
184-
elif command == "systemctl list-dependencies --plain sonic.target | sed '1d'":
185-
return 'swss', 0
186-
elif command == "systemctl is-enabled gnmi.timer":
187-
return 'enabled', 0
188-
else:
189-
return '', 0
190-
191-
192153
# Load sonic-cfggen from source since /usr/local/bin/sonic-cfggen does not have .py extension.
193154
sonic_cfggen = load_module_from_source('sonic_cfggen', '/usr/local/bin/sonic-cfggen')
194155

@@ -234,32 +195,6 @@ def test_config_reload(self, get_cmd_module, setup_single_broadcom_asic):
234195

235196
assert "\n".join([l.rstrip() for l in result.output.split('\n')][:1]) == reload_config_with_sys_info_command_output
236197

237-
def test_config_reload_untriggered_timer(self, get_cmd_module, setup_single_broadcom_asic):
238-
with mock.patch("utilities_common.cli.run_command", mock.MagicMock(side_effect=mock_run_command_side_effect_untriggered_timer)) as mock_run_command:
239-
(config, show) = get_cmd_module
240-
241-
jsonfile_config = os.path.join(mock_db_path, "config_db.json")
242-
jsonfile_init_cfg = os.path.join(mock_db_path, "init_cfg.json")
243-
244-
# create object
245-
config.INIT_CFG_FILE = jsonfile_init_cfg
246-
config.DEFAULT_CONFIG_DB_FILE = jsonfile_config
247-
248-
db = Db()
249-
runner = CliRunner()
250-
obj = {'config_db': db.cfgdb}
251-
252-
# simulate 'config reload' to provoke load_sys_info option
253-
result = runner.invoke(config.config.commands["reload"], ["-l", "-y"], obj=obj)
254-
255-
print(result.exit_code)
256-
print(result.output)
257-
traceback.print_tb(result.exc_info[2])
258-
259-
assert result.exit_code == 1
260-
261-
assert "\n".join([l.rstrip() for l in result.output.split('\n')][:2]) == reload_config_with_untriggered_timer_output
262-
263198
@classmethod
264199
def teardown_class(cls):
265200
print("TEARDOWN")
@@ -292,25 +227,7 @@ def test_load_minigraph(self, get_cmd_module, setup_single_broadcom_asic):
292227
assert "\n".join([l.rstrip() for l in result.output.split('\n')]) == load_minigraph_command_output
293228
# Verify "systemctl reset-failed" is called for services under sonic.target
294229
mock_run_command.assert_any_call('systemctl reset-failed swss')
295-
# Verify "systemctl reset-failed" is called for services under sonic-delayed.target
296-
mock_run_command.assert_any_call('systemctl reset-failed snmp')
297-
assert mock_run_command.call_count == 11
298-
299-
def test_load_minigraph_with_gnmi_timer(self, get_cmd_module, setup_single_broadcom_asic):
300-
with mock.patch("utilities_common.cli.run_command", mock.MagicMock(side_effect=mock_run_command_side_effect_gnmi)) as mock_run_command:
301-
(config, show) = get_cmd_module
302-
runner = CliRunner()
303-
result = runner.invoke(config.config.commands["load_minigraph"], ["-y"])
304-
print(result.exit_code)
305-
print(result.output)
306-
traceback.print_tb(result.exc_info[2])
307-
assert result.exit_code == 0
308-
assert "\n".join([l.rstrip() for l in result.output.split('\n')]) == load_minigraph_command_output
309-
# Verify "systemctl reset-failed" is called for services under sonic.target
310-
mock_run_command.assert_any_call('systemctl reset-failed swss')
311-
# Verify "systemctl reset-failed" is called for services under sonic-delayed.target
312-
mock_run_command.assert_any_call('systemctl reset-failed gnmi')
313-
assert mock_run_command.call_count == 11
230+
assert mock_run_command.call_count == 8
314231

315232
def test_load_minigraph_with_port_config_bad_format(self, get_cmd_module, setup_single_broadcom_asic):
316233
with mock.patch(

tests/counterpoll_input/config_db.json

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,31 +2235,31 @@
22352235
"auto_restart": "enabled",
22362236
"state": "enabled",
22372237
"has_global_scope": "True",
2238-
"has_timer": "False"
2238+
"delayed": "False"
22392239
},
22402240
"pmon": {
22412241
"has_per_asic_scope": "False",
22422242
"high_mem_alert": "disabled",
22432243
"auto_restart": "enabled",
22442244
"state": "enabled",
22452245
"has_global_scope": "True",
2246-
"has_timer": "False"
2246+
"delayed": "False"
22472247
},
22482248
"sflow": {
22492249
"has_per_asic_scope": "False",
22502250
"high_mem_alert": "disabled",
22512251
"auto_restart": "enabled",
22522252
"state": "disabled",
22532253
"has_global_scope": "True",
2254-
"has_timer": "False"
2254+
"delayed": "False"
22552255
},
22562256
"database": {
22572257
"has_per_asic_scope": "True",
22582258
"high_mem_alert": "disabled",
22592259
"auto_restart": "disabled",
22602260
"state": "enabled",
22612261
"has_global_scope": "True",
2262-
"has_timer": "False"
2262+
"delayed": "False"
22632263
},
22642264
"telemetry": {
22652265
"has_per_asic_scope": "False",
@@ -2268,79 +2268,79 @@
22682268
"auto_restart": "enabled",
22692269
"state": "enabled",
22702270
"has_global_scope": "True",
2271-
"has_timer": "True"
2271+
"delayed": "True"
22722272
},
22732273
"snmp": {
22742274
"has_per_asic_scope": "False",
22752275
"high_mem_alert": "disabled",
22762276
"auto_restart": "enabled",
22772277
"state": "enabled",
22782278
"has_global_scope": "True",
2279-
"has_timer": "True"
2279+
"delayed": "True"
22802280
},
22812281
"bgp": {
22822282
"has_per_asic_scope": "True",
22832283
"high_mem_alert": "disabled",
22842284
"auto_restart": "enabled",
22852285
"state": "enabled",
22862286
"has_global_scope": "False",
2287-
"has_timer": "False"
2287+
"delayed": "False"
22882288
},
22892289
"radv": {
22902290
"has_per_asic_scope": "False",
22912291
"high_mem_alert": "disabled",
22922292
"auto_restart": "enabled",
22932293
"state": "enabled",
22942294
"has_global_scope": "True",
2295-
"has_timer": "False"
2295+
"delayed": "False"
22962296
},
22972297
"mgmt-framework": {
22982298
"has_per_asic_scope": "False",
22992299
"high_mem_alert": "disabled",
23002300
"auto_restart": "enabled",
23012301
"state": "enabled",
23022302
"has_global_scope": "True",
2303-
"has_timer": "True"
2303+
"delayed": "True"
23042304
},
23052305
"nat": {
23062306
"has_per_asic_scope": "False",
23072307
"high_mem_alert": "disabled",
23082308
"auto_restart": "enabled",
23092309
"state": "disabled",
23102310
"has_global_scope": "True",
2311-
"has_timer": "False"
2311+
"delayed": "False"
23122312
},
23132313
"teamd": {
23142314
"has_per_asic_scope": "True",
23152315
"high_mem_alert": "disabled",
23162316
"auto_restart": "enabled",
23172317
"state": "enabled",
23182318
"has_global_scope": "False",
2319-
"has_timer": "False"
2319+
"delayed": "False"
23202320
},
23212321
"dhcp_relay": {
23222322
"has_per_asic_scope": "False",
23232323
"high_mem_alert": "disabled",
23242324
"auto_restart": "enabled",
23252325
"state": "enabled",
23262326
"has_global_scope": "True",
2327-
"has_timer": "False"
2327+
"delayed": "False"
23282328
},
23292329
"swss": {
23302330
"has_per_asic_scope": "True",
23312331
"high_mem_alert": "disabled",
23322332
"auto_restart": "enabled",
23332333
"state": "enabled",
23342334
"has_global_scope": "False",
2335-
"has_timer": "False"
2335+
"delayed": "False"
23362336
},
23372337
"syncd": {
23382338
"has_per_asic_scope": "True",
23392339
"high_mem_alert": "disabled",
23402340
"auto_restart": "enabled",
23412341
"state": "enabled",
23422342
"has_global_scope": "False",
2343-
"has_timer": "False"
2343+
"delayed": "False"
23442344
}
23452345
},
23462346
"DSCP_TO_TC_MAP": {
@@ -2669,4 +2669,4 @@
26692669
"size": "56368"
26702670
}
26712671
}
2672-
}
2672+
}

tests/db_migrator_input/config_db/feature-expected.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@
33
"auto_restart": "disabled",
44
"has_global_scope": "False",
55
"has_per_asic_scope": "True",
6-
"has_timer": "False",
6+
"delayed": "False",
77
"high_mem_alert": "disabled",
88
"state": "enabled"
99
},
1010
"FEATURE|syncd": {
1111
"auto_restart": "enabled",
1212
"has_global_scope": "False",
1313
"has_per_asic_scope": "True",
14-
"has_timer": "False",
14+
"delayed": "False",
1515
"high_mem_alert": "disabled",
1616
"state": "enabled"
1717
},
1818
"FEATURE|telemetry": {
1919
"auto_restart": "enabled",
2020
"has_global_scope": "False",
2121
"has_per_asic_scope": "True",
22-
"has_timer": "False",
22+
"delayed": "True",
2323
"high_mem_alert": "disabled",
2424
"state": "enabled"
2525
}

0 commit comments

Comments
 (0)