diff --git a/Changelog.md b/Changelog.md index d151d640e871746771be86027194f79b037f8dcb..58e216a048bbd7da5b30b386935f8d658d7bb95a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,9 @@ # Changelog -## [2.47] - 2025-04-15 +## [2.48] - 2025-04-14 +- Make updating iBGP and SBP meshes optional in mesh update workflow + +## [2.47] - 2025-04-14 - Make generation of new virtual circuit ID optional in layer 2 circuit migration workflow - Add REST API endpoint for getting the list of available versions diff --git a/gso/utils/workflow_steps.py b/gso/utils/workflow_steps.py index 50f754a96a6b8ba263ce24ee49ae67d5f1f125f6..0b6071fd982d658a08d87552758b045b86167dc5 100644 --- a/gso/utils/workflow_steps.py +++ b/gso/utils/workflow_steps.py @@ -307,13 +307,13 @@ def remove_pe_from_sdp_mesh_real(subscription: dict[str, Any], tt_number: str, p return _update_sdp_mesh(subscription, tt_number, process_id, dry_run=False, verb="remove_pe_from_sdp_mesh") -@step("[DRY RUN] Configure SDP on the PE to all other Nokia PEs") +@step("[DRY RUN] Configure SDP on the PE to all other PEs") def update_sdp_single_pe_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: """Perform a dry run of configuring SDP on a new PE router to all other NOKIA PE routers.""" return _update_sdp_single_pe(subscription, tt_number, process_id, dry_run=True) -@step("[FOR REAL] Configure SDP on the PE to all other Nokia PEs") +@step("[FOR REAL] Configure SDP on the PE to all other PEs") def update_sdp_single_pe_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: """Configure SDP on a new PE router to all other NOKIA PE routers.""" return _update_sdp_single_pe(subscription, tt_number, process_id, dry_run=False) diff --git a/gso/workflows/router/update_ibgp_mesh.py b/gso/workflows/router/update_ibgp_mesh.py index d04a50946f6a7567335e800adb9698e1683bc926..6d51ef23f070976c92177aa3053bdfca0e82bf4e 100644 --- a/gso/workflows/router/update_ibgp_mesh.py +++ b/gso/workflows/router/update_ibgp_mesh.py @@ -69,6 +69,8 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: model_config = ConfigDict(title=f"Add {subscription.router.router_fqdn} to the iBGP mesh?") tt_number: TTNumber + update_ibgp_mesh: bool = True + update_sbp_mesh: bool = True @model_validator(mode="before") def router_has_a_trunk(cls, data: Any) -> Any: @@ -232,28 +234,31 @@ def update_ibgp_mesh() -> StepList: router_is_pe = conditional(lambda state: state["subscription"]["router"]["router_role"] == RouterRole.PE) router_is_p = conditional(lambda state: state["subscription"]["router"]["router_role"] == RouterRole.P) + update_bgp = conditional(lambda state: bool(state["update_ibgp_mesh"])) + update_sbp = conditional(lambda state: bool(state["update_sbp_mesh"])) + return ( begin >> store_process_subscription(Target.MODIFY) >> unsync - >> router_is_p(lso_interaction(add_p_to_mesh_dry)) - >> router_is_p(lso_interaction(add_p_to_mesh_real)) - >> router_is_p(lso_interaction(add_all_pe_to_p_dry)) - >> router_is_p(lso_interaction(add_all_pe_to_p_real)) - >> router_is_p(lso_interaction(check_ibgp_session)) - >> router_is_pe(lso_interaction(add_pe_mesh_to_pe_dry)) - >> router_is_pe(lso_interaction(add_pe_mesh_to_pe_real)) - >> router_is_pe(lso_interaction(add_pe_to_pe_mesh_dry)) - >> router_is_pe(lso_interaction(add_pe_to_pe_mesh_real)) - >> router_is_pe(lso_interaction(add_all_p_to_pe_dry)) - >> router_is_pe(lso_interaction(add_all_p_to_pe_real)) - >> router_is_pe(lso_interaction(add_pe_to_all_p_dry)) - >> router_is_pe(lso_interaction(add_pe_to_all_p_real)) - >> router_is_pe(lso_interaction(update_sdp_single_pe_dry)) - >> router_is_pe(lso_interaction(update_sdp_single_pe_real)) - >> router_is_pe(lso_interaction(add_pe_to_sdp_mesh_dry)) - >> router_is_pe(lso_interaction(add_pe_to_sdp_mesh_real)) - >> router_is_pe(lso_interaction(check_pe_ibgp)) + >> update_bgp(router_is_p(lso_interaction(add_p_to_mesh_dry))) + >> update_bgp(router_is_p(lso_interaction(add_p_to_mesh_real))) + >> update_bgp(router_is_p(lso_interaction(add_all_pe_to_p_dry))) + >> update_bgp(router_is_p(lso_interaction(add_all_pe_to_p_real))) + >> update_bgp(router_is_p(lso_interaction(check_ibgp_session))) + >> update_bgp(router_is_pe(lso_interaction(add_pe_mesh_to_pe_dry))) + >> update_bgp(router_is_pe(lso_interaction(add_pe_mesh_to_pe_real))) + >> update_bgp(router_is_pe(lso_interaction(add_pe_to_pe_mesh_dry))) + >> update_bgp(router_is_pe(lso_interaction(add_pe_to_pe_mesh_real))) + >> update_bgp(router_is_pe(lso_interaction(add_all_p_to_pe_dry))) + >> update_bgp(router_is_pe(lso_interaction(add_all_p_to_pe_real))) + >> update_bgp(router_is_pe(lso_interaction(add_pe_to_all_p_dry))) + >> update_bgp(router_is_pe(lso_interaction(add_pe_to_all_p_real))) + >> update_sbp(router_is_pe(lso_interaction(update_sdp_single_pe_dry))) + >> update_sbp(router_is_pe(lso_interaction(update_sdp_single_pe_real))) + >> update_sbp(router_is_pe(lso_interaction(add_pe_to_sdp_mesh_dry))) + >> update_sbp(router_is_pe(lso_interaction(add_pe_to_sdp_mesh_real))) + >> update_bgp(router_is_pe(lso_interaction(check_pe_ibgp))) >> router_is_pe(lso_interaction(check_l3_services)) >> add_device_to_librenms >> prompt_insert_in_radius diff --git a/setup.py b/setup.py index f6a1d79b7d6a3f5dc76ec0522547dd1dfe148002..53cdde31a7ea5f6ba40ab98f665003c52c5f84d7 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import find_packages, setup setup( name="geant-service-orchestrator", - version="2.47", + version="2.48", author="GÉANT Orchestration and Automation Team", author_email="goat@geant.org", description="GÉANT Service Orchestrator", diff --git a/test/workflows/router/test_update_ibgp_mesh.py b/test/workflows/router/test_update_ibgp_mesh.py index 06b54521eb9f014b693373f38cf74403cd8cfd41..2cd098b3986dbf2adc58e0a9bd209b0925b0d829 100644 --- a/test/workflows/router/test_update_ibgp_mesh.py +++ b/test/workflows/router/test_update_ibgp_mesh.py @@ -18,6 +18,8 @@ from test.workflows import ( @pytest.mark.parametrize("trunk_status", [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE]) @pytest.mark.parametrize("router_role", [RouterRole.P, RouterRole.PE]) +@pytest.mark.parametrize("update_ibgp_mesh", [True, False]) +@pytest.mark.parametrize("update_sbp_mesh", [True, False]) @pytest.mark.workflow() @patch("gso.services.lso_client._send_request") @patch("gso.workflows.router.update_ibgp_mesh.librenms_client.LibreNMSClient.add_device") @@ -26,6 +28,8 @@ def test_update_ibgp_mesh_success( mock_librenms_device_exists, mock_librenms_add_device, mock_execute_playbook, + update_sbp_mesh, + update_ibgp_mesh, router_role, trunk_status, iptrunk_subscription_factory, @@ -41,12 +45,29 @@ def test_update_ibgp_mesh_success( router_subscription_factory() ip_trunk = iptrunk_subscription_factory(status=trunk_status, iptrunk_sides=[side_a, side_b]) - callback_step_count = 5 if router_role == RouterRole.P else 14 + callback_step_count = 0 + if router_role == RouterRole.PE: + callback_step_count += 1 + if update_ibgp_mesh: + callback_step_count += 9 + if update_sbp_mesh: + callback_step_count += 4 + elif router_role == RouterRole.P and update_ibgp_mesh: + callback_step_count += 5 + ibgp_mesh_input_form_data = { "subscription_id": ip_trunk.iptrunk.iptrunk_sides[0].iptrunk_side_node.owner_subscription_id } result, process_stat, step_log = run_workflow( - "update_ibgp_mesh", [ibgp_mesh_input_form_data, {"tt_number": faker.tt_number()}] + "update_ibgp_mesh", + [ + ibgp_mesh_input_form_data, + { + "tt_number": faker.tt_number(), + "update_ibgp_mesh": update_ibgp_mesh, + "update_sbp_mesh": update_sbp_mesh, + }, + ], ) for _ in range(callback_step_count):