Skip to content

Promote p to pe

Promote a P router to a PE router.

initial_input_form_generator(subscription_id)

Promote P router to PE router.

Source code in gso/workflows/router/promote_p_to_pe.py
def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
    """Promote P router to PE router."""
    subscription = Router.from_subscription(subscription_id)

    class PromotePToPEForm(SubmitFormPage):
        model_config = ConfigDict(title=f"Promote {subscription.router.router_fqdn} to PE router?")

        tt_number: TTNumber

        @model_validator(mode="before")
        def router_must_be_nokia_p(cls, data: Any) -> Any:
            if not (subscription.router.router_role == RouterRole.P and subscription.router.vendor == Vendor.NOKIA):
                msg = "PE promotion workflow can only be run on Nokia P routers."
                raise ValueError(msg)

            return data

    user_input = yield PromotePToPEForm

    return user_input.model_dump() | {"subscription": subscription}

run_pre_checks(subscription)

Run pre-deployment checks.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("Run pre-deployment checks")
def run_pre_checks(subscription: dict[str, Any]) -> LSOState:
    """Run pre-deployment checks."""
    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": {"subscription": subscription, "verb": "pre_checks"},
    }

deploy_pe_base_config_dry(subscription, tt_number, process_id)

Perform a dry run of adding the base config to the router.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[DRY RUN] Deploy PE base config")
def deploy_pe_base_config_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a dry run of adding the base config to the router."""
    extra_vars = {
        "dry_run": True,
        "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_routers(RouterRole.PE)["all"]["hosts"],
        "geant_sites": json.loads(json_dumps(get_all_active_sites())),
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

deploy_pe_base_config_real(subscription, tt_number, process_id)

Perform a real run of adding the base config to the router.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[FOR REAL] Deploy PE base config")
def deploy_pe_base_config_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a real run of adding the base config to the router."""
    extra_vars = {
        "dry_run": False,
        "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_routers(RouterRole.PE)["all"]["hosts"],
        "geant_sites": json.loads(json_dumps(get_all_active_sites())),
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

prompt_insert_in_earl(subscription)

Wait for confirmation from an operator that the router has been inserted in EARL.

Source code in gso/workflows/router/promote_p_to_pe.py
@inputstep("Prompt EARL insertion", assignee=Assignee.SYSTEM)
def prompt_insert_in_earl(subscription: dict[str, Any]) -> FormGenerator:
    """Wait for confirmation from an operator that the router has been inserted in EARL."""

    class EARLPrompt(SubmitFormPage):
        model_config = ConfigDict(title="Update RADIUS clients")

        info_label: Label = f"Please add the router {subscription["router"]["router_fqdn"]} to EARL."

    yield EARLPrompt

    return {}

remove_p_from_pe_dry(subscription, tt_number, process_id)

Perform a dry run of removing the P router from all the PE routers.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[DRY RUN] Remove P from all PEs")
def remove_p_from_pe_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a dry run of removing the P router from all the PE routers."""
    extra_vars = {
        "dry_run": True,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
        f"Remove P-only router neighbour {subscription["router"]["router_fqdn"]} from PE routers P-only group",
        "verb": "remove_p_from_pe",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
        "inventory": generate_inventory_for_routers(RouterRole.PE),
        "extra_vars": extra_vars,
    }

remove_p_from_pe_real(subscription, tt_number, process_id)

Remove the P router from all the PE routers.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[FOR REAL] Remove P from all PEs")
def remove_p_from_pe_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Remove the P router from all the PE routers."""
    extra_vars = {
        "dry_run": False,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
        f"Remove P-only router neighbour {subscription["router"]["router_fqdn"]} from PE routers P-only group",
        "verb": "remove_p_from_pe",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/update_ibgp_mesh.yaml",
        "inventory": generate_inventory_for_routers(RouterRole.PE),
        "extra_vars": extra_vars,
    }

deploy_routing_instances_dry(subscription, tt_number, process_id)

Perform a dry run of deploying routing instances.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[DRY RUN] Deploy routing instances")
def deploy_routing_instances_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a dry run of deploying routing instances."""
    extra_vars = {
        "dry_run": True,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy PE base config",
        "verb": "deploy_routing_instances",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

deploy_routing_instances_real(subscription, tt_number, process_id)

Perform a real run of deploying routing instances.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[FOR REAL] Deploy routing instances")
def deploy_routing_instances_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a real run of deploying routing instances."""
    extra_vars = {
        "dry_run": False,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy PE base config",
        "verb": "deploy_routing_instances",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

run_post_checks(subscription)

Run post-deployment checks.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("Run post-deployment checks")
def run_post_checks(subscription: dict[str, Any]) -> LSOState:
    """Run post-deployment checks."""
    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": {"subscription": subscription, "verb": "post_checks"},
    }

update_subscription_model(subscription)

Update the subscription model to set router role to PE.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("Set router role to PE (Update subscription model)")
def update_subscription_model(subscription: Router) -> State:
    """Update the subscription model to set router role to PE."""
    subscription.router.router_role = RouterRole.PE

    return {"subscription": subscription}

delete_default_routes_dry(subscription, tt_number, process_id)

Perform a dry run of deleting the default routes.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[DRY RUN] Delete default routes")
def delete_default_routes_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a dry run of deleting the default routes."""
    extra_vars = {
        "dry_run": True,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
        f"Delete static default routes (part of P base-config)",
        "verb": "delete_default_routes",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

delete_default_routes_real(subscription, tt_number, process_id)

Perform a real run of deleting the default routes.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[FOR REAL] Delete default routes")
def delete_default_routes_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a real run of deleting the default routes."""
    extra_vars = {
        "dry_run": False,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
        f"Delete static default routes (part of P base-config)",
        "verb": "delete_default_routes",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

add_pe_static_routes_dry(subscription, tt_number, process_id)

Perform a dry run of adding the PE static routes.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[DRY RUN] Add PE static routes")
def add_pe_static_routes_dry(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a dry run of adding the PE static routes."""
    extra_vars = {
        "dry_run": True,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
        f"Delete static default routes (part of P base-config)",
        "verb": "add_pe_static_routes",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

add_pe_static_routes_real(subscription, tt_number, process_id)

Perform a real run of adding the PE static routes.

Source code in gso/workflows/router/promote_p_to_pe.py
@step("[FOR REAL] Add PE static routes")
def add_pe_static_routes_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> LSOState:
    """Perform a real run of adding the PE static routes."""
    extra_vars = {
        "dry_run": False,
        "subscription": subscription,
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - "
        f"Delete static default routes (part of P base-config)",
        "verb": "add_pe_static_routes",
    }

    return {
        "playbook_name": "gap_ansible/playbooks/promote_p_to_pe.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

promote_p_to_pe()

Promote a P router to a PE router.

Source code in gso/workflows/router/promote_p_to_pe.py
@workflow(
    "Promote P router to PE router",
    initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator),
    target=Target.MODIFY,
)
def promote_p_to_pe() -> StepList:
    """Promote a P router to a PE router."""
    return (
        begin
        >> store_process_subscription(Target.MODIFY)
        >> unsync
        >> lso_interaction(run_pre_checks)
        >> lso_interaction(deploy_pe_base_config_dry)
        >> lso_interaction(deploy_pe_base_config_real)
        >> prompt_insert_in_earl
        >> create_kentik_device
        >> lso_interaction(remove_p_from_pe_dry)
        >> lso_interaction(remove_p_from_pe_real)
        >> lso_interaction(add_pe_mesh_to_pe_dry)
        >> lso_interaction(add_pe_mesh_to_pe_real)
        >> lso_interaction(add_pe_to_pe_mesh_dry)
        >> lso_interaction(add_pe_to_pe_mesh_real)
        >> lso_interaction(check_pe_ibgp)
        >> lso_interaction(deploy_routing_instances_dry)
        >> lso_interaction(deploy_routing_instances_real)
        >> lso_interaction(check_l3_services)
        >> lso_interaction(update_sdp_mesh_dry)
        >> lso_interaction(update_sdp_mesh_real)
        >> lso_interaction(add_all_p_to_pe_dry)
        >> lso_interaction(add_all_p_to_pe_real)
        >> lso_interaction(add_pe_to_all_p_dry)
        >> lso_interaction(add_pe_to_all_p_real)
        >> lso_interaction(delete_default_routes_dry)
        >> lso_interaction(delete_default_routes_real)
        >> lso_interaction(add_pe_static_routes_dry)
        >> lso_interaction(add_pe_static_routes_real)
        >> lso_interaction(run_post_checks)
        >> update_subscription_model
        >> resync
        >> done
    )