Skip to content
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

Store tables without yang #69

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion src/sonic-yang-mgmt/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def run (self):
include_package_data=True,
keywords='sonic_yang_mgmt',
name='sonic_yang_mgmt',
py_modules=['sonic_yang', '_sonic_yang_ext'],
py_modules=['sonic_yang', 'sonic_yang_ext'],
packages=find_packages(),
setup_requires=setup_requirements,
version='1.0',
Expand Down
8 changes: 5 additions & 3 deletions src/sonic-yang-mgmt/sonic_yang.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from json import dump
from glob import glob
from _sonic_yang_ext import sonic_yang_ext_mixin
from sonic_yang_ext import sonic_yang_ext_mixin

"""
Yang schema and data tree python APIs based on libyang python
Expand Down Expand Up @@ -34,6 +34,8 @@ def __init__(self, yang_dir, debug=False):
self.xlateJson = dict()
# reverse translation from yang JSON, == config db json
self.revXlateJson = dict()
# below dict store the input config tables which have no YANG models
self.tablesWithOutYang = dict()

try:
self.ctx = ly.Context(yang_dir)
Expand Down Expand Up @@ -368,7 +370,7 @@ def find_data_node_schema_xpath(self, data_xpath):
return path

"""
add_node(): add a node to Yang schema or data tree
add_data_node(): add a node to Yang schema or data tree
input: xpath and value of the node to be added
returns: Exception if failed
"""
Expand All @@ -378,7 +380,7 @@ def add_data_node(self, data_xpath, value):
#check if the node added to the data tree
self.find_data_node(data_xpath)
except Exception as e:
print("add_node(): Failed to add data node for xpath: " + str(data_xpath))
print("add_data_node(): Failed to add data node for xpath: " + str(data_xpath))
self.fail(e)

"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This script is used as extension of sonic_yang class. It has methods of
# class sonic_yang. A separate file is used to avoid a single large file.

from __future__ import print_function
import yang as ly
import re
import syslog
Expand Down Expand Up @@ -115,16 +116,23 @@ def get_module_TLC_container(self, table):
"""
Crop config as per yang models,
This Function crops from config only those TABLEs, for which yang models is
provided.
provided. The Tables without YANG models are stored in
self.tablesWithOutYangModels.
"""
def cropConfigDB(self, croppedFile=None, allowExtraTables=True):
def cropConfigDB(self, croppedFile=None):

for table in self.jIn.keys():
if table not in self.confDbYangMap:
if allowExtraTables:
del self.jIn[table]
else:
raise(Exception("No Yang Model Exist for {}".format(table)))
# store in tablesWithOutYang
self.tablesWithOutYang[table] = self.jIn[table]
del self.jIn[table]

if len(self.tablesWithOutYang):
print("Note: Below table(s) have no YANG models:")
self.sysLog(msg="Extra Tables in Config {}".format(self.tablesWithOutYang.keys))
for table in self.tablesWithOutYang.keys():
print(unicode(table), end=", ")
print()

if croppedFile:
with open(croppedFile, 'w') as f:
Expand Down Expand Up @@ -581,14 +589,15 @@ def findXpathList(self, xpath, list, keys):
input: data
returns: True - success False - failed
"""
def load_data(self, configdbJson, allowExtraTables=True):
def load_data(self, configdbJson):

try:
self.jIn = configdbJson
# reset xlate
# reset xlate and tablesWithOutYang
self.xlateJson = dict()
self.tablesWithOutYang = dict()
# self.jIn will be cropped
self.cropConfigDB(allowExtraTables=allowExtraTables)
self.cropConfigDB()
# xlated result will be in self.xlateJson
self.xlateConfigDB()
#print(self.xlateJson)
Expand Down
50 changes: 43 additions & 7 deletions src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,20 +261,40 @@ def test_get_leafref_type_schema(self, yang_s, data):
data_type = yang_s.get_leafref_type_schema(xpath)
assert expected_type == data_type

def test_xlate_rev_xlate(self):
"""
This is helper function to load YANG models for tests cases, which works
on Real SONiC Yang models. Mainly tests for translation and reverse
translation.
"""
@pytest.fixture(autouse=True, scope='class')
def sonic_yang_data(self):
sonic_yang_dir = "/sonic/src/sonic-yang-models/yang-models/"
sonic_yang_test_file = "/sonic/src/sonic-yang-models/tests/yang_model_tests/yangTest.json"

