@@ -1302,84 +1302,141 @@ class NtpCfg(object):
1302
1302
1) ntp-config.service handles the configuration updates and then starts ntp.service
1303
1303
2) Both of them start after all the feature services start
1304
1304
3) Purpose of this daemon is to propagate runtime config changes in
1305
- NTP, NTP_SERVER and LOOPBACK_INTERFACE
1305
+ NTP, NTP_SERVER, NTP_KEY, and LOOPBACK_INTERFACE
1306
1306
"""
1307
+ NTP_CONF_RESTART = ['service' , 'ntp-config' , 'restart' ]
1308
+
1307
1309
def __init__ (self ):
1308
- self .ntp_global = {}
1309
- self .ntp_servers = set ()
1310
+ self .cache = {}
1311
+
1312
+ def load (self , ntp_global_conf : dict , ntp_server_conf : dict ,
1313
+ ntp_key_conf : dict ):
1314
+ """Load initial NTP configuration
1310
1315
1311
- def load (self , ntp_global_conf , ntp_server_conf ):
1312
- syslog .syslog (syslog .LOG_INFO , "NtpCfg load ..." )
1316
+ Force load cache on init. NTP config should be taken at boot-time by
1317
+ ntp and ntp-config services. So loading whole config here.
1318
+
1319
+ Args:
1320
+ ntp_global_conf: Global configuration
1321
+ ntp_server_conf: Servers configuration
1322
+ ntp_key_conf: Keys configuration
1323
+ """
1313
1324
1314
- for row in ntp_global_conf :
1315
- self .ntp_global_update (row , ntp_global_conf [row ], is_load = True )
1325
+ syslog .syslog (syslog .LOG_INFO , "NtpCfg: load initial" )
1316
1326
1317
- # Force reload on init
1318
- self .ntp_server_update (0 , None , is_load = True )
1327
+ if ntp_global_conf is None :
1328
+ ntp_global_conf = {}
1329
+
1330
+ # Force load cache on init.
1331
+ # NTP config should be taken at boot-time by ntp and ntp-config
1332
+ # services.
1333
+ self .cache = {
1334
+ 'global' : ntp_global_conf .get ('global' , {}),
1335
+ 'servers' : ntp_server_conf ,
1336
+ 'keys' : ntp_key_conf
1337
+ }
1319
1338
1320
1339
def handle_ntp_source_intf_chg (self , intf_name ):
1321
- # if no ntp server configured, do nothing
1322
- if not self .ntp_servers :
1340
+ # If no ntp server configured, do nothing. Source interface will be
1341
+ # taken once any server will be configured.
1342
+ if not self .cache .get ('servers' ):
1323
1343
return
1324
1344
1325
1345
# check only the intf configured as source interface
1326
- if intf_name not in self .ntp_global .get ('src_intf' , '' ).split (';' ):
1346
+ ifs = self .cache .get ('global' , {}).get ('src_intf' , '' ).split (';' )
1347
+ if intf_name not in ifs :
1348
+ return
1349
+
1350
+ # Just restart ntp config
1351
+ try :
1352
+ run_cmd (self .NTP_CONF_RESTART , True , True )
1353
+ except Exception :
1354
+ syslog .syslog (syslog .LOG_ERR , 'NtpCfg: Failed to restart '
1355
+ 'ntp-config service' )
1356
+ return
1357
+
1358
+ def ntp_global_update (self , key : str , data : dict ):
1359
+ """Update NTP global configuration
1360
+
1361
+ The table holds NTP global configuration. It has some configs that
1362
+ require reloading only but some other require restarting ntp daemon.
1363
+ Handle each of them accordingly.
1364
+
1365
+ Args:
1366
+ key: Triggered table's key. Should be always "global"
1367
+ data: Global configuration data
1368
+ """
1369
+
1370
+ syslog .syslog (syslog .LOG_NOTICE , 'NtpCfg: Global configuration update' )
1371
+ if key != 'global' or self .cache .get ('global' , {}) == data :
1372
+ syslog .syslog (syslog .LOG_NOTICE , 'NtpCfg: Nothing to update' )
1327
1373
return
1328
- else :
1329
- # just restart ntp config
1330
- cmd = ['systemctl' , 'restart' , 'ntp-config' ]
1331
- run_cmd (cmd )
1332
1374
1333
- def ntp_global_update (self , key , data , is_load = False ):
1334
- syslog .syslog (syslog .LOG_INFO , 'NTP GLOBAL Update' )
1335
- orig_src = self .ntp_global .get ('src_intf' , '' )
1336
- orig_src_set = set (orig_src .split (";" ))
1337
- orig_vrf = self .ntp_global .get ('vrf' , '' )
1375
+ syslog .syslog (syslog .LOG_INFO , f'NtpCfg: Set global config: { data } ' )
1338
1376
1339
- new_src = data .get ('src_intf' , '' )
1340
- new_src_set = set (new_src .split (";" ))
1341
- new_vrf = data .get ('vrf' , '' )
1377
+ old_dhcp = self .cache .get (key , {}).get ('dhcp' )
1378
+ old_vrf = self .cache .get (key , {}).get ('vrf' )
1379
+ new_dhcp = data .get ('dhcp' )
1380
+ new_vrf = data .get ('vrf' )
1381
+
1382
+ restart_ntpd = False
1383
+ if new_dhcp != old_dhcp or new_vrf != old_vrf :
1384
+ restart_ntpd = True
1385
+
1386
+ # Restarting the service
1387
+ try :
1388
+ run_cmd (self .NTP_CONF_RESTART , True , True )
1389
+ if restart_ntpd :
1390
+ run_cmd (['service' , 'ntp' , 'restart' ], True , True )
1391
+ except Exception :
1392
+ syslog .syslog (syslog .LOG_ERR , f'NtpCfg: Failed to restart ntp '
1393
+ 'services' )
1394
+ return
1342
1395
1343
1396
# Update the Local Cache
1344
- self .ntp_global = data
1397
+ self .cache [key ] = data
1398
+
1399
+ def ntp_srv_key_update (self , ntp_servers : dict , ntp_keys : dict ):
1400
+ """Update NTP server/key configuration
1345
1401
1346
- # If initial load don't restart daemon
1347
- if is_load : return
1402
+ The tables holds only NTP servers config and/or NTP authentication keys
1403
+ config, so any change to those tables should cause NTP config reload.
1404
+ It does not make sense to handle each of the separately. NTP config
1405
+ reload takes whole configuration, so once got to this handler - cache
1406
+ whole config.
1348
1407
1349
- # check if ntp server configured, if not, do nothing
1350
- if not self .ntp_servers :
1351
- syslog .syslog (syslog .LOG_INFO , "No ntp server when global config change, do nothing" )
1408
+ Args:
1409
+ ntp_servers: Servers config table
1410
+ ntp_keys: Keys config table
1411
+ """
1412
+
1413
+ syslog .syslog (syslog .LOG_NOTICE , 'NtpCfg: Server/key configuration '
1414
+ 'update' )
1415
+
1416
+ if (self .cache .get ('servers' , {}) == ntp_servers and
1417
+ self .cache .get ('keys' , {}) == ntp_keys ):
1418
+ syslog .syslog (syslog .LOG_NOTICE , 'NtpCfg: Nothing to update' )
1352
1419
return
1353
1420
1354
- if orig_src_set != new_src_set :
1355
- syslog .syslog (syslog .LOG_INFO , "ntp global update for source intf old {} new {}, restarting ntp-config"
1356
- .format (orig_src_set , new_src_set ))
1357
- cmd = ['systemctl' , 'restart' , 'ntp-config' ]
1358
- run_cmd (cmd )
1359
- elif new_vrf != orig_vrf :
1360
- syslog .syslog (syslog .LOG_INFO , "ntp global update for vrf old {} new {}, restarting ntp service"
1361
- .format (orig_vrf , new_vrf ))
1362
- cmd = ['service' , 'ntp' , 'restart' ]
1363
- run_cmd (cmd )
1421
+ # Pop keys values to print
1422
+ ntp_keys_print = copy .deepcopy (ntp_keys )
1423
+ for key in ntp_keys_print :
1424
+ ntp_keys_print [key ].pop ('value' , None )
1364
1425
1365
- def ntp_server_update (self , key , op , is_load = False ):
1366
- syslog .syslog (syslog .LOG_INFO , 'ntp server update key {}' .format (key ))
1367
-
1368
- restart_config = False
1369
- if not is_load :
1370
- if op == "SET" and key not in self .ntp_servers :
1371
- restart_config = True
1372
- self .ntp_servers .add (key )
1373
- elif op == "DEL" and key in self .ntp_servers :
1374
- restart_config = True
1375
- self .ntp_servers .remove (key )
1376
- else :
1377
- restart_config = True
1426
+ syslog .syslog (syslog .LOG_INFO , f'NtpCfg: Set servers: { ntp_servers } ' )
1427
+ syslog .syslog (syslog .LOG_INFO , f'NtpCfg: Set keys: { ntp_keys_print } ' )
1378
1428
1379
- if restart_config :
1380
- cmd = ['systemctl' , 'restart' , 'ntp-config' ]
1381
- syslog .syslog (syslog .LOG_INFO , 'ntp server update, restarting ntp-config, ntp servers configured {}' .format (self .ntp_servers ))
1382
- run_cmd (cmd )
1429
+ # Restarting the service
1430
+ try :
1431
+ run_cmd (self .NTP_CONF_RESTART , True , True )
1432
+ except Exception :
1433
+ syslog .syslog (syslog .LOG_ERR , f'NtpCfg: Failed to restart '
1434
+ 'ntp-config service' )
1435
+ return
1436
+
1437
+ # Updating the cache
1438
+ self .cache ['servers' ] = ntp_servers
1439
+ self .cache ['keys' ] = ntp_keys
1383
1440
1384
1441
class PamLimitsCfg (object ):
1385
1442
"""
@@ -1721,26 +1778,26 @@ class HostConfigDaemon:
1721
1778
radius_global = init_data ['RADIUS' ]
1722
1779
radius_server = init_data ['RADIUS_SERVER' ]
1723
1780
lpbk_table = init_data ['LOOPBACK_INTERFACE' ]
1724
- ntp_server = init_data ['NTP_SERVER' ]
1725
- ntp_global = init_data ['NTP' ]
1726
1781
kdump = init_data ['KDUMP' ]
1727
1782
passwh = init_data ['PASSW_HARDENING' ]
1728
1783
dev_meta = init_data .get (swsscommon .CFG_DEVICE_METADATA_TABLE_NAME , {})
1729
1784
mgmt_ifc = init_data .get (swsscommon .CFG_MGMT_INTERFACE_TABLE_NAME , {})
1730
1785
mgmt_vrf = init_data .get (swsscommon .CFG_MGMT_VRF_CONFIG_TABLE_NAME , {})
1731
1786
syslog_cfg = init_data .get (swsscommon .CFG_SYSLOG_CONFIG_TABLE_NAME , {})
1732
1787
syslog_srv = init_data .get (swsscommon .CFG_SYSLOG_SERVER_TABLE_NAME , {})
1733
-
1788
+ ntp_global = init_data .get (swsscommon .CFG_NTP_GLOBAL_TABLE_NAME )
1789
+ ntp_servers = init_data .get (swsscommon .CFG_NTP_SERVER_TABLE_NAME )
1790
+ ntp_keys = init_data .get (swsscommon .CFG_NTP_KEY_TABLE_NAME )
1734
1791
1735
1792
self .feature_handler .sync_state_field (features )
1736
1793
self .aaacfg .load (aaa , tacacs_global , tacacs_server , radius_global , radius_server )
1737
1794
self .iptables .load (lpbk_table )
1738
- self .ntpcfg .load (ntp_global , ntp_server )
1739
1795
self .kdumpCfg .load (kdump )
1740
1796
self .passwcfg .load (passwh )
1741
1797
self .devmetacfg .load (dev_meta )
1742
1798
self .mgmtifacecfg .load (mgmt_ifc , mgmt_vrf )
1743
1799
self .rsyslogcfg .load (syslog_cfg , syslog_srv )
1800
+ self .ntpcfg .load (ntp_global , ntp_servers , ntp_keys )
1744
1801
1745
1802
# Update AAA with the hostname
1746
1803
self .aaacfg .hostname_update (self .devmetacfg .hostname )
@@ -1826,12 +1883,16 @@ class HostConfigDaemon:
1826
1883
key = ConfigDBConnector .deserialize_key (key )
1827
1884
self .aaacfg .handle_radius_source_intf_ip_chg (key )
1828
1885
1829
- def ntp_server_handler (self , key , op , data ):
1830
- self .ntpcfg .ntp_server_update (key , op )
1831
-
1832
1886
def ntp_global_handler (self , key , op , data ):
1887
+ syslog .syslog (syslog .LOG_NOTICE , 'Handling NTP global config' )
1833
1888
self .ntpcfg .ntp_global_update (key , data )
1834
1889
1890
+ def ntp_srv_key_handler (self , key , op , data ):
1891
+ syslog .syslog (syslog .LOG_NOTICE , 'Handling NTP server/key config' )
1892
+ self .ntpcfg .ntp_srv_key_update (
1893
+ self .config_db .get_table (swsscommon .CFG_NTP_SERVER_TABLE_NAME ),
1894
+ self .config_db .get_table (swsscommon .CFG_NTP_KEY_TABLE_NAME ))
1895
+
1835
1896
def kdump_handler (self , key , op , data ):
1836
1897
syslog .syslog (syslog .LOG_INFO , 'Kdump handler...' )
1837
1898
self .kdumpCfg .kdump_update (key , data )
@@ -1885,9 +1946,6 @@ class HostConfigDaemon:
1885
1946
self .config_db .subscribe ('PASSW_HARDENING' , make_callback (self .passwh_handler ))
1886
1947
# Handle IPTables configuration
1887
1948
self .config_db .subscribe ('LOOPBACK_INTERFACE' , make_callback (self .lpbk_handler ))
1888
- # Handle NTP & NTP_SERVER updates
1889
- self .config_db .subscribe ('NTP' , make_callback (self .ntp_global_handler ))
1890
- self .config_db .subscribe ('NTP_SERVER' , make_callback (self .ntp_server_handler ))
1891
1949
# Handle updates to src intf changes in radius
1892
1950
self .config_db .subscribe ('MGMT_INTERFACE' , make_callback (self .mgmt_intf_handler ))
1893
1951
self .config_db .subscribe ('VLAN_INTERFACE' , make_callback (self .vlan_intf_handler ))
@@ -1909,6 +1967,14 @@ class HostConfigDaemon:
1909
1967
self .config_db .subscribe (swsscommon .CFG_SYSLOG_SERVER_TABLE_NAME ,
1910
1968
make_callback (self .rsyslog_server_handler ))
1911
1969
1970
+ # Handle NTP, NTP_SERVER, and NTP_KEY updates
1971
+ self .config_db .subscribe (swsscommon .CFG_NTP_GLOBAL_TABLE_NAME ,
1972
+ make_callback (self .ntp_global_handler ))
1973
+ self .config_db .subscribe (swsscommon .CFG_NTP_SERVER_TABLE_NAME ,
1974
+ make_callback (self .ntp_srv_key_handler ))
1975
+ self .config_db .subscribe (swsscommon .CFG_NTP_KEY_TABLE_NAME ,
1976
+ make_callback (self .ntp_srv_key_handler ))
1977
+
1912
1978
syslog .syslog (syslog .LOG_INFO ,
1913
1979
"Waiting for systemctl to finish initialization" )
1914
1980
self .wait_till_system_init_done ()
0 commit comments