Skip to content
Snippets Groups Projects

Add BFD configuration to Service binding ports

Merged Karel van Klink requested to merge feature/bfd-in-sbp into develop
Compare and Show latest version
2 files
+ 52
65
Compare changes
  • Side-by-side
  • Inline
Files
2
"""Create a new NREN L3 Core Service subscription including GÉANT IP and IAS."""
from typing import Annotated, Any
from typing import Any
from uuid import uuid4
from orchestrator.forms import FormPage
@@ -10,7 +10,7 @@ from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUID
from orchestrator.workflow import StepList, begin, done, step, workflow
from orchestrator.workflows.steps import resync, set_status, store_process_subscription
from orchestrator.workflows.utils import wrap_create_initial_input_form
from pydantic import AfterValidator, BaseModel, ConfigDict, Field, computed_field
from pydantic import BaseModel, ConfigDict, Field, computed_field
from pydantic_forms.validators import Divider
from gso.products.product_blocks.bgp_session import BFDSettings, BGPSession, IPFamily
@@ -44,24 +44,15 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
edge_port: active_edge_port_selector(partner_id=initial_user_input.partner) # type: ignore[valid-type]
ap_type: APType
def validate_edge_ports_are_unique(edge_ports: list[EdgePortSelection]) -> list[EdgePortSelection]:
"""Verify if interfaces are unique."""
port_names = [port.edge_port for port in edge_ports]
if len(port_names) != len(set(port_names)):
msg = "Edge Ports must be unique."
raise ValueError(msg)
return edge_ports
class EdgePortSelectionForm(FormPage):
model_config = ConfigDict(title=f"{product_name} - Select Edge Ports")
info_label: Label = Field(
f"Please select the Edge Ports where this {product_name} service will terminate", exclude=True
)
edge_ports: Annotated[list[EdgePortSelection], AfterValidator(validate_edge_ports_are_unique)]
edge_port: EdgePortSelection
selected_edge_ports = yield EdgePortSelectionForm
ep_list = selected_edge_ports.edge_ports
selected_edge_port = yield EdgePortSelectionForm
class BFDSettingsForm(BaseModel):
bfd_enabled: bool = False
@@ -69,9 +60,9 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
bfd_multiplier: int | None = None
class BaseBGPPeer(BaseModel):
bfd_settings: BFDSettingsForm
bfd_settings: BFDSettingsForm = BFDSettingsForm(bfd_enabled=False)
has_custom_policies: bool = False
authentication_key: str | None
authentication_key: str | None = None
multipath_enabled: bool = False
send_default_route: bool = False
is_passive: bool = False
@@ -94,47 +85,41 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
def families(self) -> list[IPFamily]:
return [IPFamily.V6UNICAST, IPFamily.V6MULTICAST] if self.add_v6_multicast else [IPFamily.V6UNICAST]
binding_port_inputs = []
for ep_index, edge_port in enumerate(ep_list):
class BindingPortsInputForm(FormPage):
model_config = ConfigDict(title=f"{product_name} - Configure Edge Ports ({ep_index + 1}/{len(ep_list)})")
info_label: Label = Field("Please configure the Service Binding Ports for each Edge Port.", exclude=True)
current_ep_label: Label = Field(
f"Currently configuring on {EdgePort.from_subscription(edge_port.edge_port).description} "
f"(Access Port type: {edge_port.ap_type})",
exclude=True,
)
geant_sid: str
is_tagged: bool = False
v4_bfd_settings: BFDSettingsForm
v6_bfd_settings: BFDSettingsForm
vlan_id: VLAN_ID
ipv4_address: IPv4AddressType
ipv4_mask: IPV4Netmask
ipv6_address: IPv6AddressType
ipv6_mask: IPV6Netmask
custom_firewall_filters: bool = False
divider: Divider = Field(None, exclude=True)
v4_bgp_peer: IPv4BGPPeer
v6_bgp_peer: IPv6BGPPeer
binding_port_input_form = yield BindingPortsInputForm
binding_port_inputs.append(
binding_port_input_form.model_dump()
| {
"bgp_peers": [
binding_port_input_form.v4_bgp_peer.model_dump(),
binding_port_input_form.v6_bgp_peer.model_dump(),
]
}
class BindingPortInputForm(FormPage):
model_config = ConfigDict(title=f"{product_name} - Configure Edge Port")
info_label: Label = Field("Please configure the Service Binding Ports for the Edge Port.", exclude=True)
current_ep_label: Label = Field(
f"Currently configuring on {EdgePort.from_subscription(selected_edge_port.edge_port.edge_port).description}"
f" (Access Port type: {selected_edge_port.edge_port.ap_type})",
exclude=True,
)
geant_sid: str
is_tagged: bool = False
v4_bfd_settings: BFDSettingsForm = BFDSettingsForm(bfd_enabled=False)
v6_bfd_settings: BFDSettingsForm = BFDSettingsForm(bfd_enabled=False)
vlan_id: VLAN_ID
ipv4_address: IPv4AddressType
ipv4_mask: IPV4Netmask
ipv6_address: IPv6AddressType
ipv6_mask: IPV6Netmask
custom_firewall_filters: bool = False
divider: Divider = Field(None, exclude=True)
v4_bgp_peer: IPv4BGPPeer
v6_bgp_peer: IPv6BGPPeer
binding_port_input_form = yield BindingPortInputForm
binding_port_input = binding_port_input_form.model_dump() | {
"bgp_peers": [
binding_port_input_form.v4_bgp_peer.model_dump(),
binding_port_input_form.v6_bgp_peer.model_dump(),
]
}
return (
initial_user_input.model_dump()
| selected_edge_ports.model_dump()
| {"binding_port_inputs": binding_port_inputs, "product_name": product_name}
| selected_edge_port.model_dump()
| {"binding_port_input": binding_port_input, "product_name": product_name}
)
@@ -154,11 +139,19 @@ def initialize_subscription(
edge_port_fqdn_list = []
edge_port_subscription = EdgePort.from_subscription(edge_port["edge_port"])
sbp_bgp_session_list = [
BGPSession.new(subscription_id=uuid4(), **session, rtbh_enabled=True, is_multi_hop=True)
BGPSession.new(
subscription_id=uuid4(),
bfd_settings=BFDSettings.new(subscription_id=uuid4(), **(session.pop("bfd_settings"))),
**session,
rtbh_enabled=True,
is_multi_hop=True,
)
for session in binding_port_input["bgp_peers"]
]
service_binding_port = ServiceBindingPortInactive.new(
subscription_id=uuid4(),
v4_bfd_settings=BFDSettings.new(subscription_id=uuid4(), **(binding_port_input.pop("v4_bfd_settings"))),
v6_bfd_settings=BFDSettings.new(subscription_id=uuid4(), **(binding_port_input.pop("v6_bfd_settings"))),
**binding_port_input,
bgp_session_list=sbp_bgp_session_list,
sbp_type=SBPType.L3,
@@ -175,15 +168,12 @@ def initialize_subscription(
subscription.description = f"{product_name} service"
partner_name = get_partner_by_id(subscription.customer_id).name
return {"subscription": subscription, "edge_port_fqdn_list": edge_port_fqdn_list, "partner_name": partner_name}
@step("[DRY RUN] Deploy service binding port")
def provision_sbp_dry(
subscription: dict[str, Any], process_id: UUIDstr, tt_number: str, edge_port_fqdn_list: list[str],
partner_name: str
subscription: dict[str, Any], process_id: UUIDstr, tt_number: str, edge_port_fqdn_list: list[str], partner_name: str
) -> LSOState:
"""Perform a dry run of deploying Service Binding Ports."""
extra_vars = {
@@ -205,8 +195,7 @@ def provision_sbp_dry(
@step("[FOR REAL] Deploy service binding port")
def provision_sbp_real(
subscription: dict[str, Any], process_id: UUIDstr, tt_number: str, edge_port_fqdn_list: list[str],
partner_name: str
subscription: dict[str, Any], process_id: UUIDstr, tt_number: str, edge_port_fqdn_list: list[str], partner_name: str
) -> LSOState:
"""Deploy Service Binding Ports."""
extra_vars = {
@@ -240,8 +229,7 @@ def check_sbp_functionality(subscription: dict[str, Any], edge_port_fqdn_list: l
@step("[DRY RUN] Deploy BGP peers")
def deploy_bgp_peers_dry(
subscription: dict[str, Any], edge_port_fqdn_list: list[str], tt_number: str, process_id: UUIDstr,
partner_name: str
subscription: dict[str, Any], edge_port_fqdn_list: list[str], tt_number: str, process_id: UUIDstr, partner_name: str
) -> LSOState:
"""Perform a dry run of deploying :term:`BGP` peers."""
extra_vars = {
@@ -263,8 +251,7 @@ def deploy_bgp_peers_dry(
@step("[FOR REAL] Deploy BGP peers")
def deploy_bgp_peers_real(
subscription: dict[str, Any], edge_port_fqdn_list: list[str], tt_number: str, process_id: UUIDstr,
partner_name: str
subscription: dict[str, Any], edge_port_fqdn_list: list[str], tt_number: str, process_id: UUIDstr, partner_name: str
) -> LSOState:
"""Deploy :term:`BGP` peers."""
extra_vars = {
Loading