Skip to content
Snippets Groups Projects
Commit 399f8c89 authored by Karel van Klink's avatar Karel van Klink :smiley_cat: Committed by Neda Moeini
Browse files

Add redeploy workflow for L3 core services

parent ef07e6b1
No related branches found
No related tags found
1 merge request!442Add redeploy workflow for L3 core services
"""Add L3 service redeploy workflow.
Revision ID: 285954f5ec04
Revises: b2b5137ef0c7
Create Date: 2025-06-24 16:49:06.495691
"""
from alembic import op
from orchestrator.migrations.helpers import (
add_products_to_workflow_by_product_tag,
create_workflow,
delete_workflow,
remove_products_from_workflow_by_product_tag
)
# revision identifiers, used by Alembic.
revision = '285954f5ec04'
down_revision = 'b2b5137ef0c7'
branch_labels = None
depends_on = None
new_workflow = {
"name": "redeploy_l3_core_service",
"target": "MODIFY",
"description": "Redeploy Layer 3 service",
"product_type": "GeantIP"
}
additional_product_tags = ["IAS", "LHC", "COP", "RE_LHCONE", "RE_PEER"]
def upgrade() -> None:
conn = op.get_bind()
create_workflow(conn, new_workflow)
for product in additional_product_tags:
add_products_to_workflow_by_product_tag(conn, new_workflow["name"], product)
def downgrade() -> None:
conn = op.get_bind()
for product in additional_product_tags:
remove_products_from_workflow_by_product_tag(conn, new_workflow["name"], product)
delete_workflow(conn, new_workflow["name"])
...@@ -159,6 +159,7 @@ ...@@ -159,6 +159,7 @@
"modify_r_and_e_lhcone": "Modify R&E LHCONE", "modify_r_and_e_lhcone": "Modify R&E LHCONE",
"promote_p_to_pe": "Promote P to PE", "promote_p_to_pe": "Promote P to PE",
"redeploy_base_config": "Redeploy base config", "redeploy_base_config": "Redeploy base config",
"redeploy_l3_core_service": "Redeploy Layer 3 service",
"redeploy_vrf": "Redeploy VRF router list", "redeploy_vrf": "Redeploy VRF router list",
"task_check_site_connectivity": "Check NETCONF connectivity of a Site", "task_check_site_connectivity": "Check NETCONF connectivity of a Site",
"task_clean_old_tasks": "Remove old cleanup tasks", "task_clean_old_tasks": "Remove old cleanup tasks",
......
...@@ -120,6 +120,9 @@ LazyWorkflowInstance("gso.workflows.edge_port.create_imported_edge_port", "creat ...@@ -120,6 +120,9 @@ LazyWorkflowInstance("gso.workflows.edge_port.create_imported_edge_port", "creat
LazyWorkflowInstance("gso.workflows.edge_port.import_edge_port", "import_edge_port") LazyWorkflowInstance("gso.workflows.edge_port.import_edge_port", "import_edge_port")
LazyWorkflowInstance("gso.workflows.edge_port.migrate_edge_port", "migrate_edge_port") LazyWorkflowInstance("gso.workflows.edge_port.migrate_edge_port", "migrate_edge_port")
# All L3 core services
LazyWorkflowInstance("gso.workflows.l3_core_service.redeploy_l3_core_service", "redeploy_l3_core_service")
# IAS workflows # IAS workflows
LazyWorkflowInstance("gso.workflows.l3_core_service.ias.create_ias", "create_ias") LazyWorkflowInstance("gso.workflows.l3_core_service.ias.create_ias", "create_ias")
LazyWorkflowInstance("gso.workflows.l3_core_service.ias.modify_ias", "modify_ias") LazyWorkflowInstance("gso.workflows.l3_core_service.ias.modify_ias", "modify_ias")
......
"""Base functionality for modifying an L3 Core Service subscription."""
from typing import TypeAlias, cast
from orchestrator import workflow
from orchestrator.domain import SubscriptionModel
from orchestrator.forms import FormPage
from orchestrator.targets import Target
from orchestrator.workflow import StepList, begin, done
from orchestrator.workflows.steps import resync, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form
from pydantic import ConfigDict
from pydantic_forms.types import FormGenerator, UUIDstr
from pydantic_forms.validators import Choice
from gso.products.product_blocks.l3_core_service import AccessPort
from gso.products.product_types.edge_port import EdgePort
from gso.services.lso_client import lso_interaction
from gso.services.partners import get_partner_by_id
from gso.utils.types.tt_number import TTNumber
from gso.workflows.l3_core_service.base_create_l3_core_service import (
deploy_bgp_peers_dry,
deploy_bgp_peers_real,
provision_sbp_dry,
provision_sbp_real,
)
def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
"""Get input which Access Port should be re-deployed."""
subscription = SubscriptionModel.from_subscription(subscription_id)
product_name = subscription.product.name
def access_port_selector() -> TypeAlias:
"""Generate a dropdown selector for choosing an Access Port in an input form."""
access_ports = subscription.l3_core.ap_list # type: ignore[attr-defined]
options = {
str(access_port.subscription_instance_id): (
f"{access_port.sbp.gs_id} on "
f"{EdgePort.from_subscription(access_port.sbp.edge_port.owner_subscription_id).description} "
f"({access_port.ap_type})"
)
for access_port in access_ports
}
return cast(
type[Choice],
Choice.__call__(
"Select an Access Port",
zip(options.keys(), options.items(), strict=True),
),
)
class AccessPortSelectionForm(FormPage):
model_config = ConfigDict(title=f"Re-deploy {product_name} subscription")
tt_number: TTNumber
access_port: access_port_selector() # type: ignore[valid-type]
user_input = yield AccessPortSelectionForm
partner_name = get_partner_by_id(subscription.customer_id).name
access_port = AccessPort.from_db(user_input.access_port)
access_port_fqdn = EdgePort.from_subscription(
access_port.sbp.edge_port.owner_subscription_id
).edge_port.node.router_fqdn
return user_input.model_dump() | {"edge_port_fqdn_list": [access_port_fqdn], "partner_name": partner_name}
@workflow(
"Redeploy Layer 3 service",
initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator),
target=Target.MODIFY,
)
def redeploy_l3_core_service() -> StepList:
"""Redeploy a Layer 3 subscription."""
return (
begin
>> store_process_subscription(Target.MODIFY)
>> unsync
>> lso_interaction(provision_sbp_dry)
>> lso_interaction(provision_sbp_real)
>> lso_interaction(deploy_bgp_peers_dry)
>> lso_interaction(deploy_bgp_peers_real)
>> resync
>> done
)
from copy import deepcopy
import pytest
from orchestrator.domain import SubscriptionModel
from gso.workflows.l3_core_service.shared import L3_PRODUCT_NAMES
from test.workflows import assert_complete, assert_lso_interaction_success, extract_state, run_workflow
@pytest.mark.parametrize("product_name", L3_PRODUCT_NAMES)
@pytest.mark.workflow()
def test_redeploy_l3_core_service_success(faker, l3_core_service_subscription_factory, product_name):
subscription = l3_core_service_subscription_factory(product_name=product_name)
old_subscription: SubscriptionModel = deepcopy(subscription)
access_port = subscription.l3_core.ap_list[0]
input_form_data = [
{"subscription_id": str(subscription.subscription_id)},
{"tt_number": faker.tt_number(), "access_port": str(access_port.subscription_instance_id)},
]
result, process_stat, step_log = run_workflow("redeploy_l3_core_service", input_form_data)
for _ in range(4):
result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
assert_complete(result)
state = extract_state(result)
subscription = SubscriptionModel.from_subscription(state["subscription_id"])
ap_list = subscription.l3_core.ap_list
old_ap_list = old_subscription.l3_core.ap_list
# Assertions that ensure the subscription is unchanged
for old_access_port, access_port in zip(old_ap_list, ap_list, strict=False):
assert access_port.sbp.gs_id == old_access_port.sbp.gs_id
assert access_port.sbp.is_tagged == old_access_port.sbp.is_tagged
assert access_port.sbp.vlan_id == old_access_port.sbp.vlan_id
assert str(access_port.sbp.ipv4_address) == str(old_access_port.sbp.ipv4_address)
assert access_port.sbp.ipv4_mask == old_access_port.sbp.ipv4_mask
assert str(access_port.sbp.ipv6_address) == str(old_access_port.sbp.ipv6_address)
assert access_port.sbp.ipv6_mask == old_access_port.sbp.ipv6_mask
assert access_port.sbp.custom_firewall_filters == old_access_port.sbp.custom_firewall_filters
assert access_port.sbp.bgp_session_list[0].bfd_enabled == old_access_port.sbp.bgp_session_list[0].bfd_enabled
assert (
access_port.sbp.bgp_session_list[0].has_custom_policies
== old_access_port.sbp.bgp_session_list[0].has_custom_policies
)
assert (
access_port.sbp.bgp_session_list[0].authentication_key
== old_access_port.sbp.bgp_session_list[0].authentication_key
)
assert (
access_port.sbp.bgp_session_list[0].multipath_enabled
== old_access_port.sbp.bgp_session_list[0].multipath_enabled
)
assert (
access_port.sbp.bgp_session_list[0].send_default_route
== old_access_port.sbp.bgp_session_list[0].send_default_route
)
assert access_port.sbp.bgp_session_list[0].is_passive == old_access_port.sbp.bgp_session_list[0].is_passive
assert access_port.sbp.bgp_session_list[1].bfd_enabled == old_access_port.sbp.bgp_session_list[1].bfd_enabled
assert (
access_port.sbp.bgp_session_list[1].has_custom_policies
== old_access_port.sbp.bgp_session_list[1].has_custom_policies
)
assert (
access_port.sbp.bgp_session_list[1].authentication_key
== old_access_port.sbp.bgp_session_list[1].authentication_key
)
assert (
access_port.sbp.bgp_session_list[1].multipath_enabled
== old_access_port.sbp.bgp_session_list[1].multipath_enabled
)
assert (
access_port.sbp.bgp_session_list[1].send_default_route
== old_access_port.sbp.bgp_session_list[1].send_default_route
)
assert access_port.sbp.bgp_session_list[1].is_passive == old_access_port.sbp.bgp_session_list[1].is_passive
assert access_port.sbp.v4_bfd_settings.bfd_enabled == old_access_port.sbp.v4_bfd_settings.bfd_enabled
assert access_port.sbp.v4_bfd_settings.bfd_interval_rx == old_access_port.sbp.v4_bfd_settings.bfd_interval_rx
assert access_port.sbp.v4_bfd_settings.bfd_interval_tx == old_access_port.sbp.v4_bfd_settings.bfd_interval_tx
assert access_port.sbp.v4_bfd_settings.bfd_multiplier == old_access_port.sbp.v4_bfd_settings.bfd_multiplier
assert access_port.sbp.v6_bfd_settings.bfd_enabled == old_access_port.sbp.v6_bfd_settings.bfd_enabled
assert access_port.sbp.v6_bfd_settings.bfd_interval_rx == old_access_port.sbp.v6_bfd_settings.bfd_interval_rx
assert access_port.sbp.v6_bfd_settings.bfd_interval_tx == old_access_port.sbp.v6_bfd_settings.bfd_interval_tx
assert access_port.sbp.v6_bfd_settings.bfd_multiplier == old_access_port.sbp.v6_bfd_settings.bfd_multiplier
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment