[minigraph.py]: Parse mux cable table (#5876)
Parse device IPv6 loopback addresses when available Add MUX_CABLE table to config DB: 'MUX_CABLE': { 'Ethernet4': { 'state': 'auto', 'server_ipv4': '10.10.10.1/32', 'server_ipv6': 'fe80::0001/128' } }
This commit is contained in:
parent
67dbbb33bf
commit
261a81d379
@ -79,6 +79,7 @@ def get_peer_switch_info(link_metadata, devices):
|
|||||||
|
|
||||||
def parse_device(device):
|
def parse_device(device):
|
||||||
lo_prefix = None
|
lo_prefix = None
|
||||||
|
lo_prefix_v6 = None
|
||||||
mgmt_prefix = None
|
mgmt_prefix = None
|
||||||
d_type = None # don't shadow type()
|
d_type = None # don't shadow type()
|
||||||
hwsku = None
|
hwsku = None
|
||||||
@ -90,6 +91,8 @@ def parse_device(device):
|
|||||||
for node in device:
|
for node in device:
|
||||||
if node.tag == str(QName(ns, "Address")):
|
if node.tag == str(QName(ns, "Address")):
|
||||||
lo_prefix = node.find(str(QName(ns2, "IPPrefix"))).text
|
lo_prefix = node.find(str(QName(ns2, "IPPrefix"))).text
|
||||||
|
elif node.tag == str(QName(ns, "AddressV6")):
|
||||||
|
lo_prefix_v6 = node.find(str(QName(ns2, "IPPrefix"))).text
|
||||||
elif node.tag == str(QName(ns, "ManagementAddress")):
|
elif node.tag == str(QName(ns, "ManagementAddress")):
|
||||||
mgmt_prefix = node.find(str(QName(ns2, "IPPrefix"))).text
|
mgmt_prefix = node.find(str(QName(ns2, "IPPrefix"))).text
|
||||||
elif node.tag == str(QName(ns, "Hostname")):
|
elif node.tag == str(QName(ns, "Hostname")):
|
||||||
@ -98,7 +101,7 @@ def parse_device(device):
|
|||||||
hwsku = node.text
|
hwsku = node.text
|
||||||
elif node.tag == str(QName(ns, "DeploymentId")):
|
elif node.tag == str(QName(ns, "DeploymentId")):
|
||||||
deployment_id = node.text
|
deployment_id = node.text
|
||||||
return (lo_prefix, mgmt_prefix, name, hwsku, d_type, deployment_id)
|
return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id)
|
||||||
|
|
||||||
def parse_png(png, hname):
|
def parse_png(png, hname):
|
||||||
neighbors = {}
|
neighbors = {}
|
||||||
@ -160,10 +163,12 @@ def parse_png(png, hname):
|
|||||||
|
|
||||||
if child.tag == str(QName(ns, "Devices")):
|
if child.tag == str(QName(ns, "Devices")):
|
||||||
for device in child.findall(str(QName(ns, "Device"))):
|
for device in child.findall(str(QName(ns, "Device"))):
|
||||||
(lo_prefix, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device)
|
(lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device)
|
||||||
device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku }
|
device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku }
|
||||||
if deployment_id:
|
if deployment_id:
|
||||||
device_data['deployment_id'] = deployment_id
|
device_data['deployment_id'] = deployment_id
|
||||||
|
if lo_prefix_v6:
|
||||||
|
device_data['lo_addr_v6'] = lo_prefix_v6
|
||||||
devices[name] = device_data
|
devices[name] = device_data
|
||||||
|
|
||||||
if name == hname:
|
if name == hname:
|
||||||
@ -281,10 +286,12 @@ def parse_asic_png(png, asic_name, hostname):
|
|||||||
|
|
||||||
if child.tag == str(QName(ns, "Devices")):
|
if child.tag == str(QName(ns, "Devices")):
|
||||||
for device in child.findall(str(QName(ns, "Device"))):
|
for device in child.findall(str(QName(ns, "Device"))):
|
||||||
(lo_prefix, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device)
|
(lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device)
|
||||||
device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku }
|
device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku }
|
||||||
if deployment_id:
|
if deployment_id:
|
||||||
device_data['deployment_id'] = deployment_id
|
device_data['deployment_id'] = deployment_id
|
||||||
|
if lo_prefix_v6:
|
||||||
|
device_data['lo_addr_v6']= lo_prefix_v6
|
||||||
devices[name] = device_data
|
devices[name] = device_data
|
||||||
return (neighbors, devices, port_speeds)
|
return (neighbors, devices, port_speeds)
|
||||||
|
|
||||||
@ -1234,6 +1241,8 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
|
|||||||
|
|
||||||
results['TUNNEL'] = get_tunnel_entries(tunnel_intfs, lo_intfs, hostname)
|
results['TUNNEL'] = get_tunnel_entries(tunnel_intfs, lo_intfs, hostname)
|
||||||
|
|
||||||
|
results['MUX_CABLE'] = get_mux_cable_entries(mux_cable_ports, neighbors, devices)
|
||||||
|
|
||||||
for nghbr in list(neighbors.keys()):
|
for nghbr in list(neighbors.keys()):
|
||||||
# remove port not in port_config.ini
|
# remove port not in port_config.ini
|
||||||
if nghbr not in ports:
|
if nghbr not in ports:
|
||||||
@ -1317,10 +1326,24 @@ def get_tunnel_entries(tunnel_intfs, lo_intfs, hostname):
|
|||||||
tunnels[tunnel_key] = tunnel_attr
|
tunnels[tunnel_key] = tunnel_attr
|
||||||
return tunnels
|
return tunnels
|
||||||
|
|
||||||
|
def get_mux_cable_entries(mux_cable_ports, neighbors, devices):
|
||||||
|
mux_cable_table = {}
|
||||||
|
|
||||||
|
for intf in mux_cable_ports:
|
||||||
|
if intf in neighbors:
|
||||||
|
entry = {}
|
||||||
|
neighbor = neighbors[intf]['name']
|
||||||
|
entry['state'] = 'auto'
|
||||||
|
entry['server_ipv4'] = devices[neighbor]['lo_addr']
|
||||||
|
if 'lo_addr_v6' in devices[neighbor]:
|
||||||
|
entry['server_ipv6'] = devices[neighbor]['lo_addr_v6']
|
||||||
|
mux_cable_table[intf] = entry
|
||||||
|
|
||||||
|
return mux_cable_table
|
||||||
|
|
||||||
def parse_device_desc_xml(filename):
|
def parse_device_desc_xml(filename):
|
||||||
root = ET.parse(filename).getroot()
|
root = ET.parse(filename).getroot()
|
||||||
(lo_prefix, mgmt_prefix, hostname, hwsku, d_type, _) = parse_device(root)
|
(lo_prefix, lo_prefix_v6, mgmt_prefix, hostname, hwsku, d_type, _) = parse_device(root)
|
||||||
|
|
||||||
results = {}
|
results = {}
|
||||||
results['DEVICE_METADATA'] = {'localhost': {
|
results['DEVICE_METADATA'] = {'localhost': {
|
||||||
@ -1329,6 +1352,8 @@ def parse_device_desc_xml(filename):
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
results['LOOPBACK_INTERFACE'] = {('lo', lo_prefix): {}}
|
results['LOOPBACK_INTERFACE'] = {('lo', lo_prefix): {}}
|
||||||
|
if lo_prefix_v6:
|
||||||
|
results['LOOPBACK_INTERFACE'] = {('lo_v6', lo_prefix_v6): {}}
|
||||||
|
|
||||||
mgmt_intf = {}
|
mgmt_intf = {}
|
||||||
mgmtipn = ipaddress.ip_network(UNICODE_TYPE(mgmt_prefix), False)
|
mgmtipn = ipaddress.ip_network(UNICODE_TYPE(mgmt_prefix), False)
|
||||||
|
@ -213,6 +213,24 @@
|
|||||||
<StartDevice>switch-02t1</StartDevice>
|
<StartDevice>switch-02t1</StartDevice>
|
||||||
<StartPort>port1</StartPort>
|
<StartPort>port1</StartPort>
|
||||||
</DeviceLinkBase>
|
</DeviceLinkBase>
|
||||||
|
<DeviceLinkBase i:type="DeviceInterfaceLink">
|
||||||
|
<ElementType>DeviceInterfaceLink</ElementType>
|
||||||
|
<AutoNegotiation>true</AutoNegotiation>
|
||||||
|
<Bandwidth>25000</Bandwidth>
|
||||||
|
<EndDevice>switch-t0</EndDevice>
|
||||||
|
<EndPort>fortyGigE0/4</EndPort>
|
||||||
|
<StartDevice>server1</StartDevice>
|
||||||
|
<StartPort>port1</StartPort>
|
||||||
|
</DeviceLinkBase>
|
||||||
|
<DeviceLinkBase i:type="DeviceInterfaceLink">
|
||||||
|
<ElementType>DeviceInterfaceLink</ElementType>
|
||||||
|
<AutoNegotiation>true</AutoNegotiation>
|
||||||
|
<Bandwidth>40000</Bandwidth>
|
||||||
|
<EndDevice>switch-t0</EndDevice>
|
||||||
|
<EndPort>fortyGigE0/8</EndPort>
|
||||||
|
<StartDevice>server2</StartDevice>
|
||||||
|
<StartPort>port1</StartPort>
|
||||||
|
</DeviceLinkBase>
|
||||||
<DeviceLinkBase i:type="LogicalLink">
|
<DeviceLinkBase i:type="LogicalLink">
|
||||||
<ElementType>LogicalLink</ElementType>
|
<ElementType>LogicalLink</ElementType>
|
||||||
<Bandwidth>10000</Bandwidth>
|
<Bandwidth>10000</Bandwidth>
|
||||||
@ -278,6 +296,34 @@
|
|||||||
</ManagementAddress>
|
</ManagementAddress>
|
||||||
<HwSku>Force10-S6000</HwSku>
|
<HwSku>Force10-S6000</HwSku>
|
||||||
</Device>
|
</Device>
|
||||||
|
<Device i:type="Server">
|
||||||
|
<ElementType>Server</ElementType>
|
||||||
|
<Address xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
|
||||||
|
<d5p1:IPPrefix>10.10.10.1/32</d5p1:IPPrefix>
|
||||||
|
</Address>
|
||||||
|
<AddressV6 xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
|
||||||
|
<d5p1:IPPrefix>fe80::0001/128</d5p1:IPPrefix>
|
||||||
|
</AddressV6>
|
||||||
|
<ManagementAddress xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
|
||||||
|
<d5p1:IPPrefix>10.0.0.1/32</d5p1:IPPrefix>
|
||||||
|
</ManagementAddress>
|
||||||
|
<Hostname>server1</Hostname>
|
||||||
|
<HwSku>server-sku</HwSku>
|
||||||
|
</Device>
|
||||||
|
<Device i:type="Server">
|
||||||
|
<ElementType>Server</ElementType>
|
||||||
|
<Address xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
|
||||||
|
<d5p1:IPPrefix>10.10.10.2/32</d5p1:IPPrefix>
|
||||||
|
</Address>
|
||||||
|
<AddressV6 xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
|
||||||
|
<d5p1:IPPrefix>fe80::0002/128</d5p1:IPPrefix>
|
||||||
|
</AddressV6>
|
||||||
|
<ManagementAddress xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
|
||||||
|
<d5p1:IPPrefix>10.0.0.2/32</d5p1:IPPrefix>
|
||||||
|
</ManagementAddress>
|
||||||
|
<Hostname>server2</Hostname>
|
||||||
|
<HwSku>server-sku</HwSku>
|
||||||
|
</Device>
|
||||||
</Devices>
|
</Devices>
|
||||||
</PngDec>
|
</PngDec>
|
||||||
<LinkMetadataDeclaration>
|
<LinkMetadataDeclaration>
|
||||||
|
@ -348,7 +348,7 @@ class TestCfgGen(TestCase):
|
|||||||
utils.to_dict(
|
utils.to_dict(
|
||||||
"{'Ethernet8': {'lanes': '37,38,39,40', 'description': 'Interface description', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '40000', 'mux_cable': 'true'}, "
|
"{'Ethernet8': {'lanes': '37,38,39,40', 'description': 'Interface description', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/8', 'admin_status': 'up', 'speed': '40000', 'mux_cable': 'true'}, "
|
||||||
"'Ethernet0': {'lanes': '29,30,31,32', 'description': 'switch-01t1:port1', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/0', 'admin_status': 'up', 'speed': '10000'}, "
|
"'Ethernet0': {'lanes': '29,30,31,32', 'description': 'switch-01t1:port1', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/0', 'admin_status': 'up', 'speed': '10000'}, "
|
||||||
"'Ethernet4': {'lanes': '25,26,27,28', 'description': 'fortyGigE0/4', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/4', 'admin_status': 'up', 'speed': '25000', 'mux_cable': 'true'}, "
|
"'Ethernet4': {'lanes': '25,26,27,28', 'description': 'server1:port1', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/4', 'admin_status': 'up', 'speed': '25000', 'mux_cable': 'true'}, "
|
||||||
"'Ethernet108': {'alias': 'fortyGigE0/108', 'pfc_asym': 'off', 'lanes': '81,82,83,84', 'description': 'fortyGigE0/108', 'mtu': '9100'}, "
|
"'Ethernet108': {'alias': 'fortyGigE0/108', 'pfc_asym': 'off', 'lanes': '81,82,83,84', 'description': 'fortyGigE0/108', 'mtu': '9100'}, "
|
||||||
"'Ethernet100': {'alias': 'fortyGigE0/100', 'pfc_asym': 'off', 'lanes': '125,126,127,128', 'description': 'fortyGigE0/100', 'mtu': '9100'}, "
|
"'Ethernet100': {'alias': 'fortyGigE0/100', 'pfc_asym': 'off', 'lanes': '125,126,127,128', 'description': 'fortyGigE0/100', 'mtu': '9100'}, "
|
||||||
"'Ethernet104': {'alias': 'fortyGigE0/104', 'pfc_asym': 'off', 'lanes': '85,86,87,88', 'description': 'fortyGigE0/104', 'mtu': '9100'}, "
|
"'Ethernet104': {'alias': 'fortyGigE0/104', 'pfc_asym': 'off', 'lanes': '85,86,87,88', 'description': 'fortyGigE0/104', 'mtu': '9100'}, "
|
||||||
|
@ -123,24 +123,41 @@ class TestCfgGenCaseInsensitive(TestCase):
|
|||||||
|
|
||||||
def test_minigraph_neighbor_metadata(self):
|
def test_minigraph_neighbor_metadata(self):
|
||||||
argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR_METADATA"'
|
argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR_METADATA"'
|
||||||
|
|
||||||
|
expected_table = {
|
||||||
|
'switch-01t1': {
|
||||||
|
'lo_addr': '10.1.0.186/32',
|
||||||
|
'mgmt_addr': '10.7.0.196/26',
|
||||||
|
'hwsku': 'Force10-S6000',
|
||||||
|
'type': 'LeafRouter',
|
||||||
|
'deployment_id': '2'
|
||||||
|
},
|
||||||
|
'switch2-t0': {
|
||||||
|
'hwsku': 'Force10-S6000',
|
||||||
|
'lo_addr': '25.1.1.10',
|
||||||
|
'mgmt_addr': '10.7.0.196/26',
|
||||||
|
'type': 'ToRRouter'
|
||||||
|
},
|
||||||
|
'server1': {
|
||||||
|
'hwsku': 'server-sku',
|
||||||
|
'lo_addr': '10.10.10.1/32',
|
||||||
|
'lo_addr_v6': 'fe80::0001/128',
|
||||||
|
'mgmt_addr': '10.0.0.1/32',
|
||||||
|
'type': 'Server'
|
||||||
|
},
|
||||||
|
'server2': {
|
||||||
|
'hwsku': 'server-sku',
|
||||||
|
'lo_addr': '10.10.10.2/32',
|
||||||
|
'lo_addr_v6': 'fe80::0002/128',
|
||||||
|
'mgmt_addr': '10.0.0.2/32',
|
||||||
|
'type': 'Server'
|
||||||
|
}
|
||||||
|
}
|
||||||
output = self.run_script(argument)
|
output = self.run_script(argument)
|
||||||
|
self.maxDiff = None
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
utils.to_dict(output.strip()),
|
utils.to_dict(output.strip()),
|
||||||
utils.to_dict("{" \
|
expected_table
|
||||||
"'switch-01t1': {" \
|
|
||||||
"'lo_addr': '10.1.0.186/32'," \
|
|
||||||
"'mgmt_addr': '10.7.0.196/26'," \
|
|
||||||
"'hwsku': 'Force10-S6000'," \
|
|
||||||
"'type': 'LeafRouter'," \
|
|
||||||
"'deployment_id': '2'" \
|
|
||||||
"}," \
|
|
||||||
"'switch2-t0': {" \
|
|
||||||
"'hwsku': 'Force10-S6000'," \
|
|
||||||
"'lo_addr': '25.1.1.10'," \
|
|
||||||
"'mgmt_addr': '10.7.0.196/26'," \
|
|
||||||
"'type': 'ToRRouter'" \
|
|
||||||
"}" \
|
|
||||||
"}")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# everflow portion is not used
|
# everflow portion is not used
|
||||||
@ -227,3 +244,25 @@ class TestCfgGenCaseInsensitive(TestCase):
|
|||||||
utils.to_dict(output.strip()),
|
utils.to_dict(output.strip()),
|
||||||
expected_tunnel
|
expected_tunnel
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_minigraph_mux_cable_table(self):
|
||||||
|
argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "MUX_CABLE"'
|
||||||
|
expected_table = {
|
||||||
|
'Ethernet4': {
|
||||||
|
'state': 'auto',
|
||||||
|
'server_ipv4': '10.10.10.1/32',
|
||||||
|
'server_ipv6': 'fe80::0001/128'
|
||||||
|
},
|
||||||
|
'Ethernet8': {
|
||||||
|
'state': 'auto',
|
||||||
|
'server_ipv4': '10.10.10.2/32',
|
||||||
|
'server_ipv6': 'fe80::0002/128'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output = self.run_script(argument)
|
||||||
|
self.assertEqual(
|
||||||
|
utils.to_dict(output.strip()),
|
||||||
|
expected_table
|
||||||
|
)
|
||||||
|
|
@ -202,8 +202,8 @@ class TestMultiNpuCfgGen(TestCase):
|
|||||||
output = json.loads(self.run_script(argument))
|
output = json.loads(self.run_script(argument))
|
||||||
self.assertDictEqual(output, \
|
self.assertDictEqual(output, \
|
||||||
{'01T2': {'lo_addr': None, 'mgmt_addr': '89.139.132.40', 'hwsku': 'VM', 'type': 'SpineRouter'},
|
{'01T2': {'lo_addr': None, 'mgmt_addr': '89.139.132.40', 'hwsku': 'VM', 'type': 'SpineRouter'},
|
||||||
'ASIC3': {'lo_addr': '0.0.0.0/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'},
|
'ASIC3': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'},
|
||||||
'ASIC2': {'lo_addr': '0.0.0.0/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}})
|
'ASIC2': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}})
|
||||||
|
|
||||||
def test_backend_asic_device_neigh(self):
|
def test_backend_asic_device_neigh(self):
|
||||||
argument = "-m {} -p {} -n asic3 --var-json \"DEVICE_NEIGHBOR\"".format(self.sample_graph, self.port_config[3])
|
argument = "-m {} -p {} -n asic3 --var-json \"DEVICE_NEIGHBOR\"".format(self.sample_graph, self.port_config[3])
|
||||||
@ -218,8 +218,8 @@ class TestMultiNpuCfgGen(TestCase):
|
|||||||
argument = "-m {} -p {} -n asic3 --var-json \"DEVICE_NEIGHBOR_METADATA\"".format(self.sample_graph, self.port_config[3])
|
argument = "-m {} -p {} -n asic3 --var-json \"DEVICE_NEIGHBOR_METADATA\"".format(self.sample_graph, self.port_config[3])
|
||||||
output = json.loads(self.run_script(argument))
|
output = json.loads(self.run_script(argument))
|
||||||
self.assertDictEqual(output, \
|
self.assertDictEqual(output, \
|
||||||
{'ASIC1': {'lo_addr': '0.0.0.0/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'},
|
{'ASIC1': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'},
|
||||||
'ASIC0': {'lo_addr': '0.0.0.0/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}})
|
'ASIC0': {'lo_addr': '0.0.0.0/0', 'lo_addr_v6': '::/0', 'mgmt_addr': '0.0.0.0/0', 'hwsku': 'multi-npu-asic', 'type': 'Asic'}})
|
||||||
|
|
||||||
def test_frontend_bgp_neighbor(self):
|
def test_frontend_bgp_neighbor(self):
|
||||||
argument = "-m {} -p {} -n asic0 --var-json \"BGP_NEIGHBOR\"".format(self.sample_graph, self.port_config[0])
|
argument = "-m {} -p {} -n asic0 --var-json \"BGP_NEIGHBOR\"".format(self.sample_graph, self.port_config[0])
|
||||||
|
Loading…
Reference in New Issue
Block a user