Skip to content

Commit 7272bf3

Browse files
authored
Revert "Revert "[DHCPv6] [202012] Update the dhcpv6_relay config/show cli (#2271)" (#2336)" (#2459)
This reverts commit c9aa65c.
1 parent 94a3436 commit 7272bf3

File tree

5 files changed

+164
-17
lines changed

5 files changed

+164
-17
lines changed

config/vlan.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,21 @@ def add_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ip):
209209
if len(vlan) == 0:
210210
ctx.fail("{} doesn't exist".format(vlan_name))
211211

212-
dhcp_relay_dests = vlan.get('dhcp_servers', [])
213-
if dhcp_relay_destination_ip in dhcp_relay_dests:
212+
# Verify all ip addresses are valid and not exist in DB
213+
dhcp_servers = vlan.get('dhcp_servers', [])
214+
dhcpv6_servers = vlan.get('dhcpv6_servers', [])
215+
216+
if dhcp_relay_destination_ip in dhcp_servers + dhcpv6_servers:
214217
click.echo("{} is already a DHCP relay destination for {}".format(dhcp_relay_destination_ip, vlan_name))
215218
return
216219

217-
dhcp_relay_dests.append(dhcp_relay_destination_ip)
218-
vlan['dhcp_servers'] = dhcp_relay_dests
220+
if clicommon.ipaddress_type(dhcp_relay_destination_ip) == 6:
221+
dhcpv6_servers.append(dhcp_relay_destination_ip)
222+
vlan['dhcpv6_servers'] = dhcpv6_servers
223+
else:
224+
dhcp_servers.append(dhcp_relay_destination_ip)
225+
vlan['dhcp_servers'] = dhcp_servers
226+
219227
db.cfgdb.set_entry('VLAN', vlan_name, vlan)
220228
click.echo("Added DHCP relay destination address {} to {}".format(dhcp_relay_destination_ip, vlan_name))
221229
try:
@@ -243,15 +251,26 @@ def del_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ip):
243251
if len(vlan) == 0:
244252
ctx.fail("{} doesn't exist".format(vlan_name))
245253

246-
dhcp_relay_dests = vlan.get('dhcp_servers', [])
247-
if not dhcp_relay_destination_ip in dhcp_relay_dests:
254+
# Remove dhcp servers if they exist in the DB
255+
dhcp_servers = vlan.get('dhcp_servers', [])
256+
dhcpv6_servers = vlan.get('dhcpv6_servers', [])
257+
258+
if not dhcp_relay_destination_ip in dhcp_servers + dhcpv6_servers:
248259
ctx.fail("{} is not a DHCP relay destination for {}".format(dhcp_relay_destination_ip, vlan_name))
249260

250-
dhcp_relay_dests.remove(dhcp_relay_destination_ip)
251-
if len(dhcp_relay_dests) == 0:
252-
del vlan['dhcp_servers']
261+
if clicommon.ipaddress_type(dhcp_relay_destination_ip) == 6:
262+
dhcpv6_servers.remove(dhcp_relay_destination_ip)
263+
if len(dhcpv6_servers) == 0:
264+
del vlan['dhcpv6_servers']
265+
else:
266+
vlan['dhcpv6_servers'] = dhcpv6_servers
253267
else:
254-
vlan['dhcp_servers'] = dhcp_relay_dests
268+
dhcp_servers.remove(dhcp_relay_destination_ip)
269+
if len(dhcp_servers) == 0:
270+
del vlan['dhcp_servers']
271+
else:
272+
vlan['dhcp_servers'] = dhcp_servers
273+
255274
db.cfgdb.set_entry('VLAN', vlan_name, vlan)
256275
click.echo("Removed DHCP relay destination address {} from {}".format(dhcp_relay_destination_ip, vlan_name))
257276
try:

show/vlan.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ def brief(db, verbose):
3232

