From 4d84b16fd14ebfe5efbd4dd1f0a7d15213c842dc Mon Sep 17 00:00:00 2001 From: Maggie Sun Date: Wed, 7 Mar 2018 12:53:24 -0800 Subject: [PATCH 1/4] [minigraph-gen]unified generate minigraph from testbed topology definition --- ansible/config_sonic_basedon_testbed_v2.yml | 123 +++++++ ansible/library/port_alias.py | 40 ++- ansible/library/test_facts.py | 52 ++- ansible/templates/alltopo.j2 | 356 ++++++++++++++++++++ ansible/vars/topo_t0-116.yml | 2 + ansible/vars/topo_t0-52.yml | 2 + ansible/vars/topo_t0-64-32.yml | 2 + ansible/vars/topo_t0-64.yml | 2 + ansible/vars/topo_t0.yml | 2 + ansible/vars/topo_t1-64-lag.yml | 2 + ansible/vars/topo_t1-lag.yml | 2 + ansible/vars/topo_t1.yml | 2 + 12 files changed, 571 insertions(+), 16 deletions(-) create mode 100644 ansible/config_sonic_basedon_testbed_v2.yml create mode 100644 ansible/templates/alltopo.j2 diff --git a/ansible/config_sonic_basedon_testbed_v2.yml b/ansible/config_sonic_basedon_testbed_v2.yml new file mode 100644 index 00000000000..d6b246a56e6 --- /dev/null +++ b/ansible/config_sonic_basedon_testbed_v2.yml @@ -0,0 +1,123 @@ +# This Playbook run time generate matching configuration file for SONiC switch(Minigraph) based on a specific testbed topology specified in testbed.csv +# When user call testbed-cli to deploy a testbed topology, use this playbook to generate matching SONiC minigraph file and deploy it into SONiC switch under test. +# Or when you know your topology name, you may use this playbook alone to generate a minigraph matching your topology name without deploy it. +# +# VM Topologies are defined inside of vars/ directory in files vars/topo_{{ topology_name}}.yml +# Every topology should have a name to distinct one topology from another on the server +# Every topology contains a ptf container which will be used as placeholder for the injected interfaces from VMs, or direct connections to PTF host +# VMs inventory file is also required to have all VMs ready for generating the minigraph file +# VMs inventory is in file 'veos' +# +# Template files for generating minigraph.xml are defined in template/topo directory +# +# To generate and deploy minigraph for SONiC switch matching the VM topology please use following command +# ansible-playbook -i lab config_sonic_basedon_testbed_v2.yml -l sonic_dut_name -e vm_base=VM0300 -e topo=t0 [-e deploy=true -e save=true] +# ansible-playbook -i lab config_sonic_basedon_testbed_v2.yml -l sonic_dut_name -e testbed_name=vms1-1 [-e deploy=true -e save=true] +# +# Parameters +# -l str-msn2700-01 - the sonic_dut_name you are going to generate minigraph for +# -e vm_base=VM0300 - the VM name which is used to as base to calculate VM name for this set +# -e topo=t0 - the name of topology to generate minigraph file +# -e testbed_name=vms1-1 - the testbed name specified in testbed.csv file +# (if you give 'testbed_name' option, will use info from testbed and ignore topo and vm_base options) +# -e deploy=True - if deploy the newly generated minigraph to the targent DUT, default is false if not defined +# -e save=True - if save the newly generated minigraph to the targent DUT as starup-config, default is false if not defined +# +# After minigraph.xml is generated, the playbook will replace the original minigraph file under ansible/minigraph/ with the newly generated minigraph file for the SONiC device. +# The playbook will based on deploy=True or False to deside if load the SONiC device with new minigraph or not. +# If deploy=true, the playbook will apply the newly generated minigraph to the SONiC switch +# If save=true, the playbook will save the newly generated minigraph to SONiC switch as startup-config +# +#################################################################################################################################################################################### + +- hosts: sonic + gather_facts: yes + tasks: + + - block: + - name: Gathering testbed information + test_facts: testbed_name="{{ testbed_name }}" + connection: local + + - fail: msg="The DUT you are trying to run test does not belongs to this testbed" + when: testbed_facts['dut'] != inventory_hostname + + - name: set testbed_type + set_fact: + topo: "{{ testbed_facts['topo'] }}" + + - name: set vm + set_fact: + vm_base: "{{ testbed_facts['vm_base'] }}" + when: "testbed_facts['vm_base'] != ''" + when: testbed_name is defined + + - set_fact: + VM_topo: "{% if 'ptf' in topo %}False{% else %}True{% endif %}" + + - name: gather testbed VM informations + testbed_vm_info: base_vm={{ testbed_facts['vm_base'] }} topo={{ testbed_facts['topo'] }} + connection: local + when: "VM_topo | bool" + + - name: find interface name mapping and indivisual interface speed if defined + port_alias: hwsku="{{ hwsku }}" + + - name: find all vlan interface names for T0 topology + set_fact: + vlan_intfs: "{{ vlan_intfs|default([])}} + ['{{ port_alias[item] }}' ]" + with_items: "{{ vm_topo_config['host_interfaces'] }}" + when: ("'host_interfaces' in vm_topo_config") and ("'tor' in vm_topo_config['dut_type'] | lower") + + - name: find all interface indexes connecting to VM + set_fact: + interface_to_vms: "{{ interface_to_vms|default({}) | combine({ item.key: item.value['interface_indexes'] }) }}" + with_dict: vm_topo_config['vm'] + + - name: find all interface names + set_fact: + intf_names: "{{ intf_names | default({}) | combine({item.key: port_alias[item.value[0]|int:item.value[-1]|int+1] }) }}" + with_dict: interface_to_vms + + - name: save original minigraph file of ansible (ignore errors when file doesnot exist) + shell: mv minigraph/{{ inventory_hostname }}.xml minigraph/{{ inventory_hostname }}.xml.orig + connection: local + ignore_errors: true + + - name: create minigraph file in ansible minigraph folder + become: true + template: src=templates/alltopo.j2 + dest=minigraph/{{ inventory_hostname}}.xml + connection: local + + - block: + - name: saved original minigraph file in SONiC DUT(ignore errors when file doesnot exist) + shell: mv /etc/sonic/minigraph.xml /etc/sonic/minigraph.xml.orig + become: true + ignore_errors: true + + - name: create new minigraph file for SONiC device + template: src=templates/alltopo.j2 + dest=/etc/sonic/minigraph.xml + become: true + + - name: disable automatic minigraph update if we are deploying new minigraph into SONiC + lineinfile: + name: /etc/sonic/updategraph.conf + regexp: '^enabled=' + line: 'enabled=false' + become: true + + - name: execute cli "config load_minigraph -y" to apply new minigraph + become: true + shell: config load_minigraph -y + + - name: execute cli "config bgp startup all" to bring up all bgp sessions for test + become: true + shell: config bgp startup all + + - name: execute cli "config save -y" to save current minigraph as startup-config + become: true + shell: config save -y + when: save is defined and save|bool == true + when: deploy is defined and deploy|bool == true diff --git a/ansible/library/port_alias.py b/ansible/library/port_alias.py index beb81fb3479..78fb4996146 100755 --- a/ansible/library/port_alias.py +++ b/ansible/library/port_alias.py @@ -30,20 +30,28 @@ port_alias: hwsku='ACS-MSN2700' ''' -### TODO: we could eventually use sonic config package to replace this port_alias module later ############### +RETURN = ''' + ansible_facts{ + port_alias: [Ethernet0, Ethernet4, ....], + port_speed: ['40000', '40000', ......] + } +''' + ### Here are the expectation of files of device port_config.ini located, in case changed please modify it here FILE_PATH = '/usr/share/sonic/device' PORTMAP_FILE = 'port_config.ini' +ALLOWED_HEADER = ['name', 'lanes', 'alias', 'index', 'speed'] class SonicPortAliasMap(): """ - Retrieve SONiC device interface port alias mapping + Retrieve SONiC device interface port alias mapping and port speed if they are definded """ def __init__(self, hwsku): self.filename = '' self.hwsku = hwsku self.portmap = [] + self.portspeed = [] return def findfile(self): @@ -57,21 +65,25 @@ def get_portmap(self): raise Exception("Something wrong when trying to find the portmap file, either the hwsku is not available or file location is not correct") with open(self.filename) as f: lines = f.readlines() - alias=False + alias_index = 0 + speed_index = 0 while len(lines) != 0: line = lines.pop(0) if re.match('^#', line): title=re.sub('#', '', line.strip().lower()).split() - if 'alias' in title: - index = title.index('alias') - alias = True - else: + for text in title: + if text in ALLOWED_HEADER: + index = title.index(text) + if 'alias' in text: + alias_index = index + if 'speed' in text: + speed_index = index + else: if re.match('^Ethernet', line): mapping = line.split() - if alias and len(mapping) > index: - self.portmap.append(mapping[index]) - else: - self.portmap.append(mapping[0]) + self.portmap.append(mapping[alias_index]) + if speed_index != 0: + self.portspeed.append(mapping[speed_index]) return def main(): @@ -85,14 +97,14 @@ def main(): try: allmap = SonicPortAliasMap(m_args['hwsku']) allmap.get_portmap() - module.exit_json(ansible_facts={'port_alias': allmap.portmap}) + module.exit_json(ansible_facts={'port_alias': allmap.portmap, 'port_speed': allmap.portspeed}) except (IOError, OSError), e: fail_msg = "IO error" + str(e) module.fail_json(msg=fail_msg) except Exception, e: - fail_msg = "failed to find the correct port names for "+m_args['hwsku'] + str(e) + fail_msg = "failed to find the correct port config for "+m_args['hwsku'] + str(e) module.fail_json(msg=fail_msg) from ansible.module_utils.basic import * if __name__ == "__main__": - main() + main() diff --git a/ansible/library/test_facts.py b/ansible/library/test_facts.py index 77d3c72f6be..f61996f40f1 100644 --- a/ansible/library/test_facts.py +++ b/ansible/library/test_facts.py @@ -92,7 +92,6 @@ TESTBED_FILE = 'testbed.csv' TESTCASE_FILE = 'roles/test/vars/testcases.yml' - class ParseTestbedTopoinfo(): ''' Parse the CSV file used to describe whole testbed info @@ -103,6 +102,7 @@ class ParseTestbedTopoinfo(): def __init__(self, testbed_file): self.testbed_filename = testbed_file self.testbed_topo = {} + self.vm_topo_config = {} def read_testbed_topo(self): with open(self.testbed_filename) as f: @@ -132,6 +132,52 @@ def get_testbed_info(self, testbed_name): else: return self.testbed_topo + def get_testbed_topo_config(self, topo_name): + if 'ptf32' in topo_name: + topo_name = 't1' + if 'ptf64' in topo_name: + topo_name = 't1-64' ###TODO: there is no t1-64 topology checked in yet + topo_filename = 'vars/topo_' + topo_name + '.yml' + vm_topo_config = dict() + ### read topology definition + if not os.path.isfile(topo_filename): + raise Exception("cannot find topology definition file under vars/topo_%s.yml file!" % topo_name) + else: + with open(topo_filename) as f: + topo_definition = yaml.load(f) + ### parse topo file specified in vars/ to reverse as dut config + if 'VMs' in topo_definition['topology']: + dut_asn = topo_definition['configuration_properties']['common']['dut_asn'] + vm_topo_config['dut_asn'] = dut_asn + vm_topo_config['dut_type'] = topo_definition['configuration_properties']['common']['dut_type'] + vmconfig = dict() + for vm in topo_definition['topology']['VMs']: + vmconfig[vm] = dict() + vmconfig[vm]['intfs'] = [] + vmconfig[vm]['properties']=topo_definition['configuration'][vm]['properties'] + vmconfig[vm]['interface_indexes'] = topo_definition['topology']['VMs'][vm]['vlans'] + vmconfig[vm]['bgp_asn'] = topo_definition['configuration'][vm]['bgp']['asn'] + for intf in topo_definition['configuration'][vm]['interfaces']: + if 'ipv4' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()): + (vmconfig[vm]['peer_ipv4'], vmconfig[vm]['ipv4mask']) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv4'].split('/') + vmconfig[vm]['ip_intf'] = intf + if 'ipv6' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()): + (ipv6_addr, vmconfig[vm]['ipv6mask']) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv6'].split('/') + vmconfig[vm]['ip_intf'] = intf + vmconfig[vm]['peer_ipv6'] = ipv6_addr.upper() + if 'Ethernet' in intf: + vmconfig[vm]['intfs'].append(intf) + for ip in topo_definition['configuration'][vm]['bgp']['peers'][dut_asn]: + if ip[0:5].upper() in vmconfig[vm]['peer_ipv4'].upper(): + vmconfig[vm]['bgp_ipv4'] = ip.upper() + if ip[0:5].upper() in vmconfig[vm]['peer_ipv6'].upper(): + vmconfig[vm]['bgp_ipv6'] = ip.upper() + vm_topo_config['vm'] = vmconfig + if 'host_interfaces' in topo_definition['topology']: + vm_topo_config['host_interfaces'] = topo_definition['topology']['host_interfaces'] + self.vm_topo_config = vm_topo_config + return vm_topo_config + class TestcasesTopology(): ''' Read testcases definition yaml file under ansible/roles/test/vars/testcases.yml @@ -176,7 +222,9 @@ def main(): testcaseinfo = TestcasesTopology(testcase_file) testcaseinfo.read_testcases() testcase_topo = testcaseinfo.get_topo_testcase() - module.exit_json(ansible_facts={'testbed_facts': testbed_topo, 'topo_testcases': testcase_topo}) + if testbed_name: + vm_topo_config = topoinfo.get_testbed_topo_config(testbed_topo['topo']) + module.exit_json(ansible_facts={'testbed_facts': testbed_topo, 'topo_testcases': testcase_topo, 'vm_topo_config': vm_topo_config}) except (IOError, OSError): module.fail_json(msg="Can not find lab testbed file "+testbed_file+" or testcase file "+testcase_file+"??") except Exception as e: diff --git a/ansible/templates/alltopo.j2 b/ansible/templates/alltopo.j2 new file mode 100644 index 00000000000..a3df6f8f2c8 --- /dev/null +++ b/ansible/templates/alltopo.j2 @@ -0,0 +1,356 @@ + + + + +{% set vms=vm_topo_config['vm'].keys() | sort %} +{% set vms_number = vms | length %} +{% for index in range(vms_number) %} +{% set vm=vms[index] %} +{% if vm_topo_config['vm'][vm]['peer_ipv4'] %} + + false + {{ inventory_hostname }} + {{ vm_topo_config['vm'][vm]['bgp_ipv4'] }} + {{ vm }} + {{ vm_topo_config['vm'][vm]['peer_ipv4'] }} + 1 + 10 + 3 + +{% endif %} +{% if vm_topo_config['vm'][vm]['peer_ipv6'] %} + + {{ inventory_hostname }} + {{ vm_topo_config['vm'][vm]['bgp_ipv6'] }} + {{ vm }} + {{ vm_topo_config['vm'][vm]['peer_ipv6'] }} + 1 + 10 + 3 + +{% endif %} +{% endfor %} + + + + {{ vm_topo_config['dut_asn'] }} + {{ inventory_hostname }} + +{% for index in range(vms_number) %} + +
{{ vm_topo_config['vm'][vms[index]]['peer_ipv4'] }}
+ + + +
+{% endfor %} +{% if 'tor' in vm_topo_config['dut_type'] | lower %} + + BGPPeer +
10.1.0.32
+ + + + BGPSLBPassive + 10.255.0.0/25 +
+ + BGPPeer +
10.1.0.32
+ + + + BGPVac + 192.168.0.0/25 +
+{% endif %} +
+ +
+{% for index in range( vms_number) %} + + {{ vm_topo_config['vm'][vms[index]]['bgp_asn'] }} + {{ vms[index] }} + + +{% endfor %} +
+
+ + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + {{ ansible_host }}/{{ mgmt_subnet_mask_length }} + + {{ ansible_host }}/{{ mgmt_subnet_mask_length }} + + + V6HostIP + eth0 + + FC00:2::32/64 + + FC00:2::32/64 + + + + + + + {{ inventory_hostname }} + +{% for index in range(vms_number) %} +{% if 'port-channel' in vm_topo_config['vm'][vms[index]]['ip_intf']|lower %} +{% set port_channel_intf=';'.join(intf_names[vms[index]]) %} + + PortChannel{{ ((index+1)|string).zfill(4) }} + {{ port_channel_intf }} + + +{% endif %} +{% endfor %} + + +{% if 'tor' in vm_topo_config['dut_type'] | lower %} +{% set vlan_intf_str=';'.join(vlan_intfs) %} + + Vlan1000 + {{ vlan_intf_str }} + False + 0.0.0.0/0 + +{% set dhcp_servers_str=';'.join(dhcp_servers) %} + {{ dhcp_servers_str }} + 1000 + 1000 + 192.168.0.0/21 + +{% endif %} + + +{% for index in range(vms_number) %} + + +{% if 'port-channel' in vm_topo_config['vm'][vms[index]]['ip_intf']|lower %} + PortChannel{{ ((index+1) |string).zfill(4) }} +{% else %} + {{ port_alias[vm_topo_config['vm'][vms[index]]['interface_indexes'][0]] }} +{% endif %} + {{ vm_topo_config['vm'][vms[index]]['bgp_ipv4'] }}/{{ vm_topo_config['vm'][vms[index]]['ipv4mask'] }} + + + +{% if 'port-channel' in (vm_topo_config['vm'][vms[index]]['ip_intf']|lower) %} + PortChannel{{ ((index+1) |string).zfill(4) }} +{% else %} + {{ port_alias[vm_topo_config['vm'][vms[index]]['interface_indexes'][0]] }} +{% endif %} + {{ vm_topo_config['vm'][vms[index]]['bgp_ipv6'] }}/{{ vm_topo_config['vm'][vms[index]]['ipv6mask'] }} + +{% endfor %} +{% if 'tor' in vm_topo_config['dut_type'] | lower %} + + + Vlan1000 + 192.168.0.1/27 + +{% endif %} + + + + + SNMP_ACL + SNMP + SNMP + + + ERSPAN + Everflow + Everflow + + + VTY_LINE + ssh-only + SSH + + + + + + + + +{% for index in range(vms_number) %} +{% set vm_intfs=vm_topo_config['vm'][vms[index]]['intfs']|sort %} +{% set dut_intfs=vm_topo_config['vm'][vms[index]]['interface_indexes']|sort %} +{% for if_index in range(vm_intfs | length) %} + + DeviceInterfaceLink + {{ vms[index] }} + {{ vm_intfs[if_index] }} + {{ inventory_hostname }} + {{ port_alias[dut_intfs[if_index]] }} + +{% endfor %} +{% endfor %} + + + + {{ inventory_hostname }} + {{ hwsku }} + + {{ ansible_host }} + + +{% if VM_topo %} +{% for dev in neighbor_eosvm_mgmt %} +{% if 'T1' in dev %} +{% set dev_type = 'LeafRouter' %} +{% elif 'T2' in dev %} +{% set dev_type = 'SpineRouter' %} +{% elif 'T0' in dev %} +{% set dev_type = 'TorRouter' %} +{% else %} +{% set dev_ytpe = 'Unknown' %} +{% endif %} + + {{ dev }} + + {{ neighbor_eosvm_mgmt[dev] }} + + Arista-VM + +{% endfor %} +{% endif %} + + + + + true + +{% set num_of_intf = port_alias | length %} +{% for index in range(num_of_intf) %} + + DeviceInterface + + true + true + 1 + {{ port_alias[index] }} + + false + 0 + 0 +{% set speed_option = port_speed | length %} +{% if speed_option == 0 %} + {{ iface_speed }} +{% else %} + {{ port_speed[index] }} +{% endif %} + +{% endfor %} + + true + 0 + {{ hwsku }} + + + + +{% set syslog_servers_str=';'.join(syslog_servers) %} +{% set dhcp_servers_str=';'.join(dhcp_servers) %} +{% set forced_mgmt_routes_str = ';'.join(forced_mgmt_routes) %} +{% set ntp_servers_str = ';'.join(ntp_servers) %} +{% set snmp_servers_str = ';'.join(snmp_servers) %} +{% set tacacs_servers_str = ';'.join(tacacs_servers) %} +{% set radius_servers_str = ';'.join(radius_servers) %} +{% set erspan_dest_str = ';'.join(erspan_dest) %} + + + {{ inventory_hostname }} + + + DhcpResources + + {{ dhcp_servers_str }} + + + NtpResources + + {{ ntp_servers_str }} + + + DeploymentId + + 1 + + + QosProfile + + Profile0 + + + RadiusResources + + {{ radius_servers_str }} + + + SnmpResources + + {{ snmp_servers_str }} + + + SyslogResources + + {{ syslog_servers_str }} + + + TacacsGroup + + {{ tacacs_group }} + + + TacacsServer + + {{ tacacs_servers_str }} + + + ForcedMgmtRoutes + + {{ forced_mgmt_routes_str }} + + + ErspanDestinationIpv4 + + {{ erspan_dest_str }} + + + + + + + {{ inventory_hostname }} + {{ hwsku }} +
diff --git a/ansible/vars/topo_t0-116.yml b/ansible/vars/topo_t0-116.yml index a46dd94a1e8..cfd91754436 100644 --- a/ansible/vars/topo_t0-116.yml +++ b/ansible/vars/topo_t0-116.yml @@ -136,6 +136,8 @@ topology: configuration_properties: common: + dut_asn: 4200065100 + dut_type: ToRRouter swrole: leaf podset_number: 200 tor_number: 16 diff --git a/ansible/vars/topo_t0-52.yml b/ansible/vars/topo_t0-52.yml index 837c5f14df7..dc419f98fd2 100644 --- a/ansible/vars/topo_t0-52.yml +++ b/ansible/vars/topo_t0-52.yml @@ -68,6 +68,8 @@ topology: configuration_properties: common: + dut_asn: 65100 + dut_type: ToRRouter swrole: leaf podset_number: 200 tor_number: 16 diff --git a/ansible/vars/topo_t0-64-32.yml b/ansible/vars/topo_t0-64-32.yml index 60533eb4e5b..ead16160e0c 100644 --- a/ansible/vars/topo_t0-64-32.yml +++ b/ansible/vars/topo_t0-64-32.yml @@ -48,6 +48,8 @@ topology: configuration_properties: common: + dut_asn: 64601 + dut_type: ToRRouter swrole: leaf podset_number: 200 tor_number: 16 diff --git a/ansible/vars/topo_t0-64.yml b/ansible/vars/topo_t0-64.yml index 7ac7f3dce41..70fb18086f8 100644 --- a/ansible/vars/topo_t0-64.yml +++ b/ansible/vars/topo_t0-64.yml @@ -80,6 +80,8 @@ topology: configuration_properties: common: + dut_asn: 64601 + dut_type: ToRRouter swrole: leaf podset_number: 200 tor_number: 16 diff --git a/ansible/vars/topo_t0.yml b/ansible/vars/topo_t0.yml index 65ffbd4c4f1..075ee8f3cde 100644 --- a/ansible/vars/topo_t0.yml +++ b/ansible/vars/topo_t0.yml @@ -48,6 +48,8 @@ topology: configuration_properties: common: + dut_asn: 65100 + dut_type: ToRRouter swrole: leaf podset_number: 200 tor_number: 16 diff --git a/ansible/vars/topo_t1-64-lag.yml b/ansible/vars/topo_t1-64-lag.yml index 5749012d0be..b64994d4843 100644 --- a/ansible/vars/topo_t1-64-lag.yml +++ b/ansible/vars/topo_t1-64-lag.yml @@ -103,6 +103,8 @@ topology: configuration_properties: common: + dut_asn: 65100 + dut_type: LeafRouter nhipv4: 10.10.246.100 nhipv6: FC0A::C9 spine: diff --git a/ansible/vars/topo_t1-lag.yml b/ansible/vars/topo_t1-lag.yml index 37418e478c0..b9c54ff961b 100644 --- a/ansible/vars/topo_t1-lag.yml +++ b/ansible/vars/topo_t1-lag.yml @@ -107,6 +107,8 @@ topology: configuration_properties: common: + dut_asn: 65100 + dut_type: LeafRouter nhipv4: 10.10.246.100 nhipv6: FC0A::C9 spine: diff --git a/ansible/vars/topo_t1.yml b/ansible/vars/topo_t1.yml index 4c6ee348242..1dcf210e2e6 100644 --- a/ansible/vars/topo_t1.yml +++ b/ansible/vars/topo_t1.yml @@ -131,6 +131,8 @@ topology: configuration_properties: common: + dut_asn: 65100 + dut_type: LeafRouter nhipv4: 10.10.246.100 nhipv6: FC0A::C9 spine: From 663b768e39170a2b84f473be3263b9ab820f8d41 Mon Sep 17 00:00:00 2001 From: Maggie Sun Date: Fri, 9 Mar 2018 15:45:24 -0800 Subject: [PATCH 2/4] split minigraph template into sections; remove turned off interfaces from vlan interface --- ansible/config_sonic_basedon_testbed_v2.yml | 10 +- ansible/templates/alltopo.j2 | 356 -------------------- ansible/templates/minigraph_cpg.j2 | 76 +++++ ansible/templates/minigraph_device.j2 | 33 ++ ansible/templates/minigraph_dpg.j2 | 125 +++++++ ansible/templates/minigraph_meta.j2 | 74 ++++ ansible/templates/minigraph_png.j2 | 47 +++ ansible/templates/minigraph_template.j2 | 11 + 8 files changed, 374 insertions(+), 358 deletions(-) delete mode 100644 ansible/templates/alltopo.j2 create mode 100644 ansible/templates/minigraph_cpg.j2 create mode 100644 ansible/templates/minigraph_device.j2 create mode 100644 ansible/templates/minigraph_dpg.j2 create mode 100644 ansible/templates/minigraph_meta.j2 create mode 100644 ansible/templates/minigraph_png.j2 create mode 100644 ansible/templates/minigraph_template.j2 diff --git a/ansible/config_sonic_basedon_testbed_v2.yml b/ansible/config_sonic_basedon_testbed_v2.yml index d6b246a56e6..5d5c171d51a 100644 --- a/ansible/config_sonic_basedon_testbed_v2.yml +++ b/ansible/config_sonic_basedon_testbed_v2.yml @@ -54,6 +54,7 @@ - set_fact: VM_topo: "{% if 'ptf' in topo %}False{% else %}True{% endif %}" + remote_dut: "{{ ansible_ssh_host }}" - name: gather testbed VM informations testbed_vm_info: base_vm={{ testbed_facts['vm_base'] }} topo={{ testbed_facts['topo'] }} @@ -62,11 +63,16 @@ - name: find interface name mapping and indivisual interface speed if defined port_alias: hwsku="{{ hwsku }}" + connection: local + - name: find all enalbed host_interfaces + set_fact: + host_if_indexes: "{{ vm_topo_config['host_interfaces'] | difference(vm_topo_config['off_host_interfaces']) }}" + - name: find all vlan interface names for T0 topology set_fact: vlan_intfs: "{{ vlan_intfs|default([])}} + ['{{ port_alias[item] }}' ]" - with_items: "{{ vm_topo_config['host_interfaces'] }}" + with_items: "{{ host_if_indexes }}" when: ("'host_interfaces' in vm_topo_config") and ("'tor' in vm_topo_config['dut_type'] | lower") - name: find all interface indexes connecting to VM @@ -86,7 +92,7 @@ - name: create minigraph file in ansible minigraph folder become: true - template: src=templates/alltopo.j2 + template: src=templates/minigraph_template.j2 dest=minigraph/{{ inventory_hostname}}.xml connection: local diff --git a/ansible/templates/alltopo.j2 b/ansible/templates/alltopo.j2 deleted file mode 100644 index a3df6f8f2c8..00000000000 --- a/ansible/templates/alltopo.j2 +++ /dev/null @@ -1,356 +0,0 @@ - - - - -{% set vms=vm_topo_config['vm'].keys() | sort %} -{% set vms_number = vms | length %} -{% for index in range(vms_number) %} -{% set vm=vms[index] %} -{% if vm_topo_config['vm'][vm]['peer_ipv4'] %} - - false - {{ inventory_hostname }} - {{ vm_topo_config['vm'][vm]['bgp_ipv4'] }} - {{ vm }} - {{ vm_topo_config['vm'][vm]['peer_ipv4'] }} - 1 - 10 - 3 - -{% endif %} -{% if vm_topo_config['vm'][vm]['peer_ipv6'] %} - - {{ inventory_hostname }} - {{ vm_topo_config['vm'][vm]['bgp_ipv6'] }} - {{ vm }} - {{ vm_topo_config['vm'][vm]['peer_ipv6'] }} - 1 - 10 - 3 - -{% endif %} -{% endfor %} - - - - {{ vm_topo_config['dut_asn'] }} - {{ inventory_hostname }} - -{% for index in range(vms_number) %} - -
{{ vm_topo_config['vm'][vms[index]]['peer_ipv4'] }}
- - - -
-{% endfor %} -{% if 'tor' in vm_topo_config['dut_type'] | lower %} - - BGPPeer -
10.1.0.32
- - - - BGPSLBPassive - 10.255.0.0/25 -
- - BGPPeer -
10.1.0.32
- - - - BGPVac - 192.168.0.0/25 -
-{% endif %} -
- -
-{% for index in range( vms_number) %} - - {{ vm_topo_config['vm'][vms[index]]['bgp_asn'] }} - {{ vms[index] }} - - -{% endfor %} -
-
- - - - - - HostIP - Loopback0 - - 10.1.0.32/32 - - 10.1.0.32/32 - - - HostIP1 - Loopback0 - - FC00:1::32/128 - - FC00:1::32/128 - - - - - HostIP - eth0 - - {{ ansible_host }}/{{ mgmt_subnet_mask_length }} - - {{ ansible_host }}/{{ mgmt_subnet_mask_length }} - - - V6HostIP - eth0 - - FC00:2::32/64 - - FC00:2::32/64 - - - - - - - {{ inventory_hostname }} - -{% for index in range(vms_number) %} -{% if 'port-channel' in vm_topo_config['vm'][vms[index]]['ip_intf']|lower %} -{% set port_channel_intf=';'.join(intf_names[vms[index]]) %} - - PortChannel{{ ((index+1)|string).zfill(4) }} - {{ port_channel_intf }} - - -{% endif %} -{% endfor %} - - -{% if 'tor' in vm_topo_config['dut_type'] | lower %} -{% set vlan_intf_str=';'.join(vlan_intfs) %} - - Vlan1000 - {{ vlan_intf_str }} - False - 0.0.0.0/0 - -{% set dhcp_servers_str=';'.join(dhcp_servers) %} - {{ dhcp_servers_str }} - 1000 - 1000 - 192.168.0.0/21 - -{% endif %} - - -{% for index in range(vms_number) %} - - -{% if 'port-channel' in vm_topo_config['vm'][vms[index]]['ip_intf']|lower %} - PortChannel{{ ((index+1) |string).zfill(4) }} -{% else %} - {{ port_alias[vm_topo_config['vm'][vms[index]]['interface_indexes'][0]] }} -{% endif %} - {{ vm_topo_config['vm'][vms[index]]['bgp_ipv4'] }}/{{ vm_topo_config['vm'][vms[index]]['ipv4mask'] }} - - - -{% if 'port-channel' in (vm_topo_config['vm'][vms[index]]['ip_intf']|lower) %} - PortChannel{{ ((index+1) |string).zfill(4) }} -{% else %} - {{ port_alias[vm_topo_config['vm'][vms[index]]['interface_indexes'][0]] }} -{% endif %} - {{ vm_topo_config['vm'][vms[index]]['bgp_ipv6'] }}/{{ vm_topo_config['vm'][vms[index]]['ipv6mask'] }} - -{% endfor %} -{% if 'tor' in vm_topo_config['dut_type'] | lower %} - - - Vlan1000 - 192.168.0.1/27 - -{% endif %} - - - - - SNMP_ACL - SNMP - SNMP - - - ERSPAN - Everflow - Everflow - - - VTY_LINE - ssh-only - SSH - - - - - - - - -{% for index in range(vms_number) %} -{% set vm_intfs=vm_topo_config['vm'][vms[index]]['intfs']|sort %} -{% set dut_intfs=vm_topo_config['vm'][vms[index]]['interface_indexes']|sort %} -{% for if_index in range(vm_intfs | length) %} - - DeviceInterfaceLink - {{ vms[index] }} - {{ vm_intfs[if_index] }} - {{ inventory_hostname }} - {{ port_alias[dut_intfs[if_index]] }} - -{% endfor %} -{% endfor %} - - - - {{ inventory_hostname }} - {{ hwsku }} - - {{ ansible_host }} - - -{% if VM_topo %} -{% for dev in neighbor_eosvm_mgmt %} -{% if 'T1' in dev %} -{% set dev_type = 'LeafRouter' %} -{% elif 'T2' in dev %} -{% set dev_type = 'SpineRouter' %} -{% elif 'T0' in dev %} -{% set dev_type = 'TorRouter' %} -{% else %} -{% set dev_ytpe = 'Unknown' %} -{% endif %} - - {{ dev }} - - {{ neighbor_eosvm_mgmt[dev] }} - - Arista-VM - -{% endfor %} -{% endif %} - - - - - true - -{% set num_of_intf = port_alias | length %} -{% for index in range(num_of_intf) %} - - DeviceInterface - - true - true - 1 - {{ port_alias[index] }} - - false - 0 - 0 -{% set speed_option = port_speed | length %} -{% if speed_option == 0 %} - {{ iface_speed }} -{% else %} - {{ port_speed[index] }} -{% endif %} - -{% endfor %} - - true - 0 - {{ hwsku }} - - - - -{% set syslog_servers_str=';'.join(syslog_servers) %} -{% set dhcp_servers_str=';'.join(dhcp_servers) %} -{% set forced_mgmt_routes_str = ';'.join(forced_mgmt_routes) %} -{% set ntp_servers_str = ';'.join(ntp_servers) %} -{% set snmp_servers_str = ';'.join(snmp_servers) %} -{% set tacacs_servers_str = ';'.join(tacacs_servers) %} -{% set radius_servers_str = ';'.join(radius_servers) %} -{% set erspan_dest_str = ';'.join(erspan_dest) %} - - - {{ inventory_hostname }} - - - DhcpResources - - {{ dhcp_servers_str }} - - - NtpResources - - {{ ntp_servers_str }} - - - DeploymentId - - 1 - - - QosProfile - - Profile0 - - - RadiusResources - - {{ radius_servers_str }} - - - SnmpResources - - {{ snmp_servers_str }} - - - SyslogResources - - {{ syslog_servers_str }} - - - TacacsGroup - - {{ tacacs_group }} - - - TacacsServer - - {{ tacacs_servers_str }} - - - ForcedMgmtRoutes - - {{ forced_mgmt_routes_str }} - - - ErspanDestinationIpv4 - - {{ erspan_dest_str }} - - - - - - - {{ inventory_hostname }} - {{ hwsku }} -
diff --git a/ansible/templates/minigraph_cpg.j2 b/ansible/templates/minigraph_cpg.j2 new file mode 100644 index 00000000000..9b1f2437816 --- /dev/null +++ b/ansible/templates/minigraph_cpg.j2 @@ -0,0 +1,76 @@ + + + +{% for index in range(vms_number) %} +{% set vm=vms[index] %} +{% if vm_topo_config['vm'][vm]['peer_ipv4'] %} + + false + {{ inventory_hostname }} + {{ vm_topo_config['vm'][vm]['bgp_ipv4'] }} + {{ vm }} + {{ vm_topo_config['vm'][vm]['peer_ipv4'] }} + 1 + 10 + 3 + +{% endif %} +{% if vm_topo_config['vm'][vm]['peer_ipv6'] %} + + {{ inventory_hostname }} + {{ vm_topo_config['vm'][vm]['bgp_ipv6'] }} + {{ vm }} + {{ vm_topo_config['vm'][vm]['peer_ipv6'] }} + 1 + 10 + 3 + +{% endif %} +{% endfor %} + + + + {{ vm_topo_config['dut_asn'] }} + {{ inventory_hostname }} + +{% for index in range(vms_number) %} + +
{{ vm_topo_config['vm'][vms[index]]['peer_ipv4'] }}
+ + + +
+{% endfor %} +{% if 'tor' in vm_topo_config['dut_type'] | lower %} + + BGPPeer +
10.1.0.32
+ + + + BGPSLBPassive + 10.255.0.0/25 +
+ + BGPPeer +
10.1.0.32
+ + + + BGPVac + 192.168.0.0/25 +
+{% endif %} +
+ +
+{% for index in range( vms_number) %} + + {{ vm_topo_config['vm'][vms[index]]['bgp_asn'] }} + {{ vms[index] }} + + +{% endfor %} +
+
+ diff --git a/ansible/templates/minigraph_device.j2 b/ansible/templates/minigraph_device.j2 new file mode 100644 index 00000000000..2d30e2146dc --- /dev/null +++ b/ansible/templates/minigraph_device.j2 @@ -0,0 +1,33 @@ + + + true + +{% set num_of_intf = port_alias | length %} +{% for index in range(num_of_intf) %} + + DeviceInterface + + true + true + 1 + {{ port_alias[index] }} + + false + 0 + 0 +{% set speed_option = port_speed | length %} +{% if speed_option == 0 %} + {{ iface_speed }} +{% else %} + {{ port_speed[index] }} +{% endif %} + +{% endfor %} + + true + 0 + {{ hwsku }} + + + + diff --git a/ansible/templates/minigraph_dpg.j2 b/ansible/templates/minigraph_dpg.j2 new file mode 100644 index 00000000000..3a93a886a9e --- /dev/null +++ b/ansible/templates/minigraph_dpg.j2 @@ -0,0 +1,125 @@ + + + + + + HostIP + Loopback0 + + 10.1.0.32/32 + + 10.1.0.32/32 + + + HostIP1 + Loopback0 + + FC00:1::32/128 + + FC00:1::32/128 + + + + + HostIP + eth0 + + {{ ansible_host }}/{{ mgmt_subnet_mask_length }} + + {{ ansible_host }}/{{ mgmt_subnet_mask_length }} + + + V6HostIP + eth0 + + FC00:2::32/64 + + FC00:2::32/64 + + + + + + + {{ inventory_hostname }} + +{% for index in range(vms_number) %} +{% if 'port-channel' in vm_topo_config['vm'][vms[index]]['ip_intf']|lower %} +{% set port_channel_intf=';'.join(intf_names[vms[index]]) %} + + PortChannel{{ ((index+1)|string).zfill(4) }} + {{ port_channel_intf }} + + +{% endif %} +{% endfor %} + + +{% if 'tor' in vm_topo_config['dut_type'] | lower %} +{% set vlan_intf_str=';'.join(vlan_intfs) %} + + Vlan1000 + {{ vlan_intf_str }} + False + 0.0.0.0/0 + +{% set dhcp_servers_str=';'.join(dhcp_servers) %} + {{ dhcp_servers_str }} + 1000 + 1000 + 192.168.0.0/21 + +{% endif %} + + +{% for index in range(vms_number) %} + + +{% if 'port-channel' in vm_topo_config['vm'][vms[index]]['ip_intf']|lower %} + PortChannel{{ ((index+1) |string).zfill(4) }} +{% else %} + {{ port_alias[vm_topo_config['vm'][vms[index]]['interface_indexes'][0]] }} +{% endif %} + {{ vm_topo_config['vm'][vms[index]]['bgp_ipv4'] }}/{{ vm_topo_config['vm'][vms[index]]['ipv4mask'] }} + + + +{% if 'port-channel' in (vm_topo_config['vm'][vms[index]]['ip_intf']|lower) %} + PortChannel{{ ((index+1) |string).zfill(4) }} +{% else %} + {{ port_alias[vm_topo_config['vm'][vms[index]]['interface_indexes'][0]] }} +{% endif %} + {{ vm_topo_config['vm'][vms[index]]['bgp_ipv6'] }}/{{ vm_topo_config['vm'][vms[index]]['ipv6mask'] }} + +{% endfor %} +{% if 'tor' in vm_topo_config['dut_type'] | lower %} + + + Vlan1000 + 192.168.0.1/27 + +{% endif %} + + + + + SNMP_ACL + SNMP + SNMP + + + ERSPAN + Everflow + Everflow + + + VTY_LINE + ssh-only + SSH + + + + + + + diff --git a/ansible/templates/minigraph_meta.j2 b/ansible/templates/minigraph_meta.j2 new file mode 100644 index 00000000000..6818414279f --- /dev/null +++ b/ansible/templates/minigraph_meta.j2 @@ -0,0 +1,74 @@ + +{% set syslog_servers_str=';'.join(syslog_servers) %} +{% set dhcp_servers_str=';'.join(dhcp_servers) %} +{% set forced_mgmt_routes_str = ';'.join(forced_mgmt_routes) %} +{% set ntp_servers_str = ';'.join(ntp_servers) %} +{% set snmp_servers_str = ';'.join(snmp_servers) %} +{% set tacacs_servers_str = ';'.join(tacacs_servers) %} +{% set radius_servers_str = ';'.join(radius_servers) %} +{% set erspan_dest_str = ';'.join(erspan_dest) %} + + + {{ inventory_hostname }} + + + DhcpResources + + {{ dhcp_servers_str }} + + + NtpResources + + {{ ntp_servers_str }} + + + DeploymentId + + 1 + + + QosProfile + + Profile0 + + + RadiusResources + + {{ radius_servers_str }} + + + SnmpResources + + {{ snmp_servers_str }} + + + SyslogResources + + {{ syslog_servers_str }} + + + TacacsGroup + + {{ tacacs_group }} + + + TacacsServer + + {{ tacacs_servers_str }} + + + ForcedMgmtRoutes + + {{ forced_mgmt_routes_str }} + + + ErspanDestinationIpv4 + + {{ erspan_dest_str }} + + + + + + + diff --git a/ansible/templates/minigraph_png.j2 b/ansible/templates/minigraph_png.j2 new file mode 100644 index 00000000000..d75dee0de40 --- /dev/null +++ b/ansible/templates/minigraph_png.j2 @@ -0,0 +1,47 @@ + + +{% for index in range(vms_number) %} +{% set vm_intfs=vm_topo_config['vm'][vms[index]]['intfs']|sort %} +{% set dut_intfs=vm_topo_config['vm'][vms[index]]['interface_indexes']|sort %} +{% for if_index in range(vm_intfs | length) %} + + DeviceInterfaceLink + {{ vms[index] }} + {{ vm_intfs[if_index] }} + {{ inventory_hostname }} + {{ port_alias[dut_intfs[if_index]] }} + +{% endfor %} +{% endfor %} + + + + {{ inventory_hostname }} + {{ hwsku }} + + {{ ansible_host }} + + +{% if VM_topo %} +{% for dev in neighbor_eosvm_mgmt %} +{% if 'T1' in dev %} +{% set dev_type = 'LeafRouter' %} +{% elif 'T2' in dev %} +{% set dev_type = 'SpineRouter' %} +{% elif 'T0' in dev %} +{% set dev_type = 'ToRRouter' %} +{% else %} +{% set dev_ytpe = 'Unknown' %} +{% endif %} + + {{ dev }} + + {{ neighbor_eosvm_mgmt[dev] }} + + Arista-VM + +{% endfor %} +{% endif %} + + + diff --git a/ansible/templates/minigraph_template.j2 b/ansible/templates/minigraph_template.j2 new file mode 100644 index 00000000000..9cbe62ad202 --- /dev/null +++ b/ansible/templates/minigraph_template.j2 @@ -0,0 +1,11 @@ + +{% set vms=vm_topo_config['vm'].keys() | sort %} +{% set vms_number = vms | length %} +{% include 'minigraph_cpg.j2' %} +{% include 'minigraph_dpg.j2' %} +{% include 'minigraph_png.j2' %} +{% include 'minigraph_device.j2' %} +{% include 'minigraph_meta.j2' %} + {{ inventory_hostname }} + {{ hwsku }} + From ba11bd1d5b2e156d9d9f3bb0f7c0c873ad684f05 Mon Sep 17 00:00:00 2001 From: Maggie Sun Date: Fri, 9 Mar 2018 16:11:24 -0800 Subject: [PATCH 3/4] add missed test_fact file --- ansible/library/test_facts.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ansible/library/test_facts.py b/ansible/library/test_facts.py index f61996f40f1..04fdbe7f389 100644 --- a/ansible/library/test_facts.py +++ b/ansible/library/test_facts.py @@ -175,6 +175,12 @@ def get_testbed_topo_config(self, topo_name): vm_topo_config['vm'] = vmconfig if 'host_interfaces' in topo_definition['topology']: vm_topo_config['host_interfaces'] = topo_definition['topology']['host_interfaces'] + else: + vm_topo_config['host_interfaces'] = [] + if 'off_host_interfaces' in topo_definition['topology']: + vm_topo_config['off_host_interfaces'] = topo_definition['topology']['off_host_interfaces'] + else: + vm_topo_config['off_host_interfaces'] = [] self.vm_topo_config = vm_topo_config return vm_topo_config From ff1b103293c1b74c1bbc6984a0b10a96c30f6606 Mon Sep 17 00:00:00 2001 From: Maggie Sun Date: Fri, 9 Mar 2018 16:15:01 -0800 Subject: [PATCH 4/4] add t0 topo file that with disabled host interfaces --- ansible/vars/topo_t0-64.yml | 21 +++++++++++++++++++++ ansible/vars/topo_t0.yml | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/ansible/vars/topo_t0-64.yml b/ansible/vars/topo_t0-64.yml index 70fb18086f8..eb96205d3b5 100644 --- a/ansible/vars/topo_t0-64.yml +++ b/ansible/vars/topo_t0-64.yml @@ -56,6 +56,27 @@ topology: - 61 - 62 - 63 + off_host_interfaces: + - 2 + - 3 + - 18 + - 19 + - 33 + - 34 + - 35 + - 43 + - 44 + - 45 + - 46 + - 47 + - 49 + - 50 + - 51 + - 59 + - 60 + - 61 + - 62 + - 63 VMs: ARISTA01T1: vlans: diff --git a/ansible/vars/topo_t0.yml b/ansible/vars/topo_t0.yml index 075ee8f3cde..92a276b4cf6 100644 --- a/ansible/vars/topo_t0.yml +++ b/ansible/vars/topo_t0.yml @@ -28,6 +28,11 @@ topology: - 25 - 26 - 27 + off_host_interfaces: + - 0 + - 25 + - 26 + - 27 VMs: ARISTA01T1: vlans: