Skip to content

Commit

Permalink
[minigraph] Update parsing logic for Storage backend devices (sonic-n…
Browse files Browse the repository at this point in the history
…et#7944)

Signed-off-by: Neetha John <nejo@microsoft.com>

Why I did it
The current logic generates 'VLAN_SUB_INTERFACE' table if the device type is backend and cluster name contains 'str'. This is not a reliable method to determine a storage backend device

How I did it
Updated the logic to generate 'VLAN_SUB_INTERFACE' table if any of the following conditions hold true
 - device is of type backend and ResourceType attribute is None
 - device is of type backend and ResourceType attribute contains "Storage"
 - device is of type backend and graph contains "Subinterface" section

Also updated the logic to set "is_storage_device" to True
 - For Backend, if any of the above conditions hold true
 - For Frontend, if ResourceType attribute contains "Storage"

How to verify it
Added new tests to verify the code changes and built sonic_config_engine-1.0-py3-none-any.whl successfully
  • Loading branch information
neethajohn authored Jun 25, 2021
1 parent ef67ba5 commit dc5d52f
Show file tree
Hide file tree
Showing 6 changed files with 1,104 additions and 60 deletions.
48 changes: 36 additions & 12 deletions src/sonic-config-engine/minigraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ def parse_png(png, hname, dpg_ecmp_content = None):
port_speeds = {}
console_ports = {}
mux_cable_ports = {}
is_storage_device = False
port_device_map = {}
png_ecmp_content = {}
FG_NHG_MEMBER = {}
Expand Down Expand Up @@ -253,10 +252,6 @@ def parse_png(png, hname, dpg_ecmp_content = None):
device_data['lo_addr_v6'] = lo_prefix_v6
devices[name] = device_data

if name == hname:
if cluster and "str" in cluster.lower():
is_storage_device = True

if child.tag == str(QName(ns, "DeviceInterfaceLinks")):
for if_link in child.findall(str(QName(ns, 'DeviceLinkBase'))):
if str(QName(ns3, "type")) in if_link.attrib:
Expand Down Expand Up @@ -293,7 +288,7 @@ def parse_png(png, hname, dpg_ecmp_content = None):

png_ecmp_content = {"FG_NHG_MEMBER": FG_NHG_MEMBER, "FG_NHG": FG_NHG, "NEIGH": NEIGH}

return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speeds, console_ports, mux_cable_ports, is_storage_device, png_ecmp_content)
return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speeds, console_ports, mux_cable_ports, png_ecmp_content)


def parse_asic_external_link(link, asic_name, hostname):
Expand Down Expand Up @@ -402,6 +397,7 @@ def parse_loopback_intf(child):
def parse_dpg(dpg, hname):
aclintfs = None
mgmtintfs = None
subintfs = None
tunnelintfs = defaultdict(dict)
for child in dpg:
"""
Expand Down Expand Up @@ -441,6 +437,16 @@ def parse_dpg(dpg, hname):
ip_intfs_map[ipprefix] = intfalias
lo_intfs = parse_loopback_intf(child)

subintfs = child.find(str(QName(ns, "SubInterfaces")))
if subintfs is not None:
for subintf in subintfs.findall(str(QName(ns, "SubInterface"))):
intfalias = subintf.find(str(QName(ns, "AttachTo"))).text
intfname = port_alias_map.get(intfalias, intfalias)
ipprefix = subintf.find(str(QName(ns, "Prefix"))).text
subintfvlan = subintf.find(str(QName(ns, "Vlan"))).text
subintfname = intfname + VLAN_SUB_INTERFACE_SEPARATOR + subintfvlan
intfs[(subintfname, ipprefix)] = {}

mvrfConfigs = child.find(str(QName(ns, "MgmtVrfConfigs")))
mvrf = {}
if mvrfConfigs != None:
Expand Down Expand Up @@ -1207,7 +1213,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_internal_sessions, bgp_voq_chassis_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname)
elif child.tag == str(QName(ns, "PngDec")):
(neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speed_png, console_ports, mux_cable_ports, is_storage_device, png_ecmp_content) = parse_png(child, hostname, dpg_ecmp_content)
(neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speed_png, console_ports, mux_cable_ports, png_ecmp_content) = parse_png(child, hostname, dpg_ecmp_content)
elif child.tag == str(QName(ns, "UngDec")):
(u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname, None)
elif child.tag == str(QName(ns, "MetadataDeclaration")):
Expand Down Expand Up @@ -1273,9 +1279,6 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw

results['DEVICE_METADATA']['localhost']['peer_switch'] = list(results['PEER_SWITCH'].keys())[0]

if is_storage_device:
results['DEVICE_METADATA']['localhost']['storage_device'] = "true"

# for this hostname, if sub_role is defined, add sub_role in
# device_metadata
if sub_role is not None:
Expand Down Expand Up @@ -1375,6 +1378,9 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
elif intf[0][0:11] == 'PortChannel':
pc_intfs[intf] = {}
pc_intfs[intf[0]] = {}
elif VLAN_SUB_INTERFACE_SEPARATOR in intf[0]:
vlan_sub_intfs[intf] = {}
vlan_sub_intfs[intf[0]] = {'admin_status': 'up'}
else:
phyport_intfs[intf] = {}
phyport_intfs[intf[0]] = {}
Expand Down Expand Up @@ -1457,6 +1463,13 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
if port[0] in ports:
ports.get(port[0])['admin_status'] = 'up'

if len(vlan_sub_intfs):
for subintf in vlan_sub_intfs:
if not isinstance(subintf, tuple):
parent_port = subintf.split(".")[0]
if parent_port in ports:
ports.get(parent_port)['admin_status'] = 'up'

for member in list(pc_members.keys()) + list(vlan_members.keys()):
port = ports.get(member[1])
if port:
Expand Down Expand Up @@ -1497,9 +1510,16 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw

results['PORTCHANNEL_INTERFACE'] = pc_intfs

if current_device['type'] in backend_device_types and is_storage_device:
# for storage backend subinterface info present in minigraph takes precedence over ResourceType
if current_device['type'] in backend_device_types and bool(vlan_sub_intfs):
del results['INTERFACE']
del results['PORTCHANNEL_INTERFACE']
is_storage_device = True
results['VLAN_SUB_INTERFACE'] = vlan_sub_intfs
elif current_device['type'] in backend_device_types and (resource_type is None or 'Storage' in resource_type):
del results['INTERFACE']
del results['PORTCHANNEL_INTERFACE']
is_storage_device = True

for intf in phyport_intfs.keys():
if isinstance(intf, tuple):
Expand All @@ -1520,8 +1540,12 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
else:
sub_intf = pc_intf + VLAN_SUB_INTERFACE_SEPARATOR + VLAN_SUB_INTERFACE_VLAN_ID
vlan_sub_intfs[sub_intf] = {"admin_status" : "up"}

results['VLAN_SUB_INTERFACE'] = vlan_sub_intfs
elif resource_type is not None and 'Storage' in resource_type:
is_storage_device = True

if is_storage_device:
results['DEVICE_METADATA']['localhost']['storage_device'] = "true"

results['VLAN'] = vlans
results['VLAN_MEMBER'] = vlan_members
Expand Down
Loading

0 comments on commit dc5d52f

Please sign in to comment.