Skip to content

Commit cdced93

Browse files
xincunli-sonicarfeigin
authored andcommitted
Add Checkpoint and Rollback for Multi ASIC. (sonic-net#3299)
#### What I did Add `config` `checkpoint`, `rollback`, `replace`, `list-checkpoints`, `delete-checkpoint` support of Multi ASIC #### How I did it Add namespace for each of operation to support Multi ASIC. #### How to verify it 1. Single ASIC ```admin@str2-msn2700-spy-1:~/gcu$ sudo config checkpoint 20240522-xincun Config Rollbacker: Config checkpoint starting. Config Rollbacker: Checkpoint name: 20240522-xincun. Config Rollbacker: Getting current config db. Config Rollbacker: Getting checkpoint full-path. Config Rollbacker: Ensuring checkpoint directory exist. Config Rollbacker: Saving config db content to /etc/sonic/checkpoints/20240522-xincun.cp.json. Config Rollbacker: Config checkpoint completed. Checkpoint created successfully. admin@str2-msn2700-spy-1:~/gcu$ sudo config list-checkpoints [ "20240522-xincun" ] admin@str2-msn2700-spy-1:~/gcu$ sudo config rollback 20240522-xincun Config Rollbacker: Config rollbacking starting. Config Rollbacker: Checkpoint name: 20240522-xincun. Config Rollbacker: Verifying '20240522-xincun' exists. Config Rollbacker: Loading checkpoint into memory. Config Rollbacker: Replacing config using 'Config Replacer'. Config Replacer: Config replacement starting. Config Replacer: Target config length: 71214. Config Replacer: Getting current config db. Config Replacer: Generating patch between target config and current config db. Config Replacer: Applying patch using 'Patch Applier'. Patch Applier: localhost: Patch application starting. Patch Applier: localhost: Patch: [] Patch Applier: localhost getting current config db. Patch Applier: localhost: simulating the target full config after applying the patch. Patch Applier: localhost: validating all JsonPatch operations are permitted on the specified fields Patch Applier: localhost: validating target config does not have empty tables, since they do not show up in ConfigDb. Patch Applier: localhost: sorting patch updates. Patch Applier: The localhost patch was converted into 0 changes. Patch Applier: localhost: applying 0 changes in order. Patch Applier: localhost: verifying patch updates are reflected on ConfigDB. Patch Applier: localhost patch application completed. Config Replacer: Verifying config replacement is reflected on ConfigDB. Config Replacer: Config replacement completed. Config Rollbacker: Config rollbacking completed. Config rolled back successfully. admin@str2-msn2700-spy-1:~/gcu$ sudo config delete-checkpoint 20240522-xincun Config Rollbacker: Deleting checkpoint starting. Config Rollbacker: Checkpoint name: 20240522-xincun. Config Rollbacker: Checking checkpoint exists. Config Rollbacker: Deleting checkpoint. Config Rollbacker: Deleting checkpoint completed. Checkpoint deleted successfully. admin@str2-msn2700-spy-1:~/gcu$ sudo config list-checkpoints [] ``` 2. Multi ASIC ``` stli@str2-7250-2-lc01:~/gcu$ sudo config checkpoint 20240522-xincun MultiASICConfigRollbacker: Config checkpoint starting. MultiASICConfigRollbacker: Checkpoint name: 20240522-xincun. MultiASICConfigRollbacker: Getting current config db. MultiASICConfigRollbacker: Getting current asic0 config db. MultiASICConfigRollbacker: Getting current asic1 config db. MultiASICConfigRollbacker: Getting checkpoint full-path. MultiASICConfigRollbacker: Ensuring checkpoint directory exist. MultiASICConfigRollbacker: Saving config db content to /etc/sonic/checkpoints/20240522-xincun.cp.json. MultiASICConfigRollbacker: Config checkpoint completed. Checkpoint created successfully. stli@str2-7250-2-lc01:~/gcu$ sudo config list-checkpoints [ "20240522-xincun" ] stli@str2-7250-2-lc01:~/gcu$ sudo config rollback 20240522-xincun MultiASICConfigRollbacker: Config rollbacking starting. MultiASICConfigRollbacker: Checkpoint name: 20240522-xincun. MultiASICConfigRollbacker: Verifying '20240522-xincun' exists. MultiASICConfigRollbacker: Loading checkpoint '20240522-xincun' into memory. MultiASICConfigRollbacker: Replacing config '20240522-xincun' using 'Config Replacer'. Config Replacer: Config replacement starting. Config Replacer: Target config length: 38147. Config Replacer: Getting current config db. Config Replacer: Generating patch between target config and current config db. Config Replacer: Applying patch using 'Patch Applier'. Patch Applier: localhost: Patch application starting. Patch Applier: localhost: Patch: [] Patch Applier: localhost getting current config db. Patch Applier: localhost: simulating the target full config after applying the patch. Patch Applier: localhost: validating all JsonPatch operations are permitted on the specified fields Patch Applier: localhost: validating target config does not have empty tables, since they do not show up in ConfigDb. Patch Applier: localhost: sorting patch updates. Patch Applier: The localhost patch was converted into 0 changes. Patch Applier: localhost: applying 0 changes in order. Patch Applier: localhost: verifying patch updates are reflected on ConfigDB. Patch Applier: localhost patch application completed. Config Replacer: Verifying config replacement is reflected on ConfigDB. Config Replacer: Config replacement completed. Config Replacer: Config replacement starting. Config Replacer: Target config length: 97546. Config Replacer: Getting current config db. Config Replacer: Generating patch between target config and current config db. Config Replacer: Applying patch using 'Patch Applier'. Patch Applier: asic0: Patch application starting. Patch Applier: asic0: Patch: [] Patch Applier: asic0 getting current config db. Patch Applier: asic0: simulating the target full config after applying the patch. Patch Applier: asic0: validating all JsonPatch operations are permitted on the specified fields Patch Applier: asic0: validating target config does not have empty tables, since they do not show up in ConfigDb. Patch Applier: asic0: sorting patch updates. Patch Applier: The asic0 patch was converted into 0 changes. Patch Applier: asic0: applying 0 changes in order. Patch Applier: asic0: verifying patch updates are reflected on ConfigDB. Patch Applier: asic0 patch application completed. Config Replacer: Verifying config replacement is reflected on ConfigDB. Config Replacer: Config replacement completed. Config Replacer: Config replacement starting. Config Replacer: Target config length: 97713. Config Replacer: Getting current config db. Config Replacer: Generating patch between target config and current config db. Config Replacer: Applying patch using 'Patch Applier'. Patch Applier: asic1: Patch application starting. Patch Applier: asic1: Patch: [] Patch Applier: asic1 getting current config db. Patch Applier: asic1: simulating the target full config after applying the patch. Patch Applier: asic1: validating all JsonPatch operations are permitted on the specified fields Patch Applier: asic1: validating target config does not have empty tables, since they do not show up in ConfigDb. Patch Applier: asic1: sorting patch updates. Patch Applier: The asic1 patch was converted into 0 changes. Patch Applier: asic1: applying 0 changes in order. Patch Applier: asic1: verifying patch updates are reflected on ConfigDB. Patch Applier: asic1 patch application completed. Config Replacer: Verifying config replacement is reflected on ConfigDB. Config Replacer: Config replacement completed. MultiASICConfigRollbacker: Config rollbacking completed. Config rolled back successfully. stli@str2-7250-2-lc01:~/gcu$ sudo config delete-checkpoint 20240522-xincun MultiASICConfigRollbacker: Deleting checkpoint starting. MultiASICConfigRollbacker: Checkpoint name: 20240522-xincun. MultiASICConfigRollbacker: Checking checkpoint: 20240522-xincun exists. MultiASICConfigRollbacker: Deleting checkpoint: 20240522-xincun. MultiASICConfigRollbacker: Deleting checkpoint: 20240522-xincun completed. Checkpoint deleted successfully. stli@str2-7250-2-lc01:~/gcu$ sudo config list-checkpoints [] stli@str2-7250-2-lc01:~/gcu$ sudo config replace 20240522-xincun.cp.json Config Replacer: Config replacement starting. Config Replacer: Target config length: 38147. Config Replacer: Getting current config db. Config Replacer: Generating patch between target config and current config db. Config Replacer: Applying patch using 'Patch Applier'. Patch Applier: localhost: Patch application starting. Patch Applier: localhost: Patch: [] Patch Applier: localhost getting current config db. Patch Applier: localhost: simulating the target full config after applying the patch. Patch Applier: localhost: validating all JsonPatch operations are permitted on the specified fields Patch Applier: localhost: validating target config does not have empty tables, since they do not show up in ConfigDb. Patch Applier: localhost: sorting patch updates. Patch Applier: The localhost patch was converted into 0 changes. Patch Applier: localhost: applying 0 changes in order. Patch Applier: localhost: verifying patch updates are reflected on ConfigDB. Patch Applier: localhost patch application completed. Config Replacer: Verifying config replacement is reflected on ConfigDB. Config Replacer: Config replacement completed. Config Replacer: Config replacement starting. Config Replacer: Target config length: 97546. Config Replacer: Getting current config db. Config Replacer: Generating patch between target config and current config db. Config Replacer: Applying patch using 'Patch Applier'. Patch Applier: asic0: Patch application starting. Patch Applier: asic0: Patch: [] Patch Applier: asic0 getting current config db. Patch Applier: asic0: simulating the target full config after applying the patch. Patch Applier: asic0: validating all JsonPatch operations are permitted on the specified fields Patch Applier: asic0: validating target config does not have empty tables, since they do not show up in ConfigDb. Patch Applier: asic0: sorting patch updates. Patch Applier: The asic0 patch was converted into 0 changes. Patch Applier: asic0: applying 0 changes in order. Patch Applier: asic0: verifying patch updates are reflected on ConfigDB. Patch Applier: asic0 patch application completed. Config Replacer: Verifying config replacement is reflected on ConfigDB. Config Replacer: Config replacement completed. Config Replacer: Config replacement starting. Config Replacer: Target config length: 97713. Config Replacer: Getting current config db. Config Replacer: Generating patch between target config and current config db. Config Replacer: Applying patch using 'Patch Applier'. Patch Applier: asic1: Patch application starting. Patch Applier: asic1: Patch: [] Patch Applier: asic1 getting current config db. Patch Applier: asic1: simulating the target full config after applying the patch. Patch Applier: asic1: validating all JsonPatch operations are permitted on the specified fields Patch Applier: asic1: validating target config does not have empty tables, since they do not show up in ConfigDb. Patch Applier: asic1: sorting patch updates. Patch Applier: The asic1 patch was converted into 0 changes. Patch Applier: asic1: applying 0 changes in order. Patch Applier: asic1: verifying patch updates are reflected on ConfigDB. Patch Applier: asic1 patch application completed. Config Replacer: Verifying config replacement is reflected on ConfigDB. Config Replacer: Config replacement completed. Config replaced successfully. ```
1 parent 2d33c0b commit cdced93

10 files changed

+420
-132
lines changed

config/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@ def apply_patch_for_scope(scope_changes, results, config_format, verbose, dry_ru
11841184
scope_for_log = scope if scope else HOST_NAMESPACE
11851185
try:
11861186
# Call apply_patch with the ASIC-specific changes and predefined parameters
1187-
GenericUpdater(namespace=scope).apply_patch(jsonpatch.JsonPatch(changes),
1187+
GenericUpdater(scope=scope).apply_patch(jsonpatch.JsonPatch(changes),
11881188
config_format,
11891189
verbose,
11901190
dry_run,

generic_config_updater/change_applier.py

+14-18
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
print_to_console = False
1818

19+
1920
def set_verbose(verbose=False):
2021
global print_to_console, logger
2122

@@ -34,11 +35,12 @@ def log_error(m):
3435
logger.log(logger.LOG_PRIORITY_ERROR, m, print_to_console)
3536

3637

37-
def get_config_db(namespace=multi_asic.DEFAULT_NAMESPACE):
38-
config_db = ConfigDBConnector(use_unix_socket_path=True, namespace=namespace)
38+
def get_config_db(scope=multi_asic.DEFAULT_NAMESPACE):
39+
config_db = ConfigDBConnector(use_unix_socket_path=True, namespace=scope)
3940
config_db.connect()
4041
return config_db
4142

43+
4244
def set_config(config_db, tbl, key, data):
4345
config_db.set_entry(tbl, key, data)
4446

@@ -61,11 +63,9 @@ class DryRunChangeApplier:
6163
def __init__(self, config_wrapper):
6264
self.config_wrapper = config_wrapper
6365

64-
6566
def apply(self, change):
6667
self.config_wrapper.apply_change_to_config_db(change)
6768

68-
6969
def remove_backend_tables_from_config(self, data):
7070
return data
7171

@@ -74,9 +74,9 @@ class ChangeApplier:
7474

7575
updater_conf = None
7676

77-
def __init__(self, namespace=multi_asic.DEFAULT_NAMESPACE):
78-
self.namespace = namespace
79-
self.config_db = get_config_db(self.namespace)
77+
def __init__(self, scope=multi_asic.DEFAULT_NAMESPACE):
78+
self.scope = scope
79+
self.config_db = get_config_db(self.scope)
8080
self.backend_tables = [
8181
"BUFFER_PG",
8282
"BUFFER_PROFILE",
@@ -86,7 +86,6 @@ def __init__(self, namespace=multi_asic.DEFAULT_NAMESPACE):
8686
with open(UPDATER_CONF_FILE, "r") as s:
8787
ChangeApplier.updater_conf = json.load(s)
8888

89-
9089
def _invoke_cmd(self, cmd, old_cfg, upd_cfg, keys):
9190
# cmd is in the format as <package/module name>.<method name>
9291
#
@@ -98,7 +97,6 @@ def _invoke_cmd(self, cmd, old_cfg, upd_cfg, keys):
9897

9998
return method_to_call(old_cfg, upd_cfg, keys)
10099

101-
102100
def _services_validate(self, old_cfg, upd_cfg, keys):
103101
lst_svcs = set()
104102
lst_cmds = set()
@@ -124,7 +122,6 @@ def _services_validate(self, old_cfg, upd_cfg, keys):
124122
log_debug("service invoked: {}".format(cmd))
125123
return 0
126124

127-
128125
def _upd_data(self, tbl, run_tbl, upd_tbl, upd_keys):
129126
for key in set(run_tbl.keys()).union(set(upd_tbl.keys())):
130127
run_data = run_tbl.get(key, None)
@@ -135,20 +132,17 @@ def _upd_data(self, tbl, run_tbl, upd_tbl, upd_keys):
135132
upd_keys[tbl][key] = {}
136133
log_debug("Patch affected tbl={} key={}".format(tbl, key))
137134

138-
139135
def _report_mismatch(self, run_data, upd_data):
140136
log_error("run_data vs expected_data: {}".format(
141137
str(jsondiff.diff(run_data, upd_data))[0:40]))
142138

143-
144139
def apply(self, change):
145140
run_data = self._get_running_config()
146141
upd_data = prune_empty_table(change.apply(copy.deepcopy(run_data)))
147142
upd_keys = defaultdict(dict)
148143

149144
for tbl in sorted(set(run_data.keys()).union(set(upd_data.keys()))):
150-
self._upd_data(tbl, run_data.get(tbl, {}),
151-
upd_data.get(tbl, {}), upd_keys)
145+
self._upd_data(tbl, run_data.get(tbl, {}), upd_data.get(tbl, {}), upd_keys)
152146

153147
ret = self._services_validate(run_data, upd_data, upd_keys)
154148
if not ret:
@@ -168,9 +162,9 @@ def remove_backend_tables_from_config(self, data):
168162

169163
def _get_running_config(self):
170164
_, fname = tempfile.mkstemp(suffix="_changeApplier")
171-
172-
if self.namespace:
173-
cmd = ['sonic-cfggen', '-d', '--print-data', '-n', self.namespace]
165+
166+
if self.scope:
167+
cmd = ['sonic-cfggen', '-d', '--print-data', '-n', self.scope]
174168
else:
175169
cmd = ['sonic-cfggen', '-d', '--print-data']
176170

@@ -181,7 +175,9 @@ def _get_running_config(self):
181175
return_code = result.returncode
182176
if return_code:
183177
os.remove(fname)
184-
raise GenericConfigUpdaterError(f"Failed to get running config for namespace: {self.namespace}, Return code: {return_code}, Error: {err}")
178+
raise GenericConfigUpdaterError(
179+
f"Failed to get running config for scope: {self.scope}," +
180+
f"Return code: {return_code}, Error: {err}")
185181

186182
run_data = {}
187183
try:

0 commit comments

Comments
 (0)