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

Add new BGP MED and local preference attributes to R&E L3 services

parent 4951a4e9
No related branches found
No related tags found
1 merge request!439Add new attributes to R&E subscriptions
Showing
with 476 additions and 9 deletions
"""Add attributes to R&E product block.
Revision ID: b2b5137ef0c7
Revises: 550e3aebc1c5
Create Date: 2025-06-20 16:45:01.403416
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = 'b2b5137ef0c7'
down_revision = '7c3094cd282a'
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('v6_bgp_local_preference', 'BGP Local Preference for IPv6') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('v4_bgp_local_preference', 'BGP Local Preference for IPv4') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('v4_bgp_med', 'BGP Multi Exit Discriminant for IPv4') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('v6_bgp_med', 'BGP Multi Exit Discriminant for IPv6') 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 ('RAndELHCOneBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_local_preference')))
"""))
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 ('RAndELHCOneBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_local_preference')))
"""))
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 ('RAndELHCOneBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_med')))
"""))
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 ('RAndELHCOneBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_med')))
"""))
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 ('RAndEPeerBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_local_preference')))
"""))
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 ('RAndEPeerBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_local_preference')))
"""))
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 ('RAndEPeerBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_med')))
"""))
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 ('RAndEPeerBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_med')))
"""))
def downgrade() -> None:
conn = op.get_bind()
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 ('RAndELHCOneBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_local_preference'))
"""))
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 ('RAndELHCOneBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_local_preference'))
"""))
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 ('RAndELHCOneBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_local_preference'))
"""))
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 ('RAndELHCOneBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_local_preference'))
"""))
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 ('RAndELHCOneBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_med'))
"""))
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 ('RAndELHCOneBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_med'))
"""))
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 ('RAndELHCOneBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_med'))
"""))
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 ('RAndELHCOneBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_med'))
"""))
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 ('RAndEPeerBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_local_preference'))
"""))
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 ('RAndEPeerBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_local_preference'))
"""))
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 ('RAndEPeerBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_local_preference'))
"""))
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 ('RAndEPeerBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_local_preference'))
"""))
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 ('RAndEPeerBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_med'))
"""))
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 ('RAndEPeerBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v4_bgp_med'))
"""))
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 ('RAndEPeerBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_med'))
"""))
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 ('RAndEPeerBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_med'))
"""))
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 ('v6_bgp_local_preference', 'v4_bgp_local_preference', 'v4_bgp_med', 'v6_bgp_med'))
"""))
conn.execute(sa.text("""
DELETE FROM resource_types WHERE resource_types.resource_type IN ('v6_bgp_local_preference', 'v4_bgp_local_preference', 'v4_bgp_med', 'v6_bgp_med')
"""))
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
from orchestrator.domain.base import ProductBlockModel from orchestrator.domain.base import ProductBlockModel
from orchestrator.types import SubscriptionLifecycle from orchestrator.types import SubscriptionLifecycle
from pydantic import NonNegativeInt
from gso.products.product_blocks.l3_core_service import ( from gso.products.product_blocks.l3_core_service import (
L3CoreServiceBlock, L3CoreServiceBlock,
L3CoreServiceBlockInactive, L3CoreServiceBlockInactive,
L3CoreServiceBlockProvisioning, L3CoreServiceBlockProvisioning,
) )
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
class RAndELHCOneBlockInactive( class RAndELHCOneBlockInactive(
...@@ -16,15 +18,27 @@ class RAndELHCOneBlockInactive( ...@@ -16,15 +18,27 @@ class RAndELHCOneBlockInactive(
"""An inactive R&E LHCONE product block. See `RAndELHCOneBlock`.""" """An inactive R&E LHCONE product block. See `RAndELHCOneBlock`."""
l3_core: L3CoreServiceBlockInactive l3_core: L3CoreServiceBlockInactive
v4_bgp_local_preference: NonNegativeInt = 100
v4_bgp_med: MultiExitDiscriminator = "igp"
v6_bgp_local_preference: NonNegativeInt = 100
v6_bgp_med: MultiExitDiscriminator = "igp"
class RAndELHCOneBlockProvisioning(RAndELHCOneBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): class RAndELHCOneBlockProvisioning(RAndELHCOneBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
"""A provisioning R&E LHCONE product block. See `RAndELHCOneBlock`.""" """A provisioning R&E LHCONE product block. See `RAndELHCOneBlock`."""
l3_core: L3CoreServiceBlockProvisioning l3_core: L3CoreServiceBlockProvisioning
v4_bgp_local_preference: NonNegativeInt
v4_bgp_med: MultiExitDiscriminator
v6_bgp_local_preference: NonNegativeInt
v6_bgp_med: MultiExitDiscriminator
class RAndELHCOneBlock(RAndELHCOneBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class RAndELHCOneBlock(RAndELHCOneBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""An active R&E LHCONE product block.""" """An active R&E LHCONE product block."""
l3_core: L3CoreServiceBlock l3_core: L3CoreServiceBlock
v4_bgp_local_preference: NonNegativeInt
v4_bgp_med: MultiExitDiscriminator
v6_bgp_local_preference: NonNegativeInt
v6_bgp_med: MultiExitDiscriminator
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
from orchestrator.domain.base import ProductBlockModel from orchestrator.domain.base import ProductBlockModel
from orchestrator.types import SubscriptionLifecycle from orchestrator.types import SubscriptionLifecycle
from pydantic import NonNegativeInt
from gso.products.product_blocks.l3_core_service import ( from gso.products.product_blocks.l3_core_service import (
L3CoreServiceBlock, L3CoreServiceBlock,
L3CoreServiceBlockInactive, L3CoreServiceBlockInactive,
L3CoreServiceBlockProvisioning, L3CoreServiceBlockProvisioning,
) )
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
class RAndEPeerBlockInactive( class RAndEPeerBlockInactive(
...@@ -16,15 +18,27 @@ class RAndEPeerBlockInactive( ...@@ -16,15 +18,27 @@ class RAndEPeerBlockInactive(
"""An inactive R&E Peer product block. See `RAndEPeerBlock`.""" """An inactive R&E Peer product block. See `RAndEPeerBlock`."""
l3_core: L3CoreServiceBlockInactive l3_core: L3CoreServiceBlockInactive
v4_bgp_local_preference: NonNegativeInt = 100
v4_bgp_med: MultiExitDiscriminator = "igp"
v6_bgp_local_preference: NonNegativeInt = 100
v6_bgp_med: MultiExitDiscriminator = "igp"
class RAndEPeerBlockProvisioning(RAndEPeerBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): class RAndEPeerBlockProvisioning(RAndEPeerBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
"""A provisioning R&E Peer product block. See `RAndEPeerBlock`.""" """A provisioning R&E Peer product block. See `RAndEPeerBlock`."""
l3_core: L3CoreServiceBlockProvisioning l3_core: L3CoreServiceBlockProvisioning
v4_bgp_local_preference: NonNegativeInt
v4_bgp_med: MultiExitDiscriminator
v6_bgp_local_preference: NonNegativeInt
v6_bgp_med: MultiExitDiscriminator
class RAndEPeerBlock(RAndEPeerBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class RAndEPeerBlock(RAndEPeerBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""An active R&E Peer product block.""" """An active R&E Peer product block."""
l3_core: L3CoreServiceBlock l3_core: L3CoreServiceBlock
v4_bgp_local_preference: NonNegativeInt
v4_bgp_med: MultiExitDiscriminator
v6_bgp_local_preference: NonNegativeInt
v6_bgp_med: MultiExitDiscriminator
...@@ -41,6 +41,8 @@ class APType(strEnum): ...@@ -41,6 +41,8 @@ class APType(strEnum):
"""Backup.""" """Backup."""
LOAD_BALANCED = "LOAD_BALANCED" LOAD_BALANCED = "LOAD_BALANCED"
"""Load-balanced.""" """Load-balanced."""
IGNORE = "IGNORE"
"""Ignored."""
class SBPType(strEnum): class SBPType(strEnum):
......
"""Type definition for a BGP Multi Exit Discriminator."""
import contextlib
from typing import Annotated, Any
from pydantic import AfterValidator, BeforeValidator
def _ensure_str(value: Any) -> Any:
if not isinstance(value, str):
return str(value)
return value
def _multi_exit_discriminator_valid(value: str) -> str:
with contextlib.suppress(ValueError):
int_value = int(value)
if int_value >= 0:
return value
if value in {"igp", "min-igp"}:
return value
msg = "Multi Exit Discriminator must be either a positive integer, 'igp', or 'min-igp'"
raise ValueError(msg)
MultiExitDiscriminator = Annotated[str, BeforeValidator(_ensure_str), AfterValidator(_multi_exit_discriminator_valid)]
"""A creation workflow for adding an existing Imported R&E LHCONE to the service database.""" """A creation workflow for adding an existing Imported R&E LHCONE to the service database."""
from orchestrator import workflow from orchestrator import workflow
from orchestrator.forms import SubmitFormPage
from orchestrator.targets import Target from orchestrator.targets import Target
from orchestrator.types import SubscriptionLifecycle from orchestrator.types import SubscriptionLifecycle
from orchestrator.workflow import StepList, begin, done, step from orchestrator.workflow import StepList, begin, done, step
from orchestrator.workflows.steps import resync, set_status, store_process_subscription from orchestrator.workflows.steps import resync, set_status, store_process_subscription
from pydantic import NonNegativeInt
from pydantic_forms.types import FormGenerator
from gso.products import ProductName from gso.products import ProductName
from gso.products.product_types.r_and_e_lhcone import ImportedRAndELHCOneInactive from gso.products.product_types.r_and_e_lhcone import ImportedRAndELHCOneInactive
from gso.services.partners import get_partner_by_name from gso.services.partners import get_partner_by_name
from gso.services.subscriptions import get_product_id_by_name from gso.services.subscriptions import get_product_id_by_name
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
from gso.workflows.l3_core_service.base_create_imported_l3_core_service import ( from gso.workflows.l3_core_service.base_create_imported_l3_core_service import (
initial_input_form_generator, ServiceBindingPort,
initialize_subscription, initialize_subscription,
) )
from gso.workflows.l3_core_service.r_and_e_lhcone.shared import update_r_and_e_lhcone_subscription_model
from gso.workflows.l3_core_service.shared import L3ProductNameType
def initial_input_form_generator() -> FormGenerator:
"""Initial input form generator for creating a new imported R&E LHCOne subscription."""
class ImportL3CoreServiceForm(SubmitFormPage):
partner: str
service_binding_ports: list[ServiceBindingPort]
product_name: L3ProductNameType
v4_bgp_local_preference: NonNegativeInt = 100
v4_bgp_med: MultiExitDiscriminator = "igp"
v6_bgp_local_preference: NonNegativeInt = 100
v6_bgp_med: MultiExitDiscriminator = "igp"
user_input = yield ImportL3CoreServiceForm
return user_input.model_dump()
@step("Create subscription") @step("Create subscription")
...@@ -37,6 +60,7 @@ def create_imported_r_and_e_lhcone() -> StepList: ...@@ -37,6 +60,7 @@ def create_imported_r_and_e_lhcone() -> StepList:
>> create_subscription >> create_subscription
>> store_process_subscription(Target.CREATE) >> store_process_subscription(Target.CREATE)
>> initialize_subscription >> initialize_subscription
>> update_r_and_e_lhcone_subscription_model
>> set_status(SubscriptionLifecycle.ACTIVE) >> set_status(SubscriptionLifecycle.ACTIVE)
>> resync >> resync
>> done >> done
......
"""Create R&E LHCONE subscription workflow.""" """Create R&E LHCONE subscription workflow."""
from orchestrator.forms import FormPage
from orchestrator.targets import Target from orchestrator.targets import Target
from orchestrator.types import SubscriptionLifecycle from orchestrator.types import SubscriptionLifecycle
from orchestrator.workflow import StepList, begin, done, step, workflow 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_forms.types import State, UUIDstr from pydantic import NonNegativeInt
from pydantic_forms.types import FormGenerator, State, UUIDstr
from gso.products.product_types.r_and_e_lhcone import RAndELHCOneInactive from gso.products.product_types.r_and_e_lhcone import RAndELHCOneInactive
from gso.services.lso_client import lso_interaction from gso.services.lso_client import lso_interaction
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
from gso.utils.workflow_steps import prompt_sharepoint_checklist_url, start_moodi, stop_moodi from gso.utils.workflow_steps import prompt_sharepoint_checklist_url, start_moodi, stop_moodi
from gso.workflows.l3_core_service.base_create_l3_core_service import ( from gso.workflows.l3_core_service.base_create_l3_core_service import (
check_bgp_peers, check_bgp_peers,
...@@ -16,12 +19,31 @@ from gso.workflows.l3_core_service.base_create_l3_core_service import ( ...@@ -16,12 +19,31 @@ from gso.workflows.l3_core_service.base_create_l3_core_service import (
create_new_sharepoint_checklist, create_new_sharepoint_checklist,
deploy_bgp_peers_dry, deploy_bgp_peers_dry,
deploy_bgp_peers_real, deploy_bgp_peers_real,
initial_input_form_generator,
initialize_subscription, initialize_subscription,
provision_sbp_dry, provision_sbp_dry,
provision_sbp_real, provision_sbp_real,
update_dns_records, update_dns_records,
) )
from gso.workflows.l3_core_service.base_create_l3_core_service import (
initial_input_form_generator as base_initial_input_form_generator,
)
from gso.workflows.l3_core_service.r_and_e_lhcone.shared import update_r_and_e_lhcone_subscription_model
def initial_input_form_generator(product_name: str) -> FormGenerator:
"""Initial input form generator for creating a new R&E LHCOne subscription."""
initial_generator = base_initial_input_form_generator(product_name)
initial_user_input = yield from initial_generator
# Additional R&E LHCOne step
class RAndELHCOneExtraForm(FormPage):
v4_bgp_local_preference: NonNegativeInt = 100
v4_bgp_med: MultiExitDiscriminator = "igp"
v6_bgp_local_preference: NonNegativeInt = 100
v6_bgp_med: MultiExitDiscriminator = "igp"
r_and_e_lhcone_extra_form = yield RAndELHCOneExtraForm
return initial_user_input | r_and_e_lhcone_extra_form.model_dump()
@step("Create subscription") @step("Create subscription")
...@@ -44,6 +66,7 @@ def create_r_and_e_lhcone() -> StepList: ...@@ -44,6 +66,7 @@ def create_r_and_e_lhcone() -> StepList:
>> create_subscription >> create_subscription
>> store_process_subscription(Target.CREATE) >> store_process_subscription(Target.CREATE)
>> initialize_subscription >> initialize_subscription
>> update_r_and_e_lhcone_subscription_model
>> start_moodi() >> start_moodi()
>> lso_interaction(provision_sbp_dry) >> lso_interaction(provision_sbp_dry)
>> lso_interaction(provision_sbp_real) >> lso_interaction(provision_sbp_real)
......
"""Modification workflow for an R&E LHCONE subscription.""" """Modification workflow for an R&E LHCONE subscription."""
from orchestrator import begin, conditional, done, workflow from orchestrator import begin, conditional, done, workflow
from orchestrator.forms import FormPage
from orchestrator.targets import Target from orchestrator.targets import Target
from orchestrator.workflow import StepList from orchestrator.workflow import StepList
from orchestrator.workflows.steps import resync, store_process_subscription, unsync from orchestrator.workflows.steps import resync, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form from orchestrator.workflows.utils import wrap_modify_initial_input_form
from pydantic import NonNegativeInt
from pydantic_forms.types import FormGenerator, UUIDstr
from gso.products.product_types.r_and_e_lhcone import RAndELHCOne
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
from gso.workflows.l3_core_service.base_modify_l3_core_service import ( from gso.workflows.l3_core_service.base_modify_l3_core_service import (
Operation, Operation,
create_new_sbp, create_new_sbp,
...@@ -13,11 +18,30 @@ from gso.workflows.l3_core_service.base_modify_l3_core_service import ( ...@@ -13,11 +18,30 @@ from gso.workflows.l3_core_service.base_modify_l3_core_service import (
modify_existing_sbp, modify_existing_sbp,
remove_old_sbp, remove_old_sbp,
) )
from gso.workflows.l3_core_service.r_and_e_lhcone.shared import update_r_and_e_lhcone_subscription_model
def modify_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
"""Initial form generator for modifying the custom attributes of an existing IAS subscription."""
initial_generator = initial_input_form_generator(subscription_id)
initial_user_input = yield from initial_generator
subscription = RAndELHCOne.from_subscription(subscription_id)
# Additional R&E LHCOne step
class RAndELHCOneExtraForm(FormPage):
v4_bgp_local_preference: NonNegativeInt = subscription.r_and_e_lhcone.v4_bgp_local_preference
v4_bgp_med: MultiExitDiscriminator = subscription.r_and_e_lhcone.v4_bgp_med
v6_bgp_local_preference: NonNegativeInt = subscription.r_and_e_lhcone.v6_bgp_local_preference
v6_bgp_med: MultiExitDiscriminator = subscription.r_and_e_lhcone.v6_bgp_med
r_and_e_lhcone_extra_form = yield RAndELHCOneExtraForm
return initial_user_input | r_and_e_lhcone_extra_form.model_dump()
@workflow( @workflow(
"Modify R&E LHCONE", "Modify R&E LHCONE",
initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator), initial_input_form=wrap_modify_initial_input_form(modify_input_form_generator),
target=Target.MODIFY, target=Target.MODIFY,
) )
def modify_r_and_e_lhcone() -> StepList: def modify_r_and_e_lhcone() -> StepList:
...@@ -30,6 +54,7 @@ def modify_r_and_e_lhcone() -> StepList: ...@@ -30,6 +54,7 @@ def modify_r_and_e_lhcone() -> StepList:
begin begin
>> store_process_subscription(Target.MODIFY) >> store_process_subscription(Target.MODIFY)
>> unsync >> unsync
>> update_r_and_e_lhcone_subscription_model
>> access_port_is_added(create_new_sbp) >> access_port_is_added(create_new_sbp)
>> access_port_is_removed(remove_old_sbp) >> access_port_is_removed(remove_old_sbp)
>> access_port_is_modified(modify_existing_sbp) >> access_port_is_modified(modify_existing_sbp)
......
"""Shared logic for R&E LHCOne service workflows."""
from orchestrator import step
from orchestrator.domain import SubscriptionModel
from pydantic import NonNegativeInt
from pydantic_forms.types import State
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
@step("Update R&E LHCOne-specific attributes")
def update_r_and_e_lhcone_subscription_model(
subscription: SubscriptionModel,
v4_bgp_local_preference: NonNegativeInt,
v4_bgp_med: MultiExitDiscriminator,
v6_bgp_local_preference: NonNegativeInt,
v6_bgp_med: MultiExitDiscriminator,
) -> State:
"""Update the subscription model of an R&E LHCOne subscription."""
subscription.r_and_e_lhcone.v4_bgp_local_preference = v4_bgp_local_preference # type: ignore[attr-defined]
subscription.r_and_e_lhcone.v4_bgp_med = v4_bgp_med # type: ignore[attr-defined]
subscription.r_and_e_lhcone.v6_bgp_local_preference = v6_bgp_local_preference # type: ignore[attr-defined]
subscription.r_and_e_lhcone.v6_bgp_med = v6_bgp_med # type: ignore[attr-defined]
return {"subscription": subscription}
"""A creation workflow for adding an existing Imported R&E Peer to the service database.""" """A creation workflow for adding an existing Imported R&E Peer to the service database."""
from orchestrator import workflow from orchestrator import workflow
from orchestrator.forms import SubmitFormPage
from orchestrator.targets import Target from orchestrator.targets import Target
from orchestrator.types import SubscriptionLifecycle from orchestrator.types import SubscriptionLifecycle
from orchestrator.workflow import StepList, begin, done, step from orchestrator.workflow import StepList, begin, done, step
from orchestrator.workflows.steps import resync, set_status, store_process_subscription from orchestrator.workflows.steps import resync, set_status, store_process_subscription
from pydantic import NonNegativeInt
from pydantic_forms.types import FormGenerator
from gso.products import ProductName from gso.products import ProductName
from gso.products.product_types.r_and_e_peer import ImportedRAndEPeerInactive from gso.products.product_types.r_and_e_peer import ImportedRAndEPeerInactive
from gso.services.partners import get_partner_by_name from gso.services.partners import get_partner_by_name
from gso.services.subscriptions import get_product_id_by_name from gso.services.subscriptions import get_product_id_by_name
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
from gso.workflows.l3_core_service.base_create_imported_l3_core_service import ( from gso.workflows.l3_core_service.base_create_imported_l3_core_service import (
initial_input_form_generator, ServiceBindingPort,
initialize_subscription, initialize_subscription,
) )
from gso.workflows.l3_core_service.r_and_e_peer.shared import update_r_and_e_peer_subscription_model
from gso.workflows.l3_core_service.shared import L3ProductNameType
def initial_input_form_generator() -> FormGenerator:
"""Initial input form generator for creating a new imported R&E Peer subscription."""
class ImportL3CoreServiceForm(SubmitFormPage):
partner: str
service_binding_ports: list[ServiceBindingPort]
product_name: L3ProductNameType
v4_bgp_local_preference: NonNegativeInt = 100
v4_bgp_med: MultiExitDiscriminator = "igp"
v6_bgp_local_preference: NonNegativeInt = 100
v6_bgp_med: MultiExitDiscriminator = "igp"
user_input = yield ImportL3CoreServiceForm
return user_input.model_dump()
@step("Create subscription") @step("Create subscription")
...@@ -37,6 +60,7 @@ def create_imported_r_and_e_peer() -> StepList: ...@@ -37,6 +60,7 @@ def create_imported_r_and_e_peer() -> StepList:
>> create_subscription >> create_subscription
>> store_process_subscription(Target.CREATE) >> store_process_subscription(Target.CREATE)
>> initialize_subscription >> initialize_subscription
>> update_r_and_e_peer_subscription_model
>> set_status(SubscriptionLifecycle.ACTIVE) >> set_status(SubscriptionLifecycle.ACTIVE)
>> resync >> resync
>> done >> done
......
"""Create R&E Peer subscription workflow.""" """Create R&E Peer subscription workflow."""
from orchestrator.forms import FormPage
from orchestrator.targets import Target from orchestrator.targets import Target
from orchestrator.types import SubscriptionLifecycle from orchestrator.types import SubscriptionLifecycle
from orchestrator.workflow import StepList, begin, done, step, workflow 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_forms.types import State, UUIDstr from pydantic import NonNegativeInt
from pydantic_forms.types import FormGenerator, State, UUIDstr
from gso.products.product_types.r_and_e_peer import RAndEPeerInactive from gso.products.product_types.r_and_e_peer import RAndEPeerInactive
from gso.services.lso_client import lso_interaction from gso.services.lso_client import lso_interaction
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
from gso.utils.workflow_steps import prompt_sharepoint_checklist_url, start_moodi, stop_moodi from gso.utils.workflow_steps import prompt_sharepoint_checklist_url, start_moodi, stop_moodi
from gso.workflows.l3_core_service.base_create_l3_core_service import ( from gso.workflows.l3_core_service.base_create_l3_core_service import (
check_bgp_peers, check_bgp_peers,
...@@ -16,12 +19,31 @@ from gso.workflows.l3_core_service.base_create_l3_core_service import ( ...@@ -16,12 +19,31 @@ from gso.workflows.l3_core_service.base_create_l3_core_service import (
create_new_sharepoint_checklist, create_new_sharepoint_checklist,
deploy_bgp_peers_dry, deploy_bgp_peers_dry,
deploy_bgp_peers_real, deploy_bgp_peers_real,
initial_input_form_generator,
initialize_subscription, initialize_subscription,
provision_sbp_dry, provision_sbp_dry,
provision_sbp_real, provision_sbp_real,
update_dns_records, update_dns_records,
) )
from gso.workflows.l3_core_service.base_create_l3_core_service import (
initial_input_form_generator as base_initial_input_form_generator,
)
from gso.workflows.l3_core_service.r_and_e_peer.shared import update_r_and_e_peer_subscription_model
def initial_input_form_generator(product_name: str) -> FormGenerator:
"""Initial input form generator for creating a new R&E Peer subscription."""
initial_generator = base_initial_input_form_generator(product_name)
initial_user_input = yield from initial_generator
# Additional R&E Peer step
class RAndEPeerExtraForm(FormPage):
v4_bgp_local_preference: NonNegativeInt = 100
v4_bgp_med: MultiExitDiscriminator = "igp"
v6_bgp_local_preference: NonNegativeInt = 100
v6_bgp_med: MultiExitDiscriminator = "igp"
r_and_e_peer_extra_form = yield RAndEPeerExtraForm
return initial_user_input | r_and_e_peer_extra_form.model_dump()
@step("Create subscription") @step("Create subscription")
...@@ -44,6 +66,7 @@ def create_r_and_e_peer() -> StepList: ...@@ -44,6 +66,7 @@ def create_r_and_e_peer() -> StepList:
>> create_subscription >> create_subscription
>> store_process_subscription(Target.CREATE) >> store_process_subscription(Target.CREATE)
>> initialize_subscription >> initialize_subscription
>> update_r_and_e_peer_subscription_model
>> start_moodi() >> start_moodi()
>> lso_interaction(provision_sbp_dry) >> lso_interaction(provision_sbp_dry)
>> lso_interaction(provision_sbp_real) >> lso_interaction(provision_sbp_real)
......
"""Modification workflow for an R&E Peer subscription.""" """Modification workflow for an R&E Peer subscription."""
from orchestrator import begin, conditional, done, workflow from orchestrator import begin, conditional, done, workflow
from orchestrator.forms import FormPage
from orchestrator.targets import Target from orchestrator.targets import Target
from orchestrator.workflow import StepList from orchestrator.workflow import StepList
from orchestrator.workflows.steps import resync, store_process_subscription, unsync from orchestrator.workflows.steps import resync, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form from orchestrator.workflows.utils import wrap_modify_initial_input_form
from pydantic import NonNegativeInt
from pydantic_forms.types import FormGenerator, UUIDstr
from gso.products.product_types.r_and_e_peer import RAndEPeer
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
from gso.workflows.l3_core_service.base_modify_l3_core_service import ( from gso.workflows.l3_core_service.base_modify_l3_core_service import (
Operation, Operation,
create_new_sbp, create_new_sbp,
...@@ -13,11 +18,30 @@ from gso.workflows.l3_core_service.base_modify_l3_core_service import ( ...@@ -13,11 +18,30 @@ from gso.workflows.l3_core_service.base_modify_l3_core_service import (
modify_existing_sbp, modify_existing_sbp,
remove_old_sbp, remove_old_sbp,
) )
from gso.workflows.l3_core_service.r_and_e_peer.shared import update_r_and_e_peer_subscription_model
def modify_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
"""Initial form generator for modifying the custom attributes of an existing IAS subscription."""
initial_generator = initial_input_form_generator(subscription_id)
initial_user_input = yield from initial_generator
subscription = RAndEPeer.from_subscription(subscription_id)
# Additional R&E Peer step
class RAndEPeerExtraForm(FormPage):
v4_bgp_local_preference: NonNegativeInt = subscription.r_and_e_peer.v4_bgp_local_preference
v4_bgp_med: MultiExitDiscriminator = subscription.r_and_e_peer.v4_bgp_med
v6_bgp_local_preference: NonNegativeInt = subscription.r_and_e_peer.v6_bgp_local_preference
v6_bgp_med: MultiExitDiscriminator = subscription.r_and_e_peer.v6_bgp_med
r_and_e_peer_extra_form = yield RAndEPeerExtraForm
return initial_user_input | r_and_e_peer_extra_form.model_dump()
@workflow( @workflow(
"Modify R&E Peer", "Modify R&E Peer",
initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator), initial_input_form=wrap_modify_initial_input_form(modify_input_form_generator),
target=Target.MODIFY, target=Target.MODIFY,
) )
def modify_r_and_e_peer() -> StepList: def modify_r_and_e_peer() -> StepList:
...@@ -30,6 +54,7 @@ def modify_r_and_e_peer() -> StepList: ...@@ -30,6 +54,7 @@ def modify_r_and_e_peer() -> StepList:
begin begin
>> store_process_subscription(Target.MODIFY) >> store_process_subscription(Target.MODIFY)
>> unsync >> unsync
>> update_r_and_e_peer_subscription_model
>> access_port_is_added(create_new_sbp) >> access_port_is_added(create_new_sbp)
>> access_port_is_removed(remove_old_sbp) >> access_port_is_removed(remove_old_sbp)
>> access_port_is_modified(modify_existing_sbp) >> access_port_is_modified(modify_existing_sbp)
......
"""Shared logic for R&E Peer service workflows."""
from orchestrator import step
from orchestrator.domain import SubscriptionModel
from pydantic import NonNegativeInt
from pydantic_forms.types import State
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
@step("Update R&E Peer-specific attributes")
def update_r_and_e_peer_subscription_model(
subscription: SubscriptionModel,
v4_bgp_local_preference: NonNegativeInt,
v4_bgp_med: MultiExitDiscriminator,
v6_bgp_local_preference: NonNegativeInt,
v6_bgp_med: MultiExitDiscriminator,
) -> State:
"""Update the subscription model of an R&E Peer subscription."""
subscription.r_and_e_peer.v4_bgp_local_preference = v4_bgp_local_preference # type: ignore[attr-defined]
subscription.r_and_e_peer.v4_bgp_med = v4_bgp_med # type: ignore[attr-defined]
subscription.r_and_e_peer.v6_bgp_local_preference = v6_bgp_local_preference # type: ignore[attr-defined]
subscription.r_and_e_peer.v6_bgp_med = v6_bgp_med # type: ignore[attr-defined]
return {"subscription": subscription}
import pytest
from pydantic import BaseModel, ValidationError
from gso.utils.types.multi_exit_discriminator import MultiExitDiscriminator
class BGPDiscriminator(BaseModel):
bgp_med: MultiExitDiscriminator
@pytest.mark.parametrize(
("input_value", "is_valid"),
[
("igp", True),
("min-igp", True),
("40", True),
("0", True),
(43, True),
("-74", False),
("45.6", False),
(-91, False),
("abc", False),
],
)
def test_multi_exit_discriminator(input_value, is_valid):
if is_valid:
assert BGPDiscriminator(bgp_med=input_value).bgp_med == str(input_value)
else:
with pytest.raises(ValidationError):
BGPDiscriminator(bgp_med=input_value)
...@@ -72,6 +72,9 @@ def test_create_imported_l3_core_service_success(faker, partner_factory, edge_po ...@@ -72,6 +72,9 @@ def test_create_imported_l3_core_service_success(faker, partner_factory, edge_po
} }
if product_name == ProductName.IAS: if product_name == ProductName.IAS:
creation_form_input_data["ias_flavor"] = IASFlavor.IASGWS creation_form_input_data["ias_flavor"] = IASFlavor.IASGWS
elif product_name in {ProductName.R_AND_E_PEER, ProductName.R_AND_E_LHCONE}:
creation_form_input_data["v6_bgp_local_preference"] = 9999
creation_form_input_data["v6_bgp_med"] = 8888
result, _, _ = run_workflow(f"{L3_CREAT_IMPORTED_WF_MAP[product_name]}", creation_form_input_data) result, _, _ = run_workflow(f"{L3_CREAT_IMPORTED_WF_MAP[product_name]}", creation_form_input_data)
state = extract_state(result) state = extract_state(result)
subscription = SubscriptionModel.from_subscription(state["subscription_id"]) subscription = SubscriptionModel.from_subscription(state["subscription_id"])
...@@ -81,3 +84,13 @@ def test_create_imported_l3_core_service_success(faker, partner_factory, edge_po ...@@ -81,3 +84,13 @@ def test_create_imported_l3_core_service_success(faker, partner_factory, edge_po
if product_name == ProductName.IAS: if product_name == ProductName.IAS:
assert subscription.ias.ias_flavor == IASFlavor.IASGWS assert subscription.ias.ias_flavor == IASFlavor.IASGWS
elif product_name == ProductName.R_AND_E_PEER:
assert subscription.r_and_e_peer.v4_bgp_local_preference == 100
assert subscription.r_and_e_peer.v4_bgp_med == "igp"
assert subscription.r_and_e_peer.v6_bgp_local_preference == 9999
assert subscription.r_and_e_peer.v6_bgp_med == "8888"
elif product_name == ProductName.R_AND_E_LHCONE:
assert subscription.r_and_e_lhcone.v4_bgp_local_preference == 100
assert subscription.r_and_e_lhcone.v4_bgp_med == "igp"
assert subscription.r_and_e_lhcone.v6_bgp_local_preference == 9999
assert subscription.r_and_e_lhcone.v6_bgp_med == "8888"
...@@ -89,6 +89,12 @@ def test_create_l3_core_service_success( ...@@ -89,6 +89,12 @@ def test_create_l3_core_service_success(
"ias_flavor": IASFlavor.IASGWS, "ias_flavor": IASFlavor.IASGWS,
} }
form_input_data.append(extra_ias_data) form_input_data.append(extra_ias_data)
elif product_name in {ProductName.R_AND_E_PEER, ProductName.R_AND_E_LHCONE}:
extra_r_and_e_data = {
"v6_bgp_local_preference": 5555,
"v6_bgp_med": "min-igp",
}
form_input_data.append(extra_r_and_e_data)
lso_interaction_count = 7 lso_interaction_count = 7
...@@ -117,3 +123,8 @@ def test_create_l3_core_service_success( ...@@ -117,3 +123,8 @@ def test_create_l3_core_service_success(
if product_name == ProductName.IAS: if product_name == ProductName.IAS:
assert subscription.ias.ias_flavor == IASFlavor.IASGWS assert subscription.ias.ias_flavor == IASFlavor.IASGWS
elif product_name == ProductName.R_AND_E_PEER:
assert subscription.r_and_e_peer.v4_bgp_local_preference == 100
assert subscription.r_and_e_peer.v4_bgp_med == "igp"
assert subscription.r_and_e_peer.v6_bgp_local_preference == 5555
assert subscription.r_and_e_peer.v6_bgp_med == "min-igp"
...@@ -26,6 +26,12 @@ def test_modify_l3_core_service_remove_edge_port_success(faker, l3_core_service_ ...@@ -26,6 +26,12 @@ def test_modify_l3_core_service_remove_edge_port_success(faker, l3_core_service_
"ias_flavor": IASFlavor.IASGWS, "ias_flavor": IASFlavor.IASGWS,
} }
input_form_data.append(extra_ias_data) input_form_data.append(extra_ias_data)
elif product_name in {ProductName.R_AND_E_PEER, ProductName.R_AND_E_LHCONE}:
extra_r_and_e_data = {
"v6_bgp_local_preference": 5555,
"v6_bgp_med": "min-igp",
}
input_form_data.append(extra_r_and_e_data)
result, _, _ = run_workflow(L3_MODIFICATION_WF_MAP[product_name], input_form_data) result, _, _ = run_workflow(L3_MODIFICATION_WF_MAP[product_name], input_form_data)
...@@ -36,6 +42,16 @@ def test_modify_l3_core_service_remove_edge_port_success(faker, l3_core_service_ ...@@ -36,6 +42,16 @@ def test_modify_l3_core_service_remove_edge_port_success(faker, l3_core_service_
assert ap_list[0].ap_type == APType.BACKUP assert ap_list[0].ap_type == APType.BACKUP
if product_name == ProductName.IAS: if product_name == ProductName.IAS:
assert subscription.ias.ias_flavor == IASFlavor.IASGWS assert subscription.ias.ias_flavor == IASFlavor.IASGWS
elif product_name == ProductName.R_AND_E_PEER:
assert subscription.r_and_e_peer.v4_bgp_local_preference == 100
assert subscription.r_and_e_peer.v4_bgp_med == "igp"
assert subscription.r_and_e_peer.v6_bgp_local_preference == 5555
assert subscription.r_and_e_peer.v6_bgp_med == "min-igp"
elif product_name == ProductName.R_AND_E_LHCONE:
assert subscription.r_and_e_lhcone.v4_bgp_local_preference == 100
assert subscription.r_and_e_lhcone.v4_bgp_med == "igp"
assert subscription.r_and_e_lhcone.v6_bgp_local_preference == 5555
assert subscription.r_and_e_lhcone.v6_bgp_med == "min-igp"
@pytest.mark.parametrize("product_name", L3_PRODUCT_NAMES) @pytest.mark.parametrize("product_name", L3_PRODUCT_NAMES)
...@@ -87,6 +103,12 @@ def test_modify_l3_core_service_add_new_edge_port_success( ...@@ -87,6 +103,12 @@ def test_modify_l3_core_service_add_new_edge_port_success(
"ias_flavor": IASFlavor.IASGWS, "ias_flavor": IASFlavor.IASGWS,
} }
input_form_data.append(extra_ias_data) input_form_data.append(extra_ias_data)
elif product_name in {ProductName.R_AND_E_PEER, ProductName.R_AND_E_LHCONE}:
extra_r_and_e_data = {
"v6_bgp_local_preference": 5555,
"v6_bgp_med": "123123",
}
input_form_data.append(extra_r_and_e_data)
result, _, _ = run_workflow(L3_MODIFICATION_WF_MAP[product_name], input_form_data) result, _, _ = run_workflow(L3_MODIFICATION_WF_MAP[product_name], input_form_data)
...@@ -104,6 +126,16 @@ def test_modify_l3_core_service_add_new_edge_port_success( ...@@ -104,6 +126,16 @@ def test_modify_l3_core_service_add_new_edge_port_success(
assert len(ap_list) == 3 assert len(ap_list) == 3
if product_name == ProductName.IAS: if product_name == ProductName.IAS:
assert subscription.ias.ias_flavor == IASFlavor.IASGWS assert subscription.ias.ias_flavor == IASFlavor.IASGWS
elif product_name == ProductName.R_AND_E_PEER:
assert subscription.r_and_e_peer.v4_bgp_local_preference == 100
assert subscription.r_and_e_peer.v4_bgp_med == "igp"
assert subscription.r_and_e_peer.v6_bgp_local_preference == 5555
assert subscription.r_and_e_peer.v6_bgp_med == "123123"
elif product_name == ProductName.R_AND_E_LHCONE:
assert subscription.r_and_e_lhcone.v4_bgp_local_preference == 100
assert subscription.r_and_e_lhcone.v4_bgp_med == "igp"
assert subscription.r_and_e_lhcone.v6_bgp_local_preference == 5555
assert subscription.r_and_e_lhcone.v6_bgp_med == "123123"
@pytest.fixture() @pytest.fixture()
...@@ -153,7 +185,7 @@ def sbp_input_form_data(faker): ...@@ -153,7 +185,7 @@ def sbp_input_form_data(faker):
@pytest.mark.parametrize("product_name", L3_PRODUCT_NAMES) @pytest.mark.parametrize("product_name", L3_PRODUCT_NAMES)
@pytest.mark.workflow() @pytest.mark.workflow()
def test_modify_l3_core_service_modify_edge_port_success( def test_modify_l3_core_service_modify_edge_port_success( # noqa: PLR0915
faker, l3_core_service_subscription_factory, product_name, sbp_input_form_data faker, l3_core_service_subscription_factory, product_name, sbp_input_form_data
): ):
subscription = l3_core_service_subscription_factory(product_name=product_name) subscription = l3_core_service_subscription_factory(product_name=product_name)
...@@ -171,6 +203,12 @@ def test_modify_l3_core_service_modify_edge_port_success( ...@@ -171,6 +203,12 @@ def test_modify_l3_core_service_modify_edge_port_success(
"ias_flavor": IASFlavor.IASGWS, "ias_flavor": IASFlavor.IASGWS,
} }
input_form_data.append(extra_ias_data) input_form_data.append(extra_ias_data)
elif product_name in {ProductName.R_AND_E_PEER, ProductName.R_AND_E_LHCONE}:
extra_r_and_e_data = {
"v6_bgp_local_preference": 5555,
"v6_bgp_med": "min-igp",
}
input_form_data.append(extra_r_and_e_data)
result, _, _ = run_workflow(L3_MODIFICATION_WF_MAP[product_name], input_form_data) result, _, _ = run_workflow(L3_MODIFICATION_WF_MAP[product_name], input_form_data)
...@@ -223,3 +261,13 @@ def test_modify_l3_core_service_modify_edge_port_success( ...@@ -223,3 +261,13 @@ def test_modify_l3_core_service_modify_edge_port_success(
if product_name == ProductName.IAS: if product_name == ProductName.IAS:
assert subscription.ias.ias_flavor == IASFlavor.IASGWS assert subscription.ias.ias_flavor == IASFlavor.IASGWS
elif product_name == ProductName.R_AND_E_PEER:
assert subscription.r_and_e_peer.v4_bgp_local_preference == 100
assert subscription.r_and_e_peer.v4_bgp_med == "igp"
assert subscription.r_and_e_peer.v6_bgp_local_preference == 5555
assert subscription.r_and_e_peer.v6_bgp_med == "min-igp"
elif product_name == ProductName.R_AND_E_LHCONE:
assert subscription.r_and_e_lhcone.v4_bgp_local_preference == 100
assert subscription.r_and_e_lhcone.v4_bgp_med == "igp"
assert subscription.r_and_e_lhcone.v6_bgp_local_preference == 5555
assert subscription.r_and_e_lhcone.v6_bgp_med == "min-igp"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment