[sonic-cfggen]: Read ACL interfaces information from minigrap (#419)
* Enable translate_acl to read acl attaching from minigraph * Add AclInterfaces into test t0 graph * Expose minigraph_ports according
This commit is contained in:
parent
6a6bc88dcb
commit
bd77f9a38a
@ -124,6 +124,7 @@ def parse_dpg(dpg, hname):
|
|||||||
|
|
||||||
ipintfs = child.find(str(QName(ns, "IPInterfaces")))
|
ipintfs = child.find(str(QName(ns, "IPInterfaces")))
|
||||||
intfs = []
|
intfs = []
|
||||||
|
intfnames = {}
|
||||||
vlan_map = {}
|
vlan_map = {}
|
||||||
pc_map = {}
|
pc_map = {}
|
||||||
for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
|
for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
|
||||||
@ -177,6 +178,7 @@ def parse_dpg(dpg, hname):
|
|||||||
if peer_addr_val is not None:
|
if peer_addr_val is not None:
|
||||||
intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
|
intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
|
||||||
intfs.append(intf)
|
intfs.append(intf)
|
||||||
|
intfnames[intf['alias']] = { 'alias': intf['name'] }
|
||||||
|
|
||||||
pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
|
pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
|
||||||
pc_intfs = []
|
pc_intfs = []
|
||||||
@ -237,10 +239,27 @@ def parse_dpg(dpg, hname):
|
|||||||
vlan_attributes.update(addrtuple)
|
vlan_attributes.update(addrtuple)
|
||||||
vlan_intfs.append(copy.deepcopy(vlan_attributes))
|
vlan_intfs.append(copy.deepcopy(vlan_attributes))
|
||||||
vlans[vintfname] = vlan_attributes
|
vlans[vintfname] = vlan_attributes
|
||||||
|
aclintfs = child.find(str(QName(ns, "AclInterfaces")))
|
||||||
|
acls = {}
|
||||||
|
for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
|
||||||
|
aclname = aclintf.find(str(QName(ns, "InAcl"))).text
|
||||||
|
aclattach = aclintf.find(str(QName(ns, "AttachTo"))).text.split(';')
|
||||||
|
acl_intfs = []
|
||||||
|
for member in aclattach:
|
||||||
|
member = member.strip()
|
||||||
|
if port_alias_map.has_key(member):
|
||||||
|
member = port_alias_map[member]
|
||||||
|
if pcs.has_key(member):
|
||||||
|
acl_intfs.extend(pcs[member]['members']) # For ACL attaching to port channels, we break them into port channel members
|
||||||
|
elif vlans.has_key(member):
|
||||||
|
print >> sys.stderr, "Warning: ACL "+aclname+" is attached to a Vlan interface, which is currently not supported"
|
||||||
|
elif intfnames.has_key(member):
|
||||||
|
acl_intfs.append(member)
|
||||||
|
if acl_intfs:
|
||||||
|
acls[aclname] = acl_intfs
|
||||||
|
|
||||||
|
return intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, intfnames, vlans, pcs, acls
|
||||||
return intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, vlans, pcs
|
return None, None, None, None, None, None, None, None
|
||||||
return None, None, None, None, None
|
|
||||||
|
|
||||||
def parse_cpg(cpg, hname):
|
def parse_cpg(cpg, hname):
|
||||||
bgp_sessions = []
|
bgp_sessions = []
|
||||||
@ -394,7 +413,7 @@ def parse_xml(filename, platform=None, port_config_file=None):
|
|||||||
|
|
||||||
for child in root:
|
for child in root:
|
||||||
if child.tag == str(QName(ns, "DpgDec")):
|
if child.tag == str(QName(ns, "DpgDec")):
|
||||||
(intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, vlans, pcs) = parse_dpg(child, hostname)
|
(intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, ports, vlans, pcs, acls) = parse_dpg(child, hostname)
|
||||||
elif child.tag == str(QName(ns, "CpgDec")):
|
elif child.tag == str(QName(ns, "CpgDec")):
|
||||||
(bgp_sessions, bgp_asn) = parse_cpg(child, hostname)
|
(bgp_sessions, bgp_asn) = parse_cpg(child, hostname)
|
||||||
elif child.tag == str(QName(ns, "PngDec")):
|
elif child.tag == str(QName(ns, "PngDec")):
|
||||||
@ -418,9 +437,11 @@ def parse_xml(filename, platform=None, port_config_file=None):
|
|||||||
results['minigraph_vlan_interfaces'] = vlan_intfs
|
results['minigraph_vlan_interfaces'] = vlan_intfs
|
||||||
results['minigraph_portchannel_interfaces'] = pc_intfs
|
results['minigraph_portchannel_interfaces'] = pc_intfs
|
||||||
results['minigraph_vlans'] = vlans
|
results['minigraph_vlans'] = vlans
|
||||||
|
results['minigraph_ports'] = ports
|
||||||
results['minigraph_portchannels'] = pcs
|
results['minigraph_portchannels'] = pcs
|
||||||
results['minigraph_mgmt_interface'] = mgmt_intf
|
results['minigraph_mgmt_interface'] = mgmt_intf
|
||||||
results['minigraph_lo_interfaces'] = lo_intfs
|
results['minigraph_lo_interfaces'] = lo_intfs
|
||||||
|
results['minigraph_acls'] = acls
|
||||||
results['minigraph_neighbors'] = neighbors
|
results['minigraph_neighbors'] = neighbors
|
||||||
results['minigraph_devices'] = devices
|
results['minigraph_devices'] = devices
|
||||||
results['minigraph_underlay_neighbors'] = u_neighbors
|
results['minigraph_underlay_neighbors'] = u_neighbors
|
||||||
|
@ -251,7 +251,14 @@
|
|||||||
</IPInterface>
|
</IPInterface>
|
||||||
</IPInterfaces>
|
</IPInterfaces>
|
||||||
<DataAcls/>
|
<DataAcls/>
|
||||||
<AclInterfaces/>
|
<AclInterfaces>
|
||||||
|
<AclInterface>
|
||||||
|
<AttachTo>
|
||||||
|
PortChannel01;PortChannel02;PortChannel03;PortChannel04
|
||||||
|
</AttachTo>
|
||||||
|
<InAcl>DataAcl</InAcl>
|
||||||
|
</AclInterface>
|
||||||
|
</AclInterfaces>
|
||||||
<DownstreamSummaries/>
|
<DownstreamSummaries/>
|
||||||
<DownstreamSummarySet xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
|
<DownstreamSummarySet xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
|
||||||
</DeviceDataPlaneInfo>
|
</DeviceDataPlaneInfo>
|
||||||
|
@ -8,6 +8,7 @@ class TestCfgGen(TestCase):
|
|||||||
self.test_dir = os.path.dirname(os.path.realpath(__file__))
|
self.test_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen')
|
self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen')
|
||||||
self.sample_graph = os.path.join(self.test_dir, 'sample_graph.xml')
|
self.sample_graph = os.path.join(self.test_dir, 'sample_graph.xml')
|
||||||
|
self.sample_graph_t0 = os.path.join(self.test_dir, 't0-sample-graph.xml')
|
||||||
|
|
||||||
def run_script(self, argument):
|
def run_script(self, argument):
|
||||||
print '\n Running sonic-cfggen ' + argument
|
print '\n Running sonic-cfggen ' + argument
|
||||||
@ -59,3 +60,8 @@ class TestCfgGen(TestCase):
|
|||||||
output = self.run_script(argument)
|
output = self.run_script(argument)
|
||||||
self.assertEqual(output.strip(), 'value1\nvalue2')
|
self.assertEqual(output.strip(), 'value1\nvalue2')
|
||||||
|
|
||||||
|
def test_minigraph_acl(self):
|
||||||
|
argument = '-m "' + self.sample_graph_t0 + '" -v minigraph_acls'
|
||||||
|
output = self.run_script(argument)
|
||||||
|
self.assertEqual(output.strip(), "{'DataAcl': ['Ethernet112', 'Ethernet116', 'Ethernet120', 'Ethernet124']}")
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import openconfig_acl
|
|
||||||
import pyangbind.lib.pybindJSON as pybindJSON
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import json
|
import json
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
import openconfig_acl
|
||||||
|
import pyangbind.lib.pybindJSON as pybindJSON
|
||||||
|
from minigraph import parse_xml
|
||||||
|
|
||||||
def dump_json(filename, data):
|
def dump_json(filename, data):
|
||||||
with open(filename, 'w') as outfile:
|
with open(filename, 'w') as outfile:
|
||||||
json.dump(data, outfile, indent=4, sort_keys=True, separators=(',', ':'))
|
json.dump(data, outfile, indent=4, sort_keys=True, separators=(',', ':'))
|
||||||
@ -97,7 +98,7 @@ def generate_rule_json(table_name, rule, max_priority):
|
|||||||
return rule_data
|
return rule_data
|
||||||
|
|
||||||
def generate_table_json(aclset, aclname, port, max_priority, output_path='.'):
|
def generate_table_json(aclset, aclname, port, max_priority, output_path='.'):
|
||||||
table_name = aclname.replace(" ", "_")
|
table_name = aclname.replace(" ", "_").replace("-", "_")
|
||||||
#table_name = generate_random_table_name()
|
#table_name = generate_random_table_name()
|
||||||
|
|
||||||
table_props = {}
|
table_props = {}
|
||||||
@ -119,21 +120,38 @@ def generate_table_json(aclset, aclname, port, max_priority, output_path='.'):
|
|||||||
|
|
||||||
dump_json(os.path.join(output_path, "rules_for_"+table_name+".json"), rule_data)
|
dump_json(os.path.join(output_path, "rules_for_"+table_name+".json"), rule_data)
|
||||||
|
|
||||||
def translate_acl(filename, output_path, port, max_priority):
|
def translate_acl_fixed_port(filename, output_path, port, max_priority):
|
||||||
yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl")
|
yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl")
|
||||||
for aclsetname in yang_acl.acl.acl_sets.acl_set:
|
for aclsetname in yang_acl.acl.acl_sets.acl_set:
|
||||||
aclset = yang_acl.acl.acl_sets.acl_set[aclsetname]
|
aclset = yang_acl.acl.acl_sets.acl_set[aclsetname]
|
||||||
generate_table_json(aclset, aclsetname, port, max_priority, output_path)
|
generate_table_json(aclset, aclsetname, port, max_priority, output_path)
|
||||||
|
return
|
||||||
|
|
||||||
|
def translate_acl(filename, output_path, attach_to, max_priority):
|
||||||
|
yang_acl = pybindJSON.load(filename, openconfig_acl, "openconfig_acl")
|
||||||
|
print attach_to.keys()
|
||||||
|
for aclsetname in yang_acl.acl.acl_sets.acl_set:
|
||||||
|
tablename = aclsetname.replace(" ", "_").replace("-", "_")
|
||||||
|
if attach_to.has_key(tablename):
|
||||||
|
port = ','.join(attach_to[tablename])
|
||||||
|
aclset = yang_acl.acl.acl_sets.acl_set[aclsetname]
|
||||||
|
generate_table_json(aclset, aclsetname, port, max_priority, output_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Translate openconfig ACL json into SONiC ACL jsons")
|
parser = argparse.ArgumentParser(description="Translate openconfig ACL json into SONiC ACL jsons")
|
||||||
parser.add_argument('input', metavar='INPUT', help='input json file in openconfig format')
|
parser.add_argument('input', metavar='INPUT', help='input json file in openconfig format')
|
||||||
parser.add_argument('-p', '--port', default='Ethernet0', help='the port(s) that this ACL is binding to')
|
group = parser.add_mutually_exclusive_group(required=True)
|
||||||
parser.add_argument('-m', '--max-priority', type=int, default=10000, help='the priority number of the first rule in ACL entries')
|
group.add_argument('-p', '--port', help='the port(s) that this ACL is attached to')
|
||||||
|
group.add_argument('-m', '--minigraph', help='read ACL attaching information from minigraph')
|
||||||
|
parser.add_argument('-n', '--max-priority', type=int, default=10000, help='the priority number of the first rule in ACL entries')
|
||||||
parser.add_argument('-o', '--output-path', default='.', help='output directory where SONiC ACL jsons will be generated')
|
parser.add_argument('-o', '--output-path', default='.', help='output directory where SONiC ACL jsons will be generated')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
translate_acl(args.input, args.output_path, args.port, args.max_priority)
|
if args.port:
|
||||||
|
translate_acl_fixed_port(args.input, args.output_path, args.port, args.max_priority)
|
||||||
|
elif args.minigraph:
|
||||||
|
mini_data = parse_xml(args.minigraph)
|
||||||
|
translate_acl(args.input, args.output_path, mini_data['minigraph_acls'], args.max_priority)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
Reference in New Issue
Block a user