Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions ansible/config_sonic_basedon_testbed.yml
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]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VM_base -> vm_base

#
# 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:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can assume /usr/share/sonic/device is there in the container.

path: /usr/share/sonic/device
register: p
connection: local

#### TODO: build the package into sonic-mgmt docker and remove this block of code ####
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sonic-device-data is in sonic-mgmt docker now. you can remove this block of code now.

- 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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this block as well.


- 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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use lineinfile module to replace the enable=true line to enable=false line.


- 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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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
25 changes: 22 additions & 3 deletions ansible/group_vars/lab/lab.yml
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']
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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
Expand Down
13 changes: 9 additions & 4 deletions ansible/lab
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
[sonic_latest]
str-msn2700-01 ansible_host=10.251.0.188 sonic_version=v2
[sonic_mlnx_40]
str-msn2700-01 ansible_host=10.251.0.188

[sonic_mlnx_40:vars]
hwsku="ACS-MSN2700"
iface_speed='40000'
mgmt_subnet_mask_length="24"

[sonic:children]
sonic_latest
sonic_mlnx_40

[ptf]
ptf_ptf1 ansible_host=10.255.0.188 ansible_ssh_user=root ansible_ssh_pass=root
ptf_vms1-1 ansible_host=10.255.0.178 ansible_ssh_user=root ansible_ssh_pass=root

[str:children]
[lab:children]
sonic
fanout

Expand Down
98 changes: 98 additions & 0 deletions ansible/library/port_alias.py
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():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SonicPortAliasMap

"""
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line is not used, remove.

self.portmap['mapping'] = {}
return
else:
self.portmap['alias'] = True
self.portmap['mapping'][mapping[0]] = mapping[2]
Copy link
Copy Markdown
Contributor

@lguohan lguohan Jul 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the portmap is index -> alias map. index is the row index in the port_config.ini. let's have the assumption that the ports in port_config.ini are from index 0 to maximum.

then if there is alias, the port_alias[index] = alias, else port_alias[index] = name.

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()
Loading