Skip to content

Commit

Permalink
[GCU] Turning port admin down before some critical port changes (soni…
Browse files Browse the repository at this point in the history
…c-net#1998)

#### What I did
Fixes sonic-net#1930 

Issue can be summarized into these 2 case:
* A patch can contain an operation to turn port `admin up` -- do at the end
* A patch that modifies config that needs the port to be down -- start by bringing the port down then do the update then bring it back up

#### How I did it
The configs that need the port to be down, we will call them `critical-port` configs.

* Added a move validator to validate `critical-port` configs, which does the following
  * If a port is up, make sure the move does not make changes to related `critical-port` configs
  * If the move is turning a port up, make sure there is no `critical-port` config are still left in the patch

* Added a move extender to `critical-port` changes:
  * If a port is up, bring down if there are critical-port changes
  * If the move is turning a port up, flip it to down if there are still `critical-port` configs left. In other words, do not turn the port back up until all `critical-port` changes are in done.

#### How to verify it
* Added `AddRack` unit-test to `tests/generic_config_updater/files/patch_sorter_test_success.json`
* Other unit-tests

#### Previous command output (if the output of a command-line utility has changed)
Check issue sonic-net#1930 for old sorting order

#### New command output (if the output of a command-line utility has changed)
Check  `AddRack` unit-test to `tests/generic_config_updater/files/patch_sorter_test_success.json` for new sorting-order
  • Loading branch information
ghooo authored Feb 18, 2022
1 parent 15670bf commit 1723206
Show file tree
Hide file tree
Showing 5 changed files with 3,162 additions and 43 deletions.
14 changes: 11 additions & 3 deletions generic_config_updater/gu_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,13 @@ def create_path(self, tokens):
return JsonPointer.from_parts(tokens).path

def has_path(self, doc, path):
return JsonPointer(path).get(doc, default=None) is not None
return self.get_from_path(doc, path) is not None

def get_from_path(self, doc, path):
return JsonPointer(path).get(doc, default=None)

def is_config_different(self, path, current, target):
return self.get_from_path(current, path) != self.get_from_path(target, path)

def get_xpath_tokens(self, xpath):
"""
Expand Down Expand Up @@ -548,7 +554,8 @@ def _get_xpath_tokens_from_leaf(self, model, token_index, path_tokens, config):
# Source: Check examples in https://netopeer.liberouter.org/doc/libyang/master/html/howto_x_path.html
return [f"{token}[.='{value}']"]

raise ValueError("Token not found")
raise ValueError(f"Path token not found.\n model: {model}\n token_index: {token_index}\n " + \
f"path_tokens: {path_tokens}\n config: {config}")

def _extractKey(self, tableKey, keys):
keyList = keys.split()
Expand Down Expand Up @@ -712,7 +719,8 @@ def _get_path_tokens_from_leaf(self, model, token_index, xpath_tokens, config):
list_idx = list_config.index(leaf_list_value)
return [leaf_list_name, list_idx]

raise Exception("no leaf")
raise ValueError(f"Xpath token not found.\n model: {model}\n token_index: {token_index}\n " + \
f"xpath_tokens: {xpath_tokens}\n config: {config}")

def _extract_key_dict(self, list_token):
# Example: VLAN_MEMBER_LIST[name='Vlan1000'][port='Ethernet8']
Expand Down
Loading

0 comments on commit 1723206

Please sign in to comment.