-
Notifications
You must be signed in to change notification settings - Fork 646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VXLAN config and show utilities #870
Changes from 18 commits
42b055d
2c609e2
7e036df
be0278f
fa13994
68521b6
39561f0
c410175
818009b
d507145
432e7c1
7221a17
c696f69
403d07e
b95be1b
86779ec
95dc9b9
d9e9df6
24958ff
074ca0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,6 @@ | |
import utilities_common.cli as clicommon | ||
from .utils import log | ||
|
||
|
||
from . import aaa | ||
from . import chassis_modules | ||
from . import console | ||
|
@@ -34,6 +33,7 @@ | |
from . import muxcable | ||
from . import nat | ||
from . import vlan | ||
from . import vxlan | ||
from .config_mgmt import ConfigMgmtDPB | ||
|
||
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help', '-?']) | ||
|
@@ -884,6 +884,7 @@ def config(ctx): | |
config.add_command(muxcable.muxcable) | ||
config.add_command(nat.nat) | ||
config.add_command(vlan.vlan) | ||
config.add_command(vxlan.vxlan) | ||
|
||
@config.command() | ||
@click.option('-y', '--yes', is_flag=True, callback=_abort_if_false, | ||
|
@@ -2930,6 +2931,56 @@ def del_vrf(ctx, vrf_name): | |
config_db.set_entry('VRF', vrf_name, None) | ||
|
||
|
||
@vrf.command('add_vrf_vni_map') | ||
@click.argument('vrfname', metavar='<vrf-name>', required=True, type=str) | ||
@click.argument('vni', metavar='<vni>', required=True) | ||
@click.pass_context | ||
def add_vrf_vni_map(ctx, vrfname, vni): | ||
config_db = ctx.obj['config_db'] | ||
found = 0 | ||
if vrfname not in config_db.get_table('VRF').keys(): | ||
ctx.fail("vrf {} doesnt exists".format(vrfname)) | ||
if not vni.isdigit(): | ||
ctx.fail("Invalid VNI {}. Only valid VNI is accepted".format(vni)) | ||
|
||
if clicommon.vni_id_is_valid(int(vni)) is False: | ||
ctx.fail("Invalid VNI {}. Valid range [1 to 16777215].".format(vni)) | ||
|
||
vxlan_table = config_db.get_table('VXLAN_TUNNEL_MAP') | ||
vxlan_keys = vxlan_table.keys() | ||
if vxlan_keys is not None: | ||
for key in vxlan_keys: | ||
if (vxlan_table[key]['vni'] == vni): | ||
found = 1 | ||
break | ||
|
||
if (found == 0): | ||
ctx.fail(" VLAN VNI not mapped. Please create VLAN VNI map entry first ") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this leading space? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. Updated code. |
||
|
||
found = 0 | ||
vrf_table = config_db.get_table('VRF') | ||
vrf_keys = vrf_table.keys() | ||
if vrf_keys is not None: | ||
for vrf_key in vrf_keys: | ||
if ('vni' in vrf_table[vrf_key] and vrf_table[vrf_key]['vni'] == vni): | ||
found = 1 | ||
break | ||
|
||
if (found == 1): | ||
ctx.fail("VNI already mapped to vrf {}".format(vrf_key)) | ||
|
||
config_db.mod_entry('VRF', vrfname, {"vni": vni}) | ||
|
||
@vrf.command('del_vrf_vni_map') | ||
@click.argument('vrfname', metavar='<vrf-name>', required=True, type=str) | ||
@click.pass_context | ||
def del_vrf_vni_map(ctx, vrfname): | ||
config_db = ctx.obj['config_db'] | ||
if vrfname not in config_db.get_table('VRF').keys(): | ||
ctx.fail("vrf {} doesnt exists".format(vrfname)) | ||
|
||
config_db.mod_entry('VRF', vrfname, {"vni": 0}) | ||
|
||
# | ||
# 'route' group ('config route ...') | ||
# | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
import click | ||
import utilities_common.cli as clicommon | ||
|
||
# | ||
# 'vxlan' group ('config vxlan ...') | ||
# | ||
@click.group() | ||
def vxlan(): | ||
pass | ||
|
||
@vxlan.command('add') | ||
@click.argument('vxlan_name', metavar='<vxlan_name>', required=True) | ||
@click.argument('src_ip', metavar='<src_ip>', required=True) | ||
@clicommon.pass_db | ||
def add_vxlan(db, vxlan_name, src_ip): | ||
"""Add VXLAN""" | ||
ctx = click.get_current_context() | ||
|
||
if not clicommon.is_ipaddress(src_ip): | ||
ctx.fail("{} invalid src ip address".format(src_ip)) | ||
|
||
vxlan_keys = db.cfgdb.get_keys('VXLAN_TUNNEL') | ||
if not vxlan_keys: | ||
vxlan_count = 0 | ||
else: | ||
vxlan_count = len(vxlan_keys) | ||
|
||
if(vxlan_count > 0): | ||
ctx.fail("VTEP already configured.") | ||
|
||
fvs = {'src_ip': src_ip} | ||
db.cfgdb.set_entry('VXLAN_TUNNEL', vxlan_name, fvs) | ||
|
||
@vxlan.command('del') | ||
@click.argument('vxlan_name', metavar='<vxlan_name>', required=True) | ||
@clicommon.pass_db | ||
def del_vxlan(db, vxlan_name): | ||
"""Del VXLAN""" | ||
ctx = click.get_current_context() | ||
|
||
vxlan_keys = db.cfgdb.get_keys('VXLAN_EVPN_NVO') | ||
if not vxlan_keys: | ||
vxlan_count = 0 | ||
else: | ||
vxlan_count = len(vxlan_keys) | ||
|
||
if(vxlan_count > 0): | ||
ctx.fail("Please delete the EVPN NVO configuration.") | ||
|
||
vxlan_keys = db.cfgdb.get_keys('CONFIG_DB', "VXLAN_TUNNEL_MAP|*") | ||
if not vxlan_keys: | ||
vxlan_count = 0 | ||
else: | ||
vxlan_count = len(vxlan_keys) | ||
|
||
if(vxlan_count > 0): | ||
ctx.fail("Please delete all VLAN VNI mappings.") | ||
|
||
db.cfgdb.set_entry('VXLAN_TUNNEL', vxlan_name, None) | ||
|
||
@vxlan.group('evpn_nvo') | ||
def vxlan_evpn_nvo(): | ||
pass | ||
|
||
@vxlan_evpn_nvo.command('add') | ||
@click.argument('nvo_name', metavar='<nvo_name>', required=True) | ||
@click.argument('vxlan_name', metavar='<vxlan_name>', required=True) | ||
@clicommon.pass_db | ||
def add_vxlan_evpn_nvo(db, nvo_name, vxlan_name): | ||
"""Add NVO""" | ||
ctx = click.get_current_context() | ||
vxlan_keys = db.cfgdb.get_keys('CONFIG_DB', "VXLAN_EVPN_NVO|*") | ||
if not vxlan_keys: | ||
vxlan_count = 0 | ||
else: | ||
vxlan_count = len(vxlan_keys) | ||
|
||
if(vxlan_count > 0): | ||
ctx.fail("EVPN NVO already configured") | ||
|
||
if len(db.cfgdb.get_entry('VXLAN_TUNNEL', vxlan_name)) == 0: | ||
ctx.fail("VTEP {} not configured".format(vxlan_name)) | ||
|
||
fvs = {'source_vtep': vxlan_name} | ||
db.cfgdb.set_entry('VXLAN_EVPN_NVO', nvo_name, fvs) | ||
|
||
@vxlan_evpn_nvo.command('del') | ||
@click.argument('nvo_name', metavar='<nvo_name>', required=True) | ||
@clicommon.pass_db | ||
def del_vxlan_evpn_nvo(db, nvo_name): | ||
"""Del NVO""" | ||
ctx = click.get_current_context() | ||
vxlan_keys = db.cfgdb.get_keys('VXLAN_TUNNEL_MAP') | ||
if not vxlan_keys: | ||
vxlan_count = 0 | ||
else: | ||
vxlan_count = len(vxlan_keys) | ||
|
||
if(vxlan_count > 0): | ||
ctx.fail("Please delete all VLAN VNI mappings.") | ||
db.cfgdb.set_entry('VXLAN_EVPN_NVO', nvo_name, None) | ||
|
||
@vxlan.group('map') | ||
def vxlan_map(): | ||
pass | ||
|
||
@vxlan_map.command('add') | ||
@click.argument('vxlan_name', metavar='<vxlan_name>', required=True) | ||
@click.argument('vlan', metavar='<vlan_id>', required=True) | ||
@click.argument('vni', metavar='<vni>', required=True) | ||
@clicommon.pass_db | ||
def add_vxlan_map(db, vxlan_name, vlan, vni): | ||
"""Add VLAN-VNI map entry""" | ||
ctx = click.get_current_context() | ||
|
||
if not vlan.isdigit(): | ||
ctx.fail("Invalid vlan {}. Only valid vlan is accepted".format(vni)) | ||
if clicommon.is_vlanid_in_range(int(vlan)) is False: | ||
ctx.fail(" Invalid Vlan Id , Valid Range : 1 to 4094 ") | ||
if not vni.isdigit(): | ||
ctx.fail("Invalid VNI {}. Only valid VNI is accepted".format(vni)) | ||
if clicommon.vni_id_is_valid(int(vni)) is False: | ||
ctx.fail("Invalid VNI {}. Valid range [1 to 16777215].".format(vni)) | ||
|
||
vlan_name = "Vlan" + vlan | ||
|
||
if len(db.cfgdb.get_entry('VXLAN_TUNNEL', vxlan_name)) == 0: | ||
ctx.fail("VTEP {} not configured".format(vxlan_name)) | ||
|
||
if len(db.cfgdb.get_entry('VLAN', vlan_name)) == 0: | ||
ctx.fail("{} not configured".format(vlan_name)) | ||
|
||
vxlan_table = db.cfgdb.get_table('VXLAN_TUNNEL_MAP') | ||
vxlan_keys = vxlan_table.keys() | ||
if vxlan_keys is not None: | ||
for key in vxlan_keys: | ||
if (vxlan_table[key]['vlan'] == vlan_name): | ||
ctx.fail(" Vlan Id already mapped ") | ||
if (vxlan_table[key]['vni'] == vni): | ||
ctx.fail(" VNI Id already mapped ") | ||
|
||
fvs = {'vni': vni, | ||
'vlan' : vlan_name} | ||
mapname = vxlan_name + '|' + 'map_' + vni + '_' + vlan_name | ||
db.cfgdb.set_entry('VXLAN_TUNNEL_MAP', mapname, fvs) | ||
|
||
@vxlan_map.command('del') | ||
@click.argument('vxlan_name', metavar='<vxlan_name>', required=True) | ||
@click.argument('vlan', metavar='<vlan_id>', required=True) | ||
@click.argument('vni', metavar='<vni>', required=True) | ||
@clicommon.pass_db | ||
def del_vxlan_map(db, vxlan_name, vlan, vni): | ||
"""Del VLAN-VNI map entry""" | ||
ctx = click.get_current_context() | ||
|
||
if not vlan.isdigit(): | ||
ctx.fail("Invalid vlan {}. Only valid vlan is accepted".format(vni)) | ||
if clicommon.is_vlanid_in_range(int(vlan)) is False: | ||
ctx.fail(" Invalid Vlan Id , Valid Range : 1 to 4094 ") | ||
if not vni.isdigit(): | ||
ctx.fail("Invalid VNI {}. Only valid VNI is accepted".format(vni)) | ||
if clicommon.vni_id_is_valid(int(vni)) is False: | ||
ctx.fail("Invalid VNI {}. Valid range [1 to 16777215].".format(vni)) | ||
|
||
if len(db.cfgdb.get_entry('VXLAN_TUNNEL', vxlan_name)) == 0: | ||
ctx.fail("VTEP {} not configured".format(vxlan_name)) | ||
found = 0 | ||
vrf_table = db.cfgdb.get_table('VRF') | ||
vrf_keys = vrf_table.keys() | ||
if vrf_keys is not None: | ||
for vrf_key in vrf_keys: | ||
if ('vni' in vrf_table[vrf_key] and vrf_table[vrf_key]['vni'] == vni): | ||
found = 1 | ||
break | ||
|
||
if (found == 1): | ||
ctx.fail("VNI mapped to vrf {}, Please remove VRF VNI mapping".format(vrf_key)) | ||
|
||
mapname = vxlan_name + '|' + 'map_' + vni + '_' + vlan | ||
db.cfgdb.set_entry('VXLAN_TUNNEL_MAP', mapname, None) | ||
mapname = vxlan_name + '|' + 'map_' + vni + '_Vlan' + vlan | ||
db.cfgdb.set_entry('VXLAN_TUNNEL_MAP', mapname, None) | ||
|
||
@vxlan.group('map_range') | ||
def vxlan_map_range(): | ||
pass | ||
|
||
@vxlan_map_range.command('add') | ||
@click.argument('vxlan_name', metavar='<vxlan_name>', required=True) | ||
@click.argument('vlan_start', metavar='<vlan_start>', required=True, type=int) | ||
@click.argument('vlan_end', metavar='<vlan_end>', required=True, type=int) | ||
@click.argument('vni_start', metavar='<vni_start>', required=True, type=int) | ||
@clicommon.pass_db | ||
def add_vxlan_map_range(db, vxlan_name, vlan_start, vlan_end, vni_start): | ||
"""Add Range of vlan-vni mappings""" | ||
ctx = click.get_current_context() | ||
if clicommon.is_vlanid_in_range(vlan_start) is False: | ||
ctx.fail(" Invalid Vlan Id , Valid Range : 1 to 4094 ") | ||
if clicommon.is_vlanid_in_range(vlan_end) is False: | ||
ctx.fail(" Invalid Vlan Id , Valid Range : 1 to 4094 ") | ||
if (vlan_start > vlan_end): | ||
ctx.fail("vlan_end should be greater or equal to vlan_start") | ||
if clicommon.vni_id_is_valid(vni_start) is False: | ||
ctx.fail("Invalid VNI {}. Valid range [1 to 16777215].".format(vni_start)) | ||
if clicommon.vni_id_is_valid(vni_start+vlan_end-vlan_start) is False: | ||
ctx.fail("Invalid VNI End {}. Valid range [1 to 16777215].".format(vni_start)) | ||
|
||
if len(db.cfgdb.get_entry('VXLAN_TUNNEL', vxlan_name)) == 0: | ||
ctx.fail("VTEP {} not configured".format(vxlan_name)) | ||
vlan_end = vlan_end + 1 | ||
vxlan_table = db.cfgdb.get_table('VXLAN_TUNNEL_MAP') | ||
vxlan_keys = vxlan_table.keys() | ||
|
||
for vid in range (vlan_start, vlan_end): | ||
vlan_name = 'Vlan{}'.format(vid) | ||
vnid = vni_start+vid-vlan_start | ||
vni_name = '{}'.format(vnid) | ||
match_found = 'no' | ||
if len(db.cfgdb.get_entry('VLAN', vlan_name)) == 0: | ||
click.echo("{} not configured".format(vlan_name)) | ||
continue | ||
if vxlan_keys is not None: | ||
for key in vxlan_keys: | ||
if (vxlan_table[key]['vlan'] == vlan_name): | ||
print(vlan_name + " already mapped") | ||
match_found = 'yes' | ||
break | ||
if (vxlan_table[key]['vni'] == vni_name): | ||
print("VNI:" + vni_name + " already mapped ") | ||
match_found = 'yes' | ||
break | ||
if (match_found == 'yes'): | ||
continue | ||
fvs = {'vni': vni_name, | ||
'vlan' : vlan_name} | ||
mapname = vxlan_name + '|' + 'map_' + vni_name + '_' + vlan_name | ||
db.cfgdb.set_entry('VXLAN_TUNNEL_MAP', mapname, fvs) | ||
|
||
@vxlan_map_range.command('del') | ||
@click.argument('vxlan_name', metavar='<vxlan_name>', required=True) | ||
@click.argument('vlan_start', metavar='<vlan_start>', required=True, type=int) | ||
@click.argument('vlan_end', metavar='<vlan_end>', required=True, type=int) | ||
@click.argument('vni_start', metavar='<vni_start>', required=True, type=int) | ||
@clicommon.pass_db | ||
def del_vxlan_map_range(db, vxlan_name, vlan_start, vlan_end, vni_start): | ||
"""Del Range of vlan-vni mappings""" | ||
ctx = click.get_current_context() | ||
if clicommon.is_vlanid_in_range(vlan_start) is False: | ||
ctx.fail(" Invalid Vlan Id , Valid Range : 1 to 4094 ") | ||
if clicommon.is_vlanid_in_range(vlan_end) is False: | ||
ctx.fail(" Invalid Vlan Id , Valid Range : 1 to 4094 ") | ||
if (vlan_start > vlan_end): | ||
ctx.fail("vlan_end should be greater or equal to vlan_start") | ||
if clicommon.vni_id_is_valid(vni_start) is False: | ||
ctx.fail("Invalid VNI {}. Valid range [1 to 16777215].".format(vni_start)) | ||
if clicommon.vni_id_is_valid(vni_start+vlan_end-vlan_start) is False: | ||
ctx.fail("Invalid VNI End {}. Valid range [1 to 16777215].".format(vni_start)) | ||
|
||
if len(db.cfgdb.get_entry('VXLAN_TUNNEL', vxlan_name)) == 0: | ||
ctx.fail("VTEP {} not configured".format(vxlan_name)) | ||
|
||
vlan_end = vlan_end + 1 | ||
for vid in range (vlan_start, vlan_end): | ||
vlan_name = 'Vlan{}'.format(vid) | ||
vnid = vni_start+vid-vlan_start | ||
vni_name = '{}'.format(vnid) | ||
if clicommon.is_vni_vrf_mapped(db, vni_name) is False: | ||
print("Skipping Vlan {} VNI {} mapped delete. ".format(vlan_name, vni_name)) | ||
continue | ||
|
||
mapname = vxlan_name + '|' + 'map_' + vni_name + '_' + vlan_name | ||
db.cfgdb.set_entry('VXLAN_TUNNEL_MAP', mapname, None) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1522,6 +1522,5 @@ def ztp(status, verbose): | |
cmd = cmd + " --verbose" | ||
run_command(cmd, display_cmd=verbose) | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change doesn't look obligatory. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will handle this in the next PR. |
||
if __name__ == '__main__': | ||
cli() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you have some test coverage for this case as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok will do.