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