-
Notifications
You must be signed in to change notification settings - Fork 812
[GCU] Loading yang-models only once #1981
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 1 commit
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 |
|---|---|---|
|
|
@@ -43,6 +43,7 @@ def __eq__(self, other): | |
| class ConfigWrapper: | ||
| def __init__(self, yang_dir = YANG_DIR): | ||
| self.yang_dir = YANG_DIR | ||
| self.sonic_yang_with_loaded_models = None | ||
|
|
||
| def get_config_db_as_json(self): | ||
| text = self._get_config_db_as_text() | ||
|
|
@@ -63,8 +64,7 @@ def get_sonic_yang_as_json(self): | |
| return self.convert_config_db_to_sonic_yang(config_db_json) | ||
|
|
||
| def convert_config_db_to_sonic_yang(self, config_db_as_json): | ||
| sy = sonic_yang.SonicYang(self.yang_dir) | ||
| sy.loadYangModel() | ||
| sy = self.create_sonic_yang_with_loaded_models() | ||
|
|
||
| # Crop config_db tables that do not have sonic yang models | ||
| cropped_config_db_as_json = self.crop_tables_without_yang(config_db_as_json) | ||
|
|
@@ -76,8 +76,7 @@ def convert_config_db_to_sonic_yang(self, config_db_as_json): | |
| return sonic_yang_as_json | ||
|
|
||
| def convert_sonic_yang_to_config_db(self, sonic_yang_as_json): | ||
| sy = sonic_yang.SonicYang(self.yang_dir) | ||
| sy.loadYangModel() | ||
| sy = self.create_sonic_yang_with_loaded_models() | ||
|
|
||
| # replace container of the format 'module:table' with just 'table' | ||
| new_sonic_yang_json = {} | ||
|
|
@@ -100,8 +99,7 @@ def convert_sonic_yang_to_config_db(self, sonic_yang_as_json): | |
| def validate_sonic_yang_config(self, sonic_yang_as_json): | ||
| config_db_as_json = self.convert_sonic_yang_to_config_db(sonic_yang_as_json) | ||
|
|
||
| sy = sonic_yang.SonicYang(self.yang_dir) | ||
| sy.loadYangModel() | ||
| sy = self.create_sonic_yang_with_loaded_models() | ||
|
|
||
| try: | ||
| sy.loadData(config_db_as_json) | ||
|
|
@@ -112,8 +110,7 @@ def validate_sonic_yang_config(self, sonic_yang_as_json): | |
| return False | ||
|
|
||
| def validate_config_db_config(self, config_db_as_json): | ||
| sy = sonic_yang.SonicYang(self.yang_dir) | ||
| sy.loadYangModel() | ||
| sy = self.create_sonic_yang_with_loaded_models() | ||
|
|
||
| try: | ||
| tmp_config_db_as_json = copy.deepcopy(config_db_as_json) | ||
|
|
@@ -126,8 +123,7 @@ def validate_config_db_config(self, config_db_as_json): | |
| return False | ||
|
|
||
| def crop_tables_without_yang(self, config_db_as_json): | ||
| sy = sonic_yang.SonicYang(self.yang_dir) | ||
| sy.loadYangModel() | ||
| sy = self.create_sonic_yang_with_loaded_models() | ||
|
|
||
| sy.jIn = copy.deepcopy(config_db_as_json) | ||
|
|
||
|
|
@@ -151,6 +147,24 @@ def remove_empty_tables(self, config): | |
| config_with_non_empty_tables[table] = copy.deepcopy(config[table]) | ||
| return config_with_non_empty_tables | ||
|
|
||
| def create_sonic_yang_with_loaded_models(self): | ||
| # sonic_yang_with_loaded_models will only be initialized once the first time this method is called | ||
| if self.sonic_yang_with_loaded_models is None: | ||
| loaded_models_sy = sonic_yang.SonicYang(self.yang_dir) | ||
| loaded_models_sy.loadYangModel() | ||
| self.sonic_yang_with_loaded_models = loaded_models_sy | ||
|
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. Could you add comment which line spends most of the time? #Closed
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. ok
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. updated |
||
|
|
||
| # create a copy of sonic_yang_with_loaded_models, only copy the loaded yang models related properties | ||
|
||
| # TODO: move to sonic-yang-mgmt directly | ||
| sy = sonic_yang.SonicYang(self.yang_dir) | ||
| sy.confDbYangMap = self.sonic_yang_with_loaded_models.confDbYangMap | ||
| sy.ctx = self.sonic_yang_with_loaded_models.ctx | ||
| sy.preProcessedYang = self.sonic_yang_with_loaded_models.preProcessedYang | ||
| sy.yangFiles = self.sonic_yang_with_loaded_models.yangFiles | ||
| sy.yJson = self.sonic_yang_with_loaded_models.yJson | ||
|
|
||
| return sy | ||
|
|
||
| class DryRunConfigWrapper(ConfigWrapper): | ||
| # This class will simulate all read/write operations to ConfigDB on a virtual storage unit. | ||
| def __init__(self, initial_imitated_config_db = None): | ||
|
|
@@ -176,7 +190,7 @@ def _init_imitated_config_db_if_none(self): | |
| class PatchWrapper: | ||
| def __init__(self, config_wrapper=None): | ||
| self.config_wrapper = config_wrapper if config_wrapper is not None else ConfigWrapper() | ||
| self.path_addressing = PathAddressing() | ||
| self.path_addressing = PathAddressing(self.config_wrapper) | ||
|
|
||
| def validate_config_db_patch_has_yang_models(self, patch): | ||
| config_db = {} | ||
|
|
@@ -256,6 +270,10 @@ class PathAddressing: | |
| """ | ||
| PATH_SEPARATOR = "/" | ||
| XPATH_SEPARATOR = "/" | ||
|
|
||
| def __init__(self, config_wrapper=None): | ||
| self.config_wrapper = config_wrapper | ||
|
|
||
| def get_path_tokens(self, path): | ||
| return JsonPointer(path).parts | ||
|
|
||
|
|
@@ -391,8 +409,7 @@ def find_ref_paths(self, path, config): | |
| return self._find_leafref_paths(path, config) | ||
|
|
||
| def _find_leafref_paths(self, path, config): | ||
| sy = sonic_yang.SonicYang(YANG_DIR) | ||
| sy.loadYangModel() | ||
| sy = self.config_wrapper.create_sonic_yang_with_loaded_models() | ||
|
|
||
| sy.loadData(config) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -258,6 +258,35 @@ def test_remove_empty_tables__multiple_empty_tables__returns_config_without_empt | |
| # Assert | ||
| self.assertDictEqual({"any_table": {"key": "value"}}, actual) | ||
|
|
||
| def test_create_sonic_yang_with_loaded_models__creates_new_sonic_yang_every_call(self): | ||
|
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.
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. updated pr description with profiling data for a specific case instead of all cases in |
||
| # check yang models fields are the same, non-yang model fields are different | ||
| def check(sy1, sy2): | ||
| # instances are different | ||
| self.assertNotEqual(sy1, sy2) | ||
|
|
||
| # yang models fields are same | ||
| self.assertTrue(sy1.confDbYangMap is sy2.confDbYangMap) | ||
| self.assertTrue(sy1.ctx is sy2.ctx) | ||
| self.assertTrue(sy1.preProcessedYang is sy2.preProcessedYang) | ||
| self.assertTrue(sy1.yangFiles is sy2.yangFiles) | ||
| self.assertTrue(sy1.yJson is sy2.yJson) | ||
|
|
||
| # non yang models fields are different | ||
| self.assertFalse(sy1.jIn is sy2.jIn) | ||
| self.assertFalse(sy1.xlateJson is sy2.xlateJson) | ||
| self.assertFalse(sy1.revXlateJson is sy2.revXlateJson) | ||
| self.assertFalse(sy1.tablesWithOutYang is sy2.tablesWithOutYang) | ||
|
|
||
| config_wrapper = gu_common.ConfigWrapper() | ||
| self.assertTrue(config_wrapper.sonic_yang_with_loaded_models is None) | ||
|
|
||
| sy1 = config_wrapper.create_sonic_yang_with_loaded_models() | ||
| sy2 = config_wrapper.create_sonic_yang_with_loaded_models() | ||
|
|
||
| check(sy1, sy2) | ||
| check(sy1, config_wrapper.sonic_yang_with_loaded_models) | ||
| check(sy2, config_wrapper.sonic_yang_with_loaded_models) | ||
|
|
||
| class TestPatchWrapper(unittest.TestCase): | ||
| def setUp(self): | ||
| self.config_wrapper_mock = gu_common.ConfigWrapper() | ||
|
|
@@ -443,7 +472,7 @@ def __assert_same_patch(self, config_db_patch, sonic_yang_patch, config_wrapper, | |
|
|
||
| class TestPathAddressing(unittest.TestCase): | ||
| def setUp(self): | ||
| self.path_addressing = gu_common.PathAddressing() | ||
| self.path_addressing = gu_common.PathAddressing(gu_common.ConfigWrapper()) | ||
| self.sy_only_models = sonic_yang.SonicYang(gu_common.YANG_DIR) | ||
| self.sy_only_models.loadYangModel() | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.
Is
sonic_yang_modelgood enough? #ClosedUh oh!
There was an error while loading. Please reload this page.
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.
I don't think so.
sonic_yang_modelrefers to the model but here we are referring toSonicYangobject check codeThis variable will hold an instance of
SonicYangbut with the models loaded hence the name