syc = sy.sonic_yang(sonic_yang_dir)
syc.loadYangModel()

sonic_yang_data = dict()
sonic_yang_data['yang_dir'] = sonic_yang_dir
sonic_yang_data['test_file'] = sonic_yang_test_file
sonic_yang_data['syc'] = syc

return sonic_yang_data

def test_xlate_rev_xlate(self, sonic_yang_data):
# In this test, xlation and revXlation is tested with latest Sonic
# YANG model.
test_file = sonic_yang_data['test_file']
syc = sonic_yang_data['syc']

yang_dir = "/sonic/src/sonic-yang-models/yang-models/"
yang_test_file = "/sonic/src/sonic-yang-models/tests/yang_model_tests/yangTest.json"
jIn = self.readIjsonInput(yang_test_file, 'SAMPLE_CONFIG_DB_JSON')
# load yang models
syc = sy.sonic_yang(yang_dir)
jIn = self.readIjsonInput(test_file, 'SAMPLE_CONFIG_DB_JSON')

syc.loadYangModel()
syc.load_data(json.loads(jIn))

syc.load_data(json.loads(jIn))

# TODO: Make sure no extra table is loaded
praveen-li marked this conversation as resolved.
Show resolved Hide resolved

syc.get_data()

if syc.jIn and syc.jIn == syc.revXlateJson:
Expand All @@ -286,5 +306,21 @@ def test_xlate_rev_xlate(self):

return

def test_table_with_no_yang(self, sonic_yang_data):
# in this test, tables with no YANG models must be stored seperately
# by this library.
test_file = sonic_yang_data['test_file']
syc = sonic_yang_data['syc']

jIn = self.readIjsonInput(test_file, 'SAMPLE_CONFIG_DB_JSON_1')

syc.load_data(json.loads(jIn))

ty = syc.tablesWithOutYang

assert (len(ty) and "UNKNOWN_TABLE" in ty) == True

return

def teardown_class(self):
pass
78 changes: 72 additions & 6 deletions src/sonic-yang-models/tests/yang_model_tests/yangTest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1255,10 +1255,76 @@
"family": "IPv4"
}
},
"CRM": {
"Config": {
"polling_interval": "0"
}
}
}
"BREAKOUT_CFG": {
"Ethernet0": {
"brkout_mode": "1x100G[40G]"
},
"Ethernet4": {
"brkout_mode": "4x25G"
},
"Ethernet8": {
"brkout_mode": "1x100G[40G]"
}
},
"VERSIONS": {
"DATABASE": {
"VERSION": "version_1_0_3"
}
},
"FLEX_COUNTER_TABLE": {
"PFCWD": {
"FLEX_COUNTER_STATUS": "enable"
},
"PG_WATERMARK": {
"FLEX_COUNTER_STATUS": "enable"
},
"PORT": {
"FLEX_COUNTER_STATUS": "enable"
},
"QUEUE": {
"FLEX_COUNTER_STATUS": "enable"
},
"QUEUE_WATERMARK": {
"FLEX_COUNTER_STATUS": "enable"
}
},
"CRM": {
"Config": {
"acl_counter_high_threshold": "85",
"acl_counter_low_threshold": "70",
"acl_counter_threshold_type": "percentage",
"polling_interval": "0"
}
}
},
"SAMPLE_CONFIG_DB_JSON_1": {
"FLEX_COUNTER_TABLE": {
"PFCWD": {
"FLEX_COUNTER_STATUS": "enable"
},
"PG_WATERMARK": {
"FLEX_COUNTER_STATUS": "enable"
},
"PORT": {
"FLEX_COUNTER_STATUS": "enable"
},
"QUEUE": {
"FLEX_COUNTER_STATUS": "enable"
},
"QUEUE_WATERMARK": {
"FLEX_COUNTER_STATUS": "enable"
}
},
"CRM": {
"Config": {
"acl_counter_high_threshold": "85",
"acl_counter_low_threshold": "70",
"acl_counter_threshold_type": "percentage",
"polling_interval": "0"
}
},
"UNKNOWN_TABLE": {
"Error": "This Table is for testing, This Table does not have YANG models."
}
}
}