[config-engine] minigraph.py refactoring (#448)
* Refactor minigraph.py See description in https://github.com/Azure/sonic-buildimage/pull/448 for detail
This commit is contained in:
parent
71d299bed4
commit
fed908fc6b
@ -1,6 +1,6 @@
|
||||
SERVERS="{{ dhcp_servers | join(' ') }}"
|
||||
|
||||
INTERFACES="{{ minigraph_vlan_interfaces[0]['name'] }}"
|
||||
INTERFACES="{{ minigraph_vlan_interfaces[0]['attachto'] }}"
|
||||
|
||||
# '-a' option provides option 82 circuit id information
|
||||
OPTIONS="-a"
|
||||
|
@ -3,7 +3,7 @@
|
||||
rm -f /var/run/rsyslogd.pid
|
||||
service rsyslog start
|
||||
|
||||
VLAN_IFACE_NAME=`sonic-cfggen -m /etc/sonic/minigraph.xml -v "minigraph_vlan_interfaces[0]['name']"`
|
||||
VLAN_IFACE_NAME=`sonic-cfggen -m /etc/sonic/minigraph.xml -v "minigraph_vlan_interfaces[0]['attachto']"`
|
||||
|
||||
# Wait for the VLAN to come up (i.e., 'ip link show' returns 0)
|
||||
until ip link show $VLAN_IFACE_NAME > /dev/null 2>&1; do
|
||||
|
@ -15,7 +15,12 @@ enable password zebra
|
||||
{% block interfaces %}
|
||||
! Enable link-detect (default disabled)
|
||||
{% for interface in minigraph_interfaces %}
|
||||
interface {{ interface['alias'] }}
|
||||
interface {{ interface['attachto'] }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
{% for interface in minigraph_portchannels.keys() %}
|
||||
interface {{ interface }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
|
@ -15,12 +15,12 @@ enable password zebra
|
||||
{% block interfaces %}
|
||||
! Enable link-detect (default disabled)
|
||||
{% for interface in minigraph_interfaces %}
|
||||
interface {{ interface['alias'] }}
|
||||
interface {{ interface['attachto'] }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
{% for interface in minigraph_portchannel_interfaces %}
|
||||
interface {{ interface['name'] }}
|
||||
{% for interface in minigraph_portchannels.keys() %}
|
||||
interface {{ interface }}
|
||||
link-detect
|
||||
!
|
||||
{% endfor %}
|
||||
|
@ -1,3 +1,3 @@
|
||||
{% for member in alias_map %}
|
||||
configure ports {{member['sonic']}} lldp portidsubtype local {{member['origin']}}
|
||||
{% for member in minigraph_ports.keys() %}
|
||||
configure ports {{member}} lldp portidsubtype local {{minigraph_ports[member]['alias']}}
|
||||
{% endfor %}
|
||||
|
5
dockers/docker-snmp-sv2/alias_map.j2
Normal file
5
dockers/docker-snmp-sv2/alias_map.j2
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
{% for member in minigraph_ports.keys() %}
|
||||
"{{member}}": "{{minigraph_ports[member]['alias']}}"
|
||||
{% endfor %}
|
||||
}
|
@ -8,7 +8,7 @@ mkdir -p /etc/snmp
|
||||
|
||||
sonic-cfggen -m /etc/sonic/minigraph.xml -y /etc/sonic/snmp.yml -t /usr/share/sonic/templates/snmpd.conf.j2 >/etc/snmp/snmpd.conf
|
||||
|
||||
sonic-cfggen -m /etc/sonic/minigraph.xml -s >/etc/snmp/alias_map.json
|
||||
sonic-cfggen -m /etc/sonic/minigraph.xml -t /usr/share/sonic/templates/alias_map.j2 >/etc/snmp/alias_map.json
|
||||
|
||||
mkdir -p /var/sonic
|
||||
echo "# Config files managed by sonic-config-engine" >/var/sonic/config_status
|
||||
|
@ -46,53 +46,53 @@ iface eth0 inet dhcp
|
||||
{% block front_panel_interfaces %}
|
||||
# The switch front panel interfaces
|
||||
{% for interface in minigraph_interfaces %}
|
||||
auto {{ interface['alias'] }}
|
||||
allow-hotplug {{ interface['alias'] }}
|
||||
iface {{ interface['alias'] }} {{ 'inet' if interface['addr'] | ipv4 else 'inet6' }} static
|
||||
auto {{ interface['attachto'] }}
|
||||
allow-hotplug {{ interface['attachto'] }}
|
||||
iface {{ interface['attachto'] }} {{ 'inet' if interface['addr'] | ipv4 else 'inet6' }} static
|
||||
address {{ interface['addr'] }}
|
||||
netmask {{ interface['mask'] }}
|
||||
#
|
||||
{% endfor %}
|
||||
{% for vlan_interface in minigraph_vlan_interfaces|unique_name %}
|
||||
{% for interface in vlan_interface['members'] %}
|
||||
auto {{ interface }}
|
||||
allow-hotplug {{ interface }}
|
||||
iface {{ interface }} inet manual
|
||||
pre-up ifconfig {{ interface }} up
|
||||
post-up brctl addif {{ vlan_interface['name'] }} {{ interface }}
|
||||
post-down ifconfig {{ interface }} down
|
||||
{% for vlan in minigraph_vlans.keys()|sort %}
|
||||
{% for member in minigraph_vlans[vlan]['members'] %}
|
||||
auto {{ member }}
|
||||
allow-hotplug {{ member }}
|
||||
iface {{ member }} inet manual
|
||||
pre-up ifconfig {{ member }} up
|
||||
post-up brctl addif {{ vlan }} {{ member }}
|
||||
post-down ifconfig {{ member }} down
|
||||
#
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
# Add || true to suppress the error when docker-teamd starts after docker-swss
|
||||
{% for pc_interface in minigraph_portchannel_interfaces|unique_name %}
|
||||
{% for interface in pc_interface['members'] %}
|
||||
{% if pc_interface['name'] not in pc_set %}
|
||||
auto {{ interface }}
|
||||
allow-hotplug {{ interface }}
|
||||
iface {{ interface }} inet manual
|
||||
pre-up teamdctl {{ pc_interface['name'] }} port add {{ interface }} || true
|
||||
post-down ifconfig {{ interface }} down
|
||||
# "|| true" is added to suppress the error when docker-teamd starts after docker-swss
|
||||
{% for pc in minigraph_portchannels.keys()|sort %}
|
||||
{% for member in minigraph_portchannels[pc]['members'] %}
|
||||
auto {{ member }}
|
||||
allow-hotplug {{ member }}
|
||||
iface {{ member }} inet manual
|
||||
pre-up teamdctl {{ pc }} port add {{ member }} || true
|
||||
post-down ifconfig {{ member }} down
|
||||
#
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endblock front_panel_interfaces %}
|
||||
{% block vlan_interfaces %}
|
||||
# Vlan interfaces
|
||||
{% for vlan_interface in minigraph_vlan_interfaces %}
|
||||
auto {{ vlan_interface['name'] }}
|
||||
iface {{ vlan_interface['name'] }} {{ 'inet' if vlan_interface['addr'] | ipv4 else 'inet6' }} static
|
||||
auto {{ vlan_interface['attachto'] }}
|
||||
iface {{ vlan_interface['attachto'] }} {{ 'inet' if vlan_interface['addr'] | ipv4 else 'inet6' }} static
|
||||
bridge_ports none
|
||||
address {{ vlan_interface['addr'] }}
|
||||
netmask {{ vlan_interface['mask'] }}
|
||||
#
|
||||
{% endfor %}
|
||||
#
|
||||
{% endblock vlan_interfaces %}
|
||||
{% block pc_interfaces %}
|
||||
# Portchannel interfaces
|
||||
{% for pc_interface in minigraph_portchannel_interfaces %}
|
||||
auto {{ pc_interface['name'] }}
|
||||
allow-hotplug {{ pc_interface['name'] }}
|
||||
iface {{ pc_interface['name'] }} {{ 'inet' if pc_interface['addr'] | ipv4 else 'inet6' }} static
|
||||
auto {{ pc_interface['attachto'] }}
|
||||
allow-hotplug {{ pc_interface['attachto'] }}
|
||||
iface {{ pc_interface['attachto'] }} {{ 'inet' if pc_interface['addr'] | ipv4 else 'inet6' }} static
|
||||
address {{ pc_interface['addr'] }}
|
||||
netmask {{ pc_interface['mask'] }}
|
||||
#
|
||||
|
3
slave.mk
3
slave.mk
@ -229,12 +229,13 @@ $(SONIC_INSTALL_TARGETS) : $(DEBS_PATH)/%-install : .platform $$(addsuffix -inst
|
||||
# $(SOME_NEW_WHL)_SRC_PATH = $(SRC_PATH)/project_name
|
||||
# $(SOME_NEW_WHL)_PYTHON_VERSION = 2 (or 3)
|
||||
# $(SOME_NEW_WHL)_DEPENDS = $(SOME_OTHER_WHL1) $(SOME_OTHER_WHL2) ...
|
||||
# SONIC_PYTHON_WHEELS += $(SOME_NEW_DEB)
|
||||
# SONIC_PYTHON_WHEELS += $(SOME_NEW_WHL)
|
||||
$(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS)) : $(PYTHON_WHEELS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_DEPENDS)))
|
||||
$(HEADER)
|
||||
pushd $($*_SRC_PATH) $(LOG)
|
||||
# apply series of patches if exist
|
||||
if [ -f ../$(notdir $($*_SRC_PATH)).patch/series ]; then QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; fi
|
||||
python$($*_PYTHON_VERSION) setup.py test $(LOG)
|
||||
python$($*_PYTHON_VERSION) setup.py bdist_wheel $(LOG)
|
||||
# clean up
|
||||
if [ -f ../$(notdir $($*_SRC_PATH)).patch/series ]; then quilt pop -a -f; fi
|
||||
|
@ -39,12 +39,15 @@ ns1 = "http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolut
|
||||
ns2 = "Microsoft.Search.Autopilot.NetMux"
|
||||
ns3 = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
|
||||
|
||||
class minigraph_encoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, (ipaddress.IPv4Network, ipaddress.IPv6Network, ipaddress.IPv4Address, ipaddress.IPv6Address)):
|
||||
if isinstance(obj,
|
||||
(ipaddress.IPv4Network, ipaddress.IPv6Network, ipaddress.IPv4Address, ipaddress.IPv6Address)):
|
||||
return str(obj)
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
|
||||
|
||||
def parse_png(png, hname):
|
||||
neighbors = {}
|
||||
devices = {}
|
||||
@ -112,7 +115,6 @@ def parse_png(png, hname):
|
||||
elif node.tag == str(QName(ns, "EndDevice")):
|
||||
mgmt_dev = node.text
|
||||
|
||||
|
||||
return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port)
|
||||
|
||||
|
||||
@ -124,11 +126,12 @@ def parse_dpg(dpg, hname):
|
||||
|
||||
ipintfs = child.find(str(QName(ns, "IPInterfaces")))
|
||||
intfs = []
|
||||
intfnames = {}
|
||||
vlan_map = {}
|
||||
pc_map = {}
|
||||
for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
|
||||
intfname = ipintf.find(str(QName(ns, "AttachTo"))).text
|
||||
intfalias = ipintf.find(str(QName(ns, "AttachTo"))).text
|
||||
if port_alias_map.has_key(intfalias):
|
||||
intfname = port_alias_map[intfalias]
|
||||
else:
|
||||
intfname = intfalias
|
||||
ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text
|
||||
ipn = ipaddress.IPNetwork(ipprefix)
|
||||
ipaddr = ipn.ip
|
||||
@ -142,24 +145,7 @@ def parse_dpg(dpg, hname):
|
||||
intf['mask'] = ipmask
|
||||
else:
|
||||
intf['mask'] = str(prefix_len)
|
||||
|
||||
if intfname[0:4] == "Vlan":
|
||||
if intfname in vlan_map:
|
||||
vlan_map[intfname].append(intf)
|
||||
else:
|
||||
vlan_map[intfname] = [intf]
|
||||
elif intfname[0:11] == "PortChannel":
|
||||
if intfname in pc_map:
|
||||
pc_map[intfname].append(intf)
|
||||
else:
|
||||
pc_map[intfname] = [intf]
|
||||
else:
|
||||
intf.update({'name': intfname, 'prefixlen': int(prefix_len)})
|
||||
|
||||
if port_alias_map.has_key(intfname):
|
||||
intf['alias'] = port_alias_map[intfname]
|
||||
else:
|
||||
intf['alias'] = intfname
|
||||
intf.update({'attachto': intfname, 'prefixlen': int(prefix_len)})
|
||||
|
||||
# TODO: remove peer_addr after dependency removed
|
||||
ipaddr_val = int(ipn.ip)
|
||||
@ -174,27 +160,9 @@ def parse_dpg(dpg, hname):
|
||||
peer_addr_val = ipaddr_val + 1
|
||||
else:
|
||||
peer_addr_val = ipaddr_val - 1
|
||||
|
||||
if peer_addr_val is not None:
|
||||
intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
|
||||
intfs.append(intf)
|
||||
intfnames[intf['alias']] = { 'alias': intf['name'] }
|
||||
|
||||
pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
|
||||
pc_intfs = []
|
||||
pcs = {}
|
||||
for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))):
|
||||
pcintfname = pcintf.find(str(QName(ns, "Name"))).text
|
||||
pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text
|
||||
pcmbr_list = pcintfmbr.split(';', 1)
|
||||
for i,member in enumerate(pcmbr_list):
|
||||
if port_alias_map.has_key(member):
|
||||
pcmbr_list[i] = port_alias_map[member]
|
||||
pc_attributes = {'name': pcintfname, 'members': pcmbr_list}
|
||||
for addrtuple in pc_map.get(pcintfname, []):
|
||||
pc_attributes.update(addrtuple)
|
||||
pc_intfs.append(copy.deepcopy(pc_attributes))
|
||||
pcs[pcintfname] = pc_attributes
|
||||
|
||||
lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
|
||||
lo_intfs = []
|
||||
@ -223,6 +191,17 @@ def parse_dpg(dpg, hname):
|
||||
gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1)
|
||||
mgmt_intf = {'addr': ipaddr, 'prefixlen': prefix_len, 'mask': ipmask, 'gwaddr': gwaddr}
|
||||
|
||||
pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
|
||||
pc_intfs = []
|
||||
pcs = {}
|
||||
for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))):
|
||||
pcintfname = pcintf.find(str(QName(ns, "Name"))).text
|
||||
pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text
|
||||
pcmbr_list = pcintfmbr.split(';', 1)
|
||||
for i, member in enumerate(pcmbr_list):
|
||||
pcmbr_list[i] = port_alias_map[member]
|
||||
pcs[pcintfname] = {'name': pcintfname, 'members': pcmbr_list}
|
||||
|
||||
vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
|
||||
vlan_intfs = []
|
||||
vlans = {}
|
||||
@ -232,13 +211,10 @@ def parse_dpg(dpg, hname):
|
||||
vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text
|
||||
vmbr_list = vintfmbr.split(';')
|
||||
for i, member in enumerate(vmbr_list):
|
||||
if port_alias_map.has_key(member):
|
||||
vmbr_list[i] = port_alias_map[member]
|
||||
vlan_attributes = {'name': vintfname, 'members': vmbr_list, 'vlanid': vlanid}
|
||||
for addrtuple in vlan_map.get(vintfname, []):
|
||||
vlan_attributes.update(addrtuple)
|
||||
vlan_intfs.append(copy.deepcopy(vlan_attributes))
|
||||
vlans[vintfname] = vlan_attributes
|
||||
|
||||
aclintfs = child.find(str(QName(ns, "AclInterfaces")))
|
||||
acls = {}
|
||||
for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
|
||||
@ -247,20 +223,19 @@ def parse_dpg(dpg, hname):
|
||||
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)
|
||||
elif port_alias_map.has_key(member):
|
||||
acl_intfs.append(port_alias_map[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, vlans, pcs, acls
|
||||
return None, None, None, None, None, None, None, None
|
||||
|
||||
|
||||
def parse_cpg(cpg, hname):
|
||||
bgp_sessions = []
|
||||
myasn = None
|
||||
@ -297,6 +272,7 @@ def parse_cpg(cpg, hname):
|
||||
|
||||
return bgp_sessions, myasn
|
||||
|
||||
|
||||
def parse_meta(meta, hname):
|
||||
syslog_servers = []
|
||||
dhcp_servers = []
|
||||
@ -320,6 +296,7 @@ def parse_meta(meta, hname):
|
||||
mgmt_routes = value_group
|
||||
return syslog_servers, dhcp_servers, ntp_servers, mgmt_routes
|
||||
|
||||
|
||||
def get_console_info(devices, dev, port):
|
||||
for k, v in devices.items():
|
||||
if k == dev:
|
||||
@ -335,6 +312,7 @@ def get_console_info(devices, dev, port):
|
||||
|
||||
return ret_val
|
||||
|
||||
|
||||
def get_mgmt_info(devices, dev, port):
|
||||
for k, v in devices.items():
|
||||
if k == dev:
|
||||
@ -350,7 +328,8 @@ def get_mgmt_info(devices, dev, port):
|
||||
|
||||
return ret_val
|
||||
|
||||
def get_alias_map_list(hwsku, platform=None, port_config_file=None):
|
||||
|
||||
def parse_port_config(hwsku, platform=None, port_config_file=None):
|
||||
port_config_candidates = []
|
||||
if port_config_file != None:
|
||||
port_config_candidates.append(port_config_file)
|
||||
@ -367,16 +346,23 @@ def get_alias_map_list(hwsku, platform=None, port_config_file=None):
|
||||
if port_config == None:
|
||||
return None
|
||||
|
||||
alias_map_list = []
|
||||
ports = {}
|
||||
with open(port_config) as data:
|
||||
for line in data:
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
tokens = line.split()
|
||||
if len(tokens) < 3:
|
||||
if len(tokens) < 2:
|
||||
continue
|
||||
alias_map_list.append({'sonic': tokens[0], 'origin': tokens[2].strip()})
|
||||
return alias_map_list
|
||||
name = tokens[0].strip()
|
||||
if len(tokens) == 2:
|
||||
alias = name
|
||||
else:
|
||||
alias = tokens[2].strip()
|
||||
ports[name] = {'name': name, 'alias': alias}
|
||||
port_alias_map[alias] = name
|
||||
return ports
|
||||
|
||||
|
||||
def parse_xml(filename, platform=None, port_config_file=None):
|
||||
root = ET.parse(filename).getroot()
|
||||
@ -410,14 +396,11 @@ def parse_xml(filename, platform=None, port_config_file=None):
|
||||
if child.tag == str(hostname_qn):
|
||||
hostname = child.text
|
||||
|
||||
alias_map_list = get_alias_map_list(hwsku, platform, port_config_file)
|
||||
if alias_map_list != None:
|
||||
for item in alias_map_list:
|
||||
port_alias_map[item['origin']] = item['sonic']
|
||||
ports = parse_port_config(hwsku, platform, port_config_file)
|
||||
|
||||
for child in root:
|
||||
if child.tag == str(QName(ns, "DpgDec")):
|
||||
(intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs, ports, vlans, pcs, acls) = parse_dpg(child, hostname)
|
||||
(intfs, lo_intfs, mgmt_intf, vlans, pcs, acls) = parse_dpg(child, hostname)
|
||||
elif child.tag == str(QName(ns, "CpgDec")):
|
||||
(bgp_sessions, bgp_asn) = parse_cpg(child, hostname)
|
||||
elif child.tag == str(QName(ns, "PngDec")):
|
||||
@ -437,11 +420,24 @@ def parse_xml(filename, platform=None, port_config_file=None):
|
||||
results['minigraph_bgp'] = sorted(bgp_sessions, key=lambda x: x['addr'])
|
||||
results['minigraph_bgp_asn'] = bgp_asn
|
||||
# TODO: sort does not work properly on all interfaces of varying lengths. Need to sort by integer group(s).
|
||||
results['minigraph_interfaces'] = sorted(intfs, key=lambda x: x['name'])
|
||||
results['minigraph_vlan_interfaces'] = vlan_intfs
|
||||
results['minigraph_portchannel_interfaces'] = pc_intfs
|
||||
results['minigraph_vlans'] = vlans
|
||||
|
||||
phyport_intfs = []
|
||||
vlan_intfs = []
|
||||
pc_intfs = []
|
||||
for intf in intfs:
|
||||
intfname = intf['attachto']
|
||||
if intfname[0:4] == 'Vlan':
|
||||
vlan_intfs.append(intf)
|
||||
elif intfname[0:11] == 'PortChannel':
|
||||
pc_intfs.append(intf)
|
||||
else:
|
||||
phyport_intfs.append(intf)
|
||||
|
||||
results['minigraph_interfaces'] = sorted(phyport_intfs, key=lambda x: x['attachto'])
|
||||
results['minigraph_vlan_interfaces'] = sorted(vlan_intfs, key=lambda x: x['attachto'])
|
||||
results['minigraph_portchannel_interfaces'] = sorted(pc_intfs, key=lambda x: x['attachto'])
|
||||
results['minigraph_ports'] = ports
|
||||
results['minigraph_vlans'] = vlans
|
||||
results['minigraph_portchannels'] = pcs
|
||||
results['minigraph_mgmt_interface'] = mgmt_intf
|
||||
results['minigraph_lo_interfaces'] = lo_intfs
|
||||
@ -460,7 +456,6 @@ def parse_xml(filename, platform=None, port_config_file=None):
|
||||
results['dhcp_servers'] = dhcp_servers
|
||||
results['ntp_servers'] = ntp_servers
|
||||
results['forced_mgmt_routes'] = mgmt_routes
|
||||
results['alias_map'] = alias_map_list
|
||||
|
||||
return results
|
||||
|
||||
@ -469,5 +464,3 @@ port_alias_map = {}
|
||||
def print_parse_xml(filename):
|
||||
results = parse_xml(filename)
|
||||
print(json.dumps(results, indent=3, cls=minigraph_encoder))
|
||||
|
||||
|
||||
|
@ -65,10 +65,8 @@ def main():
|
||||
parser.add_argument("-a", "--additional-data", help="addition data, in json string")
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument("-t", "--template", help="render the data with the template file")
|
||||
group.add_argument("-s", "--alias-mapping", help="print alias mapping json if available", action='store_true')
|
||||
group.add_argument("-v", "--var", help="print the value of a variable, support jinja2 expression")
|
||||
group.add_argument("--var-json", help="print the value of a variable, in json format")
|
||||
group.add_argument("--var-keys", help="print all keys of a map variable - to be deprecated, use -v and keys()")
|
||||
group.add_argument("--print-data", help="print all data", action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
@ -118,17 +116,6 @@ def main():
|
||||
if args.var_json != None:
|
||||
print json.dumps(data[args.var_json], indent=4, cls=minigraph_encoder)
|
||||
|
||||
if args.var_keys != None:
|
||||
for key in data[args.var_keys].keys():
|
||||
print key
|
||||
|
||||
if args.alias_mapping:
|
||||
mapping = {}
|
||||
if data.has_key('alias_map'):
|
||||
for item in data['alias_map']:
|
||||
mapping[item['sonic']] = item['origin']
|
||||
print json.dumps(mapping)
|
||||
|
||||
if args.print_data:
|
||||
print json.dumps(data, indent=4, cls=minigraph_encoder)
|
||||
|
||||
|
205
src/sonic-config-engine/tests/simple-sample-graph.xml
Normal file
205
src/sonic-config-engine/tests/simple-sample-graph.xml
Normal file
@ -0,0 +1,205 @@
|
||||
<DeviceMiniGraph xmlns="Microsoft.Search.Autopilot.Evolution" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<CpgDec>
|
||||
<IsisRouters xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
|
||||
<PeeringSessions>
|
||||
<BGPSession>
|
||||
<MacSec>false</MacSec>
|
||||
<StartRouter>switch-t0</StartRouter>
|
||||
<StartPeer>10.0.0.56</StartPeer>
|
||||
<EndRouter>ARISTA01T1</EndRouter>
|
||||
<EndPeer>10.0.0.57</EndPeer>
|
||||
<Multihop>1</Multihop>
|
||||
<HoldTime>180</HoldTime>
|
||||
<KeepAliveTime>60</KeepAliveTime>
|
||||
</BGPSession>
|
||||
<BGPSession>
|
||||
<StartRouter>switch-t0</StartRouter>
|
||||
<StartPeer>FC00::71</StartPeer>
|
||||
<EndRouter>ARISTA01T1</EndRouter>
|
||||
<EndPeer>FC00::72</EndPeer>
|
||||
<Multihop>1</Multihop>
|
||||
<HoldTime>180</HoldTime>
|
||||
<KeepAliveTime>60</KeepAliveTime>
|
||||
</BGPSession>
|
||||
<BGPSession>
|
||||
<MacSec>false</MacSec>
|
||||
<StartRouter>switch-t0</StartRouter>
|
||||
<StartPeer>10.0.0.58</StartPeer>
|
||||
<EndRouter>ARISTA02T1</EndRouter>
|
||||
<EndPeer>10.0.0.59</EndPeer>
|
||||
<Multihop>1</Multihop>
|
||||
<HoldTime>180</HoldTime>
|
||||
<KeepAliveTime>60</KeepAliveTime>
|
||||
</BGPSession>
|
||||
<BGPSession>
|
||||
<StartRouter>switch-t0</StartRouter>
|
||||
<StartPeer>FC00::75</StartPeer>
|
||||
<EndRouter>ARISTA02T1</EndRouter>
|
||||
<EndPeer>FC00::76</EndPeer>
|
||||
<Multihop>1</Multihop>
|
||||
<HoldTime>180</HoldTime>
|
||||
<KeepAliveTime>60</KeepAliveTime>
|
||||
</BGPSession>
|
||||
</PeeringSessions>
|
||||
<Routers xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution">
|
||||
<a:BGPRouterDeclaration>
|
||||
<a:ASN>65100</a:ASN>
|
||||
<a:Hostname>switch-t0</a:Hostname>
|
||||
<a:Peers>
|
||||
<BGPPeer>
|
||||
<Address>10.0.0.57</Address>
|
||||
<RouteMapIn i:nil="true"/>
|
||||
<RouteMapOut i:nil="true"/>
|
||||
<Vrf i:nil="true"/>
|
||||
</BGPPeer>
|
||||
<BGPPeer>
|
||||
<Address>10.0.0.59</Address>
|
||||
<RouteMapIn i:nil="true"/>
|
||||
<RouteMapOut i:nil="true"/>
|
||||
<Vrf i:nil="true"/>
|
||||
</BGPPeer>
|
||||
</a:Peers>
|
||||
<a:RouteMaps/>
|
||||
</a:BGPRouterDeclaration>
|
||||
<a:BGPRouterDeclaration>
|
||||
<a:ASN>64600</a:ASN>
|
||||
<a:Hostname>ARISTA01T1</a:Hostname>
|
||||
<a:RouteMaps/>
|
||||
</a:BGPRouterDeclaration>
|
||||
<a:BGPRouterDeclaration>
|
||||
<a:ASN>64600</a:ASN>
|
||||
<a:Hostname>ARISTA02T1</a:Hostname>
|
||||
<a:RouteMaps/>
|
||||
</a:BGPRouterDeclaration>
|
||||
<a:BGPRouterDeclaration>
|
||||
<a:ASN>64600</a:ASN>
|
||||
<a:Hostname>ARISTA03T1</a:Hostname>
|
||||
<a:RouteMaps/>
|
||||
</a:BGPRouterDeclaration>
|
||||
<a:BGPRouterDeclaration>
|
||||
<a:ASN>64600</a:ASN>
|
||||
<a:Hostname>ARISTA04T1</a:Hostname>
|
||||
<a:RouteMaps/>
|
||||
</a:BGPRouterDeclaration>
|
||||
</Routers>
|
||||
</CpgDec>
|
||||
<DpgDec>
|
||||
<DeviceDataPlaneInfo>
|
||||
<IPSecTunnels/>
|
||||
<LoopbackIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution">
|
||||
<a:LoopbackIPInterface>
|
||||
<Name>HostIP</Name>
|
||||
<AttachTo>Loopback0</AttachTo>
|
||||
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.Evolution">
|
||||
<b:IPPrefix>10.1.0.32/32</b:IPPrefix>
|
||||
</a:Prefix>
|
||||
<a:PrefixStr>10.1.0.32/32</a:PrefixStr>
|
||||
</a:LoopbackIPInterface>
|
||||
<a:LoopbackIPInterface>
|
||||
<Name>HostIP1</Name>
|
||||
<AttachTo>Loopback0</AttachTo>
|
||||
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.Evolution">
|
||||
<b:IPPrefix>FC00:1::32/128</b:IPPrefix>
|
||||
</a:Prefix>
|
||||
<a:PrefixStr>FC00:1::32/128</a:PrefixStr>
|
||||
</a:LoopbackIPInterface>
|
||||
</LoopbackIPInterfaces>
|
||||
<ManagementIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution">
|
||||
<a:ManagementIPInterface>
|
||||
<Name>HostIP</Name>
|
||||
<AttachTo>eth0</AttachTo>
|
||||
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.Evolution">
|
||||
<b:IPPrefix>10.0.0.100/24</b:IPPrefix>
|
||||
</a:Prefix>
|
||||
<a:PrefixStr>10.0.0.100/24</a:PrefixStr>
|
||||
</a:ManagementIPInterface>
|
||||
</ManagementIPInterfaces>
|
||||
<ManagementVIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
|
||||
<MplsInterfaces/>
|
||||
<MplsTeInterfaces/>
|
||||
<RsvpInterfaces/>
|
||||
<Hostname>switch-t0</Hostname>
|
||||
<PortChannelInterfaces>
|
||||
<PortChannel>
|
||||
<Name>PortChannel01</Name>
|
||||
<AttachTo>fortyGigE0/4</AttachTo>
|
||||
<SubInterface/>
|
||||
</PortChannel>
|
||||
</PortChannelInterfaces>
|
||||
<VlanInterfaces>
|
||||
<VlanInterface>
|
||||
<Name>Vlan1000</Name>
|
||||
<AttachTo>fortyGigE0/8</AttachTo>
|
||||
<VlanID>1000</VlanID>
|
||||
<Tag>1000</Tag>
|
||||
<Subnets>192.168.0.0/27</Subnets>
|
||||
</VlanInterface>
|
||||
</VlanInterfaces>
|
||||
<IPInterfaces>
|
||||
<IPInterface>
|
||||
<Name i:nil="true"/>
|
||||
<AttachTo>PortChannel01</AttachTo>
|
||||
<Prefix>10.0.0.56/31</Prefix>
|
||||
</IPInterface>
|
||||
<IPInterface>
|
||||
<Name i:Name="true"/>
|
||||
<AttachTo>PortChannel01</AttachTo>
|
||||
<Prefix>FC00::71/126</Prefix>
|
||||
</IPInterface>
|
||||
<IPInterface>
|
||||
<Name i:nil="true"/>
|
||||
<AttachTo>fortyGigE0/0</AttachTo>
|
||||
<Prefix>10.0.0.58/31</Prefix>
|
||||
</IPInterface>
|
||||
<IPInterface>
|
||||
<Name i:nil="true"/>
|
||||
<AttachTo>fortyGigE0/0</AttachTo>
|
||||
<Prefix>FC00::75/126</Prefix>
|
||||
</IPInterface>
|
||||
<IPInterface>
|
||||
<Name i:nil="true"/>
|
||||
<AttachTo>Vlan1000</AttachTo>
|
||||
<Prefix>192.168.0.1/27</Prefix>
|
||||
</IPInterface>
|
||||
</IPInterfaces>
|
||||
<DataAcls/>
|
||||
<AclInterfaces>
|
||||
<AclInterface>
|
||||
<AttachTo>
|
||||
PortChannel01
|
||||
</AttachTo>
|
||||
<InAcl>DataAcl</InAcl>
|
||||
</AclInterface>
|
||||
</AclInterfaces>
|
||||
<DownstreamSummaries/>
|
||||
<DownstreamSummarySet xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
|
||||
</DeviceDataPlaneInfo>
|
||||
</DpgDec>
|
||||
<PngDec>
|
||||
<DeviceInterfaceLinks/>
|
||||
<Devices>
|
||||
<Device i:type="ToRRouter">
|
||||
<Hostname>switch-t0</Hostname>
|
||||
<HwSku>Force10-S6000</HwSku>
|
||||
</Device>
|
||||
<Device i:type="LeafRouter">
|
||||
<Hostname>ARISTA01T1</Hostname>
|
||||
<HwSku>Arista</HwSku>
|
||||
</Device>
|
||||
<Device i:type="LeafRouter">
|
||||
<Hostname>ARISTA02T1</Hostname>
|
||||
<HwSku>Arista</HwSku>
|
||||
</Device>
|
||||
<Device i:type="LeafRouter">
|
||||
<Hostname>ARISTA03T1</Hostname>
|
||||
<HwSku>Arista</HwSku>
|
||||
</Device>
|
||||
<Device i:type="LeafRouter">
|
||||
<Hostname>ARISTA04T1</Hostname>
|
||||
<HwSku>Arista</HwSku>
|
||||
</Device>
|
||||
</Devices>
|
||||
</PngDec>
|
||||
<Hostname>switch-t0</Hostname>
|
||||
<HwSku>Force10-S6000</HwSku>
|
||||
</DeviceMiniGraph>
|
@ -9,6 +9,8 @@ class TestCfgGen(TestCase):
|
||||
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_t0 = os.path.join(self.test_dir, 't0-sample-graph.xml')
|
||||
self.sample_graph_simple = os.path.join(self.test_dir, 'simple-sample-graph.xml')
|
||||
self.port_config = os.path.join(self.test_dir, 't0-sample-port-config.ini')
|
||||
|
||||
def run_script(self, argument):
|
||||
print '\n Running sonic-cfggen ' + argument
|
||||
@ -40,11 +42,6 @@ class TestCfgGen(TestCase):
|
||||
output = self.run_script(argument)
|
||||
self.assertEqual(output.strip(), 'LeafRouter')
|
||||
|
||||
def test_print_alias_mapping(self):
|
||||
argument = '-s'
|
||||
output = self.run_script(argument)
|
||||
self.assertTrue(len(output.strip()) > 0)
|
||||
|
||||
def test_additional_json_data(self):
|
||||
argument = '-a \'{"key1":"value1"}\' -v key1'
|
||||
output = self.run_script(argument)
|
||||
@ -61,7 +58,32 @@ class TestCfgGen(TestCase):
|
||||
self.assertEqual(output.strip(), 'value1\nvalue2')
|
||||
|
||||
def test_minigraph_acl(self):
|
||||
argument = '-m "' + self.sample_graph_t0 + '" -v minigraph_acls'
|
||||
argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v minigraph_acls'
|
||||
output = self.run_script(argument)
|
||||
self.assertEqual(output.strip(), "{'DataAcl': ['Ethernet112', 'Ethernet116', 'Ethernet120', 'Ethernet124']}")
|
||||
|
||||
def test_minigraph_interfaces(self):
|
||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v minigraph_interfaces'
|
||||
output = self.run_script(argument)
|
||||
self.assertEqual(output.strip(), "[{'subnet': IPv4Network('10.0.0.58/31'), 'peer_addr': IPv4Address('10.0.0.59'), 'addr': IPv4Address('10.0.0.58'), 'mask': IPv4Address('255.255.255.254'), 'attachto': 'Ethernet0', 'prefixlen': 31}, {'subnet': IPv6Network('fc00::74/126'), 'peer_addr': IPv6Address('fc00::76'), 'addr': IPv6Address('fc00::75'), 'mask': '126', 'attachto': 'Ethernet0', 'prefixlen': 126}]")
|
||||
|
||||
def test_minigraph_vlans(self):
|
||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v minigraph_vlans'
|
||||
output = self.run_script(argument)
|
||||
self.assertEqual(output.strip(), "{'Vlan1000': {'name': 'Vlan1000', 'members': ['Ethernet8'], 'vlanid': '1000'}}")
|
||||
|
||||
def test_minigraph_vlan_interfaces(self):
|
||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v minigraph_vlan_interfaces'
|
||||
output = self.run_script(argument)
|
||||
self.assertEqual(output.strip(), "[{'prefixlen': 27, 'subnet': IPv4Network('192.168.0.0/27'), 'mask': IPv4Address('255.255.255.224'), 'addr': IPv4Address('192.168.0.1'), 'attachto': 'Vlan1000'}]")
|
||||
|
||||
def test_minigraph_portchannels(self):
|
||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v minigraph_portchannels'
|
||||
output = self.run_script(argument)
|
||||
self.assertEqual(output.strip(), "{'PortChannel01': {'name': 'PortChannel01', 'members': ['Ethernet4']}}")
|
||||
|
||||
def test_minigraph_portchannels(self):
|
||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v minigraph_portchannel_interfaces'
|
||||
output = self.run_script(argument)
|
||||
self.assertEqual(output.strip(), "[{'subnet': IPv4Network('10.0.0.56/31'), 'peer_addr': IPv4Address('10.0.0.57'), 'addr': IPv4Address('10.0.0.56'), 'mask': IPv4Address('255.255.255.254'), 'attachto': 'PortChannel01', 'prefixlen': 31}, {'subnet': IPv6Network('fc00::70/126'), 'peer_addr': IPv6Address('fc00::72'), 'addr': IPv6Address('fc00::71'), 'mask': '126', 'attachto': 'PortChannel01', 'prefixlen': 126}]")
|
||||
|
||||
|
@ -16,6 +16,11 @@ class TestJ2Files(TestCase):
|
||||
print 'CMD: sonic-cfggen ' + argument
|
||||
return subprocess.check_output(self.script_file + ' ' + argument, shell=True)
|
||||
|
||||
def test_interfaces(self):
|
||||
interfaces_template = os.path.join(self.test_dir, '..', '..', '..', 'files', 'image_config', 'interfaces', 'interfaces.j2')
|
||||
argument = '-m "' + self.t0_minigraph + '" -p "' + self.t0_port_config + '" -t "' + interfaces_template + '"'
|
||||
output = self.run_script(argument)
|
||||
|
||||
def test_teamd(self):
|
||||
argument = '-m ' + self.t0_minigraph + ' -p ' + self.t0_port_config + ' -v "minigraph_portchannels.keys() | join(\' \')"'
|
||||
output = self.run_script(argument) # Mock the output via config.sh in docker-teamd
|
||||
|
Loading…
Reference in New Issue
Block a user