3333
# Parsing DHCP Helpers info
3434
for key in natsorted(list(vlan_dhcp_helper_data.keys())):
35-
try:
36-
if vlan_dhcp_helper_data[key]['dhcp_servers']:
37-
vlan_dhcp_helper_dict[key.strip('Vlan')] = vlan_dhcp_helper_data[key]['dhcp_servers']
38-
except KeyError:
39-
vlan_dhcp_helper_dict[key.strip('Vlan')] = " "
35+
dhcp_helpers = vlan_dhcp_helper_data.get(key, {}).get("dhcp_servers", [])
36+
dhcpv6_helpers = vlan_dhcp_helper_data.get(key, {}).get("dhcpv6_servers", [])
37+
all_helpers = dhcp_helpers + dhcpv6_helpers
38+
vlan_dhcp_helper_dict[key.strip('Vlan')] = all_helpers
4039

4140
# Parsing VLAN Gateway info
4241
for key in vlan_ip_data:

tests/mock_tables/config_db.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@
498498
},
499499
"VLAN|Vlan1000": {
500500
"dhcp_servers@": "192.0.0.1,192.0.0.2,192.0.0.3,192.0.0.4",
501+
"dhcpv6_servers@": "fc02:2000::1,fc02:2000::2",
501502
"vlanid": "1000"
502503
},
503504
"VLAN|Vlan2000": {

tests/vlan_test.py

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | |
1717
| | | Ethernet12 | untagged | 192.0.0.3 | |
1818
| | | Ethernet16 | untagged | 192.0.0.4 | |
19+
| | | | | fc02:2000::1 | |
20+
| | | | | fc02:2000::2 | |
1921
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
2022
| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled |
2123
| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | |
@@ -36,6 +38,8 @@
3638
| | fc02:1000::1/64 | etp3 | untagged | 192.0.0.2 | |
3739
| | | etp4 | untagged | 192.0.0.3 | |
3840
| | | etp5 | untagged | 192.0.0.4 | |
41+
| | | | | fc02:2000::1 | |
42+
| | | | | fc02:2000::2 | |
3943
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
4044
| 2000 | 192.168.0.10/21 | etp7 | untagged | 192.0.0.1 | enabled |
4145
| | fc02:1011::1/64 | etp8 | untagged | 192.0.0.2 | |
@@ -71,7 +75,8 @@
7175
| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | |
7276
| | | Ethernet12 | untagged | 192.0.0.3 | |
7377
| | | Ethernet16 | untagged | 192.0.0.4 | |
74-
| | | PortChannel1001 | untagged | | |
78+
| | | PortChannel1001 | untagged | fc02:2000::1 | |
79+
| | | | | fc02:2000::2 | |
7580
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
7681
| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled |
7782
| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | |
@@ -120,6 +125,16 @@
120125
Restarting DHCP relay service...
121126
"""
122127

128+
config_vlan_add_dhcp_relayv6_output="""\
129+
Added DHCP relay destination address fc02:2000::3 to Vlan1000
130+
Restarting DHCP relay service...
131+
"""
132+
133+
config_vlan_del_dhcp_relayv6_output="""\
134+
Removed DHCP relay destination address fc02:2000::3 from Vlan1000
135+
Restarting DHCP relay service...
136+
"""
137+
123138
show_vlan_brief_output_with_new_dhcp_relay_address="""\
124139
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
125140
| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP |
@@ -129,6 +144,31 @@
129144
| | | Ethernet12 | untagged | 192.0.0.3 | |
130145
| | | Ethernet16 | untagged | 192.0.0.4 | |
131146
| | | | | 192.0.0.100 | |
147+
| | | | | fc02:2000::1 | |
148+
| | | | | fc02:2000::2 | |
149+
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
150+
| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled |
151+
| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | |
152+
| | | | | 192.0.0.3 | |
153+
| | | | | 192.0.0.4 | |
154+
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
155+
| 3000 | | | | | disabled |
156+
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
157+
| 4000 | | PortChannel1001 | tagged | | disabled |
158+
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
159+
"""
160+
161+
show_vlan_brief_output_with_new_dhcp_relayv6_address="""\
162+
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
163+
| VLAN ID | IP Address | Ports | Port Tagging | DHCP Helper Address | Proxy ARP |
164+
+===========+=================+=================+================+=======================+=============+
165+
| 1000 | 192.168.0.1/21 | Ethernet4 | untagged | 192.0.0.1 | disabled |
166+
| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | |
167+
| | | Ethernet12 | untagged | 192.0.0.3 | |
168+
| | | Ethernet16 | untagged | 192.0.0.4 | |
169+
| | | | | fc02:2000::1 | |
170+
| | | | | fc02:2000::2 | |
171+
| | | | | fc02:2000::3 | |
132172
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
133173
| 2000 | 192.168.0.10/21 | Ethernet24 | untagged | 192.0.0.1 | enabled |
134174
| | fc02:1011::1/64 | Ethernet28 | untagged | 192.0.0.2 | |
@@ -149,6 +189,8 @@
149189
| | fc02:1000::1/64 | Ethernet8 | untagged | 192.0.0.2 | |
150190
| | | Ethernet12 | untagged | 192.0.0.3 | |
151191
| | | Ethernet16 | untagged | 192.0.0.4 | |
192+
| | | | | fc02:2000::1 | |
193+
| | | | | fc02:2000::2 | |
152194
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
153195
| 1001 | | Ethernet20 | untagged | | disabled |
154196
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
@@ -171,6 +213,8 @@
171213
| | fc02:1000::1/64 | etp3 | untagged | 192.0.0.2 | |
172214
| | | etp4 | untagged | 192.0.0.3 | |
173215
| | | etp5 | untagged | 192.0.0.4 | |
216+
| | | | | fc02:2000::1 | |
217+
| | | | | fc02:2000::2 | |
174218
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
175219
| 1001 | | etp6 | untagged | | disabled |
176220
+-----------+-----------------+-----------------+----------------+-----------------------+-------------+
@@ -535,6 +579,19 @@ def test_config_vlan_add_dhcp_relay_with_invalid_ip(self):
535579
assert result.exit_code != 0
536580
assert "Error: 192.0.0.1000 is invalid IP address" in result.output
537581
assert mock_run_command.call_count == 0
582+
583+
def test_config_vlan_add_dhcp_relay_with_invalid_ipv6(self):
584+
runner = CliRunner()
585+
586+
with mock.patch('utilities_common.cli.run_command') as mock_run_command:
587+
result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"],
588+
["1000", "fe80:2030:31:24"])
589+
print(result.exit_code)
590+
print(result.output)
591+
# traceback.print_tb(result.exc_info[2])
592+
assert result.exit_code != 0
593+
assert "Error: fe80:2030:31:24 is invalid IP address" in result.output
594+
assert mock_run_command.call_count == 0
538595

539596
def test_config_vlan_add_dhcp_relay_with_invalid_ip_2(self):
540597
runner = CliRunner()
@@ -561,6 +618,19 @@ def test_config_vlan_add_dhcp_relay_with_exist_ip(self):
561618
assert result.exit_code == 0
562619
assert "192.0.0.1 is already a DHCP relay destination for Vlan1000" in result.output
563620
assert mock_run_command.call_count == 0
621+
622+
def test_config_vlan_add_dhcp_relay_with_exist_ipv6(self):
623+
runner = CliRunner()
624+
625+
with mock.patch('utilities_common.cli.run_command') as mock_run_command:
626+
result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"],
627+
["1000", "fc02:2000::1"])
628+
print(result.exit_code)
629+
print(result.output)
630+
# traceback.print_tb(result.exc_info[2])
631+
assert result.exit_code == 0
632+
assert "fc02:2000::1 is already a DHCP relay destination for Vlan1000" in result.output
633+
assert mock_run_command.call_count == 0
564634

565635
def test_config_vlan_add_del_dhcp_relay_dest(self):
566636
runner = CliRunner()
@@ -596,6 +666,40 @@ def test_config_vlan_add_del_dhcp_relay_dest(self):
596666
print(result.output)
597667
assert result.output == show_vlan_brief_output
598668

