[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:
Taoyu Li 2017-03-30 15:25:31 -07:00 committed by GitHub
parent 71d299bed4
commit fed908fc6b
14 changed files with 365 additions and 142 deletions

View File

@ -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"

View File

@ -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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -0,0 +1,5 @@
{
{% for member in minigraph_ports.keys() %}
"{{member}}": "{{minigraph_ports[member]['alias']}}"
{% endfor %}
}

View File

@ -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

View File

@ -37,7 +37,7 @@ iface eth0 inet static
{% for prefix in forced_mgmt_routes %}
down ip route delete {{ prefix }} via {{ minigraph_mgmt_interface['gwaddr'] }} dev eth0
{% endfor %}
{# TODO: COPP policy type rules #}
{# TODO: COPP policy type rules #}
{% else %}
iface eth0 inet dhcp
{% endif %}
@ -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'] }}
#

View File

@ -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

View File

@ -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,59 +145,24 @@ def parse_dpg(dpg, hname):
intf['mask'] = ipmask
else:
intf['mask'] = str(prefix_len)
intf.update({'attachto': intfname, 'prefixlen': int(prefix_len)})
if intfname[0:4] == "Vlan":
if intfname in vlan_map:
vlan_map[intfname].append(intf)
# TODO: remove peer_addr after dependency removed
ipaddr_val = int(ipn.ip)
peer_addr_val = None
if int(prefix_len) == addr_bits - 2:
if ipaddr_val & 0x3 == 1:
peer_addr_val = ipaddr_val + 1
else:
vlan_map[intfname] = [intf]
elif intfname[0:11] == "PortChannel":
if intfname in pc_map:
pc_map[intfname].append(intf)
peer_addr_val = ipaddr_val - 1
elif int(prefix_len) == addr_bits - 1:
if ipaddr_val & 0x1 == 0:
peer_addr_val = ipaddr_val + 1
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
# TODO: remove peer_addr after dependency removed
ipaddr_val = int(ipn.ip)
peer_addr_val = None
if int(prefix_len) == addr_bits - 2:
if ipaddr_val & 0x3 == 1:
peer_addr_val = ipaddr_val + 1
else:
peer_addr_val = ipaddr_val - 1
elif int(prefix_len) == addr_bits - 1:
if ipaddr_val & 0x1 == 0:
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
peer_addr_val = ipaddr_val - 1
if peer_addr_val is not None:
intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
intfs.append(intf)
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 = {}
@ -231,14 +210,11 @@ def parse_dpg(dpg, hname):
vlanid = vintf.find(str(QName(ns, "VlanID"))).text
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]
for i, member in enumerate(vmbr_list):
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)
print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a Vlan interface, which is currently not supported"
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))

View File

@ -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)

View 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>

View File

@ -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}]")

View File

@ -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