Skip to content
Snippets Groups Projects
Verified Commit 4da7fbe5 authored by Karel van Klink's avatar Karel van Klink :smiley_cat:
Browse files

update workflows to make use of infoblox service

parent f6b358fe
No related branches found
No related tags found
1 merge request!65Feature/add infoblox service
......@@ -34,7 +34,7 @@ def _allocate_network(
dns_view: str,
netmask: int,
containers: list[str],
comment: str,
comment: str | None = "",
) -> ipaddress.IPv4Network | ipaddress.IPv6Network:
for container in [ipaddress.ip_network(con) for con in containers]:
for network in container.subnets(new_prefix=netmask):
......@@ -58,7 +58,7 @@ def allocate_v4_network(service_type: str, comment: str | None = "") -> ipaddres
containers = getattr(oss, service_type).V4.containers
dns_view = getattr(oss, service_type).dns_view
return _allocate_network(conn, dns_view, netmask, containers, comment)
return ipaddress.IPv4Network(_allocate_network(conn, dns_view, netmask, containers, comment))
def allocate_v6_network(service_type: str, comment: str | None = "") -> ipaddress.IPv6Network:
......@@ -67,11 +67,11 @@ def allocate_v6_network(service_type: str, comment: str | None = "") -> ipaddres
containers = getattr(oss, service_type).V6.containers
dns_view = getattr(oss, service_type).dns_view
return _allocate_network(conn, dns_view, netmask, containers, comment)
return ipaddress.IPv6Network(_allocate_network(conn, dns_view, netmask, containers, comment))
def delete_network(ip_network: ipaddress.IPv4Network | ipaddress.IPv6Network) -> None:
conn = _setup_connection()
conn, _ = _setup_connection()
network = objects.Network.search(conn, cidr=str(ip_network))
if network:
network.delete()
......@@ -92,7 +92,7 @@ def allocate_host(
created_v6 = None
for ipv6_range in allocation_networks_v6:
v6_alloc = objects.IPAllocation.next_available_ip_from_cidr(dns_view, ipv6_range)
v6_alloc = objects.IPAllocation.next_available_ip_from_cidr(dns_view, str(ipv6_range))
ipv6_object = objects.IP.create(ip=v6_alloc, mac="00:00:00:00:00:00", configure_for_dhcp=False)
try:
new_host = objects.HostRecord.create(
......@@ -107,12 +107,13 @@ def allocate_host(
created_v4 = None
for ipv4_range in allocation_networks_v4:
v4_alloc = objects.IPAllocation.next_available_ip_from_cidr(dns_view, ipv4_range)
v4_alloc = objects.IPAllocation.next_available_ip_from_cidr(dns_view, str(ipv4_range))
ipv4_object = objects.IP.create(ip=v4_alloc, mac="00:00:00:00:00:00", configure_for_dhcp=False)
new_host = objects.HostRecord.search(conn, name=hostname)
new_host.ipv4addrs = [ipv4_object]
try:
new_host.update()
new_host = objects.HostRecord.search(conn, name=hostname)
created_v4 = ipaddress.IPv4Address(new_host.ipv4addr)
except InfobloxCannotUpdateObject:
logger.warning(f"Cannot find 1 available IP address in network {ipv4_range}.")
......@@ -124,7 +125,7 @@ def allocate_host(
def delete_host_by_ip(ip_addr: ipaddress.IPv4Address | ipaddress.IPv6Address) -> None:
conn = _setup_connection()
conn, _ = _setup_connection()
host = objects.HostRecord.search(conn, ipv4addr=ip_addr)
if host:
host.delete()
......@@ -133,6 +134,6 @@ def delete_host_by_ip(ip_addr: ipaddress.IPv4Address | ipaddress.IPv6Address) ->
def delete_host_by_fqdn(fqdn: str) -> None:
conn = _setup_connection()
conn, _ = _setup_connection()
host = objects.HostRecord.search(conn, name=fqdn)
host.delete()
......@@ -10,7 +10,7 @@ from gso.products.product_blocks import PhyPortCapacity
from gso.products.product_blocks.iptrunk import IptrunkType
from gso.products.product_types.iptrunk import IptrunkInactive, IptrunkProvisioning
from gso.products.product_types.router import Router
from gso.services import ipam, provisioning_proxy, subscriptions
from gso.services import infoblox, provisioning_proxy, subscriptions
from gso.services.provisioning_proxy import pp_interaction
from gso.workflows.utils import customer_selector
......@@ -90,15 +90,13 @@ def create_subscription(product: UUIDstr, customer: UUIDstr) -> State:
@step("Get information from IPAM")
def get_info_from_ipam(subscription: IptrunkProvisioning) -> State:
# TODO: get info about how these should be generated
subscription.iptrunk.iptrunk_ipv4_network = ipam.allocate_ipv4_network(
service_type="TRUNK",
comment=subscription.iptrunk.iptrunk_description,
).v4
subscription.iptrunk.iptrunk_ipv6_network = ipam.allocate_ipv6_network(
service_type="TRUNK",
comment=subscription.iptrunk.iptrunk_description,
).v6
subscription.iptrunk.iptrunk_ipv4_network = infoblox.allocate_v4_network(
"TRUNK", subscription.iptrunk.iptrunk_description
)
subscription.iptrunk.iptrunk_ipv6_network = infoblox.allocate_v6_network(
"TRUNK", subscription.iptrunk.iptrunk_description
)
return {"subscription": subscription}
......
......@@ -10,8 +10,7 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
from workflows.iptrunk import set_isis_to_9000
from gso.products.product_types.iptrunk import Iptrunk
from gso.services import ipam, provisioning_proxy
from gso.services.ipam import V4ServiceNetwork, V6ServiceNetwork
from gso.services import infoblox, provisioning_proxy
from gso.services.provisioning_proxy import pp_interaction
......@@ -59,21 +58,17 @@ def deprovision_ip_trunk_real(subscription: Iptrunk, process_id: UUIDstr) -> Sta
@step("Deprovision IPv4 networks")
def deprovision_ip_trunk_ipv4(subscription: Iptrunk) -> dict[str, V4ServiceNetwork | V6ServiceNetwork]:
service_network = ipam.delete_network(
network=ipaddress.ip_network(subscription.iptrunk.iptrunk_ipv4_network),
service_type="TRUNK",
)
return {"service_network": service_network}
def deprovision_ip_trunk_ipv4(subscription: Iptrunk) -> dict:
infoblox.delete_network(ipaddress.IPv4Network(subscription.iptrunk.iptrunk_ipv4_network))
return {"subscription": subscription}
@step("Deprovision IPv6 networks")
def deprovision_ip_trunk_ipv6(subscription: Iptrunk) -> dict[str, V4ServiceNetwork | V6ServiceNetwork]:
service_network = ipam.delete_network(
network=ipaddress.ip_network(subscription.iptrunk.iptrunk_ipv6_network),
service_type="TRUNK",
)
return {"service_network": service_network}
def deprovision_ip_trunk_ipv6(subscription: Iptrunk) -> dict:
infoblox.delete_network(ipaddress.IPv6Network(subscription.iptrunk.iptrunk_ipv6_network))
return {"subscription": subscription}
@workflow(
......@@ -82,8 +77,8 @@ def deprovision_ip_trunk_ipv6(subscription: Iptrunk) -> dict[str, V4ServiceNetwo
target=Target.TERMINATE,
)
def terminate_iptrunk() -> StepList:
run_config_steps = conditional(lambda state: state.get("remove_configuration", True))
run_ipam_steps = conditional(lambda state: state.get("clean_up_ipam", True))
run_config_steps = conditional(lambda state: state["remove_configuration"])
run_ipam_steps = conditional(lambda state: state["clean_up_ipam"])
config_steps = (
StepList([set_isis_to_9000])
......
......@@ -6,7 +6,7 @@ from orchestrator.forms import FormPage
from orchestrator.forms.validators import Choice
from orchestrator.targets import Target
from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUIDstr
from orchestrator.workflow import StepList, done, init, step, workflow
from orchestrator.workflow import StepList, conditional, done, init, step, workflow
from orchestrator.workflows.steps import resync, set_status, store_process_subscription
from orchestrator.workflows.utils import wrap_create_initial_input_form
......@@ -15,7 +15,7 @@ from gso.products.product_types import router
from gso.products.product_types.router import RouterInactive, RouterProvisioning
from gso.products.product_types.site import Site
from gso.products.shared import PortNumber
from gso.services import ipam, provisioning_proxy, subscriptions
from gso.services import infoblox, provisioning_proxy, subscriptions
from gso.services.provisioning_proxy import pp_interaction
from gso.workflows.utils import customer_selector, iso_from_ipv4
......@@ -59,26 +59,26 @@ def create_subscription(product: UUIDstr, customer: UUIDstr) -> State:
}
@step("Get information from IPAM")
def get_info_from_ipam(subscription: RouterProvisioning, is_ias_connected: bool) -> State:
lo0_alias = re.sub(".geant.net", "", subscription.router.router_fqdn)
lo0_name = f"lo0.{lo0_alias}"
lo0_addr = ipam.allocate_host(hostname=lo0_name, service_type="LO", cname_aliases=[lo0_alias])
subscription.router.router_lo_ipv4_address = lo0_addr.v4
subscription.router.router_lo_ipv6_address = lo0_addr.v6
@step("Allocate loopback interfaces in IPAM")
def ipam_allocate_loopback(subscription: RouterProvisioning, is_ias_connected: bool) -> State:
fqdn = subscription.router.router_fqdn
loopback_v4, loopback_v6 = infoblox.allocate_host(f"lo0.{fqdn}", "LO", [fqdn])
subscription.router.router_lo_ipv4_address = loopback_v4
subscription.router.router_lo_ipv6_address = loopback_v6
subscription.router.router_lo_iso_address = iso_from_ipv4(subscription.router.router_lo_ipv4_address)
subscription.router.router_is_ias_connected = is_ias_connected
if is_ias_connected is True:
subscription.router.router_si_ipv4_network = ipam.allocate_ipv4_network(
service_type="SI", comment=f"SI for {lo0_name}"
).v4
subscription.router.router_ias_lt_ipv4_network = ipam.allocate_ipv4_network(
service_type="LT_IAS", comment=f"LT for {lo0_name}"
).v4
subscription.router.router_ias_lt_ipv6_network = ipam.allocate_ipv6_network(
service_type="LT_IAS", comment=f"LT for {lo0_name}"
).v6
return {"subscription": subscription}
@step("Allocate IAS connection in IPAM")
def ipam_allocate_ias_networks(subscription: RouterProvisioning) -> State:
fqdn = subscription.router.router_fqdn
subscription.router.router_si_ipv4_network = infoblox.allocate_v4_network("SI", f"SI for {fqdn}")
subscription.router.router_ias_lt_ipv4_network = infoblox.allocate_v4_network("LT_IAS", f"LT for {fqdn}")
subscription.router.router_ias_lt_ipv6_network = infoblox.allocate_v6_network("LT_IAS", f"LT for {fqdn}")
return {"subscription": subscription}
......@@ -142,12 +142,15 @@ def provision_router_real(subscription: RouterProvisioning, process_id: UUIDstr)
target=Target.CREATE,
)
def create_router() -> StepList:
should_allocate_ias = conditional(lambda state: state["is_ias_connected"])
return (
init
>> create_subscription
>> store_process_subscription(Target.CREATE)
>> initialize_subscription
>> get_info_from_ipam
>> ipam_allocate_loopback
>> should_allocate_ias(ipam_allocate_ias_networks)
>> pp_interaction(provision_router_dry, 3)
>> pp_interaction(provision_router_real, 3)
>> set_status(SubscriptionLifecycle.ACTIVE)
......
......@@ -10,8 +10,7 @@ from orchestrator.workflows.steps import resync, set_status, store_process_subsc
from orchestrator.workflows.utils import wrap_modify_initial_input_form
from gso.products.product_types.router import Router
from gso.services import ipam
from gso.services.ipam import HostAddresses, V4ServiceNetwork, V6ServiceNetwork
from gso.services import infoblox
logger = logging.getLogger(__name__)
......@@ -31,47 +30,26 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
return user_input.dict()
@step("Deprovision loopback IPs from IPAM/DNS")
def deprovision_loopback_ips(subscription: Router) -> dict[str, HostAddresses]:
input_host_addresses = ipam.HostAddresses(
v4=ipaddress.IPv4Address(subscription.router.router_lo_ipv4_address),
v6=ipaddress.IPv6Address(subscription.router.router_lo_ipv6_address),
)
fqdn_as_list = subscription.router.router_fqdn.split(".")
hostname = str(fqdn_as_list[0]) + "." + str(fqdn_as_list[1]) + "." + str(fqdn_as_list[2])
lo0_name = "lo0." + hostname
host_addresses = ipam.delete_host(
hostname=lo0_name,
host_addresses=input_host_addresses,
cname_aliases=[hostname],
service_type="LO",
)
return {"addresses": host_addresses}
@step("Deprovision loopback IPs from IPAM")
def deprovision_loopback_ips(subscription: Router) -> dict:
infoblox.delete_host_by_ip(ipaddress.IPv4Address(subscription.router.router_lo_ipv4_address))
return {"subscription": subscription}
@step("Deprovision SI- interface IPs from IPAM/DNS")
def deprovision_si_ips(subscription: Router) -> dict[str, V4ServiceNetwork | V6ServiceNetwork]:
service_network = ipam.delete_network(
network=ipaddress.ip_network(subscription.router.router_si_ipv4_network), # type: ignore
service_type="SI",
)
return {"service_network": service_network}
@step("Deprovision SI interface network from IPAM")
def deprovision_si_ips(subscription: Router) -> dict:
infoblox.delete_network(ipaddress.IPv4Network(subscription.router.router_si_ipv4_network))
@step("Deprovision LT- interface (IAS) IPs from IPAM/DNS")
def deprovision_lt_ips(subscription: Router) -> dict[str, V4ServiceNetwork | V6ServiceNetwork]:
service_network_v4 = ipam.delete_network(
network=ipaddress.ip_network(subscription.router.router_ias_lt_ipv4_network), # type: ignore
service_type="LT_IAS",
)
service_network_v6 = ipam.delete_network(
network=ipaddress.ip_network(subscription.router.router_ias_lt_ipv6_network), # type: ignore
service_type="LT_IAS",
)
return {
"service_network_v4": service_network_v4,
"service_network_v6": service_network_v6,
}
return {"subscription": subscription}
@step("Deprovision IAS LT interfaces from IPAM")
def deprovision_lt_ips(subscription: Router) -> dict:
infoblox.delete_network(ipaddress.IPv4Network(subscription.router.router_ias_lt_ipv4_network))
infoblox.delete_network(ipaddress.IPv6Network(subscription.router.router_ias_lt_ipv6_network))
return {"subscription": subscription}
@step("Remove configuration from router")
......@@ -85,14 +63,13 @@ def remove_config_from_router() -> None:
target=Target.TERMINATE,
)
def terminate_router() -> StepList:
run_ipam_steps = conditional(lambda state: state.get("clean_up_ipam", True))
run_config_steps = conditional(lambda state: state.get("remove_configuration", True))
run_ias_removal = conditional(lambda subscription: "router_ias_lt_ipv4_network" in subscription.get("router", {}))
run_si_removal = conditional(lambda subscription: "router_si_ipv4_network" in subscription.get("router", {}))
run_ipam_steps = conditional(lambda state: state["clean_up_ipam"])
run_config_steps = conditional(lambda state: state["remove_configuration"])
run_ias_removal = conditional(lambda state: state["subscription"]["router"]["router_is_ias_connected"])
ipam_steps = (
StepList([deprovision_loopback_ips])
>> run_si_removal(deprovision_si_ips)
>> run_ias_removal(deprovision_si_ips)
>> run_ias_removal(deprovision_lt_ips)
)
......
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