diff --git a/gso/utils/workflow_steps.py b/gso/utils/workflow_steps.py index 9e3a35090f44776936483c445c03a64091530608..fb166950d5cf821390b34dd04b0264deb3a54acb 100644 --- a/gso/utils/workflow_steps.py +++ b/gso/utils/workflow_steps.py @@ -12,9 +12,12 @@ from pydantic_forms.core import FormPage from pydantic_forms.types import FormGenerator from pydantic_forms.validators import Label +from gso.products.product_blocks.router import RouterRole from gso.products.product_types.iptrunk import Iptrunk from gso.services.lso_client import LSOState from gso.settings import load_oss_params +from gso.utils.helpers import generate_inventory_for_active_routers +from gso.utils.shared_enums import Vendor def _deploy_base_config( @@ -38,6 +41,164 @@ def _deploy_base_config( } +def _update_sdp_mesh( + subscription: dict[str, Any], + tt_number: str, + process_id: UUIDstr, + *, + dry_run: bool, +) -> LSOState: + inventory = generate_inventory_for_active_routers( + router_role=RouterRole.PE, router_vendor=Vendor.NOKIA, exclude_routers=[subscription["router"]["router_fqdn"]] + ) + + extra_vars = { + "dry_run": dry_run, + "subscription": subscription, + "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": { + subscription["router"]["router_fqdn"]: { + "lo4": str(subscription["router"]["router_lo_ipv4_address"]), + "lo6": str(subscription["router"]["router_lo_ipv6_address"]), + } + }, + } + + return { + "playbook_name": "update_pe_sdp_mesh.yaml", + "inventory": inventory, + "extra_vars": extra_vars, + } + + +def _update_sdp_single_pe( + subscription: dict[str, Any], + tt_number: str, + process_id: UUIDstr, + *, + dry_run: bool, +) -> LSOState: + extra_vars = { + "dry_run": dry_run, + "subscription": subscription, + "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( + router_role=RouterRole.PE, + router_vendor=Vendor.NOKIA, + exclude_routers=[subscription["router"]["router_fqdn"]], + )["all"]["hosts"], + } + + return { + "playbook_name": "update_pe_sdp_mesh.yaml", + "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}}, + "extra_vars": extra_vars, + } + + +def _add_pe_mesh_to_pe( + subscription: dict[str, Any], + tt_number: str, + process_id: UUIDstr, + *, + dry_run: bool, +) -> LSOState: + extra_vars = { + "dry_run": dry_run, + "subscription": subscription, + "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( + router_role=RouterRole.PE, exclude_routers=[subscription["router"]["router_fqdn"]] + )["all"]["hosts"], + } + + return { + "playbook_name": "update_ibgp_mesh.yaml", + "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}}, + "extra_vars": extra_vars, + } + + +def _add_pe_to_pe_mesh( + subscription: dict[str, Any], + tt_number: str, + process_id: UUIDstr, + *, + dry_run: bool, +) -> LSOState: + inventory = generate_inventory_for_active_routers( + router_role=RouterRole.PE, exclude_routers=[subscription["router"]["router_fqdn"]] + ) + extra_vars = { + "dry_run": dry_run, + "subscription": subscription, + "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - " + f"Add the PE router to all PE routers in iGEANT/iGEANT6.", + "verb": "add_pe_to_pe_mesh", + } + + return { + "playbook_name": "update_ibgp_mesh.yaml", + "inventory": inventory, + "extra_vars": extra_vars, + } + + +def _add_all_p_to_pe( + subscription: dict[str, Any], + tt_number: str, + process_id: UUIDstr, + *, + dry_run: bool, +) -> LSOState: + extra_vars = { + "dry_run": dry_run, + "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( + router_role=RouterRole.P, exclude_routers=[subscription["router"]["router_fqdn"]] + )["all"]["hosts"], + } + + return { + "playbook_name": "update_ibgp_mesh.yaml", + "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}}, + "extra_vars": extra_vars, + } + + +def _add_pe_to_all_p( + subscription: dict[str, Any], + tt_number: str, + process_id: UUIDstr, + *, + dry_run: bool, +) -> LSOState: + inventory = generate_inventory_for_active_routers( + router_role=RouterRole.P, exclude_routers=[subscription["router"]["router_fqdn"]] + ) + extra_vars = { + "dry_run": dry_run, + "subscription": subscription, + "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - " + f"Add promoted router to all PE routers in iGEANT/iGEANT6", + "verb": "add_pe_to_all_p", + } + + return { + "playbook_name": "update_ibgp_mesh.yaml", + "inventory": inventory, + "extra_vars": extra_vars, + } + + @step("[DRY RUN] Deploy base config") def deploy_base_config_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: """Perform a dry run of provisioning base config on a router.""" @@ -50,6 +211,78 @@ def deploy_base_config_real(subscription: dict[str, Any], tt_number: str, proces return _deploy_base_config(subscription, tt_number, process_id, dry_run=False) +@step("[DRY RUN] Add the PE to all P routers") +def add_pe_to_all_p_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a dry run of adding the PE router to all P routers.""" + return _add_pe_to_all_p(subscription, tt_number, process_id, dry_run=True) + + +@step("[FOR REAL] Add the PE to all P routers") +def add_pe_to_all_p_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a real run of adding the PE router to all P routers.""" + return _add_pe_to_all_p(subscription, tt_number, process_id, dry_run=False) + + +@step("[DRY RUN] Add all P routers to the PE") +def add_all_p_to_pe_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a dry run of adding all P routers to the PE router.""" + return _add_all_p_to_pe(subscription, tt_number, process_id, dry_run=True) + + +@step("[FOR REAL] Add all P routers to the PE") +def add_all_p_to_pe_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a real run of adding all P routers to the PE router.""" + return _add_all_p_to_pe(subscription, tt_number, process_id, dry_run=False) + + +@step("[DRY RUN] Add the PE to PE mesh") +def add_pe_to_pe_mesh_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a dry run of adding the PE router to all PE routers in iGEANT/iGEANT6.""" + return _add_pe_to_pe_mesh(subscription, tt_number, process_id, dry_run=True) + + +@step("[FOR REAL] Add the PE to PE mesh") +def add_pe_to_pe_mesh_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a real run of adding the PE router to all PE routers in iGEANT/iGEANT6.""" + return _add_pe_to_pe_mesh(subscription, tt_number, process_id, dry_run=False) + + +@step("[DRY RUN] Add PE mesh to the PE") +def add_pe_mesh_to_pe_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a dry run of adding list of PE routers into iGEANT/iGEANT6 of the router.""" + return _add_pe_mesh_to_pe(subscription, tt_number, process_id, dry_run=True) + + +@step("[FOR REAL] Add PE mesh to the PE") +def add_pe_mesh_to_pe_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a real run of adding list of PE routers into iGEANT/iGEANT6 of the router.""" + return _add_pe_mesh_to_pe(subscription, tt_number, process_id, dry_run=False) + + +@step("[DRY RUN] Include the PE into SDP mesh on other Nokia PEs") +def update_sdp_mesh_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a dry run of including new PE router in SDP mesh on other NOKIA PE routers.""" + return _update_sdp_mesh(subscription, tt_number, process_id, dry_run=True) + + +@step("[FOR REAL] Include the PE into SDP mesh on other Nokia PEs") +def update_sdp_mesh_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State: + """Perform a real run of including new PE router in SDP mesh on other NOKIA PE routers.""" + return _update_sdp_mesh(subscription, tt_number, process_id, dry_run=False) + + +@step("[DRY RUN] Configure SDP on the PE to all other Nokia 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") +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) + + @step("[FOR REAL] Set ISIS metric to very high value") def set_isis_to_max(subscription: Iptrunk, process_id: UUIDstr, tt_number: str) -> LSOState: """Workflow step for setting the :term:`ISIS` metric to an arbitrarily high value to drain a link.""" @@ -91,6 +324,38 @@ def run_checks_after_base_config(subscription: dict[str, Any]) -> LSOState: } +@step("Check iBGP session") +def check_pe_ibgp(subscription: dict[str, Any]) -> LSOState: + """Check the iBGP session.""" + extra_vars = { + "dry_run": False, + "subscription": subscription, + "verb": "check_pe_ibgp", + } + + return { + "playbook_name": "check_ibgp.yaml", + "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}}, + "extra_vars": extra_vars, + } + + +@step("Check L3 services") +def check_l3_services(subscription: dict[str, Any]) -> LSOState: + """Check L3 services.""" + extra_vars = { + "dry_run": False, + "subscription": subscription, + "verb": "check_base_ris", + } + + return { + "playbook_name": "check_l3_services.yaml", + "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}}, + "extra_vars": extra_vars, + } + + @inputstep("Prompt for new SharePoint checklist", assignee=Assignee.SYSTEM) def prompt_sharepoint_checklist_url(checklist_url: str) -> FormGenerator: """Prompt the operator with the checklist in SharePoint for approving a new subscription."""