Skip to content
Snippets Groups Projects
Commit 03755cf5 authored by Neda Moeini's avatar Neda Moeini
Browse files

Added more steps in router termination including:

- Remove the terminated router from iGEANT/iGEANT6 on all the PEs
- Remove the terminated router from iGEANT_P_ONLY/iGEANT_P_ONLY_6 on all Ps
- Remove router from LibreNMS
parent 3cd22c24
No related branches found
No related tags found
No related merge requests found
Pipeline #87894 failed
......@@ -12,7 +12,9 @@ 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.products.product_types.router import Router
from gso.services import lso_client, subscriptions
from gso.settings import load_oss_params
......@@ -160,3 +162,40 @@ def add_all_pe_to_p_real(
inventory=subscription["router"]["router_fqdn"],
extra_vars=extra_vars,
)
@step("Calculate list of all active PE routers")
def calculate_pe_router_list() -> State:
"""Calculate a list of all active PE routers in the network."""
all_routers = [
Router.from_subscription(r["subscription_id"]) for r in subscriptions.get_active_router_subscriptions()
]
all_pe_routers = [router for router in all_routers if router.router.router_role == RouterRole.PE]
return {"pe_router_list": all_pe_routers}
@step("Calculate list of all active P routers")
def calculate_p_router_list() -> State:
"""Calculate a list of all active P routers in the network."""
all_routers = [
Router.from_subscription(r["subscription_id"]) for r in subscriptions.get_active_router_subscriptions()
]
all_pe_routers = [router for router in all_routers if router.router.router_role == RouterRole.P]
return {"pe_router_list": all_pe_routers}
def generate_inventory(router_list: list[Router]) -> dict[str, Any]:
"""Generate an Ansible-compatible inventory for executing playbooks. Contains all active routers."""
return {
"all": {
"hosts": {
router.router.router_fqdn: {
"lo4": str(router.router.router_lo_ipv4_address),
"lo6": str(router.router.router_lo_ipv6_address),
"vendor": str(router.router.vendor),
}
for router in router_list
}
},
}
......@@ -19,10 +19,12 @@ from orchestrator.workflows.steps import (
from orchestrator.workflows.utils import wrap_modify_initial_input_form
from gso.products.product_types.router import Router
from gso.services import infoblox
from gso.services import infoblox, lso_client
from gso.services.librenms_client import LibreNMSClient
from gso.services.lso_client import execute_playbook, lso_interaction
from gso.services.netbox_client import NetboxClient
from gso.utils.shared_enums import Vendor
from gso.utils.workflow_steps import calculate_p_router_list, calculate_pe_router_list, generate_inventory
logger = logging.getLogger(__name__)
......@@ -44,7 +46,10 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
remove_configuration: bool = True
user_input = yield TerminateForm
return user_input.model_dump() | {"router_is_nokia": router.router.vendor == Vendor.NOKIA}
return user_input.model_dump() | {
"router_is_nokia": router.router.vendor == Vendor.NOKIA,
"router_role": router.router.router_role,
}
@step("Deprovision loopback IPs from IPAM")
......@@ -104,6 +109,145 @@ def remove_device_from_netbox(subscription: Router) -> dict[str, Router]:
return {"subscription": subscription}
@step("[DRY RUN] Remove P router from the mesh of PE routers")
def remove_p_from_mesh_dry(
subscription: Router, callback_route: str, pe_router_list: list[Router], tt_number: str, process_id: UUIDstr
) -> None:
"""Perform a dry run of removing the terminated router from the mesh of PE routers."""
extra_vars = {
"dry_run": True,
"subscription": subscription,
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
f"Remove {subscription.router.router_fqdn} from iBGP mesh",
"verb": "remove_p_from_pe",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=generate_inventory(pe_router_list),
extra_vars=extra_vars,
)
@step("[REAL RUN] Remove P router from the mesh of PE routers")
def remove_p_from_mesh_real(
subscription: Router, callback_route: str, pe_router_list: list[Router], tt_number: str, process_id: UUIDstr
) -> None:
"""Perform a real run of removing the terminated router from the mesh of PE routers."""
extra_vars = {
"dry_run": False,
"subscription": subscription,
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
f"Remove {subscription.router.router_fqdn} from iBGP mesh",
"verb": "remove_p_from_pe",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=generate_inventory(pe_router_list),
extra_vars=extra_vars,
)
@step("[DRY RUN] Remove all PE routers from P router iBGP table")
def remove_all_pe_from_p_dry(
subscription: Router, callback_route: str, pe_router_list: list[Router], tt_number: str, process_id: UUIDstr
) -> None:
"""Perform a dry run of removing all PE routers from P router iBGP table."""
pe_router_list_excluding_current_router = [
router for router in pe_router_list if router.router.router_fqdn != subscription.router.router_fqdn
]
extra_vars = {
"dry_run": True,
"subscription": subscription,
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
f"Remove {subscription.router.router_fqdn} from iBGP mesh",
"verb": "remove_p_from_net",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=generate_inventory(pe_router_list_excluding_current_router),
extra_vars=extra_vars,
)
@step("[REAL RUN] Remove all PE routers from P router iBGP table")
def remove_all_pe_from_p_real(
subscription: Router, callback_route: str, pe_router_list: list[Router], tt_number: str, process_id: UUIDstr
) -> None:
"""Perform a real run of removing PE router from P router iBGP table."""
pe_router_list_excluding_current_router = [
router for router in pe_router_list if router.router.router_fqdn != subscription.router.router_fqdn
]
extra_vars = {
"dry_run": False,
"subscription": subscription,
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
f"Remove {subscription.router.router_fqdn} from iBGP mesh",
"verb": "remove_p_from_net",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=generate_inventory(pe_router_list_excluding_current_router),
extra_vars=extra_vars,
)
@step("[DRY RUN] Remove PE router from the mesh of P routers")
def remove_pe_from_mesh_dry(
subscription: Router, callback_route: str, p_router_list: list[Router], tt_number: str, process_id: UUIDstr
) -> None:
"""Perform a dry run of removing PE router from the mesh of P routers."""
extra_vars = {
"dry_run": True,
"subscription": subscription,
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
f"Remove {subscription.router.router_fqdn} from iBGP mesh",
"verb": "remove_pe_from_p",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=generate_inventory(p_router_list),
extra_vars=extra_vars,
)
@step("[REAL RUN] Remove PE router from the mesh of P routers")
def remove_pe_from_mesh_real(
subscription: Router, callback_route: str, p_router_list: list[Router], tt_number: str, process_id: UUIDstr
) -> None:
"""Perform a dry run of removing PE router from the mesh of P routers."""
extra_vars = {
"dry_run": False,
"subscription": subscription,
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
f"Remove {subscription.router.router_fqdn} from iBGP mesh",
"verb": "remove_pe_from_p",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=generate_inventory(p_router_list),
extra_vars=extra_vars,
)
@step("Remove Device from Librenms")
def remove_device_from_librenms(subscription: Router) -> dict[str, Router]:
"""Remove the device from LibreNMS."""
LibreNMSClient().remove_device(subscription.router.router_fqdn)
return {"subscription": subscription}
@workflow(
"Terminate router",
initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator),
......@@ -119,15 +263,26 @@ def terminate_router() -> StepList:
"""
run_config_steps = conditional(lambda state: state["remove_configuration"])
router_is_nokia = conditional(lambda state: state["router_is_nokia"])
router_is_pe = conditional(lambda state: state["router_is_pe"] == "PE")
router_is_p = conditional(lambda state: state["router_is_p"] == "P")
return (
begin
>> store_process_subscription(Target.TERMINATE)
>> unsync
>> calculate_pe_router_list
>> router_is_p(lso_interaction(remove_p_from_mesh_dry))
>> router_is_p(lso_interaction(remove_p_from_mesh_real))
>> router_is_pe(calculate_p_router_list)
>> router_is_pe(lso_interaction(remove_all_pe_from_p_dry))
>> router_is_pe(lso_interaction(remove_all_pe_from_p_real))
>> router_is_pe(lso_interaction(remove_pe_from_mesh_dry))
>> router_is_pe(lso_interaction(remove_pe_from_mesh_real))
>> deprovision_loopback_ips
>> run_config_steps(lso_interaction(remove_config_from_router_dry))
>> run_config_steps(lso_interaction(remove_config_from_router_real))
>> router_is_nokia(remove_device_from_netbox)
>> remove_device_from_librenms
>> set_status(SubscriptionLifecycle.TERMINATED)
>> resync
>> done
......
......@@ -13,11 +13,12 @@ from orchestrator.workflows.utils import wrap_modify_initial_input_form
from pydantic import ConfigDict, model_validator
from gso.products.product_types.router import Router
from gso.services import librenms_client, lso_client, subscriptions
from gso.services import librenms_client, lso_client
from gso.services.lso_client import lso_interaction
from gso.services.subscriptions import get_trunks_that_terminate_on_router
from gso.utils.helpers import SNMPVersion
from gso.utils.workflow_steps import add_all_pe_to_p_dry, add_all_pe_to_p_real
from gso.utils.workflow_steps import calculate_pe_router_list, generate_inventory
def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
......@@ -85,6 +86,62 @@ def add_p_to_mesh_real(subscription: dict[str, Any], callback_route: str, tt_num
)
@step("[DRY RUN] Add all PE routers to P router iBGP table")
def add_all_pe_to_p_dry(
subscription: dict[str, Any], pe_router_list: list[Router], callback_route: str, tt_number: str, process_id: UUIDstr
) -> None:
"""Perform a dry run of adding the list of all PE routers to the new P router."""
extra_vars = {
"dry_run": True,
"subscription": subscription,
"pe_router_list": {
router.router.router_fqdn: {
"lo4": str(router.router.router_lo_ipv4_address),
"lo6": str(router.router.router_lo_ipv6_address),
"vendor": router.router.vendor,
}
for router in pe_router_list
},
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Update iBGP mesh",
"verb": "add_pe_to_p",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=subscription["router"]["router_fqdn"],
extra_vars=extra_vars,
)
@step("[FOR REAL] Add all PE routers to P router iBGP table")
def add_all_pe_to_p_real(
subscription: dict[str, Any], pe_router_list: list[Router], callback_route: str, tt_number: str, process_id: UUIDstr
) -> None:
"""Add the list of all PE routers to the new P router."""
extra_vars = {
"dry_run": False,
"subscription": subscription,
"pe_router_list": {
router.router.router_fqdn: {
"lo4": str(router.router.router_lo_ipv4_address),
"lo6": str(router.router.router_lo_ipv6_address),
"vendor": router.router.vendor,
}
for router in pe_router_list
},
"commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Update iBGP mesh",
"verb": "add_pe_to_p",
}
lso_client.execute_playbook(
playbook_name="update_ibgp_mesh.yaml",
callback_route=callback_route,
inventory=subscription["router"]["router_fqdn"],
extra_vars=extra_vars,
)
@step("Verify iBGP session health")
def check_ibgp_session(subscription: Router, callback_route: str) -> None:
"""Run a playbook using the provisioning proxy, to check the health of the new iBGP session."""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment