@@ -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"
@@ -1296,6 +1297,143 @@ class PamLimitsCfg(object):
1296
1297
"modify pam_limits config file failed with exception: {}"
1297
1298
.format (e ))
1298
1299
1300
+ class DeviceMetaCfg (object ):
1301
+ """
1302
+ DeviceMetaCfg Config Daemon
1303
+ Handles changes in DEVICE_METADATA table.
1304
+ 1) Handle hostname change
1305
+ """
1306
+
1307
+ def __init__ (self ):
1308
+ self .hostname = ''
1309
+
1310
+ def load (self , dev_meta = {}):
1311
+ # Get hostname initial
1312
+ self .hostname = dev_meta .get ('localhost' , {}).get ('hostname' , '' )
1313
+ syslog .syslog (syslog .LOG_DEBUG , f'Initial hostname: { self .hostname } ' )
1314
+
1315
+ def hostname_update (self , data ):
1316
+ """
1317
+ Apply hostname handler.
1318
+
1319
+ Args:
1320
+ data: Read table's key's data.
1321
+ """
1322
+ syslog .syslog (syslog .LOG_DEBUG , 'DeviceMetaCfg: hostname update' )
1323
+ new_hostname = data .get ('hostname' )
1324
+
1325
+ # Restart hostname-config service when hostname was changed.
1326
+ # Empty not allowed
1327
+ if new_hostname and new_hostname != self .hostname :
1328
+ syslog .syslog (syslog .LOG_INFO , 'DeviceMetaCfg: Set new hostname: {}'
1329
+ .format (new_hostname ))
1330
+ self .hostname = new_hostname
1331
+ try :
1332
+ run_cmd ('sudo service hostname-config restart' , True , True )
1333
+ except subprocess .CalledProcessError as e :
1334
+ syslog .syslog (syslog .LOG_ERR , 'DeviceMetaCfg: Failed to set new'
1335
+ ' hostname: {}' .format (e ))
1336
+ return
1337
+
1338
+ run_cmd ('sudo monit reload' )
1339
+ else :
1340
+ msg = 'Hostname was not updated: '
1341
+ msg += 'Already set up' if new_hostname else 'Empty not allowed'
1342
+ syslog .syslog (syslog .LOG_ERR , msg )
1343
+
1344
+
1345
+ class MgmtIfaceCfg (object ):
1346
+ """
1347
+ MgmtIfaceCfg Config Daemon
1348
+ Handles changes in MGMT_INTERFACE, MGMT_VRF_CONFIG tables.
1349
+ 1) Handle change of interface ip
1350
+ 2) Handle change of management VRF state
1351
+ """
1352
+
1353
+ def __init__ (self ):
1354
+ self .iface_config_data = {}
1355
+ self .mgmt_vrf_enabled = ''
1356
+
1357
+ def load (self , mgmt_iface = {}, mgmt_vrf = {}):
1358
+ # Get initial data
1359
+ self .iface_config_data = mgmt_iface
1360
+ self .mgmt_vrf_enabled = mgmt_vrf .get ('mgmtVrfEnabled' , '' )
1361
+ syslog .syslog (syslog .LOG_DEBUG ,
1362
+ f'Initial mgmt interface conf: { self .iface_config_data } ' )
1363
+ syslog .syslog (syslog .LOG_DEBUG ,
1364
+ f'Initial mgmt VRF state: { self .mgmt_vrf_enabled } ' )
1365
+
1366
+ def update_mgmt_iface (self , iface , key , data ):
1367
+ """Handle update management interface config
1368
+ """
1369
+ syslog .syslog (syslog .LOG_DEBUG , 'MgmtIfaceCfg: mgmt iface update' )
1370
+
1371
+ # Restart management interface service when config was changed
1372
+ if data != self .iface_config_data .get (key ):
1373
+ cfg = {key : data }
1374
+ syslog .syslog (syslog .LOG_INFO , f'MgmtIfaceCfg: Set new interface '
1375
+ f'config { cfg } for { iface } ' )
1376
+ try :
1377
+ run_cmd ('sudo systemctl restart interfaces-config' , True , True )
1378
+ run_cmd ('sudo systemctl restart ntp-config' , True , True )
1379
+ except subprocess .CalledProcessError :
1380
+ syslog .syslog (syslog .LOG_ERR , f'Failed to restart management '
1381
+ 'interface services' )
1382
+ return
1383
+
1384
+ self .iface_config_data [key ] = data
1385
+
1386
+ def update_mgmt_vrf (self , data ):
1387
+ """Handle update management VRF state
1388
+ """
1389
+ syslog .syslog (syslog .LOG_DEBUG , 'MgmtIfaceCfg: mgmt vrf state update' )
1390
+
1391
+ # Restart mgmt vrf services when mgmt vrf config was changed.
1392
+ # Empty not allowed.
1393
+ enabled = data .get ('mgmtVrfEnabled' , '' )
1394
+ if not enabled or enabled == self .mgmt_vrf_enabled :
1395
+ return
1396
+
1397
+ syslog .syslog (syslog .LOG_INFO , f'Set mgmt vrf state { enabled } ' )
1398
+
1399
+ # Restart related vrfs services
1400
+ try :
1401
+ run_cmd ('service ntp stop' , True , True )
1402
+ run_cmd ('systemctl restart interfaces-config' , True , True )
1403
+ run_cmd ('service ntp start' , True , True )
1404
+ except subprocess .CalledProcessError :
1405
+ syslog .syslog (syslog .LOG_ERR , f'Failed to restart management vrf '
1406
+ 'services' )
1407
+ return
1408
+
1409
+ # Remove mgmt if route
1410
+ if enabled == 'true' :
1411
+ """
1412
+ The regular expression for grep in below cmd is to match eth0 line
1413
+ in /proc/net/route, sample file:
1414
+ $ cat /proc/net/route
1415
+ Iface Destination Gateway Flags RefCnt Use
1416
+ eth0 00000000 01803B0A 0003 0 0
1417
+ #################### Line break here ####################
1418
+ Metric Mask MTU Window IRTT
1419
+ 202 00000000 0 0 0
1420
+ """
1421
+ try :
1422
+ run_cmd (r"""cat /proc/net/route | grep -E \"eth0\s+"""
1423
+ r"""00000000\s+[0-9A-Z]+\s+[0-9]+\s+[0-9]+\s+[0-9]+"""
1424
+ r"""\s+202\" | wc -l""" ,
1425
+ True , True )
1426
+ except subprocess .CalledProcessError :
1427
+ syslog .syslog (syslog .LOG_ERR , 'MgmtIfaceCfg: Could not delete '
1428
+ 'eth0 route' )
1429
+ return
1430
+
1431
+ run_cmd ("ip -4 route del default dev eth0 metric 202" , False )
1432
+
1433
+ # Update cache
1434
+ self .mgmt_vrf_enabled = enabled
1435
+
1436
+
1299
1437
class HostConfigDaemon :
1300
1438
def __init__ (self ):
1301
1439
# Just a sanity check to verify if the CONFIG_DB has been initialized
@@ -1327,7 +1465,6 @@ class HostConfigDaemon:
1327
1465
self .is_multi_npu = device_info .is_multi_npu ()
1328
1466
1329
1467
# Initialize AAACfg
1330
- self .hostname_cache = ""
1331
1468
self .aaacfg = AaaCfg ()
1332
1469
1333
1470
# Initialize PasswHardening
@@ -1337,6 +1474,12 @@ class HostConfigDaemon:
1337
1474
self .pamLimitsCfg = PamLimitsCfg (self .config_db )
1338
1475
self .pamLimitsCfg .update_config_file ()
1339
1476
1477
+ # Initialize DeviceMetaCfg
1478
+ self .devmetacfg = DeviceMetaCfg ()
1479
+
1480
+ # Initialize MgmtIfaceCfg
1481
+ self .mgmtifacecfg = MgmtIfaceCfg ()
1482
+
1340
1483
def load (self , init_data ):
1341
1484
features = init_data ['FEATURE' ]
1342
1485
aaa = init_data ['AAA' ]
@@ -1349,21 +1492,21 @@ class HostConfigDaemon:
1349
1492
ntp_global = init_data ['NTP' ]
1350
1493
kdump = init_data ['KDUMP' ]
1351
1494
passwh = init_data ['PASSW_HARDENING' ]
1495
+ dev_meta = init_data .get (swsscommon .CFG_DEVICE_METADATA_TABLE_NAME , {})
1496
+ mgmt_ifc = init_data .get (swsscommon .CFG_MGMT_INTERFACE_TABLE_NAME , {})
1497
+ mgmt_vrf = init_data .get (swsscommon .CFG_MGMT_VRF_CONFIG_TABLE_NAME , {})
1352
1498
1353
1499
self .feature_handler .sync_state_field (features )
1354
1500
self .aaacfg .load (aaa , tacacs_global , tacacs_server , radius_global , radius_server )
1355
1501
self .iptables .load (lpbk_table )
1356
1502
self .ntpcfg .load (ntp_global , ntp_server )
1357
1503
self .kdumpCfg .load (kdump )
1358
1504
self .passwcfg .load (passwh )
1359
-
1360
- dev_meta = self .config_db .get_table ('DEVICE_METADATA' )
1361
- if 'localhost' in dev_meta :
1362
- if 'hostname' in dev_meta ['localhost' ]:
1363
- self .hostname_cache = dev_meta ['localhost' ]['hostname' ]
1505
+ self .devmetacfg .load (dev_meta )
1506
+ self .mgmtifacecfg .load (mgmt_ifc , mgmt_vrf )
1364
1507
1365
1508
# Update AAA with the hostname
1366
- self .aaacfg .hostname_update (self .hostname_cache )
1509
+ self .aaacfg .hostname_update (self .devmetacfg . hostname )
1367
1510
1368
1511
def __get_intf_name (self , key ):
1369
1512
if isinstance (key , tuple ) and key :
@@ -1413,6 +1556,10 @@ class HostConfigDaemon:
1413
1556
mgmt_intf_name = self .__get_intf_name (key )
1414
1557
self .aaacfg .handle_radius_source_intf_ip_chg (mgmt_intf_name )
1415
1558
self .aaacfg .handle_radius_nas_ip_chg (mgmt_intf_name )
1559
+ self .mgmtifacecfg .update_mgmt_iface (mgmt_intf_name , key , data )
1560
+
1561
+ def mgmt_vrf_handler (self , key , op , data ):
1562
+ self .mgmtifacecfg .update_mgmt_vrf (data )
1416
1563
1417
1564
def lpbk_handler (self , key , op , data ):
1418
1565
key = ConfigDBConnector .deserialize_key (key )
@@ -1452,6 +1599,10 @@ class HostConfigDaemon:
1452
1599
syslog .syslog (syslog .LOG_INFO , 'Kdump handler...' )
1453
1600
self .kdumpCfg .kdump_update (key , data )
1454
1601
1602
+ def device_metadata_handler (self , key , op , data ):
1603
+ syslog .syslog (syslog .LOG_INFO , 'DeviceMeta handler...' )
1604
+ self .devmetacfg .hostname_update (data )
1605
+
1455
1606
def wait_till_system_init_done (self ):
1456
1607
# No need to print the output in the log file so using the "--quiet"
1457
1608
# flag
@@ -1491,6 +1642,14 @@ class HostConfigDaemon:
1491
1642
self .config_db .subscribe ('PORTCHANNEL_INTERFACE' , make_callback (self .portchannel_intf_handler ))
1492
1643
self .config_db .subscribe ('INTERFACE' , make_callback (self .phy_intf_handler ))
1493
1644
1645
+ # Handle DEVICE_MEATADATA changes
1646
+ self .config_db .subscribe (swsscommon .CFG_DEVICE_METADATA_TABLE_NAME ,
1647
+ make_callback (self .device_metadata_handler ))
1648
+
1649
+ # Handle MGMT_VRF_CONFIG changes
1650
+ self .config_db .subscribe (swsscommon .CFG_MGMT_VRF_CONFIG_TABLE_NAME ,
1651
+ make_callback (self .mgmt_vrf_handler ))
1652
+
1494
1653
syslog .syslog (syslog .LOG_INFO ,
1495
1654
"Waiting for systemctl to finish initialization" )
1496
1655
self .wait_till_system_init_done ()
0 commit comments