|
1 | 1 | import click
|
2 | 2 | import utilities_common.cli as clicommon
|
| 3 | +import ipaddress |
3 | 4 |
|
4 | 5 | @click.group(cls=clicommon.AbbreviationGroup, name='dhcp_relay')
|
5 | 6 | def vlan_dhcp_relay():
|
6 | 7 | pass
|
7 | 8 |
|
8 | 9 | @vlan_dhcp_relay.command('add')
|
9 | 10 | @click.argument('vid', metavar='<vid>', required=True, type=int)
|
10 |
| -@click.argument('dhcp_relay_destination_ip', metavar='<dhcp_relay_destination_ip>', required=True) |
| 11 | +@click.argument('dhcp_relay_destination_ips', nargs=-1, required=True) |
11 | 12 | @clicommon.pass_db
|
12 |
| -def add_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ip): |
| 13 | +def add_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ips): |
13 | 14 | """ Add a destination IP address to the VLAN's DHCP relay """
|
14 | 15 |
|
15 | 16 | ctx = click.get_current_context()
|
| 17 | + added_servers = [] |
16 | 18 |
|
17 |
| - if not clicommon.is_ipaddress(dhcp_relay_destination_ip): |
18 |
| - ctx.fail('{} is invalid IP address'.format(dhcp_relay_destination_ip)) |
19 |
| - |
| 19 | + # Verify vlan is valid |
20 | 20 | vlan_name = 'Vlan{}'.format(vid)
|
21 | 21 | vlan = db.cfgdb.get_entry('VLAN', vlan_name)
|
22 | 22 | if len(vlan) == 0:
|
23 | 23 | ctx.fail("{} doesn't exist".format(vlan_name))
|
24 | 24 |
|
25 |
| - dhcp_relay_dests = vlan.get('dhcp_servers', []) |
26 |
| - if dhcp_relay_destination_ip in dhcp_relay_dests: |
27 |
| - click.echo("{} is already a DHCP relay destination for {}".format(dhcp_relay_destination_ip, vlan_name)) |
28 |
| - return |
| 25 | + # Verify all ip addresses are valid and not exist in DB |
| 26 | + dhcp_servers = vlan.get('dhcp_servers', []) |
| 27 | + dhcpv6_servers = vlan.get('dhcpv6_servers', []) |
| 28 | + |
| 29 | + for ip_addr in dhcp_relay_destination_ips: |
| 30 | + try: |
| 31 | + ipaddress.ip_address(ip_addr) |
| 32 | + if (ip_addr in dhcp_servers) or (ip_addr in dhcpv6_servers): |
| 33 | + click.echo("{} is already a DHCP relay destination for {}".format(ip_addr, vlan_name)) |
| 34 | + continue |
| 35 | + if clicommon.ipaddress_type(ip_addr) == 4: |
| 36 | + dhcp_servers.append(ip_addr) |
| 37 | + else: |
| 38 | + dhcpv6_servers.append(ip_addr) |
| 39 | + added_servers.append(ip_addr) |
| 40 | + except: |
| 41 | + ctx.fail('{} is invalid IP address'.format(ip_addr)) |
| 42 | + |
| 43 | + # Append new dhcp servers to config DB |
| 44 | + if len(dhcp_servers): |
| 45 | + vlan['dhcp_servers'] = dhcp_servers |
| 46 | + if len(dhcpv6_servers): |
| 47 | + vlan['dhcpv6_servers'] = dhcpv6_servers |
29 | 48 |
|
30 |
| - dhcp_relay_dests.append(dhcp_relay_destination_ip) |
31 |
| - vlan['dhcp_servers'] = dhcp_relay_dests |
32 | 49 | db.cfgdb.set_entry('VLAN', vlan_name, vlan)
|
33 |
| - click.echo("Added DHCP relay destination address {} to {}".format(dhcp_relay_destination_ip, vlan_name)) |
34 |
| - try: |
35 |
| - click.echo("Restarting DHCP relay service...") |
36 |
| - clicommon.run_command("systemctl stop dhcp_relay", display_cmd=False) |
37 |
| - clicommon.run_command("systemctl reset-failed dhcp_relay", display_cmd=False) |
38 |
| - clicommon.run_command("systemctl start dhcp_relay", display_cmd=False) |
39 |
| - except SystemExit as e: |
40 |
| - ctx.fail("Restart service dhcp_relay failed with error {}".format(e)) |
| 50 | + |
| 51 | + if len(added_servers): |
| 52 | + click.echo("Added DHCP relay destination addresses {} to {}".format(added_servers, vlan_name)) |
| 53 | + try: |
| 54 | + click.echo("Restarting DHCP relay service...") |
| 55 | + clicommon.run_command("systemctl stop dhcp_relay", display_cmd=False) |
| 56 | + clicommon.run_command("systemctl reset-failed dhcp_relay", display_cmd=False) |
| 57 | + clicommon.run_command("systemctl start dhcp_relay", display_cmd=False) |
| 58 | + except SystemExit as e: |
| 59 | + ctx.fail("Restart service dhcp_relay failed with error {}".format(e)) |
41 | 60 |
|
42 | 61 | @vlan_dhcp_relay.command('del')
|
43 | 62 | @click.argument('vid', metavar='<vid>', required=True, type=int)
|
44 |
| -@click.argument('dhcp_relay_destination_ip', metavar='<dhcp_relay_destination_ip>', required=True) |
| 63 | +@click.argument('dhcp_relay_destination_ips', nargs=-1, required=True) |
45 | 64 | @clicommon.pass_db
|
46 |
| -def del_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ip): |
| 65 | +def del_vlan_dhcp_relay_destination(db, vid, dhcp_relay_destination_ips): |
47 | 66 | """ Remove a destination IP address from the VLAN's DHCP relay """
|
48 | 67 |
|
49 | 68 | ctx = click.get_current_context()
|
50 | 69 |
|
51 |
| - if not clicommon.is_ipaddress(dhcp_relay_destination_ip): |
52 |
| - ctx.fail('{} is invalid IP address'.format(dhcp_relay_destination_ip)) |
53 |
| - |
| 70 | + # Verify vlan is valid |
54 | 71 | vlan_name = 'Vlan{}'.format(vid)
|
55 | 72 | vlan = db.cfgdb.get_entry('VLAN', vlan_name)
|
56 | 73 | if len(vlan) == 0:
|
57 | 74 | ctx.fail("{} doesn't exist".format(vlan_name))
|
58 | 75 |
|
59 |
| - dhcp_relay_dests = vlan.get('dhcp_servers', []) |
60 |
| - if not dhcp_relay_destination_ip in dhcp_relay_dests: |
61 |
| - ctx.fail("{} is not a DHCP relay destination for {}".format(dhcp_relay_destination_ip, vlan_name)) |
| 76 | + # Remove dhcp servers if they exist in the DB |
| 77 | + dhcp_servers = vlan.get('dhcp_servers', []) |
| 78 | + dhcpv6_servers = vlan.get('dhcpv6_servers', []) |
| 79 | + |
| 80 | + for ip_addr in dhcp_relay_destination_ips: |
| 81 | + if (ip_addr not in dhcp_servers) and (ip_addr not in dhcpv6_servers): |
| 82 | + ctx.fail("{} is not a DHCP relay destination for {}".format(ip_addr, vlan_name)) |
| 83 | + if clicommon.ipaddress_type(ip_addr) == 4: |
| 84 | + dhcp_servers.remove(ip_addr) |
| 85 | + else: |
| 86 | + dhcpv6_servers.remove(ip_addr) |
| 87 | + |
| 88 | + # Update dhcp servers to config DB |
| 89 | + if len(dhcp_servers): |
| 90 | + vlan['dhcp_servers'] = dhcp_servers |
| 91 | + else: |
| 92 | + if 'dhcp_servers' in vlan.keys(): |
| 93 | + del vlan['dhcp_servers'] |
62 | 94 |
|
63 |
| - dhcp_relay_dests.remove(dhcp_relay_destination_ip) |
64 |
| - if len(dhcp_relay_dests) == 0: |
65 |
| - del vlan['dhcp_servers'] |
| 95 | + if len(dhcpv6_servers): |
| 96 | + vlan['dhcpv6_servers'] = dhcpv6_servers |
66 | 97 | else:
|
67 |
| - vlan['dhcp_servers'] = dhcp_relay_dests |
| 98 | + if 'dhcpv6_servers' in vlan.keys(): |
| 99 | + del vlan['dhcpv6_servers'] |
| 100 | + |
68 | 101 | db.cfgdb.set_entry('VLAN', vlan_name, vlan)
|
69 |
| - click.echo("Removed DHCP relay destination address {} from {}".format(dhcp_relay_destination_ip, vlan_name)) |
| 102 | + click.echo("Removed DHCP relay destination addresses {} from {}".format(dhcp_relay_destination_ips, vlan_name)) |
70 | 103 | try:
|
71 | 104 | click.echo("Restarting DHCP relay service...")
|
72 | 105 | clicommon.run_command("systemctl stop dhcp_relay", display_cmd=False)
|
|
0 commit comments