Skip to content
Snippets Groups Projects
Commit ad16d7e6 authored by JORGE SASIAIN's avatar JORGE SASIAIN
Browse files

NAT-152: some cleanup and pending TODOs

parent 3bd18928
No related branches found
No related tags found
1 merge request!9Ipam service
......@@ -12,7 +12,7 @@
"V4": {"container": "1.1.0.0/24", "mask": 31},
"V6": {"container": "dead:beef::/64", "mask": 126},
"domain_name": ".lo"
},
},
"TRUNK": {
"V4": {"container": "1.1.1.0/24", "mask": 31},
"V6": {"container": "dead:beef::/64", "mask": 126},
......
......@@ -106,6 +106,7 @@ def find_networks(network_container=None, network=None, ip_version=4):
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False
)
# TODO: propagate "network not found" error to caller
assert r.status_code >= 200 and r.status_code < 300, f"HTTP error {r.status_code}: {r.reason}\n\n{r.text}"
return r.json()
......@@ -135,7 +136,7 @@ def get_network_capacity(network=None):
return utilization
def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params: Union[settings.V4NetworkParams, settings.V6NetworkParams], ip_version=4):
def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params: Union[settings.V4NetworkParams, settings.V6NetworkParams], ip_version=4) -> Union[V4ServiceNetwork, V6ServiceNetwork]:
assert ip_version in [4, 6]
endpoint = 'network' if ip_version == 4 else 'ipv6network'
......@@ -177,15 +178,17 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
headers={'content-type': "application/json"},
verify=False
)
# TODO: handle no more available space for networks in the container
assert r.status_code >= 200 and r.status_code < 300, f"HTTP error {r.status_code}: {r.reason}\n\n{r.text}"
assert 'network' in r.json()
allocated_network = r.json()['network']
if ip_version==4:
return V4ServiceNetwork(v4=allocated_network)
else:
return V6ServiceNetwork(v6=allocated_network)
def allocate_service_ipv4_network(service_type):
def allocate_service_ipv4_network(service_type) -> V4ServiceNetwork:
"""
Allocate IPv4 network within the container of the specified service type.
"""
......@@ -195,7 +198,7 @@ def allocate_service_ipv4_network(service_type):
assert hasattr(ipam_params, service_type) and service_type != 'INFOBLOX', "Invalid service type."
return _allocate_network(ipam_params.INFOBLOX, getattr(ipam_params, service_type).V4, 4)
def allocate_service_ipv6_network(service_type):
def allocate_service_ipv6_network(service_type) -> V6ServiceNetwork:
"""
Allocate IPv6 network within the container of the specified service type.
"""
......@@ -205,10 +208,12 @@ def allocate_service_ipv6_network(service_type):
assert hasattr(ipam_params, service_type) and service_type != 'INFOBLOX', "Invalid service type."
return _allocate_network(ipam_params.INFOBLOX, getattr(ipam_params, service_type).V6, 6)
def delete_network(network):
def delete_network(network) -> Union[V4ServiceNetwork, V6ServiceNetwork]:
"""
Delete IPv4 or IPv6 network by CIDR.
"""
# TODO: should we check that there are no hosts in this network?
# Deleting a network deletes the hosts in it, but not the associated DNS records.
oss = settings.load_oss_params()
assert oss.IPAM.INFOBLOX
infoblox_params = oss.IPAM.INFOBLOX
......@@ -240,17 +245,20 @@ def _find_next_available_ip(infoblox_params, network_ref):
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False
)
# TODO: handle no more available IPs in the network
assert r.status_code >= 200 and r.status_code < 300, f"HTTP error {r.status_code}: {r.reason}\n\n{r.text}"
assert 'ips' in r.json()
received_ip = r.json()['ips']
assert len(received_ip) == 1
return received_ip[0]
def allocate_host(hostname=None, addr=None, network=None):
def allocate_host(hostname=None, addr=None, network=None) -> Union[V4HostAddress, V6HostAddress]:
"""
If network is not None, allocate host in that network.
Otherwise if addr is not None, allocate host with that address.
hostname parameter must be full name including domain name.
"""
# TODO: should hostnames be unique (i.e. fail if hostname already exists in this domain)?
assert addr or network, "You must specify either the host address or the network CIDR."
oss = settings.load_oss_params()
assert oss.IPAM.INFOBLOX
......@@ -267,8 +275,6 @@ def allocate_host(hostname=None, addr=None, network=None):
else:
ip_version = _ip_addr_version(addr)
# TODO: use same request for both IP and DNS records
ipv4_req_payload = {
"ipv4addrs": [
{
......@@ -333,7 +339,7 @@ def allocate_host(hostname=None, addr=None, network=None):
else:
return V6HostAddress(v6=addr)
def allocate_host_by_service_type(hostname=None, service_type=None):
def allocate_service_host(hostname=None, service_type=None) -> HostAddresses:
"""
Allocate host with both IPv4 and IPv6 address (and respective DNS records).
The first network with available space for this service type is used.
......@@ -359,7 +365,9 @@ def allocate_host_by_service_type(hostname=None, service_type=None):
if capacity < 1000:
first_nonfull_ipv4_network = ipv4_network_info["network"]
break
# TODO: create a new network if available space in the container.
# Create a new network if the existing networks in the container for the service type are all full.
if not first_nonfull_ipv4_network:
first_nonfull_ipv4_network = str(allocate_service_ipv4_network(service_type=service_type).v4)
assert first_nonfull_ipv4_network, "No available IPv4 addresses for this service type."
v4_host = allocate_host(hostname=hostname+domain_name, network=first_nonfull_ipv4_network)
......@@ -368,6 +376,7 @@ def allocate_host_by_service_type(hostname=None, service_type=None):
ipv6_networks_info = find_networks(network_container=str(ipv6_container), ip_version=6)
assert len(ipv6_networks_info) >= 1, "No IPv6 network exists in the container for this service type."
assert 'network' in ipv6_networks_info[0]
# TODO: if "no available IP" error, create a new network?
v6_host = allocate_host(hostname=hostname+domain_name, network=ipv6_networks_info[0]['network'])
return HostAddresses(v4=v4_host,v6=v6_host)
......@@ -451,7 +460,7 @@ if __name__ == '__main__':
elif choice == '2':
ip_version = int(input("Enter IP version (4 or 6): "))
networks = find_networks(ip_version=ip_version) #, network_container="10.255.255.0/24"
networks = find_networks(ip_version=ip_version)
print(json.dumps(networks, indent=2))
elif choice == '3':
......@@ -477,21 +486,21 @@ if __name__ == '__main__':
print(json.dumps(str(deleted_network), indent=2))
elif choice == '6':
hostname = input("Enter host name: ")
hostname = input("Enter host name (full name including domain name): ")
addr = input("Enter IP address to allocate: ")
alloc_ip = allocate_host(hostname=hostname, addr=addr)
print(json.dumps(str(alloc_ip), indent=2))
elif choice == '7':
hostname = input("Enter host name: ")
hostname = input("Enter host name (full name including domain name): ")
network = input("Enter an existing network to allocate from (in CIDR notation): ")
alloc_ip = allocate_host(hostname=hostname, network=network)
print(json.dumps(str(alloc_ip), indent=2))
elif choice == '8':
hostname = input("Enter host name: ")
hostname = input("Enter host name (not including domain name): ")
service_type = input("Enter service type: ")
alloc_ip = allocate_host_by_service_type(hostname=hostname, service_type=service_type)
alloc_ip = allocate_service_host(hostname=hostname, service_type=service_type)
print(json.dumps(str(alloc_ip), indent=2))
elif choice == '9':
......
......@@ -39,10 +39,10 @@ def new_service_networks(service_type) -> ServiceNetworks:
v6=v6_service_network)
def new_device_lo_address(hostname) -> HostAddresses:
return _ipam.allocate_host_by_service_type(hostname=hostname, service_type='LO')
def new_service_host(hostname, service_type) -> HostAddresses:
return _ipam.allocate_service_host(hostname=hostname, service_type=service_type)
if __name__ == '__main__':
#new_service_networks('TRUNK')
new_device_lo_address('newhost1')
\ No newline at end of file
new_service_networks('TRUNK')
#new_service_host('newhost12', 'TRUNK')
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment