@@ -12,6 +12,7 @@ import re
1212import jinja2
1313from sonic_py_common import device_info
1414from swsscommon .swsscommon import ConfigDBConnector , DBConnector , Table
15+ from swsscommon import swsscommon
1516
1617# FILE
1718PAM_AUTH_CONF = "/etc/pam.d/common-auth-sonic"
@@ -1296,6 +1297,143 @@ class PamLimitsCfg(object):
12961297 "modify pam_limits config file failed with exception: {}"
12971298 .format (e ))
12981299
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+
12991437class HostConfigDaemon :
13001438 def __init__ (self ):
13011439 # Just a sanity check to verify if the CONFIG_DB has been initialized
@@ -1327,7 +1465,6 @@ class HostConfigDaemon:
13271465 self .is_multi_npu = device_info .is_multi_npu ()
13281466
13291467 # Initialize AAACfg
1330- self .hostname_cache = ""
13311468 self .aaacfg = AaaCfg ()
13321469
13331470 # Initialize PasswHardening
@@ -1337,6 +1474,12 @@ class HostConfigDaemon:
13371474 self .pamLimitsCfg = PamLimitsCfg (self .config_db )
13381475 self .pamLimitsCfg .update_config_file ()
13391476
1477+ # Initialize DeviceMetaCfg
1478+ self .devmetacfg = DeviceMetaCfg ()
1479+
1480+ # Initialize MgmtIfaceCfg
1481+ self .mgmtifacecfg = MgmtIfaceCfg ()
1482+
13401483 def load (self , init_data ):
13411484 features = init_data ['FEATURE' ]
13421485 aaa = init_data ['AAA' ]
@@ -1349,21 +1492,21 @@ class HostConfigDaemon:
13491492 ntp_global = init_data ['NTP' ]
13501493 kdump = init_data ['KDUMP' ]
13511494 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 , {})
13521498
13531499 self .feature_handler .sync_state_field (features )
13541500 self .aaacfg .load (aaa , tacacs_global , tacacs_server , radius_global , radius_server )
13551501 self .iptables .load (lpbk_table )
13561502 self .ntpcfg .load (ntp_global , ntp_server )
13571503 self .kdumpCfg .load (kdump )
13581504 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 )
13641507
13651508 # Update AAA with the hostname
1366- self .aaacfg .hostname_update (self .hostname_cache )
1509+ self .aaacfg .hostname_update (self .devmetacfg . hostname )
13671510
13681511 def __get_intf_name (self , key ):
13691512 if isinstance (key , tuple ) and key :
@@ -1413,6 +1556,10 @@ class HostConfigDaemon:
14131556 mgmt_intf_name = self .__get_intf_name (key )
14141557 self .aaacfg .handle_radius_source_intf_ip_chg (mgmt_intf_name )
14151558 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 )
14161563
14171564 def lpbk_handler (self , key , op , data ):
14181565 key = ConfigDBConnector .deserialize_key (key )
@@ -1452,6 +1599,10 @@ class HostConfigDaemon:
14521599 syslog .syslog (syslog .LOG_INFO , 'Kdump handler...' )
14531600 self .kdumpCfg .kdump_update (key , data )
14541601
1602+ def device_metadata_handler (self , key , op , data ):
1603+ syslog .syslog (syslog .LOG_INFO , 'DeviceMeta handler...' )
1604+ self .devmetacfg .hostname_update (data )
1605+
14551606 def wait_till_system_init_done (self ):
14561607 # No need to print the output in the log file so using the "--quiet"
14571608 # flag
@@ -1491,6 +1642,14 @@ class HostConfigDaemon:
14911642 self .config_db .subscribe ('PORTCHANNEL_INTERFACE' , make_callback (self .portchannel_intf_handler ))
14921643 self .config_db .subscribe ('INTERFACE' , make_callback (self .phy_intf_handler ))
14931644
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+
14941653 syslog .syslog (syslog .LOG_INFO ,
14951654 "Waiting for systemctl to finish initialization" )
14961655 self .wait_till_system_init_done ()
0 commit comments