Skip to content

Commit f952f68

Browse files
committed
Add mgmt handling to hostcfgd
Signed-off-by: Yevhen Fastiuk <yfastiuk@nvidia.com>
1 parent 1086349 commit f952f68

3 files changed

Lines changed: 161 additions & 5 deletions

File tree

scripts/hostcfgd

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,98 @@ class DeviceMetaCfg(object):
12991299
syslog.syslog(syslog.LOG_ERR, msg)
13001300

13011301

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+
13021394
class HostConfigDaemon:
13031395
def __init__(self):
13041396
# Just a sanity check to verify if the CONFIG_DB has been initialized
@@ -1342,6 +1434,9 @@ class HostConfigDaemon:
13421434
# Initialize DeviceMetaCfg
13431435
self.devmetacfg = DeviceMetaCfg()
13441436

1437+
# Initialize MgmtIfaceCfg
1438+
self.mgmtifacecfg = MgmtIfaceCfg()
1439+
13451440
def load(self, init_data):
13461441
features = init_data['FEATURE']
13471442
aaa = init_data['AAA']
@@ -1355,6 +1450,8 @@ class HostConfigDaemon:
13551450
kdump = init_data['KDUMP']
13561451
passwh = init_data['PASSW_HARDENING']
13571452
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, {})
13581455

13591456
self.feature_handler.sync_state_field(features)
13601457
self.aaacfg.load(aaa, tacacs_global, tacacs_server, radius_global, radius_server)
@@ -1363,6 +1460,7 @@ class HostConfigDaemon:
13631460
self.kdumpCfg.load(kdump)
13641461
self.passwcfg.load(passwh)
13651462
self.devmetacfg.load(dev_meta)
1463+
self.mgmtifacecfg.load(mgmt_ifc, mgmt_vrf)
13661464

13671465
# Update AAA with the hostname
13681466
self.aaacfg.hostname_update(self.devmetacfg.hostname)
@@ -1415,6 +1513,10 @@ class HostConfigDaemon:
14151513
mgmt_intf_name = self.__get_intf_name(key)
14161514
self.aaacfg.handle_radius_source_intf_ip_chg(mgmt_intf_name)
14171515
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)
14181520

14191521
def lpbk_handler(self, key, op, data):
14201522
key = ConfigDBConnector.deserialize_key(key)
@@ -1501,6 +1603,10 @@ class HostConfigDaemon:
15011603
self.config_db.subscribe(swsscommon.CFG_DEVICE_METADATA_TABLE_NAME,
15021604
make_callback(self.device_metadata_handler))
15031605

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+
15041610
syslog.syslog(syslog.LOG_INFO,
15051611
"Waiting for systemctl to finish initialization")
15061612
self.wait_till_system_init_done()

tests/hostcfgd/hostcfgd_test.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,45 @@ def test_devicemeta_event(self):
390390
]
391391
mocked_subprocess.check_call.assert_has_calls(expected,
392392
any_order=True)
393+
394+
def test_mgmtiface_event(self):
395+
"""
396+
Test handling mgmt events.
397+
1) Management interface setup
398+
2) Management vrf setup
399+
"""
400+
MockConfigDb.set_config_db(HOSTCFG_DAEMON_CFG_DB)
401+
MockConfigDb.event_queue = [
402+
(swsscommon.CFG_MGMT_INTERFACE_TABLE_NAME, 'eth0|1.2.3.4/24'),
403+
(swsscommon.CFG_MGMT_VRF_CONFIG_TABLE_NAME, 'vrf_global')
404+
]
405+
daemon = hostcfgd.HostConfigDaemon()
406+
daemon.register_callbacks()
407+
daemon.aaacfg = mock.MagicMock()
408+
daemon.iptables = mock.MagicMock()
409+
daemon.passwcfg = mock.MagicMock()
410+
daemon.load(HOSTCFG_DAEMON_INIT_CFG_DB)
411+
with mock.patch('hostcfgd.subprocess') as mocked_subprocess:
412+
popen_mock = mock.Mock()
413+
attrs = {'communicate.return_value': ('output', 'error')}
414+
popen_mock.configure_mock(**attrs)
415+
mocked_subprocess.Popen.return_value = popen_mock
416+
417+
try:
418+
daemon.start()
419+
except TimeoutError:
420+
pass
421+
422+
expected = [
423+
call('sudo systemctl restart interfaces-config', shell=True),
424+
call('sudo systemctl restart ntp-config', shell=True),
425+
call('service ntp stop', shell=True),
426+
call('systemctl restart interfaces-config', shell=True),
427+
call('service ntp start', shell=True),
428+
call('cat /proc/net/route | grep -E \\"eth0\\s+00000000'
429+
'\\s+[0-9A-Z]+\\s+[0-9]+\\s+[0-9]+\\s+[0-9]+\\s+202\\" | '
430+
'wc -l', shell=True),
431+
call('ip -4 route del default dev eth0 metric 202', shell=True)
432+
]
433+
mocked_subprocess.check_call.assert_has_calls(expected,
434+
any_order=True)

tests/hostcfgd/test_vectors.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"enabled": "false",
2020
"num_dumps": "3",
2121
"memory": "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M"
22-
}
22+
}
2323
},
2424
"FEATURE": {
2525
"dhcp_relay": {
@@ -118,7 +118,7 @@
118118
"enabled": "false",
119119
"num_dumps": "3",
120120
"memory": "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M"
121-
}
121+
}
122122
},
123123
"FEATURE": {
124124
"dhcp_relay": {
@@ -235,7 +235,7 @@
235235
"enabled": "false",
236236
"num_dumps": "3",
237237
"memory": "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M"
238-
}
238+
}
239239
},
240240
"FEATURE": {
241241
"dhcp_relay": {
@@ -331,7 +331,7 @@
331331
"enabled": "false",
332332
"num_dumps": "3",
333333
"memory": "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M"
334-
}
334+
}
335335
},
336336
"FEATURE": {
337337
"dhcp_relay": {
@@ -431,7 +431,7 @@
431431
"enabled": "false",
432432
"num_dumps": "3",
433433
"memory": "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M"
434-
}
434+
}
435435
},
436436
"FEATURE": {
437437
"dhcp_relay": {
@@ -592,5 +592,13 @@
592592
"type": "ToRRouter",
593593
"hostname": "SomeNewHostname"
594594
}
595+
},
596+
"MGMT_INTERFACE": {
597+
"eth0|1.2.3.4/24": {}
598+
},
599+
"MGMT_VRF_CONFIG": {
600+
"vrf_global": {
601+
'mgmtVrfEnabled': 'true'
602+
}
595603
}
596604
}

0 commit comments

Comments
 (0)