@@ -12,6 +12,7 @@ import re
12
12
import jinja2
13
13
from sonic_py_common import device_info
14
14
from swsscommon .swsscommon import ConfigDBConnector , DBConnector , Table
15
+ from swsscommon import swsscommon
15
16
16
17
# FILE
17
18
PAM_AUTH_CONF = "/etc/pam.d/common-auth-sonic"
@@ -1253,6 +1254,143 @@ class PamLimitsCfg(object):
1253
1254
"modify pam_limits config file failed with exception: {}"
1254
1255
.format (e ))
1255
1256
1257
+ class DeviceMetaCfg (object ):
1258
+ """
1259
+ DeviceMetaCfg Config Daemon
1260
+ Handles changes in DEVICE_METADATA table.
1261
+ 1) Handle hostname change
1262
+ """
1263
+
1264
+ def __init__ (self ):
1265
+ self .hostname = ''
1266
+
1267
+ def load (self , dev_meta = {}):
1268
+ # Get hostname initial
1269
+ self .hostname = dev_meta .get ('localhost' , {}).get ('hostname' , '' )
1270
+ syslog .syslog (syslog .LOG_DEBUG , f'Initial hostname: { self .hostname } ' )
1271
+
1272
+ def hostname_update (self , data ):
1273
+ """
1274
+ Apply hostname handler.
1275
+
1276
+ Args:
1277
+ data: Read table's key's data.
1278
+ """
1279
+ syslog .syslog (syslog .LOG_DEBUG , 'DeviceMetaCfg: hostname update' )
1280
+ new_hostname = data .get ('hostname' )
1281
+
1282
+ # Restart hostname-config service when hostname was changed.
1283
+ # Empty not allowed
1284
+ if new_hostname and new_hostname != self .hostname :
1285
+ syslog .syslog (syslog .LOG_INFO , 'DeviceMetaCfg: Set new hostname: {}'
1286
+ .format (new_hostname ))
1287
+ self .hostname = new_hostname
1288
+ try :
1289
+ run_cmd ('sudo service hostname-config restart' , True , True )
1290
+ except subprocess .CalledProcessError as e :
1291
+ syslog .syslog (syslog .LOG_ERR , 'DeviceMetaCfg: Failed to set new'
1292
+ ' hostname: {}' .format (e ))
1293
+ return
1294
+
1295
+ run_cmd ('sudo monit reload' )
1296
+ else :
1297
+ msg = 'Hostname was not updated: '
1298
+ msg += 'Already set up' if new_hostname else 'Empty not allowed'
1299
+ syslog .syslog (syslog .LOG_ERR , msg )
1300
+
1301
+
1302
+ class MgmtIfaceCfg (object ):
1303
+ """
1304
+ MgmtIfaceCfg Config Daemon
1305
+ Handles changes in MGMT_INTERFACE, MGMT_VRF_CONFIG tables.
1306
+ 1) Handle change of interface ip
1307
+ 2) Handle change of management VRF state
1308
+ """
1309
+
1310
+ def __init__ (self ):
1311
+ self .iface_config_data = {}
1312
+ self .mgmt_vrf_enabled = ''
1313
+
1314
+ def load (self , mgmt_iface = {}, mgmt_vrf = {}):
1315
+ # Get initial data
1316
+ self .iface_config_data = mgmt_iface
1317
+ self .mgmt_vrf_enabled = mgmt_vrf .get ('mgmtVrfEnabled' , '' )
1318
+ syslog .syslog (syslog .LOG_DEBUG ,
1319
+ f'Initial mgmt interface conf: { self .iface_config_data } ' )
1320
+ syslog .syslog (syslog .LOG_DEBUG ,
1321
+ f'Initial mgmt VRF state: { self .mgmt_vrf_enabled } ' )
1322
+
1323
+ def update_mgmt_iface (self , iface , key , data ):
1324
+ """Handle update management interface config
1325
+ """
1326
+ syslog .syslog (syslog .LOG_DEBUG , 'MgmtIfaceCfg: mgmt iface update' )
1327
+
1328
+ # Restart management interface service when config was changed
1329
+ if data != self .iface_config_data .get (key ):
1330
+ cfg = {key : data }
1331
+ syslog .syslog (syslog .LOG_INFO , f'MgmtIfaceCfg: Set new interface '
1332
+ f'config { cfg } for { iface } ' )
1333
+ try :
1334
+ run_cmd ('sudo systemctl restart interfaces-config' , True , True )
1335
+ run_cmd ('sudo systemctl restart ntp-config' , True , True )
1336
+ except subprocess .CalledProcessError :
1337
+ syslog .syslog (syslog .LOG_ERR , f'Failed to restart management '
1338
+ 'interface services' )
1339
+ return
1340
+
1341
+ self .iface_config_data [key ] = data
1342
+
1343
+ def update_mgmt_vrf (self , data ):
1344
+ """Handle update management VRF state
1345
+ """
1346
+ syslog .syslog (syslog .LOG_DEBUG , 'MgmtIfaceCfg: mgmt vrf state update' )
1347
+
1348
+ # Restart mgmt vrf services when mgmt vrf config was changed.
1349
+ # Empty not allowed.
1350
+ enabled = data .get ('mgmtVrfEnabled' , '' )
1351
+ if not enabled or enabled == self .mgmt_vrf_enabled :
1352
+ return
1353
+
1354
+ syslog .syslog (syslog .LOG_INFO , f'Set mgmt vrf state { enabled } ' )
1355
+
1356
+ # Restart related vrfs services
1357
+ try :
1358
+ run_cmd ('service ntp stop' , True , True )
1359
+ run_cmd ('systemctl restart interfaces-config' , True , True )
1360
+ run_cmd ('service ntp start' , True , True )
1361
+ except subprocess .CalledProcessError :
1362
+ syslog .syslog (syslog .LOG_ERR , f'Failed to restart management vrf '
1363
+ 'services' )
1364
+ return
1365
+
1366
+ # Remove mgmt if route
1367
+ if enabled == 'true' :
1368
+ """
1369
+ The regular expression for grep in below cmd is to match eth0 line
1370
+ in /proc/net/route, sample file:
1371
+ $ cat /proc/net/route
1372
+ Iface Destination Gateway Flags RefCnt Use
1373
+ eth0 00000000 01803B0A 0003 0 0
1374
+ #################### Line break here ####################
1375
+ Metric Mask MTU Window IRTT
1376
+ 202 00000000 0 0 0
1377
+ """
1378
+ try :
1379
+ run_cmd (r"""cat /proc/net/route | grep -E \"eth0\s+"""
1380
+ r"""00000000\s+[0-9A-Z]+\s+[0-9]+\s+[0-9]+\s+[0-9]+"""
1381
+ r"""\s+202\" | wc -l""" ,
1382
+ True , True )
1383
+ except subprocess .CalledProcessError :
1384
+ syslog .syslog (syslog .LOG_ERR , 'MgmtIfaceCfg: Could not delete '
1385
+ 'eth0 route' )
1386
+ return
1387
+
1388
+ run_cmd ("ip -4 route del default dev eth0 metric 202" , False )
1389
+
1390
+ # Update cache
1391
+ self .mgmt_vrf_enabled = enabled
1392
+
1393
+
1256
1394
class HostConfigDaemon :
1257
1395
def __init__ (self ):
1258
1396
# Just a sanity check to verify if the CONFIG_DB has been initialized
@@ -1284,7 +1422,6 @@ class HostConfigDaemon:
1284
1422
self .is_multi_npu = device_info .is_multi_npu ()
1285
1423
1286
1424
# Initialize AAACfg
1287
- self .hostname_cache = ""
1288
1425
self .aaacfg = AaaCfg ()
1289
1426
1290
1427
# Initialize PasswHardening
@@ -1294,6 +1431,12 @@ class HostConfigDaemon:
1294
1431
self .pamLimitsCfg = PamLimitsCfg (self .config_db )
1295
1432
self .pamLimitsCfg .update_config_file ()
1296
1433
1434
+ # Initialize DeviceMetaCfg
1435
+ self .devmetacfg = DeviceMetaCfg ()
1436
+
1437
+ # Initialize MgmtIfaceCfg
1438
+ self .mgmtifacecfg = MgmtIfaceCfg ()
1439
+
1297
1440
def load (self , init_data ):
1298
1441
features = init_data ['FEATURE' ]
1299
1442
aaa = init_data ['AAA' ]
@@ -1306,21 +1449,21 @@ class HostConfigDaemon:
1306
1449
ntp_global = init_data ['NTP' ]
1307
1450
kdump = init_data ['KDUMP' ]
1308
1451
passwh = init_data ['PASSW_HARDENING' ]
1452
+ dev_meta = init_data .get (swsscommon .CFG_DEVICE_METADATA_TABLE_NAME , {})
1453
+ mgmt_ifc = init_data .get (swsscommon .CFG_MGMT_INTERFACE_TABLE_NAME , {})
1454
+ mgmt_vrf = init_data .get (swsscommon .CFG_MGMT_VRF_CONFIG_TABLE_NAME , {})
1309
1455
1310
1456
self .feature_handler .sync_state_field (features )
1311
1457
self .aaacfg .load (aaa , tacacs_global , tacacs_server , radius_global , radius_server )
1312
1458
self .iptables .load (lpbk_table )
1313
1459
self .ntpcfg .load (ntp_global , ntp_server )
1314
1460
self .kdumpCfg .load (kdump )
1315
1461
self .passwcfg .load (passwh )
1316
-
1317
- dev_meta = self .config_db .get_table ('DEVICE_METADATA' )
1318
- if 'localhost' in dev_meta :
1319
- if 'hostname' in dev_meta ['localhost' ]:
1320
- self .hostname_cache = dev_meta ['localhost' ]['hostname' ]
1462
+ self .devmetacfg .load (dev_meta )
1463
+ self .mgmtifacecfg .load (mgmt_ifc , mgmt_vrf )
1321
1464
1322
1465
# Update AAA with the hostname
1323
- self .aaacfg .hostname_update (self .hostname_cache )
1466
+ self .aaacfg .hostname_update (self .devmetacfg . hostname )
1324
1467
1325
1468
def __get_intf_name (self , key ):
1326
1469
if isinstance (key , tuple ) and key :
@@ -1370,6 +1513,10 @@ class HostConfigDaemon:
1370
1513
mgmt_intf_name = self .__get_intf_name (key )
1371
1514
self .aaacfg .handle_radius_source_intf_ip_chg (mgmt_intf_name )
1372
1515
self .aaacfg .handle_radius_nas_ip_chg (mgmt_intf_name )
1516
+ self .mgmtifacecfg .update_mgmt_iface (mgmt_intf_name , key , data )
1517
+
1518
+ def mgmt_vrf_handler (self , key , op , data ):
1519
+ self .mgmtifacecfg .update_mgmt_vrf (data )
1373
1520
1374
1521
def lpbk_handler (self , key , op , data ):
1375
1522
key = ConfigDBConnector .deserialize_key (key )
@@ -1409,6 +1556,10 @@ class HostConfigDaemon:
1409
1556
syslog .syslog (syslog .LOG_INFO , 'Kdump handler...' )
1410
1557
self .kdumpCfg .kdump_update (key , data )
1411
1558
1559
+ def device_metadata_handler (self , key , op , data ):
1560
+ syslog .syslog (syslog .LOG_INFO , 'DeviceMeta handler...' )
1561
+ self .devmetacfg .hostname_update (data )
1562
+
1412
1563
def wait_till_system_init_done (self ):
1413
1564
# No need to print the output in the log file so using the "--quiet"
1414
1565
# flag
@@ -1448,6 +1599,14 @@ class HostConfigDaemon:
1448
1599
self .config_db .subscribe ('PORTCHANNEL_INTERFACE' , make_callback (self .portchannel_intf_handler ))
1449
1600
self .config_db .subscribe ('INTERFACE' , make_callback (self .phy_intf_handler ))
1450
1601
1602
+ # Handle DEVICE_MEATADATA changes
1603
+ self .config_db .subscribe (swsscommon .CFG_DEVICE_METADATA_TABLE_NAME ,
1604
+ make_callback (self .device_metadata_handler ))
1605
+
1606
+ # Handle MGMT_VRF_CONFIG changes
1607
+ self .config_db .subscribe (swsscommon .CFG_MGMT_VRF_CONFIG_TABLE_NAME ,
1608
+ make_callback (self .mgmt_vrf_handler ))
1609
+
1451
1610
syslog .syslog (syslog .LOG_INFO ,
1452
1611
"Waiting for systemctl to finish initialization" )
1453
1612
self .wait_till_system_init_done ()
0 commit comments