[cfg engine] Separate portconfig.py as individual module for port_config.ini parsing (#1072)

Move port_config.ini related parsing code out of minigraph.py and create an independent portconfig.py.
Add support to multiple optional fields according to Porting Guide
This commit is contained in:
Taoyu Li 2017-10-24 10:56:09 -07:00 committed by GitHub
parent f073d8c654
commit 8b8b8a130f
5 changed files with 64 additions and 58 deletions

View File

@ -12,27 +12,13 @@ from collections import defaultdict
from lxml import etree as ET
from lxml.etree import QName
DOCUMENTATION = '''
---
module: minigraph_facts
from portconfig import get_port_config
"""minigraph.py
version_added: "1.9"
author: Guohan Lu (gulv@microsoft.com)
short_description: Retrive minigraph facts for a device.
description:
- Retrieve minigraph facts for a device, the facts will be
inserted to the ansible_facts key.
options:
host:
description:
- Set to target snmp server (normally {{inventory_hostname}})
required: true
'''
EXAMPLES = '''
# Gather minigraph facts
- name: Gathering minigraph facts about the device
minigraph_facts: host={{ hostname }}
'''
short_description: Parse minigraph xml file and device description xml file
"""
ns = "Microsoft.Search.Autopilot.Evolution"
ns1 = "http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"
@ -319,40 +305,6 @@ def parse_deviceinfo(meta, hwsku):
ethernet_interfaces[port_alias_map.get(alias, alias)] = speed
return ethernet_interfaces
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)
port_config_candidates.append('/usr/share/sonic/hwsku/port_config.ini')
if platform != None:
port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, 'port_config.ini'))
port_config_candidates.append(os.path.join('/usr/share/sonic/platform', hwsku, 'port_config.ini'))
port_config_candidates.append(os.path.join('/usr/share/sonic', hwsku, 'port_config.ini'))
port_config = None
for candidate in port_config_candidates:
if os.path.isfile(candidate):
port_config = candidate
break
if port_config == None:
return None
ports = {}
with open(port_config) as data:
for line in data:
if line.startswith('#'):
continue
tokens = line.split()
if len(tokens) < 2:
continue
name = tokens[0].strip()
if len(tokens) == 2:
alias = name
else:
alias = tokens[2].strip()
ports[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()
mini_graph_path = filename
@ -389,8 +341,8 @@ def parse_xml(filename, platform=None, port_config_file=None):
if child.tag == str(hostname_qn):
hostname = child.text
ports = parse_port_config(hwsku, platform, port_config_file)
(ports, alias_map) = get_port_config(hwsku, platform, port_config_file)
port_alias_map.update(alias_map)
for child in root:
if child.tag == str(QName(ns, "DpgDec")):
(intfs, lo_intfs, mgmt_intf, vlans, pcs, acls) = parse_dpg(child, hostname)

View File

@ -0,0 +1,54 @@
#!/usr/bin/env python
import os
import sys
def get_port_config_file_name(hwsku=None, platform=None):
port_config_candidates = []
port_config_candidates.append('/usr/share/sonic/hwsku/port_config.ini')
if hwsku:
if platform:
port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, 'port_config.ini'))
port_config_candidates.append(os.path.join('/usr/share/sonic/platform', hwsku, 'port_config.ini'))
port_config_candidates.append(os.path.join('/usr/share/sonic', hwsku, 'port_config.ini'))
for candidate in port_config_candidates:
if os.path.isfile(candidate):
return candidate
return None
def get_port_config(hwsku=None, platform=None, port_config_file=None):
if not port_config_file:
port_config_file = get_port_config_file_name(hwsku, platform)
if not port_config_file:
return ({}, {})
return parse_port_config_file(port_config_file)
def parse_port_config_file(port_config_file):
ports = {}
port_alias_map = {}
# Default column definition
titles = ['name', 'lanes', 'alias', 'index']
with open(port_config_file) as data:
for line in data:
if line.startswith('#'):
if "name" in line:
titles = line.strip('#').split()
continue;
tokens = line.split()
if len(tokens) < 2:
continue
name_index = titles.index('name')
name = tokens[name_index]
data = {}
for i, item in enumerate(tokens):
if i == name_index:
continue
data[titles[i]] = item
data.setdefault('alias', name)
ports[name] = data
port_alias_map[data['alias']] = name
return (ports, port_alias_map)

View File

@ -15,7 +15,7 @@ setup(name='sonic-config-engine',
author='Taoyu Li',
author_email='taoyl@microsoft.com',
url='https://github.com/Azure/sonic-buildimage',
py_modules=['minigraph', 'openconfig_acl', 'sonic_platform'],
py_modules=['portconfig', 'minigraph', 'openconfig_acl', 'sonic_platform'],
scripts=['sonic-cfggen', 'translate_acl'],
install_requires=['lxml', 'jinja2', 'netaddr', 'ipaddr', 'pyyaml', 'pyangbind'],
test_suite='setup.get_test_suite',

View File

@ -2,7 +2,7 @@
{
"ACL_TABLE:EVERFLOW":{
"policy_desc":"everflow",
"ports":"Ethernet24,Ethernet40,Ethernet20,Ethernet44,Ethernet48,Ethernet28,Ethernet96,Ethernet92,Ethernet76,Ethernet116,Ethernet72,Ethernet112,Ethernet52,Ethernet108,Ethernet56,Ethernet32,Ethernet16,Ethernet36,Ethernet12,Ethernet120,Ethernet8,Ethernet4,Ethernet0,Ethernet124,Ethernet68,Ethernet84,Ethernet100,Ethernet80,Ethernet60,Ethernet104,Ethernet64,Ethernet88",
"ports":"Ethernet24,Ethernet40,Ethernet20,Ethernet44,Ethernet48,Ethernet28,Ethernet96,Ethernet92,Ethernet76,Ethernet116,Ethernet72,Ethernet112,Ethernet52,Ethernet80,Ethernet56,Ethernet32,Ethernet16,Ethernet36,Ethernet12,Ethernet60,Ethernet8,Ethernet4,Ethernet0,Ethernet64,Ethernet68,Ethernet84,Ethernet88,Ethernet108,Ethernet120,Ethernet104,Ethernet124,Ethernet100",
"type":"mirror"
},
"OP":"SET"

View File

@ -128,4 +128,4 @@ class TestCfgGen(TestCase):
def test_minigraph_ethernet_interfaces(self):
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet8\']"'
output = self.run_script(argument)
self.assertEqual(output.strip(), "{'alias': 'fortyGigE0/8', 'speed': '40000'}")
self.assertEqual(output.strip(), "{'alias': 'fortyGigE0/8', 'lanes': '37,38,39,40', 'speed': '40000'}")