Skip to content

Commit bf55ceb

Browse files
[nvgre] Added auto-generated CLI plugins and test for NVGRE Tunnel feature (sonic-net#1915)
- What I did Added a click CLI plugins for NVGRE Tunnel feature - How I did it The CLI plugins were auto-generated (by using the sonic-cli-gen) for the show and config CLI groups. - How to verify it Added UT. Signed-off-by: Vadym Hlushko <[email protected]>
1 parent a2e68a0 commit bf55ceb

File tree

8 files changed

+895
-0
lines changed

8 files changed

+895
-0
lines changed

config/plugins/nvgre_tunnel.py

+349
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
"""
2+
Autogenerated config CLI plugin for NVGRE Tunnel feature.
3+
"""
4+
5+
import copy
6+
import click
7+
import utilities_common.cli as clicommon
8+
import utilities_common.general as general
9+
from config import config_mgmt
10+
11+
12+
# Load sonic-cfggen from source since /usr/local/bin/sonic-cfggen does not have .py extension.
13+
sonic_cfggen = general.load_module_from_source('sonic_cfggen', '/usr/local/bin/sonic-cfggen')
14+
15+
16+
def exit_with_error(*args, **kwargs):
17+
""" Print a message with click.secho and abort CLI.
18+
19+
Args:
20+
args: Positional arguments to pass to click.secho
21+
kwargs: Keyword arguments to pass to click.secho
22+
"""
23+
24+
click.secho(*args, **kwargs)
25+
raise click.Abort()
26+
27+
28+
def validate_config_or_raise(cfg):
29+
""" Validate config db data using ConfigMgmt.
30+
31+
Args:
32+
cfg (Dict): Config DB data to validate.
33+
Raises:
34+
Exception: when cfg does not satisfy YANG schema.
35+
"""
36+
37+
try:
38+
cfg = sonic_cfggen.FormatConverter.to_serialized(copy.deepcopy(cfg))
39+
config_mgmt.ConfigMgmt().loadData(cfg)
40+
except Exception as err:
41+
raise Exception('Failed to validate configuration: {}'.format(err))
42+
43+
44+
def add_entry_validated(db, table, key, data):
45+
""" Add new entry in table and validate configuration.
46+
47+
Args:
48+
db (swsscommon.ConfigDBConnector): Config DB connector obect.
49+
table (str): Table name to add new entry to.
50+
key (Union[str, Tuple]): Key name in the table.
51+
data (Dict): Entry data.
52+
Raises:
53+
Exception: when cfg does not satisfy YANG schema.
54+
"""
55+
56+
cfg = db.get_config()
57+
cfg.setdefault(table, {})
58+
if key in cfg[table]:
59+
raise Exception(f"{key} already exists")
60+
61+
cfg[table][key] = data
62+
63+
validate_config_or_raise(cfg)
64+
db.set_entry(table, key, data)
65+
66+
67+
def update_entry_validated(db, table, key, data, create_if_not_exists=False):
68+
""" Update entry in table and validate configuration.
69+
If attribute value in data is None, the attribute is deleted.
70+
71+
Args:
72+
db (swsscommon.ConfigDBConnector): Config DB connector obect.
73+
table (str): Table name to add new entry to.
74+
key (Union[str, Tuple]): Key name in the table.
75+
data (Dict): Entry data.
76+
create_if_not_exists (bool):
77+
In case entry does not exists already a new entry
78+
is not created if this flag is set to False and
79+
creates a new entry if flag is set to True.
80+
Raises:
81+
Exception: when cfg does not satisfy YANG schema.
82+
"""
83+
84+
cfg = db.get_config()
85+
cfg.setdefault(table, {})
86+
87+
if not data:
88+
raise Exception(f"No field/values to update {key}")
89+
90+
if create_if_not_exists:
91+
cfg[table].setdefault(key, {})
92+
93+
if key not in cfg[table]:
94+
raise Exception(f"{key} does not exist")
95+
96+
entry_changed = False
97+
for attr, value in data.items():
98+
if value == cfg[table][key][attr]:
99+
continue
100+
entry_changed = True
101+
if value is None:
102+
cfg[table][key].pop(attr, None)
103+
else:
104+
cfg[table][key][attr] = value
105+
106+
if not entry_changed:
107+
return
108+
109+
validate_config_or_raise(cfg)
110+
db.set_entry(table, key, cfg[table][key])
111+
112+
113+
def del_entry_validated(db, table, key):
114+
""" Delete entry in table and validate configuration.
115+
116+
Args:
117+
db (swsscommon.ConfigDBConnector): Config DB connector obect.
118+
table (str): Table name to add new entry to.
119+
key (Union[str, Tuple]): Key name in the table.
120+
Raises:
121+
Exception: when cfg does not satisfy YANG schema.
122+
"""
123+
124+
cfg = db.get_config()
125+
cfg.setdefault(table, {})
126+
if key not in cfg[table]:
127+
raise Exception(f"{key} does not exist")
128+
129+
cfg[table].pop(key)
130+
131+
validate_config_or_raise(cfg)
132+
db.set_entry(table, key, None)
133+
134+
135+
def add_list_entry_validated(db, table, key, attr, data):
136+
""" Add new entry into list in table and validate configuration.
137+
138+
Args:
139+
db (swsscommon.ConfigDBConnector): Config DB connector obect.
140+
table (str): Table name to add data to.
141+
key (Union[str, Tuple]): Key name in the table.
142+
attr (str): Attribute name which represents a list the data needs to be added to.
143+
data (List): Data list to add to config DB.
144+
Raises:
145+
Exception: when cfg does not satisfy YANG schema.
146+
"""
147+
148+
cfg = db.get_config()
149+
cfg.setdefault(table, {})
150+
if key not in cfg[table]:
151+
raise Exception(f"{key} does not exist")
152+
cfg[table][key].setdefault(attr, [])
153+
for entry in data:
154+
if entry in cfg[table][key][attr]:
155+
raise Exception(f"{entry} already exists")
156+
cfg[table][key][attr].append(entry)
157+
158+
validate_config_or_raise(cfg)
159+
db.set_entry(table, key, cfg[table][key])
160+
161+
162+
def del_list_entry_validated(db, table, key, attr, data):
163+
""" Delete entry from list in table and validate configuration.
164+
165+
Args:
166+
db (swsscommon.ConfigDBConnector): Config DB connector obect.
167+
table (str): Table name to remove data from.
168+
key (Union[str, Tuple]): Key name in the table.
169+
attr (str): Attribute name which represents a list the data needs to be removed from.
170+
data (Dict): Data list to remove from config DB.
171+
Raises:
172+
Exception: when cfg does not satisfy YANG schema.
173+
"""
174+
175+
cfg = db.get_config()
176+
cfg.setdefault(table, {})
177+
if key not in cfg[table]:
178+
raise Exception(f"{key} does not exist")
179+
cfg[table][key].setdefault(attr, [])
180+
for entry in data:
181+
if entry not in cfg[table][key][attr]:
182+
raise Exception(f"{entry} does not exist")
183+
cfg[table][key][attr].remove(entry)
184+
if not cfg[table][key][attr]:
185+
cfg[table][key].pop(attr)
186+
187+
validate_config_or_raise(cfg)
188+
db.set_entry(table, key, cfg[table][key])
189+
190+
191+
def clear_list_entry_validated(db, table, key, attr):
192+
""" Clear list in object and validate configuration.
193+
194+
Args:
195+
db (swsscommon.ConfigDBConnector): Config DB connector obect.
196+
table (str): Table name to remove the list attribute from.
197+
key (Union[str, Tuple]): Key name in the table.
198+
attr (str): Attribute name which represents a list that needs to be removed.
199+
Raises:
200+
Exception: when cfg does not satisfy YANG schema.
201+
"""
202+
203+
update_entry_validated(db, table, key, {attr: None})
204+
205+
206+
@click.group(
207+
name="nvgre-tunnel",
208+
cls=clicommon.AliasedGroup)
209+
def NVGRE_TUNNEL():
210+
""" NVGRE_TUNNEL part of config_db.json """
211+
212+
pass
213+
214+
215+
@NVGRE_TUNNEL.command(name="add")
216+
@click.argument(
217+
"tunnel-name",
218+
nargs=1,
219+
required=True,
220+
)
221+
@click.option(
222+
"--src-ip",
223+
required=True,
224+
help="Source IP address[mandatory]",
225+
)
226+
@clicommon.pass_db
227+
def NVGRE_TUNNEL_add(db, tunnel_name, src_ip):
228+
""" Add object in NVGRE_TUNNEL. """
229+
230+
table = "NVGRE_TUNNEL"
231+
key = tunnel_name
232+
data = {}
233+
if src_ip is not None:
234+
data["src_ip"] = src_ip
235+
236+
try:
237+
add_entry_validated(db.cfgdb, table, key, data)
238+
except Exception as err:
239+
exit_with_error(f"Error: {err}", fg="red")
240+
241+
242+
@NVGRE_TUNNEL.command(name="delete")
243+
@click.argument(
244+
"tunnel-name",
245+
nargs=1,
246+
required=True,
247+
)
248+
@clicommon.pass_db
249+
def NVGRE_TUNNEL_delete(db, tunnel_name):
250+
""" Delete object in NVGRE_TUNNEL. """
251+
252+
table = "NVGRE_TUNNEL"
253+
key = tunnel_name
254+
try:
255+
del_entry_validated(db.cfgdb, table, key)
256+
except Exception as err:
257+
exit_with_error(f"Error: {err}", fg="red")
258+
259+
260+
@click.group(
261+
name="nvgre-tunnel-map",
262+
cls=clicommon.AliasedGroup)
263+
def NVGRE_TUNNEL_MAP():
264+
""" NVGRE_TUNNEL_MAP part of config_db.json """
265+
266+
pass
267+
268+
269+
@NVGRE_TUNNEL_MAP.command(name="add")
270+
@click.argument(
271+
"tunnel-name",
272+
nargs=1,
273+
required=True,
274+
)
275+
@click.argument(
276+
"tunnel-map-name",
277+
nargs=1,
278+
required=True,
279+
)
280+
281+
@click.option(
282+
"--vlan-id",
283+
required=True,
284+
help="VLAN identifier[mandatory]",
285+
)
286+
@click.option(
287+
"--vsid",
288+
required=True,
289+
help="Virtual Subnet Identifier[mandatory]",
290+
)
291+
@clicommon.pass_db
292+
def NVGRE_TUNNEL_MAP_add(db, tunnel_name, tunnel_map_name, vlan_id, vsid):
293+
""" Add object in NVGRE_TUNNEL_MAP. """
294+
295+
table = "NVGRE_TUNNEL_MAP"
296+
key = tunnel_name, tunnel_map_name
297+
data = {}
298+
if vlan_id is not None:
299+
data["vlan_id"] = vlan_id
300+
if vsid is not None:
301+
data["vsid"] = vsid
302+
303+
try:
304+
add_entry_validated(db.cfgdb, table, key, data)
305+
except Exception as err:
306+
exit_with_error(f"Error: {err}", fg="red")
307+
308+
309+
@NVGRE_TUNNEL_MAP.command(name="delete")
310+
@click.argument(
311+
"tunnel-name",
312+
nargs=1,
313+
required=True,
314+
)
315+
@click.argument(
316+
"tunnel-map-name",
317+
nargs=1,
318+
required=True,
319+
)
320+
@clicommon.pass_db
321+
def NVGRE_TUNNEL_MAP_delete(db, tunnel_name, tunnel_map_name):
322+
""" Delete object in NVGRE_TUNNEL_MAP. """
323+
324+
table = "NVGRE_TUNNEL_MAP"
325+
key = tunnel_name, tunnel_map_name
326+
try:
327+
del_entry_validated(db.cfgdb, table, key)
328+
except Exception as err:
329+
exit_with_error(f"Error: {err}", fg="red")
330+
331+
332+
def register(cli):
333+
""" Register new CLI nodes in root CLI.
334+
335+
Args:
336+
cli: Root CLI node.
337+
Raises:
338+
Exception: when root CLI already has a command
339+
we are trying to register.
340+
"""
341+
cli_node = NVGRE_TUNNEL
342+
if cli_node.name in cli.commands:
343+
raise Exception(f"{cli_node.name} already exists in CLI")
344+
cli.add_command(NVGRE_TUNNEL)
345+
cli_node = NVGRE_TUNNEL_MAP
346+
if cli_node.name in cli.commands:
347+
raise Exception(f"{cli_node.name} already exists in CLI")
348+
cli.add_command(NVGRE_TUNNEL_MAP)
349+

0 commit comments

Comments
 (0)