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

When creating a router, the FQDN may not be already in use

parent fd0bb61c
No related branches found
No related tags found
1 merge request!65Feature/add infoblox service
...@@ -44,6 +44,10 @@ class RouterBlockInactive( ...@@ -44,6 +44,10 @@ class RouterBlockInactive(
router_is_ias_connected: Optional[bool] = None router_is_ias_connected: Optional[bool] = None
def generate_fqdn(hostname: str, site_name: str, country_code: str) -> str:
return f"{hostname}.{site_name.lower()}.{country_code.lower()}.geant.net"
class RouterBlockProvisioning(RouterBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): class RouterBlockProvisioning(RouterBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
"""A router that's being provisioned. See {class}`RouterBlock`.""" """A router that's being provisioned. See {class}`RouterBlock`."""
......
from typing import Optional from ipaddress import IPv4Network, IPv6Network
from typing import Any
import infoblox_client.objects
# noinspection PyProtectedMember # noinspection PyProtectedMember
from orchestrator.forms import FormPage from orchestrator.forms import FormPage
...@@ -10,6 +9,7 @@ from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUID ...@@ -10,6 +9,7 @@ from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUID
from orchestrator.workflow import StepList, conditional, 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
from products.product_blocks.router import RouterRole, RouterVendor, generate_fqdn
from pydantic import validator from pydantic import validator
from gso.products.product_types.router import RouterInactive, RouterProvisioning from gso.products.product_types.router import RouterInactive, RouterProvisioning
...@@ -18,7 +18,6 @@ from gso.products.shared import PortNumber ...@@ -18,7 +18,6 @@ from gso.products.shared import PortNumber
from gso.services import infoblox, 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
from products.product_blocks.router import RouterRole, RouterVendor, generate_fqdn
def _site_selector() -> Choice: def _site_selector() -> Choice:
...@@ -43,13 +42,17 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -43,13 +42,17 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
ts_port: PortNumber ts_port: PortNumber
router_vendor: RouterVendor router_vendor: RouterVendor
router_role: RouterRole router_role: RouterRole
is_ias_connected: Optional[bool] is_ias_connected: bool | None
@validator("hostname", allow_reuse=True) @validator("hostname", allow_reuse=True)
def hostname_must_be_available(cls, hostname: str, **kwargs) -> str: def hostname_must_be_available(cls, hostname: str, **kwargs: dict[str, Any]) -> str:
selected_site = Site.from_subscription(kwargs["values"].get("router_site", "")).site router_site = kwargs["values"].get("router_site")
if not router_site:
raise ValueError("Please select a site before setting the hostname.")
selected_site = Site.from_subscription(router_site).site
input_fqdn = generate_fqdn(hostname, selected_site.site_name, selected_site.site_country_code) input_fqdn = generate_fqdn(hostname, selected_site.site_name, selected_site.site_country_code)
if not infoblox.hostname_available(input_fqdn): if not infoblox.hostname_available(f"lo0.{input_fqdn}"):
raise ValueError(f'FQDN "{input_fqdn}" is not available.') raise ValueError(f'FQDN "{input_fqdn}" is not available.')
return hostname return hostname
...@@ -154,18 +157,16 @@ def provision_router_real(subscription: RouterProvisioning, process_id: UUIDstr) ...@@ -154,18 +157,16 @@ def provision_router_real(subscription: RouterProvisioning, process_id: UUIDstr)
def verify_ipam_loopback(subscription: RouterProvisioning) -> State: def verify_ipam_loopback(subscription: RouterProvisioning) -> State:
host_record = infoblox.find_host_by_fqdn(f"lo0.{subscription.router.router_fqdn}") host_record = infoblox.find_host_by_fqdn(f"lo0.{subscription.router.router_fqdn}")
if not host_record or str(subscription.subscription_id) not in host_record.comment: if not host_record or str(subscription.subscription_id) not in host_record.comment:
return { return {"ipam_warning": "Loopback record is incorrectly configured in IPAM, please investigate this manually!"}
"ipam_warning": "!!! Loopback record is incorrectly configured in IPAM, please investigate this manually. !!!"
}
return {"subscription": subscription} return {"subscription": subscription}
@step("Verify IPAM resources for IAS/LT networks") @step("Verify IPAM resources for IAS/LT networks")
def verify_ipam_ias(subscription: RouterProvisioning) -> State: def verify_ipam_ias(subscription: RouterProvisioning) -> State:
si_ipv4_network = infoblox.find_network_by_cidr(subscription.router.router_si_ipv4_network) si_ipv4_network = infoblox.find_network_by_cidr(IPv4Network(subscription.router.router_si_ipv4_network))
ias_lt_ipv4_network = infoblox.find_network_by_cidr(subscription.router.router_ias_lt_ipv4_network) ias_lt_ipv4_network = infoblox.find_network_by_cidr(IPv4Network(subscription.router.router_ias_lt_ipv4_network))
ias_lt_ipv6_network = infoblox.find_network_by_cidr(subscription.router.router_ias_lt_ipv6_network) ias_lt_ipv6_network = infoblox.find_network_by_cidr(IPv6Network(subscription.router.router_ias_lt_ipv6_network))
new_state = {} new_state = {}
...@@ -176,13 +177,15 @@ def verify_ipam_ias(subscription: RouterProvisioning) -> State: ...@@ -176,13 +177,15 @@ def verify_ipam_ias(subscription: RouterProvisioning) -> State:
} }
if not ias_lt_ipv4_network or str(subscription.subscription_id) not in ias_lt_ipv4_network.comment: if not ias_lt_ipv4_network or str(subscription.subscription_id) not in ias_lt_ipv4_network.comment:
new_state = new_state | { new_state = new_state | {
"ipam_ias_lt_ipv4_warning": f"IAS/LT IPv4 network expected at {subscription.router.router_ias_lt_ipv4_network}, " "ipam_ias_lt_ipv4_warning": "IAS/LT IPv4 network expected at "
f"but it was not found or misconfigured, please investigate and adjust if necessary." f"{subscription.router.router_ias_lt_ipv4_network}, but it was not found or misconfigured, please "
"investigate and adjust if necessary."
} }
if not ias_lt_ipv6_network or str(subscription.subscription_id) not in ias_lt_ipv6_network.comment: if not ias_lt_ipv6_network or str(subscription.subscription_id) not in ias_lt_ipv6_network.comment:
new_state = new_state | { new_state = new_state | {
"ipam_ias_lt_ipv6_warning": f"IAS/LT IPv6 network expected at {subscription.router.router_ias_lt_ipv6_network}, " "ipam_ias_lt_ipv6_warning": f"IAS/LT IPv6 network expected at "
f"but it was not found or misconfigured, please investigate and adjust if necessary." f"{subscription.router.router_ias_lt_ipv6_network}, but it was not found or misconfigured, please "
"investigate and adjust if necessary."
} }
return new_state return new_state
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment