Support DHCP reservations in networks on client side
This commit is contained in:
parent
c66a83e6c5
commit
5d35adb4fc
|
@ -581,7 +581,7 @@ def cli_network():
|
||||||
@click.option(
|
@click.option(
|
||||||
'-d', '--description', 'description',
|
'-d', '--description', 'description',
|
||||||
default="",
|
default="",
|
||||||
help='Description of the network.'
|
help='Description of the network. Should not contain whitespace.'
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
'-i', '--ipnet', 'ip_network',
|
'-i', '--ipnet', 'ip_network',
|
||||||
|
@ -621,7 +621,7 @@ def net_add(vni, description, ip_network, ip_gateway, dhcp_flag):
|
||||||
@click.option(
|
@click.option(
|
||||||
'-d', '--description', 'description',
|
'-d', '--description', 'description',
|
||||||
default=None,
|
default=None,
|
||||||
help='Description of the network.'
|
help='Description of the network. Should not contain whitespace.'
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
'-i', '--ipnet', 'ip_network',
|
'-i', '--ipnet', 'ip_network',
|
||||||
|
@ -715,6 +715,93 @@ def net_list(limit):
|
||||||
retcode, retmsg = pvc_network.get_list(zk_conn, limit)
|
retcode, retmsg = pvc_network.get_list(zk_conn, limit)
|
||||||
cleanup(retcode, retmsg, zk_conn)
|
cleanup(retcode, retmsg, zk_conn)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# pvc network dhcp
|
||||||
|
###############################################################################
|
||||||
|
@click.group(name='dhcp', short_help='Manage a PVC virtual network DHCP reservations.', context_settings=CONTEXT_SETTINGS)
|
||||||
|
def net_dhcp():
|
||||||
|
"""
|
||||||
|
Manage host DHCP reservations of a VXLAN network in the PVC cluster.
|
||||||
|
|
||||||
|
Note: DHCP reservations are only useful if the network has DHCP enabled.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# pvc network dhcp add
|
||||||
|
###############################################################################
|
||||||
|
@click.command(name='add', short_help='Add a DHCP reservation to a virtual network.')
|
||||||
|
@click.option(
|
||||||
|
'-d', '--description', 'description',
|
||||||
|
default=None,
|
||||||
|
help='Description of the DHCP reservation; defaults to MACADDR if unspecified. Should not contain whitespace.'
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
'net'
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
'ipaddr'
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
'macaddr'
|
||||||
|
)
|
||||||
|
def net_dhcp_add(net, ipaddr, macaddr, description):
|
||||||
|
"""
|
||||||
|
Add a new DHCP reservation of IP address IPADDR for MAC address MACADDR to virtual network NET; NET can be either a VNI or description.
|
||||||
|
"""
|
||||||
|
|
||||||
|
zk_conn = pvc_common.startZKConnection(zk_host)
|
||||||
|
retcode, retmsg = pvc_network.add_dhcp_reservation(zk_conn, net, ipaddr, macaddr, description)
|
||||||
|
cleanup(retcode, retmsg, zk_conn)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# pvc network dhcp remove
|
||||||
|
###############################################################################
|
||||||
|
@click.command(name='remove', short_help='Remove a DHCP reservation from a virtual network.')
|
||||||
|
@click.argument(
|
||||||
|
'net'
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
'reservation'
|
||||||
|
)
|
||||||
|
def net_dhcp_remove(net, reservation):
|
||||||
|
"""
|
||||||
|
Remove a DHCP reservation RESERVATION from virtual network NET; RESERVATION can be either a MAC address, an IP address, or a description; NET can be either a VNI or description.
|
||||||
|
"""
|
||||||
|
|
||||||
|
zk_conn = pvc_common.startZKConnection(zk_host)
|
||||||
|
retcode, retmsg = pvc_network.remove_dhcp_reservation(zk_conn, net, reservation)
|
||||||
|
cleanup(retcode, retmsg, zk_conn)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# pvc network dhcp list
|
||||||
|
###############################################################################
|
||||||
|
@click.command(name='list', short_help='List all DHCP reservation objects.')
|
||||||
|
@click.argument(
|
||||||
|
'net'
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
'limit', default=None, required=False
|
||||||
|
)
|
||||||
|
def net_dhcp_list(net, limit):
|
||||||
|
"""
|
||||||
|
List all DHCP reservations in virtual network NET; optionally only match elements matching regex LIMIT; NET can be either a VNI or description.
|
||||||
|
"""
|
||||||
|
|
||||||
|
zk_conn = pvc_common.startZKConnection(zk_host)
|
||||||
|
retcode, retmsg = pvc_network.get_list_dhcp_reservations(zk_conn, net, limit)
|
||||||
|
cleanup(retcode, retmsg, zk_conn)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# pvc network acl
|
||||||
|
###############################################################################
|
||||||
|
@click.group(name='acl', short_help='Manage a PVC virtual network firewall ACL rule.', context_settings=CONTEXT_SETTINGS)
|
||||||
|
def net_acl():
|
||||||
|
"""
|
||||||
|
Manage firewall ACLs of a VXLAN network in the PVC cluster.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -813,6 +900,12 @@ cli_network.add_command(net_modify)
|
||||||
cli_network.add_command(net_remove)
|
cli_network.add_command(net_remove)
|
||||||
cli_network.add_command(net_info)
|
cli_network.add_command(net_info)
|
||||||
cli_network.add_command(net_list)
|
cli_network.add_command(net_list)
|
||||||
|
cli_network.add_command(net_dhcp)
|
||||||
|
cli_network.add_command(net_acl)
|
||||||
|
|
||||||
|
net_dhcp.add_command(net_dhcp_add)
|
||||||
|
net_dhcp.add_command(net_dhcp_remove)
|
||||||
|
net_dhcp.add_command(net_dhcp_list)
|
||||||
|
|
||||||
cli.add_command(cli_node)
|
cli.add_command(cli_node)
|
||||||
cli.add_command(cli_router)
|
cli.add_command(cli_router)
|
||||||
|
|
|
@ -101,23 +101,27 @@ def getNetworkDescription(zk_conn, network):
|
||||||
return net_description
|
return net_description
|
||||||
|
|
||||||
def getNetworkDHCPReservations(zk_conn, vni):
|
def getNetworkDHCPReservations(zk_conn, vni):
|
||||||
n_dhcp_reservations = zk_conn.get_children('/networks/{}/dhcp_reservations'.format(vni))
|
# Get a list of VNIs by listing the children of /networks/<vni>/dhcp_reservations
|
||||||
return None
|
dhcp_reservations = sorted(zk_conn.get_children('/networks/{}/dhcp_reservations'.format(vni)))
|
||||||
|
return dhcp_reservations
|
||||||
|
|
||||||
def getNetworkFirewallRules(zk_conn, vni):
|
def getNetworkFirewallRules(zk_conn, vni):
|
||||||
n_firewall_rules = zk_conn.get_children('/networks/{}/firewall_rules'.format(vni))
|
firewall_rules = zk_conn.get_children('/networks/{}/firewall_rules'.format(vni))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getNetworkInformation(zk_conn, vni):
|
def getNetworkInformation(zk_conn, vni):
|
||||||
# Obtain basic information
|
|
||||||
description = zk_conn.get('/networks/{}'.format(vni))[0].decode('ascii')
|
description = zk_conn.get('/networks/{}'.format(vni))[0].decode('ascii')
|
||||||
ip_network = zk_conn.get('/networks/{}/ip_network'.format(vni))[0].decode('ascii')
|
ip_network = zk_conn.get('/networks/{}/ip_network'.format(vni))[0].decode('ascii')
|
||||||
ip_gateway = zk_conn.get('/networks/{}/ip_gateway'.format(vni))[0].decode('ascii')
|
ip_gateway = zk_conn.get('/networks/{}/ip_gateway'.format(vni))[0].decode('ascii')
|
||||||
dhcp_flag = zk_conn.get('/networks/{}/dhcp_flag'.format(vni))[0].decode('ascii')
|
dhcp_flag = zk_conn.get('/networks/{}/dhcp_flag'.format(vni))[0].decode('ascii')
|
||||||
|
|
||||||
# Add a human-friendly space
|
|
||||||
return description, ip_network, ip_gateway, dhcp_flag
|
return description, ip_network, ip_gateway, dhcp_flag
|
||||||
|
|
||||||
|
def getDHCPReservationInformation(zk_conn, vni, reservation):
|
||||||
|
description = zkhandler.readdata(zk_conn, '/networks/{}/dhcp_reservations/{}'.format(vni, reservation))
|
||||||
|
ip_address = zkhandler.readdata(zk_conn, '/networks/{}/dhcp_reservations/{}/ipv4addr'.format(vni, reservation))
|
||||||
|
mac_address = zkhandler.readdata(zk_conn, '/networks/{}/dhcp_reservations/{}/macaddr'.format(vni, reservation))
|
||||||
|
return description, ip_address, mac_address
|
||||||
|
|
||||||
def formatNetworkInformation(zk_conn, vni, long_output):
|
def formatNetworkInformation(zk_conn, vni, long_output):
|
||||||
description, ip_network, ip_gateway, dhcp_flag = getNetworkInformation(zk_conn, vni)
|
description, ip_network, ip_gateway, dhcp_flag = getNetworkInformation(zk_conn, vni)
|
||||||
|
|
||||||
|
@ -139,110 +143,26 @@ def formatNetworkInformation(zk_conn, vni, long_output):
|
||||||
ainformation.append('{}DHCP enabled:{} {}{}{}'.format(ansiiprint.purple(), ansiiprint.end(), dhcp_flag_colour, dhcp_flag, colour_off))
|
ainformation.append('{}DHCP enabled:{} {}{}{}'.format(ansiiprint.purple(), ansiiprint.end(), dhcp_flag_colour, dhcp_flag, colour_off))
|
||||||
|
|
||||||
if long_output:
|
if long_output:
|
||||||
dhcp_reservations = getNetworkDHCPReservations(zk_conn, vni)
|
dhcp_reservations_list = zk_conn.get_children('/networks/{}/dhcp_reservations'.format(vni))
|
||||||
if dhcp_reservations:
|
if dhcp_reservations_list:
|
||||||
ainformation.append('')
|
ainformation.append('')
|
||||||
ainformation.append('{}Client DHCP reservations:{}'.format(ansiiprint.bold(), ansiiprint.end()))
|
ainformation.append('{}Client DHCP reservations:{}'.format(ansiiprint.bold(), ansiiprint.end()))
|
||||||
ainformation.append('')
|
ainformation.append('')
|
||||||
|
dhcp_reservations_string = formatDHCPReservationList(zk_conn, vni, dhcp_reservations_list)
|
||||||
firewall_rules = getNetworkFirewallRules(zk_conn, vni)
|
for line in dhcp_reservations_string.split('\n'):
|
||||||
|
ainformation.append(line)
|
||||||
|
firewall_rules = zk_conn.get_children('/networks/{}/firewall_rules'.format(vni))
|
||||||
if firewall_rules:
|
if firewall_rules:
|
||||||
ainformation.append('')
|
ainformation.append('')
|
||||||
ainformation.append('{}Network firewall rules:{}'.format(ansiiprint.bold(), ansiiprint.end()))
|
ainformation.append('{}Network firewall rules:{}'.format(ansiiprint.bold(), ansiiprint.end()))
|
||||||
ainformation.append('')
|
ainformation.append('')
|
||||||
|
formatted_firewall_rules = get_list_firewall_rules(zk_conn, vni)
|
||||||
|
|
||||||
# Join it all together
|
# Join it all together
|
||||||
information = '\n'.join(ainformation)
|
information = '\n'.join(ainformation)
|
||||||
return information
|
return information
|
||||||
|
|
||||||
#
|
def formatNetworkList(zk_conn, net_list):
|
||||||
# Direct functions
|
|
||||||
#
|
|
||||||
def add_network(zk_conn, vni, description, ip_network, ip_gateway, dhcp_flag):
|
|
||||||
if description == '':
|
|
||||||
description = vni
|
|
||||||
|
|
||||||
# Check if a network with this VNI already exists
|
|
||||||
if zk_conn.exists('/networks/{}'.format(vni)):
|
|
||||||
return False, 'ERROR: A network with VNI {} already exists!'.format(vni)
|
|
||||||
|
|
||||||
# Add the new network to Zookeeper
|
|
||||||
transaction = zk_conn.transaction()
|
|
||||||
transaction.create('/networks/{}'.format(vni), description.encode('ascii'))
|
|
||||||
transaction.create('/networks/{}/ip_network'.format(vni), ip_network.encode('ascii'))
|
|
||||||
transaction.create('/networks/{}/ip_gateway'.format(vni), ip_gateway.encode('ascii'))
|
|
||||||
transaction.create('/networks/{}/dhcp_flag'.format(vni), str(dhcp_flag).encode('ascii'))
|
|
||||||
transaction.create('/networks/{}/dhcp_reservations'.format(vni), ''.encode('ascii'))
|
|
||||||
transaction.create('/networks/{}/firewall_rules'.format(vni), ''.encode('ascii'))
|
|
||||||
results = transaction.commit()
|
|
||||||
|
|
||||||
return True, 'Network "{}" added successfully!'.format(description)
|
|
||||||
|
|
||||||
def modify_network(zk_conn, vni, **parameters):
|
|
||||||
# Add the new network to Zookeeper
|
|
||||||
transaction = zk_conn.transaction()
|
|
||||||
if parameters['description'] != None:
|
|
||||||
transaction.set_data('/networks/{}'.format(vni), parameters['description'].encode('ascii'))
|
|
||||||
if parameters['ip_network'] != None:
|
|
||||||
transaction.set_data('/networks/{}/ip_network'.format(vni), parameters['ip_network'].encode('ascii'))
|
|
||||||
if parameters['ip_gateway'] != None:
|
|
||||||
transaction.set_data('/networks/{}/ip_gateway'.format(vni), parameters['ip_gateway'].encode('ascii'))
|
|
||||||
if parameters['dhcp_flag'] != None:
|
|
||||||
transaction.set_data('/networks/{}/dhcp_flag'.format(vni), str(parameters['dhcp_flag']).encode('ascii'))
|
|
||||||
results = transaction.commit()
|
|
||||||
|
|
||||||
return True, 'Network "{}" modified successfully!'.format(vni)
|
|
||||||
|
|
||||||
def remove_network(zk_conn, network):
|
|
||||||
# Validate and obtain alternate passed value
|
|
||||||
vni = getNetworkVNI(zk_conn, network)
|
|
||||||
description = getNetworkDescription(zk_conn, network)
|
|
||||||
if not vni:
|
|
||||||
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
|
||||||
|
|
||||||
# Delete the configuration
|
|
||||||
try:
|
|
||||||
zk_conn.delete('/networks/{}'.format(vni), recursive=True)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return True, 'Network "{}" removed successfully!'.format(description)
|
|
||||||
|
|
||||||
def get_info(zk_conn, network, long_output):
|
|
||||||
# Validate and obtain alternate passed value
|
|
||||||
net_vni = getNetworkVNI(zk_conn, network)
|
|
||||||
if net_vni == None:
|
|
||||||
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
|
||||||
|
|
||||||
information = formatNetworkInformation(zk_conn, net_vni, long_output)
|
|
||||||
click.echo(information)
|
|
||||||
click.echo('')
|
|
||||||
|
|
||||||
return True, ''
|
|
||||||
|
|
||||||
def get_list(zk_conn, limit):
|
|
||||||
net_list = []
|
|
||||||
full_net_list = zk_conn.get_children('/networks')
|
|
||||||
|
|
||||||
for net in full_net_list:
|
|
||||||
description = zkhandler.readdata(zk_conn, '/networks/{}'.format(net))
|
|
||||||
if limit != None:
|
|
||||||
try:
|
|
||||||
# Implcitly assume fuzzy limits
|
|
||||||
if re.match('\^.*', limit) == None:
|
|
||||||
limit = '.*' + limit
|
|
||||||
if re.match('.*\$', limit) == None:
|
|
||||||
limit = limit + '.*'
|
|
||||||
|
|
||||||
if re.match(limit, net) != None:
|
|
||||||
net_list.append(net)
|
|
||||||
if re.match(limit, description) != None:
|
|
||||||
net_list.append(net)
|
|
||||||
except Exception as e:
|
|
||||||
return False, 'Regex Error: {}'.format(e)
|
|
||||||
else:
|
|
||||||
net_list.append(net)
|
|
||||||
|
|
||||||
net_list_output = []
|
net_list_output = []
|
||||||
description = {}
|
description = {}
|
||||||
ip_network = {}
|
ip_network = {}
|
||||||
|
@ -260,7 +180,6 @@ def get_list(zk_conn, limit):
|
||||||
else:
|
else:
|
||||||
dhcp_flag_colour[net] = ansiiprint.blue()
|
dhcp_flag_colour[net] = ansiiprint.blue()
|
||||||
|
|
||||||
|
|
||||||
# Determine optimal column widths
|
# Determine optimal column widths
|
||||||
# Dynamic columns: node_name, hypervisor, migrated
|
# Dynamic columns: node_name, hypervisor, migrated
|
||||||
net_vni_length = 5
|
net_vni_length = 5
|
||||||
|
@ -331,7 +250,293 @@ def get_list(zk_conn, limit):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
click.echo(net_list_output_header)
|
output_string = net_list_output_header + '\n' + '\n'.join(sorted(net_list_output))
|
||||||
click.echo('\n'.join(sorted(net_list_output)))
|
return output_string
|
||||||
|
|
||||||
|
def formatDHCPReservationList(zk_conn, vni, dhcp_reservations_list):
|
||||||
|
dhcp_reservation_list_output = []
|
||||||
|
description = {}
|
||||||
|
ip_address = {}
|
||||||
|
mac_address = {}
|
||||||
|
|
||||||
|
# Gather information for printing
|
||||||
|
for dhcp_reservation in dhcp_reservations_list:
|
||||||
|
# get info
|
||||||
|
description[dhcp_reservation], ip_address[dhcp_reservation], mac_address[dhcp_reservation] = getDHCPReservationInformation(zk_conn, vni, dhcp_reservation)
|
||||||
|
|
||||||
|
|
||||||
|
# Determine optimal column widths
|
||||||
|
# Dynamic columns: node_name, hypervisor, migrated
|
||||||
|
reservation_description_length = 13
|
||||||
|
reservation_ip_address_length = 13
|
||||||
|
reservation_mac_address_length = 13
|
||||||
|
for dhcp_reservation in dhcp_reservations_list:
|
||||||
|
# description column
|
||||||
|
_reservation_description_length = len(description[dhcp_reservation]) + 1
|
||||||
|
if _reservation_description_length > reservation_description_length:
|
||||||
|
reservation_description_length = _reservation_description_length
|
||||||
|
# ip_network column
|
||||||
|
_reservation_ip_address_length = len(ip_address[dhcp_reservation]) + 1
|
||||||
|
if _reservation_ip_address_length > reservation_ip_address_length:
|
||||||
|
reservation_ip_address_length = _reservation_ip_address_length
|
||||||
|
# ip_gateway column
|
||||||
|
_reservation_mac_address_length = len(mac_address[dhcp_reservation]) + 1
|
||||||
|
if _reservation_mac_address_length > reservation_mac_address_length:
|
||||||
|
reservation_mac_address_length = _reservation_mac_address_length
|
||||||
|
|
||||||
|
# Format the string (header)
|
||||||
|
dhcp_reservation_list_output_header = '{bold}\
|
||||||
|
{reservation_description: <{reservation_description_length}} \
|
||||||
|
{reservation_ip_address: <{reservation_ip_address_length}} \
|
||||||
|
{reservation_mac_address: <{reservation_mac_address_length}} \
|
||||||
|
{end_bold}'.format(
|
||||||
|
bold=ansiiprint.bold(),
|
||||||
|
end_bold=ansiiprint.end(),
|
||||||
|
reservation_description_length=reservation_description_length,
|
||||||
|
reservation_ip_address_length=reservation_ip_address_length,
|
||||||
|
reservation_mac_address_length=reservation_mac_address_length,
|
||||||
|
reservation_description='Description',
|
||||||
|
reservation_ip_address='IP Address',
|
||||||
|
reservation_mac_address='MAC Address'
|
||||||
|
)
|
||||||
|
|
||||||
|
for dhcp_reservation in dhcp_reservations_list:
|
||||||
|
dhcp_reservation_list_output.append('{bold}\
|
||||||
|
{reservation_description: <{reservation_description_length}} \
|
||||||
|
{reservation_ip_address: <{reservation_ip_address_length}} \
|
||||||
|
{reservation_mac_address: <{reservation_mac_address_length}} \
|
||||||
|
{end_bold}'.format(
|
||||||
|
bold='',
|
||||||
|
end_bold='',
|
||||||
|
reservation_description_length=reservation_description_length,
|
||||||
|
reservation_ip_address_length=reservation_ip_address_length,
|
||||||
|
reservation_mac_address_length=reservation_mac_address_length,
|
||||||
|
reservation_description=description[dhcp_reservation],
|
||||||
|
reservation_ip_address=ip_address[dhcp_reservation],
|
||||||
|
reservation_mac_address=mac_address[dhcp_reservation]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
output_string = dhcp_reservation_list_output_header + '\n' + '\n'.join(sorted(dhcp_reservation_list_output))
|
||||||
|
return output_string
|
||||||
|
|
||||||
|
def isValidMAC(macaddr):
|
||||||
|
allowed = re.compile(r"""
|
||||||
|
(
|
||||||
|
^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$
|
||||||
|
)
|
||||||
|
""",
|
||||||
|
re.VERBOSE|re.IGNORECASE)
|
||||||
|
|
||||||
|
if allowed.match(macaddr) is None:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isValidIP(ipaddr):
|
||||||
|
ip_blocks = str(ipaddr).split(".")
|
||||||
|
if len(ip_blocks) == 4:
|
||||||
|
for block in ip_blocks:
|
||||||
|
# Check if number is digit, if not checked before calling this function
|
||||||
|
if not block.isdigit():
|
||||||
|
return False
|
||||||
|
tmp = int(block)
|
||||||
|
if 0 > tmp > 255:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
#
|
||||||
|
# Direct functions
|
||||||
|
#
|
||||||
|
def add_network(zk_conn, vni, description, ip_network, ip_gateway, dhcp_flag):
|
||||||
|
if description == '':
|
||||||
|
description = vni
|
||||||
|
|
||||||
|
# Check if a network with this VNI already exists
|
||||||
|
if zk_conn.exists('/networks/{}'.format(vni)):
|
||||||
|
return False, 'ERROR: A network with VNI {} already exists!'.format(vni)
|
||||||
|
|
||||||
|
# Add the new network to Zookeeper
|
||||||
|
transaction = zk_conn.transaction()
|
||||||
|
transaction.create('/networks/{}'.format(vni), description.encode('ascii'))
|
||||||
|
transaction.create('/networks/{}/ip_network'.format(vni), ip_network.encode('ascii'))
|
||||||
|
transaction.create('/networks/{}/ip_gateway'.format(vni), ip_gateway.encode('ascii'))
|
||||||
|
transaction.create('/networks/{}/dhcp_flag'.format(vni), str(dhcp_flag).encode('ascii'))
|
||||||
|
transaction.create('/networks/{}/dhcp_reservations'.format(vni), ''.encode('ascii'))
|
||||||
|
transaction.create('/networks/{}/firewall_rules'.format(vni), ''.encode('ascii'))
|
||||||
|
results = transaction.commit()
|
||||||
|
|
||||||
|
return True, 'Network "{}" added successfully!'.format(description)
|
||||||
|
|
||||||
|
def modify_network(zk_conn, vni, **parameters):
|
||||||
|
# Add the new network to Zookeeper
|
||||||
|
transaction = zk_conn.transaction()
|
||||||
|
if parameters['description'] != None:
|
||||||
|
transaction.set_data('/networks/{}'.format(vni), parameters['description'].encode('ascii'))
|
||||||
|
if parameters['ip_network'] != None:
|
||||||
|
transaction.set_data('/networks/{}/ip_network'.format(vni), parameters['ip_network'].encode('ascii'))
|
||||||
|
if parameters['ip_gateway'] != None:
|
||||||
|
transaction.set_data('/networks/{}/ip_gateway'.format(vni), parameters['ip_gateway'].encode('ascii'))
|
||||||
|
if parameters['dhcp_flag'] != None:
|
||||||
|
transaction.set_data('/networks/{}/dhcp_flag'.format(vni), str(parameters['dhcp_flag']).encode('ascii'))
|
||||||
|
results = transaction.commit()
|
||||||
|
|
||||||
|
return True, 'Network "{}" modified successfully!'.format(vni)
|
||||||
|
|
||||||
|
def remove_network(zk_conn, network):
|
||||||
|
# Validate and obtain alternate passed value
|
||||||
|
vni = getNetworkVNI(zk_conn, network)
|
||||||
|
description = getNetworkDescription(zk_conn, network)
|
||||||
|
if not vni:
|
||||||
|
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
||||||
|
|
||||||
|
# Delete the configuration
|
||||||
|
try:
|
||||||
|
zk_conn.delete('/networks/{}'.format(vni), recursive=True)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return True, 'Network "{}" removed successfully!'.format(description)
|
||||||
|
|
||||||
|
|
||||||
|
def add_dhcp_reservation(zk_conn, network, ipaddress, macaddress, description):
|
||||||
|
# Validate and obtain standard passed value
|
||||||
|
net_vni = getNetworkVNI(zk_conn, network)
|
||||||
|
if net_vni == None:
|
||||||
|
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
||||||
|
|
||||||
|
# Use lowercase MAC format exclusively
|
||||||
|
macaddress = macaddress.lower()
|
||||||
|
|
||||||
|
if not isValidMAC(macaddress):
|
||||||
|
return False, 'ERROR: MAC address "{}" is not valid! Always use ":" as a separator.'.format(macaddress)
|
||||||
|
|
||||||
|
if not isValidIP(ipaddress):
|
||||||
|
return False, 'ERROR: IP address "{}" is not valid!'.format(macaddress)
|
||||||
|
|
||||||
|
if not description:
|
||||||
|
description = macaddress
|
||||||
|
|
||||||
|
if zk_conn.exists('/networks/{}/dhcp_reservations/{}'.format(net_vni, description)):
|
||||||
|
return False, 'ERROR: A reservation with description {} already exists!'.format(description)
|
||||||
|
|
||||||
|
# Add the new network to ZK
|
||||||
|
try:
|
||||||
|
zkhandler.writedata(zk_conn, {
|
||||||
|
'/networks/{}/dhcp_reservations/{}'.format(net_vni, description): description,
|
||||||
|
'/networks/{}/dhcp_reservations/{}/macaddr'.format(net_vni, description): macaddress,
|
||||||
|
'/networks/{}/dhcp_reservations/{}/ipv4addr'.format(net_vni, description): ipaddress
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
return False, 'ERROR: Failed to write to Zookeeper! Exception: "{}".'.format(e)
|
||||||
|
|
||||||
|
return True, 'DHCP reservation "{}" added successfully!'.format(description)
|
||||||
|
|
||||||
|
def remove_dhcp_reservation(zk_conn, network, reservation):
|
||||||
|
# Validate and obtain standard passed value
|
||||||
|
net_vni = getNetworkVNI(zk_conn, network)
|
||||||
|
if net_vni == None:
|
||||||
|
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
||||||
|
|
||||||
|
match_description = ''
|
||||||
|
|
||||||
|
# Check if the reservation matches a description, a mac, or an IP address currently in the database
|
||||||
|
reservation_list = zk_conn.get_children('/networks/{}/dhcp_reservations'.format(net_vni))
|
||||||
|
for description in reservation_list:
|
||||||
|
macaddress = zkhandler.readdata(zk_conn, '/networks/{}/dhcp_reservations/{}/macaddr'.format(net_vni, description))
|
||||||
|
ipaddress = zkhandler.readdata(zk_conn, '/networks/{}/dhcp_reservations/{}/ipv4addr'.format(net_vni, description))
|
||||||
|
if reservation == description or reservation == macaddress or reservation == ipaddress:
|
||||||
|
match_description = description
|
||||||
|
|
||||||
|
if not match_description:
|
||||||
|
return False, 'ERROR: No DHCP reservation exists matching "{}"!'.format(reservation)
|
||||||
|
|
||||||
|
# Remove the entry from zookeeper
|
||||||
|
try:
|
||||||
|
zk_conn.delete('/networks/{}/dhcp_reservations/{}'.format(net_vni, match_description), recursive=True)
|
||||||
|
except:
|
||||||
|
return False, 'ERROR: Failed to write to Zookeeper!'
|
||||||
|
|
||||||
|
return True, 'DHCP reservation "{}" removed successfully!'.format(match_description)
|
||||||
|
|
||||||
|
def get_info(zk_conn, network, long_output):
|
||||||
|
# Validate and obtain alternate passed value
|
||||||
|
net_vni = getNetworkVNI(zk_conn, network)
|
||||||
|
if net_vni == None:
|
||||||
|
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
||||||
|
|
||||||
|
information = formatNetworkInformation(zk_conn, net_vni, long_output)
|
||||||
|
click.echo(information)
|
||||||
|
click.echo('')
|
||||||
|
|
||||||
return True, ''
|
return True, ''
|
||||||
|
|
||||||
|
def get_list(zk_conn, limit):
|
||||||
|
net_list = []
|
||||||
|
full_net_list = zk_conn.get_children('/networks')
|
||||||
|
|
||||||
|
for net in full_net_list:
|
||||||
|
description = zkhandler.readdata(zk_conn, '/networks/{}'.format(net))
|
||||||
|
if limit != None:
|
||||||
|
try:
|
||||||
|
# Implcitly assume fuzzy limits
|
||||||
|
if re.match('\^.*', limit) == None:
|
||||||
|
limit = '.*' + limit
|
||||||
|
if re.match('.*\$', limit) == None:
|
||||||
|
limit = limit + '.*'
|
||||||
|
|
||||||
|
if re.match(limit, net) != None:
|
||||||
|
net_list.append(net)
|
||||||
|
if re.match(limit, description) != None:
|
||||||
|
net_list.append(net)
|
||||||
|
except Exception as e:
|
||||||
|
return False, 'Regex Error: {}'.format(e)
|
||||||
|
else:
|
||||||
|
net_list.append(net)
|
||||||
|
|
||||||
|
output_string = formatNetworkList(zk_conn, net_list)
|
||||||
|
click.echo(output_string)
|
||||||
|
|
||||||
|
return True, ''
|
||||||
|
|
||||||
|
def get_list_dhcp_reservations(zk_conn, network, limit):
|
||||||
|
# Validate and obtain alternate passed value
|
||||||
|
net_vni = getNetworkVNI(zk_conn, network)
|
||||||
|
if net_vni == None:
|
||||||
|
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
||||||
|
|
||||||
|
dhcp_reservations_list = []
|
||||||
|
full_dhcp_reservations_list = zk_conn.get_children('/networks/{}/dhcp_reservations'.format(net_vni))
|
||||||
|
|
||||||
|
for dhcp_reservation in full_dhcp_reservations_list:
|
||||||
|
if limit != None:
|
||||||
|
try:
|
||||||
|
# Implcitly assume fuzzy limits
|
||||||
|
if re.match('\^.*', limit) == None:
|
||||||
|
limit = '.*' + limit
|
||||||
|
if re.match('.*\$', limit) == None:
|
||||||
|
limit = limit + '.*'
|
||||||
|
|
||||||
|
if re.match(limit, net) != None:
|
||||||
|
dhcp_reservations_list.append(dhcp_reservation)
|
||||||
|
if re.match(limit, description) != None:
|
||||||
|
dhcp_reservations_list.append(dhcp_reservation)
|
||||||
|
except Exception as e:
|
||||||
|
return False, 'Regex Error: {}'.format(e)
|
||||||
|
else:
|
||||||
|
dhcp_reservations_list.append(dhcp_reservation)
|
||||||
|
|
||||||
|
output_string = formatDHCPReservationList(zk_conn, net_vni, dhcp_reservations_list)
|
||||||
|
click.echo(output_string)
|
||||||
|
|
||||||
|
return True, ''
|
||||||
|
|
||||||
|
def get_list_firewall_rules(zk_conn, network):
|
||||||
|
# Validate and obtain alternate passed value
|
||||||
|
net_vni = getNetworkVNI(zk_conn, network)
|
||||||
|
if net_vni == None:
|
||||||
|
return False, 'ERROR: Could not find network "{}" in the cluster!'.format(network)
|
||||||
|
|
||||||
|
firewall_rules = getNetworkFirewallRules(zk_conn, net_vni)
|
||||||
|
return firewall_rules
|
||||||
|
|
Loading…
Reference in New Issue