-
Notifications
You must be signed in to change notification settings - Fork 1k
[minigraph] generate device under test minigraph file #207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
473ddce
7eb5c51
47a484e
b2ba867
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| # 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.yml --vault-password-file=~/.password -l sonic_dut_name -e VM_base=VM0300 -e topo=t0 [-e deploy=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 deploy=True - if deploy the newly generated minigraph to the targent DUT, 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 reboot the SONiC switch after change to new minigraph to make it take effect | ||
| # | ||
| #################################################################################################################################################################################### | ||
|
|
||
| - hosts: sonic | ||
| gather_facts: yes | ||
| tasks: | ||
| - fail: msg="need to provide topology type and vm base like topo=t0 and vm_base=VM100" | ||
| when: (topo is not defined) or (vm_base is not defined) | ||
|
|
||
| - fail: msg="need hwsku, interface speed, netmask and interface prefix/postfix defined to generate configuration file" | ||
| when: (hwsku is not defined) or (iface_speed is not defined) or (mgmt_subnet_mask_length is not defined) | ||
|
|
||
| - stat: | ||
|
||
| path: /usr/share/sonic/device | ||
| register: p | ||
| connection: local | ||
|
|
||
| #### TODO: build the package into sonic-mgmt docker and remove this block of code #### | ||
|
||
| - block: | ||
| - file: path=/tmp/buildimage state=absent | ||
| connection: local | ||
|
|
||
| - name: git download | ||
| shell: git clone https://github.com/azure/sonic-buildimage /tmp/buildimage | ||
| connection: local | ||
|
|
||
| - name: create folder | ||
| file: path=/usr/share/sonic state=directory | ||
| connection: local | ||
| become: true | ||
|
|
||
| - name: move files | ||
| shell: cp -r /tmp/buildimage/device /usr/share/sonic/ | ||
| become: true | ||
| connection: local | ||
| when: p.stat.isdir is not defined | ||
|
|
||
| - set_fact: | ||
| VM_topo: "{% if 'ptf' in topo %}False{% else %}True{% endif %}" | ||
| remote_dut: "{{ ansible_ssh_host }}" | ||
| template_name: "{{ 't1' if topo=='ptf32' else topo }}" | ||
|
|
||
| - testbed_vm_info: base_vm="{{ vm_base }}" topo="{{ topo }}" | ||
| connection: local | ||
| when: VM_topo | ||
|
|
||
| - name: find interface name mapping | ||
| port_alias: hwsku="{{ hwsku }}" | ||
| connection: local | ||
|
|
||
| - debug: var=port_alias | ||
|
|
||
| - name: save original minigraph file (if original file does not exist, then ignore errors) | ||
| shell: mv minigraph/{{ inventory_hostname }}.xml minigraph/{{ inventory_hostname }}.xml.orig | ||
| connection: local | ||
| ignore_errors: true | ||
|
|
||
| - name: create minigraph file in minigraph folder | ||
| become: true | ||
| template: src=templates/topo/{{ template_name }}.j2 | ||
| dest=minigraph/{{ inventory_hostname}}.xml | ||
| connection: local | ||
|
|
||
| #### TODO: remove this step block when the device data package is built into sonic-mgmt docker #### | ||
| - block: | ||
| - name: remove tempfile | ||
| file: path=/usr/share/sonic/device state=absent | ||
| connection: local | ||
| become: true | ||
|
|
||
| - name: remove tempfile | ||
| file: path=/tmp/buildimage state=absent | ||
| when: p.stat.isdir is not defined | ||
| connection: local | ||
| when: p.stat.isdir is not defined | ||
|
||
|
|
||
| - block: | ||
| - name: saved original minigraph file (if original file may don't exist, then ignore errors) | ||
| shell: mv /etc/sonic/minigraph.xml /etc/sonic/minigraph.xml.orig | ||
| become: true | ||
| ignore_errors: true | ||
|
|
||
| - name: save original updategraph configuration (if original file may don't exist, then ignore errors) | ||
| shell: mv /etc/sonic/updategraph.conf /etc/sonic/updategrph.conf.orig | ||
| become: true | ||
| ignore_errors: true | ||
|
||
|
|
||
| - name: create minigraph file for SONiC device | ||
| template: src=templates/topo/{{ template_name }}.j2 | ||
| dest=/etc/sonic/minigraph.xml | ||
| become: true | ||
|
|
||
| - name: disable automatic minigraph update if we are deploying new minigraph into SONiC | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see above. |
||
| copy: src=templates/topo/updategraph.conf | ||
| dest=/etc/sonic/updategraph.conf | ||
| become: true | ||
|
|
||
| # reload the device and wait it to come back | ||
| - name: Reboot is required for minigraph change | ||
| shell: sleep 2 && shutdown -r now "Ansible Create new configuration Minigraph file, triggered reboot." | ||
| async: 1 | ||
| poll: 0 | ||
| become: true | ||
| ignore_errors: true | ||
|
|
||
| - name: waiting for switch to come back | ||
| local_action: | ||
| wait_for host={{ remote_dut }} | ||
| port=22 | ||
| state=started | ||
| delay=30 | ||
| timeout=300 | ||
| become: false | ||
| changed_when: false | ||
| when: deploy is defined and deploy|bool == true | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,34 @@ | ||
| --- | ||
| #starlab (str) group variables | ||
| # file: group_vars/str.yml | ||
| #testlab (lab) group variables | ||
| # file: group_vars/lab.yml | ||
|
|
||
| # ntp variables | ||
| ntp_servers: ['10.0.0.1', '10.0.0.2'] | ||
|
|
||
| # syslog variables | ||
| syslog_servers: ['10.0.0.5', '10.0.0.6'] | ||
| # | ||
|
|
||
| # dns variables | ||
| dns_servers: ['10.0.0.5', '10.0.0.6'] | ||
|
|
||
| # forced_mgmt_routes | ||
| forced_mgmt_routes: ['10.0.0.100/31', '10.250.0.8', '10.255.0.0/28'] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure here: It should be '10.250.0.8' (without prefix), or '10.250.0.8/32'
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checked with current graph format, no /32 |
||
|
|
||
| # ErspanDestinationIpv4 | ||
| erspan_dest: ['10.0.0.7'] | ||
|
|
||
| radius_servers: [] | ||
|
|
||
| tacacs_servers: ['10.0.0.9', '10.0.0.8'] | ||
|
|
||
| # tacacs grous | ||
| tacacs_group: 'testlab' | ||
|
|
||
| # snmp servers | ||
| snmp_servers: ['10.0.0.9'] | ||
|
|
||
| # dhcp replay servers | ||
| dhcp_servers: ['10.0.0.1'] | ||
| # | ||
| # snmp variables | ||
| snmp_rocommunity: public | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| #!/usr/bin/env python | ||
|
|
||
| import re | ||
| import os | ||
| import traceback | ||
| import subprocess | ||
| from operator import itemgetter | ||
| from itertools import groupby | ||
| from collections import defaultdict | ||
|
|
||
| DOCUMENTATION = ''' | ||
| module: port_alias.py | ||
| Ansible_version_added: 2.0.0.2 | ||
| short_description: Find SONiC device port alias mapping if there is alias mapping | ||
| Description: | ||
| Minigraph file is using SONiC deivce alias to describe the interface name, it's vendor and and hardware platform dependent | ||
| This module try to find the correct port_config.ini for the hwsku and return Ansible ansible_facts.port_alias | ||
| The definition of this mapping is specified in http://github.com/azure/sonic-buildimage/device | ||
| docker-sonic-mgmt will gather and include the information from sonic-buildimage | ||
| Input: | ||
| hwsku | ||
|
|
||
| Return Ansible_facts: | ||
| port_alias: SONiC interface name mapping to actual vendor specified name | ||
|
|
||
| ''' | ||
|
|
||
| EXAMPLES = ''' | ||
| - name: get hardware interface alias name | ||
| port_alias: hwsku='ACS-MSN2700' | ||
| ''' | ||
|
|
||
| ### TODO: use sonic config sonic-cfggen to replace this port_alias module ############### | ||
| ### 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' | ||
|
|
||
| class SonicPortmap(): | ||
|
||
| """ | ||
| Retrieve SONiC device interface port alias mapping | ||
|
|
||
| """ | ||
| def __init__(self, hwsku): | ||
| self.filename = '' | ||
| self.hwsku = hwsku | ||
| self.portmap = dict() | ||
| return | ||
|
|
||
| def findfile(self): | ||
| for (rootdir, dirnames, filenames) in os.walk(FILE_PATH): | ||
| if self.hwsku in rootdir and len(dirnames) == 0 and PORTMAP_FILE in filenames: | ||
| self.filename = rootdir+'/'+PORTMAP_FILE | ||
|
|
||
| def get_portmap(self): | ||
| self.findfile() | ||
| if self.filename == '': | ||
| 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() | ||
| self.portmap['mapping'] = dict() | ||
| for line in lines: | ||
| if 'Ethernet' in line: | ||
| mapping = line.split() | ||
| if len(mapping) < 3: | ||
| self.portmap['alias'] = False | ||
|
||
| self.portmap['mapping'] = {} | ||
| return | ||
| else: | ||
| self.portmap['alias'] = True | ||
| self.portmap['mapping'][mapping[0]] = mapping[2] | ||
|
||
| return | ||
|
|
||
| def main(): | ||
| module = AnsibleModule( | ||
| argument_spec=dict( | ||
| hwsku=dict(required=True, type='str') | ||
| ), | ||
| supports_check_mode=False | ||
| ) | ||
| m_args = module.params | ||
| try: | ||
| allmap = SonicPortmap(m_args['hwsku']) | ||
| allmap.get_portmap() | ||
| module.exit_json(ansible_facts={'port_alias': allmap.portmap}) | ||
| except (IOError, OSError): | ||
| module.fail_json(msg=allmap.portmap) | ||
| except Exception: | ||
| module.fail_json(msg=allmap.portmap) | ||
|
|
||
| def debugmain(): | ||
| allmap = SonicPortmap('Arista-7050-QX32') | ||
| allmap.get_portmap() | ||
| print allmap.portmap | ||
|
|
||
| from ansible.module_utils.basic import * | ||
| if __name__ == "__main__": | ||
| #debugmain() | ||
| main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VM_base -> vm_base