669+
def test_config_vlan_add_del_dhcp_relayv6_dest(self):
670+
runner = CliRunner()
671+
db = Db()
672+
673+
# add new relay dest
674+
with mock.patch("utilities_common.cli.run_command") as mock_run_command:
675+
result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["add"],
676+
["1000", "fc02:2000::3"], obj=db)
677+
print(result.exit_code)
678+
print(result.output)
679+
assert result.exit_code == 0
680+
assert result.output == config_vlan_add_dhcp_relayv6_output
681+
assert mock_run_command.call_count == 3
682+
683+
# show output
684+
result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db)
685+
print(result.output)
686+
assert result.output == show_vlan_brief_output_with_new_dhcp_relayv6_address
687+
688+
# del relay dest
689+
with mock.patch("utilities_common.cli.run_command") as mock_run_command:
690+
result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["del"],
691+
["1000", "fc02:2000::3"], obj=db)
692+
print(result.exit_code)
693+
print(result.output)
694+
assert result.exit_code == 0
695+
assert result.output == config_vlan_del_dhcp_relayv6_output
696+
assert mock_run_command.call_count == 3
697+
698+
# show output
699+
result = runner.invoke(show.cli.commands["vlan"].commands["brief"], [], obj=db)
700+
print(result.output)
701+
assert result.output == show_vlan_brief_output
702+
599703
def test_config_vlan_remove_nonexist_dhcp_relay_dest(self):
600704
runner = CliRunner()
601705

@@ -608,6 +712,19 @@ def test_config_vlan_remove_nonexist_dhcp_relay_dest(self):
608712
assert result.exit_code != 0
609713
assert "Error: 192.0.0.100 is not a DHCP relay destination for Vlan1000" in result.output
610714
assert mock_run_command.call_count == 0
715+
716+
def test_config_vlan_remove_nonexist_dhcp_relayv6_dest(self):
717+
runner = CliRunner()
718+
719+
with mock.patch('utilities_common.cli.run_command') as mock_run_command:
720+
result = runner.invoke(config.config.commands["vlan"].commands["dhcp_relay"].commands["del"],
721+
["1000", "fc02:2000::3"])
722+
print(result.exit_code)
723+
print(result.output)
724+
# traceback.print_tb(result.exc_info[2])
725+
assert result.exit_code != 0
726+
assert "Error: fc02:2000::3 is not a DHCP relay destination for Vlan1000" in result.output
727+
assert mock_run_command.call_count == 0
611728

612729
def test_config_vlan_remove_dhcp_relay_dest_with_nonexist_vlanid(self):
613730
runner = CliRunner()

utilities_common/cli.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import click
88
import json
9+
import netaddr
910

1011
from natsort import natsorted
1112
from sonic_py_common import multi_asic
@@ -190,7 +191,6 @@ def get_interface_naming_mode():
190191

191192
def is_ipaddress(val):
192193
""" Validate if an entry is a valid IP """
193-
import netaddr
194194
if not val:
195195
return False
196196
try:
@@ -199,6 +199,17 @@ def is_ipaddress(val):
199199
return False
200200
return True
201201

202+
def ipaddress_type(val):
203+
""" Return the IP address type """
204+
if not val:
205+
return None
206+
207+
try:
208+
ip_version = netaddr.IPAddress(str(val))
209+
except netaddr.core.AddrFormatError:
210+
return None
211+
212+
return ip_version.version
202213

203214
def is_ip_prefix_in_key(key):
204215
'''

0 commit comments

Comments
 (0)