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 @@ ...@@ -12,7 +12,7 @@
"V4": {"container": "1.1.0.0/24", "mask": 31}, "V4": {"container": "1.1.0.0/24", "mask": 31},
"V6": {"container": "dead:beef::/64", "mask": 126}, "V6": {"container": "dead:beef::/64", "mask": 126},
"domain_name": ".lo" "domain_name": ".lo"
}, },
"TRUNK": { "TRUNK": {
"V4": {"container": "1.1.1.0/24", "mask": 31}, "V4": {"container": "1.1.1.0/24", "mask": 31},
"V6": {"container": "dead:beef::/64", "mask": 126}, "V6": {"container": "dead:beef::/64", "mask": 126},
......
...@@ -106,6 +106,7 @@ def find_networks(network_container=None, network=None, ip_version=4): ...@@ -106,6 +106,7 @@ def find_networks(network_container=None, network=None, ip_version=4):
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password), auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False 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}" 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() return r.json()
...@@ -135,7 +136,7 @@ def get_network_capacity(network=None): ...@@ -135,7 +136,7 @@ def get_network_capacity(network=None):
return utilization 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] assert ip_version in [4, 6]
endpoint = 'network' if ip_version == 4 else 'ipv6network' endpoint = 'network' if ip_version == 4 else 'ipv6network'
...@@ -177,15 +178,17 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params: ...@@ -177,15 +178,17 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
headers={'content-type': "application/json"}, headers={'content-type': "application/json"},
verify=False 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 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'] allocated_network = r.json()['network']
if ip_version==4: if ip_version==4:
return V4ServiceNetwork(v4=allocated_network) return V4ServiceNetwork(v4=allocated_network)
else: else:
return V6ServiceNetwork(v6=allocated_network) 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. Allocate IPv4 network within the container of the specified service type.
""" """
...@@ -195,7 +198,7 @@ def allocate_service_ipv4_network(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." 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) 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. Allocate IPv6 network within the container of the specified service type.
""" """
...@@ -205,10 +208,12 @@ def allocate_service_ipv6_network(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." 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) 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. 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() oss = settings.load_oss_params()
assert oss.IPAM.INFOBLOX assert oss.IPAM.INFOBLOX
infoblox_params = oss.IPAM.INFOBLOX infoblox_params = oss.IPAM.INFOBLOX
...@@ -240,17 +245,20 @@ def _find_next_available_ip(infoblox_params, network_ref): ...@@ -240,17 +245,20 @@ def _find_next_available_ip(infoblox_params, network_ref):
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password), auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False 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 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() assert 'ips' in r.json()
received_ip = r.json()['ips'] received_ip = r.json()['ips']
assert len(received_ip) == 1 assert len(received_ip) == 1
return received_ip[0] 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. If network is not None, allocate host in that network.
Otherwise if addr is not None, allocate host with that address. 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." assert addr or network, "You must specify either the host address or the network CIDR."
oss = settings.load_oss_params() oss = settings.load_oss_params()
assert oss.IPAM.INFOBLOX assert oss.IPAM.INFOBLOX
...@@ -267,8 +275,6 @@ def allocate_host(hostname=None, addr=None, network=None): ...@@ -267,8 +275,6 @@ def allocate_host(hostname=None, addr=None, network=None):
else: else:
ip_version = _ip_addr_version(addr) ip_version = _ip_addr_version(addr)
# TODO: use same request for both IP and DNS records
ipv4_req_payload = { ipv4_req_payload = {
"ipv4addrs": [ "ipv4addrs": [
{ {
...@@ -333,7 +339,7 @@ def allocate_host(hostname=None, addr=None, network=None): ...@@ -333,7 +339,7 @@ def allocate_host(hostname=None, addr=None, network=None):
else: else:
return V6HostAddress(v6=addr) 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). Allocate host with both IPv4 and IPv6 address (and respective DNS records).
The first network with available space for this service type is used. 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): ...@@ -359,7 +365,9 @@ def allocate_host_by_service_type(hostname=None, service_type=None):
if capacity < 1000: if capacity < 1000:
first_nonfull_ipv4_network = ipv4_network_info["network"] first_nonfull_ipv4_network = ipv4_network_info["network"]
break 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." 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) 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): ...@@ -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) 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 len(ipv6_networks_info) >= 1, "No IPv6 network exists in the container for this service type."
assert 'network' in ipv6_networks_info[0] 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']) v6_host = allocate_host(hostname=hostname+domain_name, network=ipv6_networks_info[0]['network'])
return HostAddresses(v4=v4_host,v6=v6_host) return HostAddresses(v4=v4_host,v6=v6_host)
...@@ -451,7 +460,7 @@ if __name__ == '__main__': ...@@ -451,7 +460,7 @@ if __name__ == '__main__':
elif choice == '2': elif choice == '2':
ip_version = int(input("Enter IP version (4 or 6): ")) 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)) print(json.dumps(networks, indent=2))
elif choice == '3': elif choice == '3':
...@@ -477,21 +486,21 @@ if __name__ == '__main__': ...@@ -477,21 +486,21 @@ if __name__ == '__main__':
print(json.dumps(str(deleted_network), indent=2)) print(json.dumps(str(deleted_network), indent=2))
elif choice == '6': 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: ") addr = input("Enter IP address to allocate: ")
alloc_ip = allocate_host(hostname=hostname, addr=addr) alloc_ip = allocate_host(hostname=hostname, addr=addr)
print(json.dumps(str(alloc_ip), indent=2)) print(json.dumps(str(alloc_ip), indent=2))
elif choice == '7': 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): ") network = input("Enter an existing network to allocate from (in CIDR notation): ")
alloc_ip = allocate_host(hostname=hostname, network=network) alloc_ip = allocate_host(hostname=hostname, network=network)
print(json.dumps(str(alloc_ip), indent=2)) print(json.dumps(str(alloc_ip), indent=2))
elif choice == '8': elif choice == '8':
hostname = input("Enter host name: ") hostname = input("Enter host name (not including domain name): ")
service_type = input("Enter service type: ") 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)) print(json.dumps(str(alloc_ip), indent=2))
elif choice == '9': elif choice == '9':
......
...@@ -39,10 +39,10 @@ def new_service_networks(service_type) -> ServiceNetworks: ...@@ -39,10 +39,10 @@ def new_service_networks(service_type) -> ServiceNetworks:
v6=v6_service_network) v6=v6_service_network)
def new_device_lo_address(hostname) -> HostAddresses: def new_service_host(hostname, service_type) -> HostAddresses:
return _ipam.allocate_host_by_service_type(hostname=hostname, service_type='LO') return _ipam.allocate_service_host(hostname=hostname, service_type=service_type)
if __name__ == '__main__': if __name__ == '__main__':
#new_service_networks('TRUNK') new_service_networks('TRUNK')
new_device_lo_address('newhost1') #new_service_host('newhost12', 'TRUNK')
\ No newline at end of file \ 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