Skip to content

Workflow steps

Workflow steps that are shared across multiple workflows.

deploy_base_config_dry(subscription, tt_number, process_id)

Perform a dry run of provisioning base config on a router.

Source code in gso/utils/workflow_steps.py
@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."""
    return _deploy_base_config(subscription, tt_number, process_id, dry_run=True)

deploy_base_config_real(subscription, tt_number, process_id)

Deploy base config on a router using the provisioning proxy.

Source code in gso/utils/workflow_steps.py
@step("[FOR REAL] Deploy base config")
def deploy_base_config_real(subscription: dict[str, Any], tt_number: str, process_id: UUIDstr) -> State:
    """Deploy base config on a router using the provisioning proxy."""
    return _deploy_base_config(subscription, tt_number, process_id, dry_run=False)

add_pe_to_all_p_dry(subscription, tt_number, process_id)

Perform a dry run of adding the PE router to all P routers.

Source code in gso/utils/workflow_steps.py
@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)

add_pe_to_all_p_real(subscription, tt_number, process_id)

Perform a real run of adding the PE router to all P routers.

Source code in gso/utils/workflow_steps.py
@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)

add_all_p_to_pe_dry(subscription, tt_number, process_id)

Perform a dry run of adding all P routers to the PE router.

Source code in gso/utils/workflow_steps.py
@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)

add_all_p_to_pe_real(subscription, tt_number, process_id)

Perform a real run of adding all P routers to the PE router.

Source code in gso/utils/workflow_steps.py
@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)

add_pe_to_pe_mesh_dry(subscription, tt_number, process_id)

Perform a dry run of adding the PE router to all PE routers in iGEANT/iGEANT6.

Source code in gso/utils/workflow_steps.py
@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)

add_pe_to_pe_mesh_real(subscription, tt_number, process_id)

Perform a real run of adding the PE router to all PE routers in iGEANT/iGEANT6.

Source code in gso/utils/workflow_steps.py
@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)

add_pe_mesh_to_pe_dry(subscription, tt_number, process_id)

Perform a dry run of adding list of PE routers into iGEANT/iGEANT6 of the router.

Source code in gso/utils/workflow_steps.py
@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)

add_pe_mesh_to_pe_real(subscription, tt_number, process_id)

Perform a real run of adding list of PE routers into iGEANT/iGEANT6 of the router.

Source code in gso/utils/workflow_steps.py
@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)

update_sdp_mesh_dry(subscription, tt_number, process_id)

Perform a dry run of including new PE router in SDP mesh on other NOKIA PE routers.

Source code in gso/utils/workflow_steps.py
@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)

update_sdp_mesh_real(subscription, tt_number, process_id)

Perform a real run of including new PE router in SDP mesh on other NOKIA PE routers.

Source code in gso/utils/workflow_steps.py
@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)

update_sdp_single_pe_dry(subscription, tt_number, process_id)

Perform a dry run of configuring SDP on a new PE router to all other NOKIA PE routers.

Source code in gso/utils/workflow_steps.py
@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)

update_sdp_single_pe_real(subscription, tt_number, process_id)

Configure SDP on a new PE router to all other NOKIA PE routers.

Source code in gso/utils/workflow_steps.py
@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)

set_isis_to_max(subscription, process_id, tt_number)

Workflow step for setting the ISIS metric to an arbitrarily high value to drain a link.

Source code in gso/utils/workflow_steps.py
@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 ISIS metric to an arbitrarily high value to drain a link."""
    old_isis_metric = subscription.iptrunk.iptrunk_isis_metric
    params = load_oss_params()
    subscription.iptrunk.iptrunk_isis_metric = params.GENERAL.isis_high_metric
    extra_vars = {
        "wfo_trunk_json": json.loads(json_dumps(subscription)),
        "dry_run": False,
        "verb": "deploy",
        "config_object": "isis_interface",
        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
        f"{subscription.iptrunk.gs_id}",
    }

    return {
        "subscription": subscription,
        "playbook_name": "gap_ansible/playbooks/iptrunks.yaml",
        "inventory": {
            "all": {
                "hosts": {
                    subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn: None,
                    subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn: None,
                }
            }
        },
        "extra_vars": extra_vars,
        "old_isis_metric": old_isis_metric,
    }

run_checks_after_base_config(subscription)

Workflow step for running show commands after installing base config.

