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

Some IPAM calls for A/AAAA records

parent 71d2b14f
No related branches found
No related tags found
1 merge request!9Ipam service
...@@ -4,6 +4,7 @@ import json ...@@ -4,6 +4,7 @@ import json
import ipaddress import ipaddress
from pydantic import BaseSettings from pydantic import BaseSettings
from typing import Union from typing import Union
import random
from gso import settings from gso import settings
...@@ -96,7 +97,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params: ...@@ -96,7 +97,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
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'
_ipv4_req_payload = { ipv4_req_payload = {
"network": { "network": {
"_object_function": "next_available_network", "_object_function": "next_available_network",
"_parameters": { "_parameters": {
...@@ -110,7 +111,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params: ...@@ -110,7 +111,7 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
} }
} }
_ipv6_req_payload = { ipv6_req_payload = {
"network": { "network": {
"_object_function": "next_available_network", "_object_function": "next_available_network",
"_parameters": { "_parameters": {
...@@ -124,12 +125,12 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params: ...@@ -124,12 +125,12 @@ def _allocate_network(infoblox_params: settings.InfoBloxParams, network_params:
} }
} }
_req_payload = _ipv4_req_payload if ip_version == 4 else _ipv6_req_payload req_payload = ipv4_req_payload if ip_version == 4 else ipv6_req_payload
r = requests.post( r = requests.post(
f'{_wapi(infoblox_params)}/{endpoint}', f'{_wapi(infoblox_params)}/{endpoint}',
params={'_return_fields': 'network'}, params={'_return_fields': 'network'},
json=_req_payload, json=req_payload,
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password), auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
headers={'content-type': "application/json"}, headers={'content-type': "application/json"},
verify=False) verify=False)
...@@ -145,16 +146,14 @@ def allocate_service_ipv4_network(service_type): ...@@ -145,16 +146,14 @@ def allocate_service_ipv4_network(service_type):
oss = settings.load_oss_params() oss = settings.load_oss_params()
assert oss.IPAM assert oss.IPAM
ipam_params = oss.IPAM ipam_params = oss.IPAM
# sanity: verify the service_type is a proper one assert hasattr(ipam_params, service_type) and service_type != 'INFOBLOX', "Invalid service type."
assert hasattr(ipam_params, service_type) and service_type != 'INFOBLOX'
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):
oss = settings.load_oss_params() oss = settings.load_oss_params()
assert oss.IPAM assert oss.IPAM
ipam_params = oss.IPAM ipam_params = oss.IPAM
# sanity: verify the service_type is a proper one assert hasattr(ipam_params, service_type) and service_type != 'INFOBLOX', "Invalid service type."
assert hasattr(ipam_params, service_type) and service_type != 'INFOBLOX'
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):
...@@ -193,7 +192,7 @@ def _find_next_available_ip(infoblox_params, network_ref): ...@@ -193,7 +192,7 @@ def _find_next_available_ip(infoblox_params, network_ref):
assert len(received_ip) == 1 assert len(received_ip) == 1
return received_ip[0] return received_ip[0]
def allocate_host(mac=None, hostname=None, addr=None, network=None): def allocate_host(mac=None, hostname=None, addr=None, network=None, service_type=None):
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
...@@ -209,7 +208,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None): ...@@ -209,7 +208,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
else: else:
ip_version = _ip_addr_version(addr) ip_version = _ip_addr_version(addr)
_ipv4_req_payload = { ipv4_req_payload = {
"ipv4addrs": [ "ipv4addrs": [
{ {
"ipv4addr": addr, "ipv4addr": addr,
...@@ -221,7 +220,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None): ...@@ -221,7 +220,7 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
"view": "default" "view": "default"
} }
_ipv6_req_payload = { ipv6_req_payload = {
"ipv6addrs": [ "ipv6addrs": [
{ {
"ipv6addr": addr "ipv6addr": addr
...@@ -232,17 +231,41 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None): ...@@ -232,17 +231,41 @@ def allocate_host(mac=None, hostname=None, addr=None, network=None):
"view": "default" "view": "default"
} }
_req_payload = _ipv4_req_payload if ip_version == 4 else _ipv6_req_payload ip_req_payload = ipv4_req_payload if ip_version == 4 else ipv6_req_payload
r = requests.post( r = requests.post(
f'{_wapi(infoblox_params)}/record:host', f'{_wapi(infoblox_params)}/record:host',
json=_req_payload, json=ip_req_payload,
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password), auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False) verify=False)
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 isinstance(r.json(), str) assert isinstance(r.json(), str)
assert r.json().startswith("record:host/") assert r.json().startswith("record:host/")
a_record_payload = {
"ipv4addr": addr,
"name": hostname,
"view": "default"
}
aaaa_record_payload = {
"ipv6addr": addr,
"name": hostname,
"view": "default"
}
endpoint = 'record:a' if ip_version == 4 else 'record:aaaa'
dns_req_payload = a_record_payload if ip_version == 4 else aaaa_record_payload
r = requests.post(
f'{_wapi(infoblox_params)}/{endpoint}',
json=dns_req_payload,
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False)
assert r.status_code >= 200 and r.status_code < 300, f"HTTP error {r.status_code}: {r.reason}\n\n{r.text}"
assert isinstance(r.json(), str)
assert r.json().startswith(f"{endpoint}/")
if ip_version == 4: if ip_version == 4:
return V4HostAddress(v4=addr) return V4HostAddress(v4=addr)
else: else:
...@@ -272,7 +295,26 @@ def delete_host_by_ip(addr): ...@@ -272,7 +295,26 @@ def delete_host_by_ip(addr):
f'{_wapi(infoblox_params)}/{host_ref}', f'{_wapi(infoblox_params)}/{host_ref}',
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password), auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False) verify=False)
r.raise_for_status() assert r.status_code >= 200 and r.status_code < 300, f"HTTP error {r.status_code}: {r.reason}\n\n{r.text}"
# Also find and delete the associated dns a/aaaa record
endpoint = 'record:a' if ip_version == 4 else 'record:aaaa'
r = requests.get(
f'{_wapi(infoblox_params)}/{endpoint}',
params={ip_param: addr},
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False)
dns_data = r.json()
assert len(dns_data) == 1, "DNS record does not exist."
assert '_ref' in dns_data[0]
dns_ref = dns_data[0]['_ref']
r = requests.delete(
f'{_wapi(infoblox_params)}/{dns_ref}',
auth=HTTPBasicAuth(infoblox_params.username, infoblox_params.password),
verify=False)
assert r.status_code >= 200 and r.status_code < 300, f"HTTP error {r.status_code}: {r.reason}\n\n{r.text}"
if ip_version == 4: if ip_version == 4:
return V4HostAddress(v4=addr) return V4HostAddress(v4=addr)
...@@ -287,8 +329,9 @@ if __name__ == '__main__': ...@@ -287,8 +329,9 @@ if __name__ == '__main__':
print("4. Delete network") print("4. Delete network")
print("5. Allocate host by IP") print("5. Allocate host by IP")
print("6. Allocate host by network CIDR") print("6. Allocate host by network CIDR")
print("7. Delete host by IP") print("7. Allocate host by service type")
print("8. Exit") print("8. Delete host by IP")
print("9. Exit")
choice = input("Enter your choice: ") choice = input("Enter your choice: ")
...@@ -322,23 +365,32 @@ if __name__ == '__main__': ...@@ -322,23 +365,32 @@ if __name__ == '__main__':
elif choice == '5': elif choice == '5':
hostname = input("Enter host name: ") hostname = input("Enter host name: ")
addr = input("Enter IP address to allocate: ") addr = input("Enter IP address to allocate: ")
mac = input("Enter mac address (you can leave empty if IPv6): ") mac = ":".join(["{:02x}".format(random.randint(0x00, 0xff)) for i in range(6)]) #input("Enter MAC address (you can leave empty if IPv6): ")
alloc_ip = allocate_host(hostname=hostname, addr=addr, mac=mac) alloc_ip = allocate_host(hostname=hostname, addr=addr, mac=mac)
print(json.dumps(str(alloc_ip), indent=2)) print(json.dumps(str(alloc_ip), indent=2))
elif choice == '6': elif choice == '6':
hostname = input("Enter host name: ") hostname = input("Enter host 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): ")
mac = input("Enter mac address (you can leave empty if IPv6): ") mac = ":".join(["{:02x}".format(random.randint(0x00, 0xff)) for i in range(6)]) #input("Enter MAC address (you can leave empty if IPv6): ")
alloc_ip = allocate_host(hostname=hostname, network=network, mac=mac) alloc_ip = allocate_host(hostname=hostname, network=network, mac=mac)
print(json.dumps(str(alloc_ip), indent=2)) print(json.dumps(str(alloc_ip), indent=2))
elif choice == '7': elif choice == '7':
print("Not implemented.")
continue
hostname = input("Enter host name: ")
service_type = input("Enter service type: ")
mac = ":".join(["{:02x}".format(random.randint(0x00, 0xff)) for i in range(6)]) #input("Enter MAC address (you can leave empty if IPv6): ")
alloc_ip = allocate_host(hostname=hostname, service_type=service_type, mac=mac)
print(json.dumps(str(alloc_ip), indent=2))
elif choice == '8':
addr = input("Enter IP address of host to delete: ") addr = input("Enter IP address of host to delete: ")
deleted_host = delete_host_by_ip(addr=addr) deleted_host = delete_host_by_ip(addr=addr)
print(json.dumps(str(deleted_host), indent=2)) print(json.dumps(str(deleted_host), indent=2))
elif choice == '8': elif choice == '9':
print("Exiting...") print("Exiting...")
break break
......
import ipaddress import ipaddress
from pydantic import BaseSettings from pydantic import BaseSettings
from gso import settings from gso import settings
import _ipam
class ServiceNetworks(BaseSettings): class V4ServiceNetwork(BaseSettings):
v4: ipaddress.IPv4Network v4: ipaddress.IPv4Network
class V6ServiceNetwork(BaseSettings):
v6: ipaddress.IPv6Network v6: ipaddress.IPv6Network
class HostAddresses(BaseSettings): class ServiceNetworks(BaseSettings):
v4: V4ServiceNetwork
v6: V6ServiceNetwork
class V4HostAddress(BaseSettings):
v4: ipaddress.IPv4Address v4: ipaddress.IPv4Address
v6: ipaddress.IPv6Address
def new_service_networks( class V6HostAddress(BaseSettings):
service_params: settings.ServiceNetworkParams) -> ServiceNetworks: v6: ipaddress.IPv6Address
oss = settings.load_oss_params()
assert oss.IPAM.INFOBLOX
# TODO: load from ipam class HostAddresses(BaseSettings):
# cf. https://gitlab.geant.org/goat/gap-jenkins/-/blob/development/service-editor/gap_service_editor/ipam.py#L35-66 # noqa: E501 v4: V4HostAddress
v6: V6HostAddress
def new_service_networks(service_type) -> ServiceNetworks:
v4_service_network = _ipam.allocate_service_ipv4_network(service_type=service_type)
v6_service_network = _ipam.allocate_service_ipv6_network(service_type=service_type)
return ServiceNetworks( return ServiceNetworks(
v4=ipaddress.IPv4Network('10.0.0.0/24'), v4=v4_service_network,
v6=ipaddress.IPv6Network('dead:beef::/120')) v6=v6_service_network)
def new_device_lo_address() -> HostAddresses: def new_device_lo_address() -> HostAddresses:
...@@ -31,3 +46,7 @@ def new_device_lo_address() -> HostAddresses: ...@@ -31,3 +46,7 @@ def new_device_lo_address() -> HostAddresses:
return HostAddresses( return HostAddresses(
v4=ipaddress.IPv4Address('10.10.10.10'), v4=ipaddress.IPv4Address('10.10.10.10'),
v6=ipaddress.IPv6Address('fc00:798:aa:1::10')) v6=ipaddress.IPv6Address('fc00:798:aa:1::10'))
if __name__ == '__main__':
new_service_networks('TRUNK')
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment