[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:
parent
f073d8c654
commit
8b8b8a130f
@ -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)
|
||||
|
54
src/sonic-config-engine/portconfig.py
Normal file
54
src/sonic-config-engine/portconfig.py
Normal 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)
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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"
|
||||
|
@ -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'}")
|
||||
|
Reference in New Issue
Block a user