From 02d113be4c7d81f529dbab6ac8b436f62db7c905 Mon Sep 17 00:00:00 2001 From: Ubuntu <jorge.sasiain@ehu.eus> Date: Wed, 3 May 2023 12:37:06 +0000 Subject: [PATCH] NAT-152: support allocate host by specific ip address in a specific service container --- gso/services/_ipam.py | 23 ++++++++++++++++------- gso/services/ipam.py | 11 +++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/gso/services/_ipam.py b/gso/services/_ipam.py index d3478337..08f54c1b 100644 --- a/gso/services/_ipam.py +++ b/gso/services/_ipam.py @@ -290,13 +290,14 @@ def _allocate_host(hostname=None, addr=None, network=None) -> Union[V4HostAddres else: return V6HostAddress(v6=addr) -def allocate_service_host(hostname=None, service_type=None, service_networks: ServiceNetworks = None) -> HostAddresses: +def allocate_service_host(hostname=None, service_type=None, service_networks: ServiceNetworks = None, host_addresses: HostAddresses = None) -> HostAddresses: """ Allocate host with both IPv4 and IPv6 address (and respective DNS records). The domain name is also taken from the service type and appended to specified hostname. If service_networks is provided, that one is used. - If service_networks is not provided, the first network with available space for this service type is used. - Note that if WFO will always specify the network after creating it, this mode won't be needed. + If service_networks is not provided, and host_addresses is provided, those specific addresses are used. + If neither is not provided, the first network with available space for this service type is used. + Note that if WFO will always specify the network/addresses after creating it, this mode won't be needed. """ oss = settings.load_oss_params() assert oss.IPAM @@ -308,7 +309,7 @@ def allocate_service_host(hostname=None, service_type=None, service_networks: Se domain_name = getattr(ipam_params, service_type).domain_name # IPv4 - if not service_networks: + if not service_networks and not host_addresses: ipv4_networks_info = _find_networks(network_container=str(ipv4_container), ip_version=4) assert len(ipv4_networks_info) >= 1, "No IPv4 network exists in the container for this service type." first_nonfull_ipv4_network = None @@ -323,13 +324,17 @@ def allocate_service_host(hostname=None, service_type=None, service_networks: Se 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) - else: + elif service_networks: network = service_networks.v4 assert network.subnet_of(ipv4_container) v4_host = _allocate_host(hostname=hostname+domain_name, network=str(network)) + elif host_addresses: + addr = host_addresses.v4 + assert addr in ipv4_container + v4_host = _allocate_host(hostname=hostname+domain_name, addr=str(addr)) # IPv6 - if not service_networks: + if not service_networks and not host_addresses: # ipv6 does not support capacity fetching (not even the GUI displays it). # Maybe it's assumed that there is always available space? ipv6_networks_info = _find_networks(network_container=str(ipv6_container), ip_version=6) @@ -337,10 +342,14 @@ def allocate_service_host(hostname=None, service_type=None, service_networks: Se 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']) - else: + elif service_networks: network = service_networks.v6 assert network.subnet_of(ipv6_container) v6_host = _allocate_host(hostname=hostname+domain_name, network=str(network)) + elif host_addresses: + addr = host_addresses.v6 + assert addr in ipv6_container + v6_host = _allocate_host(hostname=hostname+domain_name, addr=str(addr)) return HostAddresses(v4=v4_host.v4,v6=v6_host.v6) diff --git a/gso/services/ipam.py b/gso/services/ipam.py index 723e112e..92e66a0e 100644 --- a/gso/services/ipam.py +++ b/gso/services/ipam.py @@ -44,12 +44,23 @@ def new_service_host(hostname, service_type, service_networks: ServiceNetworks) if __name__ == '__main__': + # sample call flow to allocate two loopback interfaces and a trunk service + # new_service_host can be called passing networks or addresses + # - the first time is called by passing a specific ipv4/ipv6 address pair + # - the rest are called by passing the ipv4/ipv6 network pair + hostname_A = 'newhost1' hostname_B = 'newhost2' + # h1 loopback lo1_service_networks = new_service_networks('LO') + lo1_v4_host_address = lo1_service_networks.v4.network_address + lo1_v6_host_address = lo1_service_networks.v6.network_address + lo1_host_addresses = HostAddresses(v4=lo1_v4_host_address, v6=lo1_v6_host_address) new_service_host(hostname_A, 'LO', lo1_service_networks) + # h2 loopback lo2_service_networks = new_service_networks('LO') new_service_host(hostname_B, 'LO', lo2_service_networks) + # h1-h2 trunk trunk12_service_networks = new_service_networks('TRUNK') new_service_host(hostname_A, 'TRUNK', trunk12_service_networks) new_service_host(hostname_B, 'TRUNK', trunk12_service_networks) \ No newline at end of file -- GitLab