Skip to content

Commit 1fbf8fb

Browse files
committed
Merge remote-tracking branch 'upstream/master' into feature
2 parents 7b8c7d1 + 91c4c42 commit 1fbf8fb

8 files changed

+625
-32
lines changed

scripts/caclmgrd

+19-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
8080
"dst_ports": ["22"],
8181
"multi_asic_ns_to_host_fwd":True
8282
},
83+
"EXTERNAL_CLIENT": {
84+
"ip_protocols": ["tcp"],
85+
"multi_asic_ns_to_host_fwd":True
86+
},
8387
"ANY": {
8488
"ip_protocols": ["any"],
8589
"dst_ports": ["0"],
@@ -545,7 +549,8 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
545549

546550
# Obtain default IP protocol(s) and destination port(s) for this service
547551
ip_protocols = self.ACL_SERVICES[acl_service]["ip_protocols"]
548-
dst_ports = self.ACL_SERVICES[acl_service]["dst_ports"]
552+
if "dst_ports" in self.ACL_SERVICES[acl_service]:
553+
dst_ports = self.ACL_SERVICES[acl_service]["dst_ports"]
549554

550555
acl_rules = {}
551556

@@ -571,6 +576,19 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
571576
elif self.is_rule_ipv4(rule_props):
572577
table_ip_version = 4
573578

579+
# Read DST_PORT info from Config DB, insert it back to ACL_SERVICES
580+
if acl_service == 'EXTERNAL_CLIENT' and "L4_DST_PORT" in rule_props:
581+
dst_ports = [rule_props["L4_DST_PORT"]]
582+
self.ACL_SERVICES[acl_service]["dst_ports"] = dst_ports
583+
elif acl_service == 'EXTERNAL_CLIENT' and "L4_DST_PORT_RANGE" in rule_props:
584+
dst_ports = []
585+
port_ranges = rule_props["L4_DST_PORT_RANGE"].split("-")
586+
port_start = int(port_ranges[0])
587+
port_end = int(port_ranges[1])
588+
for port in range(port_start, port_end + 1):
589+
dst_ports.append(port)
590+
self.ACL_SERVICES[acl_service]["dst_ports"] = dst_ports
591+
574592
if (self.is_rule_ipv6(rule_props) and (table_ip_version == 4)):
575593
self.log_error("CtrlPlane ACL table {} is a IPv4 based table and rule {} is a IPV6 rule! Ignoring rule."
576594
.format(table_name, rule_id))

scripts/determine-reboot-cause

+51-17
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ def find_hardware_reboot_cause():
122122
else:
123123
sonic_logger.log_info("No reboot cause found from platform api")
124124

125-
hardware_reboot_cause = "{} ({})".format(hardware_reboot_cause_major, hardware_reboot_cause_minor)
125+
hardware_reboot_cause_minor_str = ""
126+
if hardware_reboot_cause_minor:
127+
hardware_reboot_cause_minor_str = " ({})".format(hardware_reboot_cause_minor)
128+
129+
hardware_reboot_cause = hardware_reboot_cause_major + hardware_reboot_cause_minor_str
130+
126131
return hardware_reboot_cause
127132

128133

@@ -158,6 +163,50 @@ def get_reboot_cause_dict(previous_reboot_cause, comment, gen_time):
158163

159164
return reboot_cause_dict
160165

166+
def determine_reboot_cause():
167+
# This variable is kept for future-use purpose. When proc_cmd_line/vendor/software provides
168+
# any additional_reboot_info it will be stored as a "comment" in REBOOT_CAUSE_HISTORY_FILE
169+
additional_reboot_info = "N/A"
170+
171+
# 1. Check if the previous reboot was warm/fast reboot by testing whether there is "fast|fastfast|warm" in /proc/cmdline
172+
proc_cmdline_reboot_cause = find_proc_cmdline_reboot_cause()
173+
174+
# 2. Check if the previous reboot was caused by hardware
175+
# If yes, the hardware reboot cause will be treated as the reboot cause
176+
hardware_reboot_cause = find_hardware_reboot_cause()
177+
178+
# 3. If there is a REBOOT_CAUSE_FILE, it will contain any software-related
179+
# reboot info. We will use it as the previous cause.
180+
software_reboot_cause = find_software_reboot_cause()
181+
182+
# The main decision logic of the reboot cause:
183+
# If there is a valid hardware reboot cause indicated by platform API,
184+
# check the software reboot cause to add additional rebot cause.
185+
# If there is a reboot cause indicated by /proc/cmdline, and/or warmreboot/fastreboot/softreboot
186+
# the software_reboot_cause which is the content of /hosts/reboot-cause/reboot-cause.txt
187+
# will be treated as the additional reboot cause
188+
# Elif there is a cmdline reboot cause,
189+
# the software_reboot_cause will be treated as the reboot cause if it's not unknown
190+
# otherwise, the cmdline_reboot_cause will be treated as the reboot cause if it's not none
191+
# Else the software_reboot_cause will be treated as the reboot cause
192+
if REBOOT_CAUSE_NON_HARDWARE not in hardware_reboot_cause:
193+
previous_reboot_cause = hardware_reboot_cause
194+
# Check if any software reboot was issued before this hardware reboot happened
195+
if software_reboot_cause is not REBOOT_CAUSE_UNKNOWN:
196+
additional_reboot_info = software_reboot_cause
197+
elif proc_cmdline_reboot_cause is not None:
198+
additional_reboot_info = proc_cmdline_reboot_cause
199+
elif proc_cmdline_reboot_cause is not None:
200+
if software_reboot_cause is not REBOOT_CAUSE_UNKNOWN:
201+
# Get the reboot cause from REBOOT_CAUSE_FILE
202+
previous_reboot_cause = software_reboot_cause
203+
else:
204+
previous_reboot_cause = proc_cmdline_reboot_cause
205+
else:
206+
previous_reboot_cause = software_reboot_cause
207+
208+
return previous_reboot_cause, additional_reboot_info
209+
161210

162211
def main():
163212
# Configure logger to log all messages INFO level and higher
@@ -177,22 +226,7 @@ def main():
177226
if os.path.exists(PREVIOUS_REBOOT_CAUSE_FILE):
178227
os.remove(PREVIOUS_REBOOT_CAUSE_FILE)
179228

180-
# This variable is kept for future-use purpose. When proc_cmd_line/vendor/software provides
181-
# any additional_reboot_info it will be stored as a "comment" in REBOOT_CAUSE_HISTORY_FILE
182-
additional_reboot_info = "N/A"
183-
184-
# Check if the previous reboot was warm/fast reboot by testing whether there is "fast|fastfast|warm" in /proc/cmdline
185-
proc_cmdline_reboot_cause = find_proc_cmdline_reboot_cause()
186-
187-
# If /proc/cmdline does not indicate reboot cause, check if the previous reboot was caused by hardware
188-
if proc_cmdline_reboot_cause is None:
189-
previous_reboot_cause = find_hardware_reboot_cause()
190-
if previous_reboot_cause.startswith(REBOOT_CAUSE_NON_HARDWARE):
191-
# If the reboot cause is non-hardware, get the reboot cause from REBOOT_CAUSE_FILE
192-
previous_reboot_cause = find_software_reboot_cause()
193-
else:
194-
# Get the reboot cause from REBOOT_CAUSE_FILE
195-
previous_reboot_cause = find_software_reboot_cause()
229+
previous_reboot_cause, additional_reboot_info = determine_reboot_cause()
196230

197231
# Current time
198232
reboot_cause_gen_time = str(datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S'))

scripts/hostcfgd

+166-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import re
1212
import jinja2
1313
from sonic_py_common import device_info
1414
from swsscommon.swsscommon import ConfigDBConnector, DBConnector, Table
15+
from swsscommon import swsscommon
1516

1617
# FILE
1718
PAM_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+
12991437
class 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

Comments
 (0)