Skip to content

Commit a817896

Browse files
authored
YANG validation for ConfigDB Updates: MGMT_INTERFACE, PORTCHANNEL_MEMBER use cases (sonic-net#2420)
1 parent 81e2aec commit a817896

File tree

1 file changed

+104
-96
lines changed

1 file changed

+104
-96
lines changed

config/main.py

+104-96
Original file line numberDiff line numberDiff line change
@@ -2113,104 +2113,109 @@ def portchannel_member(ctx):
21132113
@click.pass_context
21142114
def add_portchannel_member(ctx, portchannel_name, port_name):
21152115
"""Add member to port channel"""
2116-
db = ctx.obj['db']
2117-
if clicommon.is_port_mirror_dst_port(db, port_name):
2118-
ctx.fail("{} is configured as mirror destination port".format(port_name))
2116+
db = ValidatedConfigDBConnector(ctx.obj['db'])
2117+
2118+
if ADHOC_VALIDATION:
2119+
if clicommon.is_port_mirror_dst_port(db, port_name):
2120+
ctx.fail("{} is configured as mirror destination port".format(port_name)) # TODO: MISSING CONSTRAINT IN YANG MODEL
21192121

2120-
# Check if the member interface given by user is valid in the namespace.
2121-
if port_name.startswith("Ethernet") is False or interface_name_is_valid(db, port_name) is False:
2122-
ctx.fail("Interface name is invalid. Please enter a valid interface name!!")
2122+
# Check if the member interface given by user is valid in the namespace.
2123+
if port_name.startswith("Ethernet") is False or interface_name_is_valid(db, port_name) is False:
2124+
ctx.fail("Interface name is invalid. Please enter a valid interface name!!")
21232125

2124-
# Dont proceed if the port channel name is not valid
2125-
if is_portchannel_name_valid(portchannel_name) is False:
2126-
ctx.fail("{} is invalid!, name should have prefix '{}' and suffix '{}'"
2127-
.format(portchannel_name, CFG_PORTCHANNEL_PREFIX, CFG_PORTCHANNEL_NO))
2126+
# Dont proceed if the port channel name is not valid
2127+
if is_portchannel_name_valid(portchannel_name) is False:
2128+
ctx.fail("{} is invalid!, name should have prefix '{}' and suffix '{}'"
2129+
.format(portchannel_name, CFG_PORTCHANNEL_PREFIX, CFG_PORTCHANNEL_NO))
21282130

2129-
# Dont proceed if the port channel does not exist
2130-
if is_portchannel_present_in_db(db, portchannel_name) is False:
2131-
ctx.fail("{} is not present.".format(portchannel_name))
2131+
# Dont proceed if the port channel does not exist
2132+
if is_portchannel_present_in_db(db, portchannel_name) is False:
2133+
ctx.fail("{} is not present.".format(portchannel_name))
21322134

2133-
# Don't allow a port to be member of port channel if it is configured with an IP address
2134-
for key,value in db.get_table('INTERFACE').items():
2135-
if type(key) == tuple:
2136-
continue
2137-
if key == port_name:
2138-
ctx.fail(" {} has ip address configured".format(port_name))
2139-
return
2135+
# Don't allow a port to be member of port channel if it is configured with an IP address
2136+
for key,value in db.get_table('INTERFACE').items():
2137+
if type(key) == tuple:
2138+
continue
2139+
if key == port_name:
2140+
ctx.fail(" {} has ip address configured".format(port_name)) # TODO: MISSING CONSTRAINT IN YANG MODEL
2141+
return
21402142

2141-
for key in db.get_keys('VLAN_SUB_INTERFACE'):
2142-
if type(key) == tuple:
2143-
continue
2144-
intf = key.split(VLAN_SUB_INTERFACE_SEPARATOR)[0]
2145-
parent_intf = get_intf_longname(intf)
2146-
if parent_intf == port_name:
2147-
ctx.fail(" {} has subinterfaces configured".format(port_name))
2148-
2149-
# Dont allow a port to be member of port channel if it is configured as a VLAN member
2150-
for k,v in db.get_table('VLAN_MEMBER'):
2151-
if v == port_name:
2152-
ctx.fail("%s Interface configured as VLAN_MEMBER under vlan : %s" %(port_name,str(k)))
2153-
return
2143+
for key in db.get_keys('VLAN_SUB_INTERFACE'):
2144+
if type(key) == tuple:
2145+
continue
2146+
intf = key.split(VLAN_SUB_INTERFACE_SEPARATOR)[0]
2147+
parent_intf = get_intf_longname(intf)
2148+
if parent_intf == port_name:
2149+
ctx.fail(" {} has subinterfaces configured".format(port_name)) # TODO: MISSING CONSTRAINT IN YANG MODEL
2150+
2151+
# Dont allow a port to be member of port channel if it is configured as a VLAN member
2152+
for k,v in db.get_table('VLAN_MEMBER'):
2153+
if v == port_name:
2154+
ctx.fail("%s Interface configured as VLAN_MEMBER under vlan : %s" %(port_name,str(k))) # TODO: MISSING CONSTRAINT IN YANG MODEL
2155+
return
21542156

2155-
# Dont allow a port to be member of port channel if it is already member of a port channel
2156-
for k,v in db.get_table('PORTCHANNEL_MEMBER'):
2157-
if v == port_name:
2158-
ctx.fail("{} Interface is already member of {} ".format(v,k))
2157+
# Dont allow a port to be member of port channel if it is already member of a port channel
2158+
for k,v in db.get_table('PORTCHANNEL_MEMBER'):
2159+
if v == port_name:
2160+
ctx.fail("{} Interface is already member of {} ".format(v,k)) # TODO: MISSING CONSTRAINT IN YANG MODEL
21592161

2160-
# Dont allow a port to be member of port channel if its speed does not match with existing members
2161-
for k,v in db.get_table('PORTCHANNEL_MEMBER'):
2162-
if k == portchannel_name:
2163-
member_port_entry = db.get_entry('PORT', v)
2162+
# Dont allow a port to be member of port channel if its speed does not match with existing members
2163+
for k,v in db.get_table('PORTCHANNEL_MEMBER'):
2164+
if k == portchannel_name:
2165+
member_port_entry = db.get_entry('PORT', v)
2166+
port_entry = db.get_entry('PORT', port_name)
2167+
2168+
if member_port_entry is not None and port_entry is not None:
2169+
member_port_speed = member_port_entry.get(PORT_SPEED)
2170+
2171+
port_speed = port_entry.get(PORT_SPEED) # TODO: MISSING CONSTRAINT IN YANG MODEL
2172+
if member_port_speed != port_speed:
2173+
ctx.fail("Port speed of {} is different than the other members of the portchannel {}"
2174+
.format(port_name, portchannel_name))
2175+
2176+
# Dont allow a port to be member of port channel if its MTU does not match with portchannel
2177+
portchannel_entry = db.get_entry('PORTCHANNEL', portchannel_name)
2178+
if portchannel_entry and portchannel_entry.get(PORT_MTU) is not None :
21642179
port_entry = db.get_entry('PORT', port_name)
21652180

2166-
if member_port_entry is not None and port_entry is not None:
2167-
member_port_speed = member_port_entry.get(PORT_SPEED)
2181+
if port_entry and port_entry.get(PORT_MTU) is not None:
2182+
port_mtu = port_entry.get(PORT_MTU)
21682183

2169-
port_speed = port_entry.get(PORT_SPEED)
2170-
if member_port_speed != port_speed:
2171-
ctx.fail("Port speed of {} is different than the other members of the portchannel {}"
2184+
portchannel_mtu = portchannel_entry.get(PORT_MTU) # TODO: MISSING CONSTRAINT IN YANG MODEL
2185+
if portchannel_mtu != port_mtu:
2186+
ctx.fail("Port MTU of {} is different than the {} MTU size"
21722187
.format(port_name, portchannel_name))
21732188

2174-
# Dont allow a port to be member of port channel if its MTU does not match with portchannel
2175-
portchannel_entry = db.get_entry('PORTCHANNEL', portchannel_name)
2176-
if portchannel_entry and portchannel_entry.get(PORT_MTU) is not None :
2189+
# Dont allow a port to be member of port channel if its TPID is not at default 0x8100
2190+
# If TPID is supported at LAG level, when member is added, the LAG's TPID is applied to the
2191+
# new member by SAI.
21772192
port_entry = db.get_entry('PORT', port_name)
2193+
if port_entry and port_entry.get(PORT_TPID) is not None:
2194+
port_tpid = port_entry.get(PORT_TPID) # TODO: MISSING CONSTRAINT IN YANG MODEL
2195+
if port_tpid != DEFAULT_TPID:
2196+
ctx.fail("Port TPID of {}: {} is not at default 0x8100".format(port_name, port_tpid))
21782197

2179-
if port_entry and port_entry.get(PORT_MTU) is not None:
2180-
port_mtu = port_entry.get(PORT_MTU)
2181-
2182-
portchannel_mtu = portchannel_entry.get(PORT_MTU)
2183-
if portchannel_mtu != port_mtu:
2184-
ctx.fail("Port MTU of {} is different than the {} MTU size"
2185-
.format(port_name, portchannel_name))
2186-
2187-
# Dont allow a port to be member of port channel if its TPID is not at default 0x8100
2188-
# If TPID is supported at LAG level, when member is added, the LAG's TPID is applied to the
2189-
# new member by SAI.
2190-
port_entry = db.get_entry('PORT', port_name)
2191-
if port_entry and port_entry.get(PORT_TPID) is not None:
2192-
port_tpid = port_entry.get(PORT_TPID)
2193-
if port_tpid != DEFAULT_TPID:
2194-
ctx.fail("Port TPID of {}: {} is not at default 0x8100".format(port_name, port_tpid))
2198+
# Don't allow a port to be a member of portchannel if already has ACL bindings
2199+
try:
2200+
acl_bindings = get_port_acl_binding(ctx.obj['db_wrap'], port_name, ctx.obj['namespace']) # TODO: MISSING CONSTRAINT IN YANG MODEL
2201+
if acl_bindings:
2202+
ctx.fail("Port {} is already bound to following ACL_TABLES: {}".format(port_name, acl_bindings))
2203+
except Exception as e:
2204+
ctx.fail(str(e))
21952205

2196-
# Don't allow a port to be a member of portchannel if already has ACL bindings
2197-
try:
2198-
acl_bindings = get_port_acl_binding(ctx.obj['db_wrap'], port_name, ctx.obj['namespace'])
2199-
if acl_bindings:
2200-
ctx.fail("Port {} is already bound to following ACL_TABLES: {}".format(port_name, acl_bindings))
2201-
except Exception as e:
2202-
ctx.fail(str(e))
2206+
# Don't allow a port to be a member of portchannel if already has PBH bindings
2207+
try:
2208+
pbh_bindings = get_port_pbh_binding(ctx.obj['db_wrap'], port_name, DEFAULT_NAMESPACE) # TODO: MISSING CONSTRAINT IN YANG MODEL
2209+
if pbh_bindings:
2210+
ctx.fail("Port {} is already bound to following PBH_TABLES: {}".format(port_name, pbh_bindings))
2211+
except Exception as e:
2212+
ctx.fail(str(e))
22032213

2204-
# Don't allow a port to be a member of portchannel if already has PBH bindings
22052214
try:
2206-
pbh_bindings = get_port_pbh_binding(ctx.obj['db_wrap'], port_name, DEFAULT_NAMESPACE)
2207-
if pbh_bindings:
2208-
ctx.fail("Port {} is already bound to following PBH_TABLES: {}".format(port_name, pbh_bindings))
2209-
except Exception as e:
2210-
ctx.fail(str(e))
2211-
2212-
db.set_entry('PORTCHANNEL_MEMBER', (portchannel_name, port_name),
2213-
{'NULL': 'NULL'})
2215+
db.set_entry('PORTCHANNEL_MEMBER', (portchannel_name, port_name),
2216+
{'NULL': 'NULL'})
2217+
except ValueError:
2218+
ctx.fail("Portchannel or interface name is invalid or nonexistent")
22142219

22152220
@portchannel_member.command('del')
22162221
@click.argument('portchannel_name', metavar='<portchannel_name>', required=True)
@@ -2223,22 +2228,25 @@ def del_portchannel_member(ctx, portchannel_name, port_name):
22232228
ctx.fail("{} is invalid!, name should have prefix '{}' and suffix '{}'"
22242229
.format(portchannel_name, CFG_PORTCHANNEL_PREFIX, CFG_PORTCHANNEL_NO))
22252230

2226-
db = ctx.obj['db']
2227-
2228-
# Check if the member interface given by user is valid in the namespace.
2229-
if interface_name_is_valid(db, port_name) is False:
2230-
ctx.fail("Interface name is invalid. Please enter a valid interface name!!")
2231+
db = ValidatedConfigDBConnector(ctx.obj['db'])
22312232

2232-
# Dont proceed if the port channel does not exist
2233-
if is_portchannel_present_in_db(db, portchannel_name) is False:
2234-
ctx.fail("{} is not present.".format(portchannel_name))
2233+
if ADHOC_VALIDATION:
2234+
# Check if the member interface given by user is valid in the namespace.
2235+
if interface_name_is_valid(db, port_name) is False:
2236+
ctx.fail("Interface name is invalid. Please enter a valid interface name!!")
22352237

2236-
# Dont proceed if the the port is not an existing member of the port channel
2237-
if not is_port_member_of_this_portchannel(db, port_name, portchannel_name):
2238-
ctx.fail("{} is not a member of portchannel {}".format(port_name, portchannel_name))
2238+
# Dont proceed if the port channel does not exist
2239+
if is_portchannel_present_in_db(db, portchannel_name) is False:
2240+
ctx.fail("{} is not present.".format(portchannel_name))
22392241

2240-
db.set_entry('PORTCHANNEL_MEMBER', (portchannel_name, port_name), None)
2241-
db.set_entry('PORTCHANNEL_MEMBER', portchannel_name + '|' + port_name, None)
2242+
# Dont proceed if the the port is not an existing member of the port channel
2243+
if not is_port_member_of_this_portchannel(db, port_name, portchannel_name):
2244+
ctx.fail("{} is not a member of portchannel {}".format(port_name, portchannel_name))
2245+
2246+
try:
2247+
db.set_entry('PORTCHANNEL_MEMBER', portchannel_name + '|' + port_name, None)
2248+
except JsonPatchConflict:
2249+
ctx.fail("Invalid or nonexistent portchannel or interface. Please ensure existence of portchannel member.")
22422250

22432251

22442252
#
@@ -4302,7 +4310,7 @@ def ip(ctx):
43024310
def add(ctx, interface_name, ip_addr, gw):
43034311
"""Add an IP address towards the interface"""
43044312
# Get the config_db connector
4305-
config_db = ctx.obj['config_db']
4313+
config_db = ValidatedConfigDBConnector(ctx.obj['config_db'])
43064314

43074315
if clicommon.get_interface_naming_mode() == "alias":
43084316
interface_name = interface_alias_to_name(config_db, interface_name)
@@ -4366,7 +4374,7 @@ def add(ctx, interface_name, ip_addr, gw):
43664374
def remove(ctx, interface_name, ip_addr):
43674375
"""Remove an IP address from the interface"""
43684376
# Get the config_db connector
4369-
config_db = ctx.obj['config_db']
4377+
config_db = ValidatedConfigDBConnector(ctx.obj['config_db'])
43704378

43714379
if clicommon.get_interface_naming_mode() == "alias":
43724380
interface_name = interface_alias_to_name(config_db, interface_name)

0 commit comments

Comments
 (0)