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

Update input form of GÉANT IP creation, update model of BGP peer

parent 8bfc7658
No related branches found
No related tags found
1 merge request!286Add Edge Port, GÉANT IP and IAS products
"""Add passive boolean to BGP session model. """Update BGP session model.
Revision ID: c3e98d657b36 Revision ID: f4239c9361b4
Revises: f900cbaa47d7 Revises: f900cbaa47d7
Create Date: 2024-09-25 14:05:57.072597 Create Date: 2024-09-25 14:20:55.540546
""" """
import sqlalchemy as sa import sqlalchemy as sa
from alembic import op from alembic import op
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'c3e98d657b36' revision = 'f4239c9361b4'
down_revision = 'f900cbaa47d7' down_revision = 'f900cbaa47d7'
branch_labels = None branch_labels = None
depends_on = None depends_on = None
...@@ -18,7 +18,13 @@ depends_on = None ...@@ -18,7 +18,13 @@ depends_on = None
def upgrade() -> None: def upgrade() -> None:
conn = op.get_bind() conn = op.get_bind()
conn.execute(sa.text(""" conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('is_passive', 'This BGP session is passive') RETURNING resource_types.resource_type_id INSERT INTO resource_types (resource_type, description) VALUES ('rtbh_enabled', 'Remote Triggered Blackhole is enabled') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('is_passive', 'BGP session is passive') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('rtbh_enabled')))
""")) """))
conn.execute(sa.text(""" conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('is_passive'))) INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('is_passive')))
...@@ -28,14 +34,20 @@ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VA ...@@ -28,14 +34,20 @@ INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VA
def downgrade() -> None: def downgrade() -> None:
conn = op.get_bind() conn = op.get_bind()
conn.execute(sa.text(""" conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('rtbh_enabled'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('rtbh_enabled'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('is_passive')) DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('is_passive'))
""")) """))
conn.execute(sa.text(""" conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('is_passive')) DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('BGPSession'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('is_passive'))
""")) """))
conn.execute(sa.text(""" conn.execute(sa.text("""
DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('is_passive')) DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('rtbh_enabled', 'is_passive'))
""")) """))
conn.execute(sa.text(""" conn.execute(sa.text("""
DELETE FROM resource_types WHERE resource_types.resource_type IN ('is_passive') DELETE FROM resource_types WHERE resource_types.resource_type IN ('rtbh_enabled', 'is_passive')
""")) """))
...@@ -33,6 +33,7 @@ class BGPSessionInactive(ProductBlockModel, lifecycle=[SubscriptionLifecycle.INI ...@@ -33,6 +33,7 @@ class BGPSessionInactive(ProductBlockModel, lifecycle=[SubscriptionLifecycle.INI
send_default_route: bool | None = None send_default_route: bool | None = None
is_multi_hop: bool = False is_multi_hop: bool = False
is_passive: bool = False is_passive: bool = False
rtbh_enabled: bool = False
class BGPSessionProvisioning(BGPSessionInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): class BGPSessionProvisioning(BGPSessionInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
...@@ -49,6 +50,7 @@ class BGPSessionProvisioning(BGPSessionInactive, lifecycle=[SubscriptionLifecycl ...@@ -49,6 +50,7 @@ class BGPSessionProvisioning(BGPSessionInactive, lifecycle=[SubscriptionLifecycl
send_default_route: bool send_default_route: bool
is_multi_hop: bool is_multi_hop: bool
is_passive: bool is_passive: bool
rtbh_enabled: bool
class BGPSession(BGPSessionProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class BGPSession(BGPSessionProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
...@@ -76,3 +78,5 @@ class BGPSession(BGPSessionProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE ...@@ -76,3 +78,5 @@ class BGPSession(BGPSessionProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE
is_multi_hop: bool is_multi_hop: bool
#: Whether this is a passive session. #: Whether this is a passive session.
is_passive: bool is_passive: bool
#: Whether Remote Triggered Blackhole is enabled
rtbh_enabled: bool
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
"router_role": "Router role", "router_role": "Router role",
"geant_s_sid": "GÉANT S-SID", "geant_s_sid": "GÉANT S-SID",
"geant_sid": "GÉANT S-SID",
"iptrunk_description": "IPtrunk description", "iptrunk_description": "IPtrunk description",
"iptrunk_type": "IPtrunk type", "iptrunk_type": "IPtrunk type",
"iptrunk_speed": "Capacity per port (in Gbits/s)", "iptrunk_speed": "Capacity per port (in Gbits/s)",
...@@ -32,13 +33,7 @@ ...@@ -32,13 +33,7 @@
"migrate_to_different_site": "Migrating to a different Site", "migrate_to_different_site": "Migrating to a different Site",
"remove_configuration": "Remove configuration from the router", "remove_configuration": "Remove configuration from the router",
"clean_up_ipam": "Clean up related entries in IPAM", "clean_up_ipam": "Clean up related entries in IPAM",
"restore_isis_metric": "Restore ISIS metric to original value", "restore_isis_metric": "Restore ISIS metric to original value"
"bgp_peers": {
"bfd_enabled": "BFD enabled",
"bfd_interval": "BFD interval",
"bfd_multiplier": "BFD multiplier"
}
} }
}, },
"workflow": { "workflow": {
......
...@@ -12,7 +12,6 @@ from orchestrator.workflow import StepList, begin, done, step, workflow ...@@ -12,7 +12,6 @@ from orchestrator.workflow import StepList, begin, done, 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 pydantic import AfterValidator, BaseModel, ConfigDict, Field, computed_field from pydantic import AfterValidator, BaseModel, ConfigDict, Field, computed_field
from pydantic_forms.types import strEnum
from pydantic_forms.validators import Divider from pydantic_forms.validators import Divider
from gso.products.product_blocks.bgp_session import BGPSession, IPFamily from gso.products.product_blocks.bgp_session import BGPSession, IPFamily
...@@ -26,7 +25,7 @@ from gso.utils.helpers import ( ...@@ -26,7 +25,7 @@ from gso.utils.helpers import (
partner_choice, partner_choice,
) )
from gso.utils.shared_enums import APType, SBPType from gso.utils.shared_enums import APType, SBPType
from gso.utils.types.ip_address import IPAddress, IPv4AddressType, IPv6AddressType from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType
from gso.utils.types.tt_number import TTNumber from gso.utils.types.tt_number import TTNumber
...@@ -41,15 +40,9 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -41,15 +40,9 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
initial_user_input = yield CreateGeantIPForm initial_user_input = yield CreateGeantIPForm
class BGPPeerFamily(strEnum):
V4 = "IPv4 only"
V6 = "IPv6 only"
DUAL_STACK = "Dual stack"
class EdgePortSelection(BaseModel): class EdgePortSelection(BaseModel):
edge_port: active_edge_port_selector(partner_id=initial_user_input.partner) # type: ignore[valid-type] edge_port: active_edge_port_selector(partner_id=initial_user_input.partner) # type: ignore[valid-type]
ap_type: APType ap_type: APType
ip_family: BGPPeerFamily
def validate_edge_ports_are_unique(edge_ports: list[EdgePortSelection]) -> list[EdgePortSelection]: def validate_edge_ports_are_unique(edge_ports: list[EdgePortSelection]) -> list[EdgePortSelection]:
"""Verify if interfaces are unique.""" """Verify if interfaces are unique."""
...@@ -76,13 +69,15 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -76,13 +69,15 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
bfd_enabled: bool = False bfd_enabled: bool = False
bfd_interval: int | None = None bfd_interval: int | None = None
bfd_multiplier: int | None = None bfd_multiplier: int | None = None
rtbh_enabled: bool = False
has_custom_policies: bool = False has_custom_policies: bool = False
authentication_key: str authentication_key: str
multipath_enabled: bool = False multipath_enabled: bool = False
send_default_route: bool = False send_default_route: bool = False
is_multi_hop: bool = False is_multi_hop: bool = False
is_passive: bool = False
class V4OnlyBGPPeer(BaseBGPPeer): class IPv4BGPPeer(BaseBGPPeer):
peer_address: IPv4AddressType peer_address: IPv4AddressType
add_v4_multicast: bool = Field(default=False, exclude=True) add_v4_multicast: bool = Field(default=False, exclude=True)
...@@ -91,7 +86,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -91,7 +86,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
def families(self) -> list[IPFamily]: def families(self) -> list[IPFamily]:
return [IPFamily.V4UNICAST, IPFamily.V4MULTICAST] if self.add_v4_multicast else [IPFamily.V4UNICAST] return [IPFamily.V4UNICAST, IPFamily.V4MULTICAST] if self.add_v4_multicast else [IPFamily.V4UNICAST]
class V6OnlyBGPPeer(BaseBGPPeer): class IPv6BGPPeer(BaseBGPPeer):
peer_address: IPv6AddressType peer_address: IPv6AddressType
add_v6_multicast: bool = Field(default=False, exclude=True) add_v6_multicast: bool = Field(default=False, exclude=True)
...@@ -100,33 +95,9 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -100,33 +95,9 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
def families(self) -> list[IPFamily]: def families(self) -> list[IPFamily]:
return [IPFamily.V6UNICAST, IPFamily.V6MULTICAST] if self.add_v6_multicast else [IPFamily.V6UNICAST] return [IPFamily.V6UNICAST, IPFamily.V6MULTICAST] if self.add_v6_multicast else [IPFamily.V6UNICAST]
class DualStackBGPPeer(V4OnlyBGPPeer, V6OnlyBGPPeer):
peer_address: IPAddress # type: ignore[assignment]
@computed_field # type: ignore[misc]
@property
def families(self) -> list[IPFamily]:
result = [IPFamily.V4UNICAST, IPFamily.V6UNICAST]
if self.add_v4_multicast:
result.append(IPFamily.V4MULTICAST)
if self.add_v6_multicast:
result.append(IPFamily.V6MULTICAST)
return result
binding_port_inputs = [] binding_port_inputs = []
while current_ep_index < total_ep_count: while current_ep_index < total_ep_count:
current_edge_port = EdgePort.from_subscription(ep_list[current_ep_index].edge_port) current_edge_port = EdgePort.from_subscription(ep_list[current_ep_index].edge_port)
bgp_peer_type: type[object]
match ep_list[current_ep_index].ip_family:
case BGPPeerFamily.V4:
bgp_peer_type = V4OnlyBGPPeer
case BGPPeerFamily.V6:
bgp_peer_type = V6OnlyBGPPeer
case BGPPeerFamily.DUAL_STACK:
bgp_peer_type = DualStackBGPPeer
case _:
msg = f"Invalid IP family selected: {ep_list[current_ep_index].ip_family}"
raise ValueError(msg)
class BindingPortsInputForm(FormPage): class BindingPortsInputForm(FormPage):
model_config = ConfigDict( model_config = ConfigDict(
...@@ -146,12 +117,17 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: ...@@ -146,12 +117,17 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
ipv6_address: IPv6AddressType ipv6_address: IPv6AddressType
custom_firewall_filters: bool = False custom_firewall_filters: bool = False
divider: Divider = Field(None, exclude=True) divider: Divider = Field(None, exclude=True)
bgp_peers: list[bgp_peer_type] # type: ignore[valid-type] v4_bgp_peer: IPv4BGPPeer
v6_bgp_peer: IPv6BGPPeer
binding_port_input_form = yield BindingPortsInputForm binding_port_input_form = yield BindingPortsInputForm
binding_port_input = binding_port_input_form.model_dump() binding_port_input = binding_port_input_form.model_dump()
binding_port_input["sbp_type"] = SBPType.L3 binding_port_input["sbp_type"] = SBPType.L3
binding_port_input["bgp_peers"] = [
binding_port_input_form.v4_bgp_peer.model_dump(),
binding_port_input_form.v6_bgp_peer.model_dump(),
]
binding_port_inputs.append(binding_port_input) binding_port_inputs.append(binding_port_input)
current_ep_index += 1 current_ep_index += 1
......
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