Source code in gso/utils/workflow_steps.py
@step("Run show commands after base config install")
def run_checks_after_base_config(subscription: dict[str, Any]) -> LSOState:
    """Workflow step for running show commands after installing base config."""
    return {
        "playbook_name": "gap_ansible/playbooks/base_config_checks.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": {"wfo_router_json": subscription},
    }

check_pe_ibgp(subscription)

Check the iBGP session.

Source code in gso/utils/workflow_steps.py
@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": "gap_ansible/playbooks/check_ibgp.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

check_l3_services(subscription)

Check L3 services.

Source code in gso/utils/workflow_steps.py
@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": "gap_ansible/playbooks/check_l3_services.yaml",
        "inventory": {"all": {"hosts": {subscription["router"]["router_fqdn"]: None}}},
        "extra_vars": extra_vars,
    }

prompt_sharepoint_checklist_url(checklist_url)

Prompt the operator with the checklist in SharePoint for approving a new subscription.

Source code in gso/utils/workflow_steps.py
@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."""

    class SharepointPrompt(SubmitFormPage):
        model_config = ConfigDict(title="Complete new checklist")

        info_label_1: Label = f"A new checklist has been created at: {checklist_url}"
        info_label_2: Label = "Click proceed to finish the workflow."

    yield SharepointPrompt

    return {}

start_moodi()

Start monitoring on demand using Moodi Telemetry stack.

Source code in gso/utils/workflow_steps.py
def start_moodi() -> StepList:
    """Start monitoring on demand using Moodi Telemetry stack."""
    host = load_oss_params().MOODI.host

    @step("Start Moodi")
    def _start_moodi(subscription: dict[str, Any]) -> LSOState:
        return {
            "playbook_name": "moodi_telemetry/playbooks/start_moodi.yaml",
            "inventory": {"all": {"hosts": {host: None}}},
            "extra_vars": {"subscription": subscription},
        }

    return _is_moodi_enabled(indifferent_lso_interaction(_start_moodi))

stop_moodi()

Stop Moodi Telemetry monitoring on demand.

Source code in gso/utils/workflow_steps.py
def stop_moodi() -> StepList:
    """Stop Moodi Telemetry monitoring on demand."""
    host = load_oss_params().MOODI.host

    @inputstep("Confirm stopping on-demand monitoring.", assignee=Assignee("SYSTEM"))
    def _confirm_stopping_moodi(state: State) -> FormGenerator:
        class ConfirmStoppingPage(SubmitFormPage):
            model_config = ConfigDict()

            run_results: Label = "Please confirm that you want to stop Moodi."

        yield ConfirmStoppingPage

        return state

    @step("Stop Moodi")
    def _stop_moodi(subscription: dict[str, Any]) -> LSOState:
        return {
            "playbook_name": "moodi_telemetry/playbooks/stop_moodi.yaml",
            "inventory": {"all": {"hosts": {host: None}}},
            "extra_vars": {"subscription": subscription},
        }

    return _is_moodi_enabled(_confirm_stopping_moodi) >> _is_moodi_enabled(
        anonymous_indifferent_lso_interaction(_stop_moodi)
    )

create_kentik_device(state)

Create a new device in Kentik.

Source code in gso/utils/workflow_steps.py
@step("Create Kentik device")
def create_kentik_device(state: State) -> State:
    """Create a new device in Kentik."""
    kentik_client = KentikClient()
    kentik_site = kentik_client.get_site_by_name(state["subscription"]["router"]["router_site"]["site_name"])

    if not kentik_site:
        msg = "Site could not be found in Kentik."
        raise ProcessFailureError(msg, details=state["subscription"]["router"]["router_site"]["site_name"])

    new_device = NewKentikDevice(
        device_name=state["subscription"]["router"]["router_fqdn"],
        device_description=str(state["subscription"]["subscription_id"]),
        sending_ips=[str(state["subscription"]["router"]["router_lo_ipv4_address"])],
        site_id=kentik_site["id"],
        device_snmp_ip=str(state["subscription"]["router"]["router_lo_ipv4_address"]),
        device_bgp_flowspec=False,
        device_bgp_neighbor_ip=str(state["subscription"]["router"]["router_lo_ipv4_address"]),
        device_bgp_neighbor_ip6=str(state["subscription"]["router"]["router_lo_ipv6_address"]),
    )
    kentik_device = kentik_client.create_device(new_device)

    return {"kentik_device": kentik_device}