From f396fe73ab27d8c92615d66521b9f4941653faf8 Mon Sep 17 00:00:00 2001
From: Karel van Klink <karel.vanklink@geant.org>
Date: Mon, 18 Nov 2024 15:08:37 +0100
Subject: [PATCH] Also include provisioning routers for iBGP mesh in trunk
 validation workflow

---
 gso/utils/helpers.py                     | 14 ++++++++++++--
 gso/utils/workflow_steps.py              | 14 +++++++-------
 gso/workflows/router/promote_p_to_pe.py  | 10 +++++-----
 gso/workflows/router/terminate_router.py | 18 +++++++-----------
 gso/workflows/router/update_ibgp_mesh.py | 10 +++++-----
 gso/workflows/router/validate_router.py  |  6 ++++--
 test/utils/test_helpers.py               | 10 +++++-----
 7 files changed, 45 insertions(+), 37 deletions(-)

diff --git a/gso/utils/helpers.py b/gso/utils/helpers.py
index 59e6f560..53c6aadb 100644
--- a/gso/utils/helpers.py
+++ b/gso/utils/helpers.py
@@ -5,6 +5,7 @@ import re
 from typing import TYPE_CHECKING
 from uuid import UUID
 
+from orchestrator.types import SubscriptionLifecycle
 from pydantic_forms.types import UUIDstr
 from pydantic_forms.validators import Choice
 
@@ -122,10 +123,12 @@ def generate_fqdn(hostname: str, site_name: str, country_code: str) -> str:
     return f"{hostname}.{site_name.lower()}.{country_code.lower()}{oss.IPAM.LO.domain_name}"
 
 
-def generate_inventory_for_active_routers(
+def generate_inventory_for_routers(
     router_role: RouterRole,
     exclude_routers: list[str] | None = None,
     router_vendor: Vendor | None = None,
+    *,
+    include_provisioning_routers: bool = False,
 ) -> dict:
     """Generate an Ansible-compatible inventory for executing playbooks.
 
@@ -134,11 +137,18 @@ def generate_inventory_for_active_routers(
     :param RouterRole router_role: The role of the routers to include in the inventory.
     :param list exclude_routers: List of routers to exclude from the inventory.
     :param Vendor router_vendor: The vendor of the routers to include in the inventory.
+    :param bool include_provisioning_routers: Include routers that are in a ``PROVISIONING`` state.
     :return: A dictionary representing the inventory of active routers.
     :rtype: dict[str, Any]
     """
+    lifecycles = (
+        [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE]
+        if include_provisioning_routers
+        else [SubscriptionLifecycle.ACTIVE]
+    )
     all_routers = [
-        Router.from_subscription(r["subscription_id"]) for r in subscriptions.get_active_router_subscriptions()
+        Router.from_subscription(r["subscription_id"])
+        for r in subscriptions.get_router_subscriptions(lifecycles=lifecycles)
     ]
     exclude_routers = exclude_routers or []
 
diff --git a/gso/utils/workflow_steps.py b/gso/utils/workflow_steps.py
index 6979d6aa..4c4bda08 100644
--- a/gso/utils/workflow_steps.py
+++ b/gso/utils/workflow_steps.py
@@ -19,7 +19,7 @@ from gso.products.product_types.iptrunk import Iptrunk
 from gso.services.kentik_client import KentikClient, NewKentikDevice
 from gso.services.lso_client import LSOState, indifferent_lso_interaction
 from gso.settings import load_oss_params
-from gso.utils.helpers import generate_inventory_for_active_routers
+from gso.utils.helpers import generate_inventory_for_routers
 from gso.utils.shared_enums import Vendor
 
 
@@ -51,7 +51,7 @@ def _update_sdp_mesh(
     *,
     dry_run: bool,
 ) -> LSOState:
-    inventory = generate_inventory_for_active_routers(
+    inventory = generate_inventory_for_routers(
         router_role=RouterRole.PE, router_vendor=Vendor.NOKIA, exclude_routers=[subscription["router"]["router_fqdn"]]
     )
 
@@ -89,7 +89,7 @@ def _update_sdp_single_pe(
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
         f"Update the SDP mesh for L2circuits(epipes) config on PE NOKIA routers",
         "verb": "update_sdp_mesh",
-        "pe_router_list": generate_inventory_for_active_routers(
+        "pe_router_list": generate_inventory_for_routers(
             router_role=RouterRole.PE,
             exclude_routers=[subscription["router"]["router_fqdn"]],
         )["all"]["hosts"],
@@ -122,7 +122,7 @@ def _add_pe_mesh_to_pe(
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
         f"Add list of PE routers into iGEANT/iGEANT6 groups of the PE router",
         "verb": "add_pe_mesh_to_pe",
-        "pe_router_list": generate_inventory_for_active_routers(
+        "pe_router_list": generate_inventory_for_routers(
             router_role=RouterRole.PE, exclude_routers=[subscription["router"]["router_fqdn"]]
         )["all"]["hosts"],
     }
@@ -148,7 +148,7 @@ def _add_pe_to_pe_mesh(
     *,
     dry_run: bool,
 ) -> LSOState:
-    inventory = generate_inventory_for_active_routers(
+    inventory = generate_inventory_for_routers(
         router_role=RouterRole.PE, exclude_routers=[subscription["router"]["router_fqdn"]]
     )
     extra_vars = {
@@ -178,7 +178,7 @@ def _add_all_p_to_pe(
         "subscription": subscription,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Add all P-routers to this new PE",
         "verb": "add_all_p_to_pe",
-        "p_router_list": generate_inventory_for_active_routers(
+        "p_router_list": generate_inventory_for_routers(
             router_role=RouterRole.P, exclude_routers=[subscription["router"]["router_fqdn"]]
         )["all"]["hosts"],
     }
@@ -204,7 +204,7 @@ def _add_pe_to_all_p(
     *,
     dry_run: bool,
 ) -> LSOState:
-    inventory = generate_inventory_for_active_routers(
+    inventory = generate_inventory_for_routers(
         router_role=RouterRole.P, exclude_routers=[subscription["router"]["router_fqdn"]]
     )
     extra_vars = {
diff --git a/gso/workflows/router/promote_p_to_pe.py b/gso/workflows/router/promote_p_to_pe.py
index 68518265..16d1ffcc 100644
--- a/gso/workflows/router/promote_p_to_pe.py
+++ b/gso/workflows/router/promote_p_to_pe.py
@@ -18,7 +18,7 @@ from gso.products.product_blocks.router import RouterRole
 from gso.products.product_types.router import Router
 from gso.services.lso_client import LSOState, lso_interaction
 from gso.services.subscriptions import get_all_active_sites
-from gso.utils.helpers import generate_inventory_for_active_routers
+from gso.utils.helpers import generate_inventory_for_routers
 from gso.utils.shared_enums import Vendor
 from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import (
@@ -85,7 +85,7 @@ def deploy_pe_base_config_dry(subscription: dict[str, Any], tt_number: str, proc
         "subscription": subscription,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - deploy PE base config",
         "verb": "deploy_pe_base_config",
-        "pe_router_list": generate_inventory_for_active_routers(RouterRole.PE)["all"]["hosts"],
+        "pe_router_list": generate_inventory_for_routers(RouterRole.PE)["all"]["hosts"],
         "geant_sites": json.loads(json_dumps(get_all_active_sites())),
     }
 
@@ -104,7 +104,7 @@ def deploy_pe_base_config_real(subscription: dict[str, Any], tt_number: str, pro
         "subscription": subscription,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - deploy PE base config",
         "verb": "deploy_pe_base_config",
-        "pe_router_list": generate_inventory_for_active_routers(RouterRole.PE)["all"]["hosts"],
+        "pe_router_list": generate_inventory_for_routers(RouterRole.PE)["all"]["hosts"],
         "geant_sites": json.loads(json_dumps(get_all_active_sites())),
     }
 
@@ -142,7 +142,7 @@ def remove_p_from_pe_dry(subscription: dict[str, Any], tt_number: str, process_i
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.PE),
+        "inventory": generate_inventory_for_routers(RouterRole.PE),
         "extra_vars": extra_vars,
     }
 
@@ -160,7 +160,7 @@ def remove_p_from_pe_real(subscription: dict[str, Any], tt_number: str, process_
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.PE),
+        "inventory": generate_inventory_for_routers(RouterRole.PE),
         "extra_vars": extra_vars,
     }
 
diff --git a/gso/workflows/router/terminate_router.py b/gso/workflows/router/terminate_router.py
index 9bc48f8c..56344fc2 100644
--- a/gso/workflows/router/terminate_router.py
+++ b/gso/workflows/router/terminate_router.py
@@ -28,7 +28,7 @@ from gso.services.librenms_client import LibreNMSClient
 from gso.services.lso_client import LSOState, lso_interaction
 from gso.services.netbox_client import NetboxClient
 from gso.settings import load_oss_params
-from gso.utils.helpers import generate_inventory_for_active_routers
+from gso.utils.helpers import generate_inventory_for_routers
 from gso.utils.shared_enums import Vendor
 from gso.utils.types.tt_number import TTNumber
 
@@ -124,7 +124,7 @@ def remove_p_from_all_pe_dry(subscription: Router, tt_number: str, process_id: U
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.PE),
+        "inventory": generate_inventory_for_routers(RouterRole.PE),
         "extra_vars": extra_vars,
     }
 
@@ -142,7 +142,7 @@ def remove_p_from_all_pe_real(subscription: Router, tt_number: str, process_id:
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.PE),
+        "inventory": generate_inventory_for_routers(RouterRole.PE),
         "extra_vars": extra_vars,
     }
 
@@ -160,9 +160,7 @@ def remove_pe_from_all_pe_dry(subscription: Router, tt_number: str, process_id:
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(
-            RouterRole.PE, exclude_routers=[subscription.router.router_fqdn]
-        ),
+        "inventory": generate_inventory_for_routers(RouterRole.PE, exclude_routers=[subscription.router.router_fqdn]),
         "extra_vars": extra_vars,
     }
 
@@ -180,9 +178,7 @@ def remove_pe_from_all_pe_real(subscription: Router, tt_number: str, process_id:
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(
-            RouterRole.PE, exclude_routers=[subscription.router.router_fqdn]
-        ),
+        "inventory": generate_inventory_for_routers(RouterRole.PE, exclude_routers=[subscription.router.router_fqdn]),
         "extra_vars": extra_vars,
     }
 
@@ -200,7 +196,7 @@ def remove_pe_from_all_p_dry(subscription: Router, tt_number: str, process_id: U
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.P),
+        "inventory": generate_inventory_for_routers(RouterRole.P),
         "extra_vars": extra_vars,
     }
 
@@ -218,7 +214,7 @@ def remove_pe_from_all_p_real(subscription: Router, tt_number: str, process_id:
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.P),
+        "inventory": generate_inventory_for_routers(RouterRole.P),
         "extra_vars": extra_vars,
     }
 
diff --git a/gso/workflows/router/update_ibgp_mesh.py b/gso/workflows/router/update_ibgp_mesh.py
index fc071ab8..7adea41c 100644
--- a/gso/workflows/router/update_ibgp_mesh.py
+++ b/gso/workflows/router/update_ibgp_mesh.py
@@ -17,7 +17,7 @@ from gso.products.product_types.router import Router
 from gso.services import librenms_client
 from gso.services.lso_client import LSOState, lso_interaction
 from gso.services.subscriptions import get_trunks_that_terminate_on_router
-from gso.utils.helpers import generate_inventory_for_active_routers
+from gso.utils.helpers import generate_inventory_for_routers
 from gso.utils.shared_enums import SNMPVersion
 from gso.utils.types.tt_number import TTNumber
 from gso.utils.workflow_steps import (
@@ -79,7 +79,7 @@ def add_p_to_mesh_dry(subscription: dict[str, Any], tt_number: str, process_id:
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.PE),
+        "inventory": generate_inventory_for_routers(RouterRole.PE),
         "extra_vars": extra_vars,
     }
 
@@ -96,7 +96,7 @@ def add_p_to_mesh_real(subscription: dict[str, Any], tt_number: str, process_id:
 
     return {
         "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
-        "inventory": generate_inventory_for_active_routers(RouterRole.PE),
+        "inventory": generate_inventory_for_routers(RouterRole.PE),
         "extra_vars": extra_vars,
     }
 
@@ -107,7 +107,7 @@ def add_all_pe_to_p_dry(subscription: dict[str, Any]) -> LSOState:
     extra_vars = {
         "dry_run": True,
         "subscription": subscription,
-        "pe_router_list": generate_inventory_for_active_routers(RouterRole.PE),
+        "pe_router_list": generate_inventory_for_routers(RouterRole.PE),
         "verb": "add_pe_to_p",
     }
 
@@ -124,7 +124,7 @@ def add_all_pe_to_p_real(subscription: dict[str, Any], tt_number: str, process_i
     extra_vars = {
         "dry_run": False,
         "subscription": subscription,
-        "pe_router_list": generate_inventory_for_active_routers(RouterRole.PE),
+        "pe_router_list": generate_inventory_for_routers(RouterRole.PE),
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Update iBGP mesh",
         "verb": "add_pe_to_p",
     }
diff --git a/gso/workflows/router/validate_router.py b/gso/workflows/router/validate_router.py
index 2403c52f..7927ab66 100644
--- a/gso/workflows/router/validate_router.py
+++ b/gso/workflows/router/validate_router.py
@@ -16,7 +16,7 @@ from gso.services.kentik_client import KentikClient
 from gso.services.librenms_client import LibreNMSClient
 from gso.services.lso_client import LSOState, anonymous_lso_interaction
 from gso.services.netbox_client import NetboxClient
-from gso.utils.helpers import generate_inventory_for_active_routers
+from gso.utils.helpers import generate_inventory_for_routers
 from gso.utils.shared_enums import Vendor
 
 
@@ -58,7 +58,9 @@ def verify_p_ibgp(subscription: dict[str, Any]) -> LSOState:
     extra_vars = {
         "dry_run": True,
         "subscription": subscription,
-        "pe_router_list": generate_inventory_for_active_routers(RouterRole.PE)["all"]["hosts"],
+        "pe_router_list": generate_inventory_for_routers(RouterRole.PE, include_provisioning_routers=True)["all"][
+            "hosts"
+        ],
         "verb": "verify_p_ibgp",
         "is_verification_workflow": "true",
     }
diff --git a/test/utils/test_helpers.py b/test/utils/test_helpers.py
index 880893b6..e9113378 100644
--- a/test/utils/test_helpers.py
+++ b/test/utils/test_helpers.py
@@ -8,7 +8,7 @@ from gso.products.product_blocks.router import RouterRole
 from gso.products.product_types.router import Router
 from gso.utils.helpers import (
     available_interfaces_choices_including_current_members,
-    generate_inventory_for_active_routers,
+    generate_inventory_for_routers,
 )
 from gso.utils.shared_enums import Vendor
 from gso.utils.types.tt_number import validate_tt_number
@@ -113,7 +113,7 @@ def test_generate_inventory_for_active_routers_with_single_active_router(router_
             }
         }
     }
-    assert generate_inventory_for_active_routers(RouterRole.P) == expected_result
+    assert generate_inventory_for_routers(RouterRole.P) == expected_result
 
 
 def test_generate_inventory_for_active_routers_with_multiple_routers(router_subscription_factory):
@@ -125,9 +125,9 @@ def test_generate_inventory_for_active_routers_with_multiple_routers(router_subs
     router_subscription_factory(status=SubscriptionLifecycle.TERMINATED)
     router_subscription_factory(status=SubscriptionLifecycle.INITIAL)
     #  Test the generation of inventory for multiple active P routers.
-    inventory = generate_inventory_for_active_routers(RouterRole.P)
+    inventory = generate_inventory_for_routers(RouterRole.P)
     assert len(inventory["all"]["hosts"]) == 5
-    inventory = generate_inventory_for_active_routers(RouterRole.PE)
+    inventory = generate_inventory_for_routers(RouterRole.PE)
     assert len(inventory["all"]["hosts"]) == 3
 
 
@@ -137,5 +137,5 @@ def test_generate_inventory_for_active_routers_with_excluded_router(router_subsc
         router_subscription_factory(router_role=RouterRole.P)
     router = router_subscription_factory(router_role=RouterRole.P)
     excluded_routers = [Router.from_subscription(router).router.router_fqdn]
-    inventory = generate_inventory_for_active_routers(RouterRole.P, exclude_routers=excluded_routers)
+    inventory = generate_inventory_for_routers(RouterRole.P, exclude_routers=excluded_routers)
     assert len(inventory["all"]["hosts"]) == 5  # 6 P routers, the last one is excluded, so 5 P routers are left.
-- 
GitLab