Skip to content
Snippets Groups Projects
Verified Commit 4bf38511 authored by Karel van Klink's avatar Karel van Klink :smiley_cat:
Browse files

reflect lifecycle state changes in workflow steps

parent f4b30155
No related branches found
No related tags found
1 merge request!162Feature/update router create workflow
Pipeline #85756 passed
This commit is part of merge request !162. Comments created here will be created in the context of that merge request.
...@@ -17,12 +17,12 @@ from pynetbox.models.dcim import Interfaces ...@@ -17,12 +17,12 @@ from pynetbox.models.dcim import Interfaces
from gso.products.product_blocks.iptrunk import ( from gso.products.product_blocks.iptrunk import (
IptrunkInterfaceBlockInactive, IptrunkInterfaceBlockInactive,
IptrunkSideBlockProvisioning, IptrunkSideBlockInactive,
IptrunkType, IptrunkType,
PhyPortCapacity, PhyPortCapacity,
) )
from gso.products.product_blocks.router import RouterVendor from gso.products.product_blocks.router import RouterVendor
from gso.products.product_types.iptrunk import IptrunkInactive, IptrunkProvisioning from gso.products.product_types.iptrunk import IptrunkInactive
from gso.products.product_types.router import Router from gso.products.product_types.router import Router
from gso.services import infoblox, subscriptions from gso.services import infoblox, subscriptions
from gso.services.crm import get_customer_by_name from gso.services.crm import get_customer_by_name
...@@ -184,7 +184,7 @@ def create_subscription(product: UUIDstr, customer: str) -> State: ...@@ -184,7 +184,7 @@ def create_subscription(product: UUIDstr, customer: str) -> State:
@step("Get information from IPAM") @step("Get information from IPAM")
def get_info_from_ipam(subscription: IptrunkProvisioning) -> State: def get_info_from_ipam(subscription: IptrunkInactive) -> State:
"""Allocate IP resources in :term:`IPAM`.""" """Allocate IP resources in :term:`IPAM`."""
subscription.iptrunk.iptrunk_ipv4_network = infoblox.allocate_v4_network( subscription.iptrunk.iptrunk_ipv4_network = infoblox.allocate_v4_network(
"TRUNK", "TRUNK",
...@@ -248,7 +248,7 @@ def initialize_subscription( ...@@ -248,7 +248,7 @@ def initialize_subscription(
@step("Provision IP trunk interface [DRY RUN]") @step("Provision IP trunk interface [DRY RUN]")
def provision_ip_trunk_iface_dry( def provision_ip_trunk_iface_dry(
subscription: IptrunkProvisioning, subscription: IptrunkInactive,
callback_route: str, callback_route: str,
process_id: UUIDstr, process_id: UUIDstr,
tt_number: str, tt_number: str,
...@@ -276,7 +276,7 @@ def provision_ip_trunk_iface_dry( ...@@ -276,7 +276,7 @@ def provision_ip_trunk_iface_dry(
@step("Provision IP trunk interface [FOR REAL]") @step("Provision IP trunk interface [FOR REAL]")
def provision_ip_trunk_iface_real( def provision_ip_trunk_iface_real(
subscription: IptrunkProvisioning, subscription: IptrunkInactive,
callback_route: str, callback_route: str,
process_id: UUIDstr, process_id: UUIDstr,
tt_number: str, tt_number: str,
...@@ -304,7 +304,7 @@ def provision_ip_trunk_iface_real( ...@@ -304,7 +304,7 @@ def provision_ip_trunk_iface_real(
@step("Check IP connectivity of the trunk") @step("Check IP connectivity of the trunk")
def check_ip_trunk_connectivity( def check_ip_trunk_connectivity(
subscription: IptrunkProvisioning, subscription: IptrunkInactive,
callback_route: str, callback_route: str,
) -> State: ) -> State:
"""Check successful connectivity across the new trunk.""" """Check successful connectivity across the new trunk."""
...@@ -322,7 +322,7 @@ def check_ip_trunk_connectivity( ...@@ -322,7 +322,7 @@ def check_ip_trunk_connectivity(
@step("Provision IP trunk ISIS interface [DRY RUN]") @step("Provision IP trunk ISIS interface [DRY RUN]")
def provision_ip_trunk_isis_iface_dry( def provision_ip_trunk_isis_iface_dry(
subscription: IptrunkProvisioning, subscription: IptrunkInactive,
callback_route: str, callback_route: str,
process_id: UUIDstr, process_id: UUIDstr,
tt_number: str, tt_number: str,
...@@ -350,7 +350,7 @@ def provision_ip_trunk_isis_iface_dry( ...@@ -350,7 +350,7 @@ def provision_ip_trunk_isis_iface_dry(
@step("Provision IP trunk ISIS interface [FOR REAL]") @step("Provision IP trunk ISIS interface [FOR REAL]")
def provision_ip_trunk_isis_iface_real( def provision_ip_trunk_isis_iface_real(
subscription: IptrunkProvisioning, subscription: IptrunkInactive,
callback_route: str, callback_route: str,
process_id: UUIDstr, process_id: UUIDstr,
tt_number: str, tt_number: str,
...@@ -378,7 +378,7 @@ def provision_ip_trunk_isis_iface_real( ...@@ -378,7 +378,7 @@ def provision_ip_trunk_isis_iface_real(
@step("Check ISIS adjacency") @step("Check ISIS adjacency")
def check_ip_trunk_isis( def check_ip_trunk_isis(
subscription: IptrunkProvisioning, subscription: IptrunkInactive,
callback_route: str, callback_route: str,
) -> State: ) -> State:
"""Run an Ansible playbook to confirm :term:`ISIS` adjacency.""" """Run an Ansible playbook to confirm :term:`ISIS` adjacency."""
...@@ -395,7 +395,7 @@ def check_ip_trunk_isis( ...@@ -395,7 +395,7 @@ def check_ip_trunk_isis(
@step("NextBox integration") @step("NextBox integration")
def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State: def reserve_interfaces_in_netbox(subscription: IptrunkInactive) -> State:
"""Create the :term:`LAG` interfaces in NetBox and attach the lag interfaces to the physical interfaces.""" """Create the :term:`LAG` interfaces in NetBox and attach the lag interfaces to the physical interfaces."""
nbclient = NetboxClient() nbclient = NetboxClient()
for trunk_side in subscription.iptrunk.iptrunk_sides: for trunk_side in subscription.iptrunk.iptrunk_sides:
...@@ -427,22 +427,25 @@ def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State: ...@@ -427,22 +427,25 @@ def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State:
} }
def _allocate_interfaces_in_netbox(iptrunk_side: IptrunkSideBlockProvisioning) -> None: def _allocate_interfaces_in_netbox(iptrunk_side: IptrunkSideBlockInactive) -> None:
for interface in iptrunk_side.iptrunk_side_ae_members: for interface in iptrunk_side.iptrunk_side_ae_members:
NetboxClient().allocate_interface( fqdn = iptrunk_side.iptrunk_side_node.router_fqdn
device_name=iptrunk_side.iptrunk_side_node.router_fqdn, iface_name = interface.interface_name
iface_name=interface.interface_name, if not fqdn or not iface_name:
) msg = f"FQDN and/or interface name missing in subscription {interface.owner_subscription_id}"
raise ValueError(msg)
NetboxClient().allocate_interface(device_name=fqdn, iface_name=iface_name)
@step("Allocate interfaces in Netbox for side A") @step("Allocate interfaces in Netbox for side A")
def netbox_allocate_side_a_interfaces(subscription: IptrunkProvisioning) -> None: def netbox_allocate_side_a_interfaces(subscription: IptrunkInactive) -> None:
"""Allocate the :term:`LAG` interfaces for the Nokia router on side A.""" """Allocate the :term:`LAG` interfaces for the Nokia router on side A."""
_allocate_interfaces_in_netbox(subscription.iptrunk.iptrunk_sides[0]) _allocate_interfaces_in_netbox(subscription.iptrunk.iptrunk_sides[0])
@step("Allocate interfaces in Netbox for side B") @step("Allocate interfaces in Netbox for side B")
def netbox_allocate_side_b_interfaces(subscription: IptrunkProvisioning) -> None: def netbox_allocate_side_b_interfaces(subscription: IptrunkInactive) -> None:
"""Allocate the :term:`LAG` interfaces for the Nokia router on side B.""" """Allocate the :term:`LAG` interfaces for the Nokia router on side B."""
_allocate_interfaces_in_netbox(subscription.iptrunk.iptrunk_sides[1]) _allocate_interfaces_in_netbox(subscription.iptrunk.iptrunk_sides[1])
......
...@@ -19,7 +19,7 @@ from gso.products.product_blocks.router import ( ...@@ -19,7 +19,7 @@ from gso.products.product_blocks.router import (
RouterVendor, RouterVendor,
generate_fqdn, generate_fqdn,
) )
from gso.products.product_types.router import RouterInactive, RouterProvisioning from gso.products.product_types.router import RouterInactive
from gso.products.product_types.site import Site from gso.products.product_types.site import Site
from gso.services import infoblox, subscriptions from gso.services import infoblox, subscriptions
from gso.services.crm import get_customer_by_name from gso.services.crm import get_customer_by_name
...@@ -127,17 +127,21 @@ def ipam_allocate_loopback(subscription: RouterInactive) -> State: ...@@ -127,17 +127,21 @@ def ipam_allocate_loopback(subscription: RouterInactive) -> State:
@step("Create NetBox Device") @step("Create NetBox Device")
def create_netbox_device(subscription: RouterProvisioning) -> State: def create_netbox_device(subscription: RouterInactive) -> State:
"""Create a new NOKIA device in Netbox.""" """Create a new NOKIA device in Netbox."""
NetboxClient().create_device( fqdn = subscription.router.router_fqdn
subscription.router.router_fqdn, site_tier = subscription.router.router_site.site_tier if subscription.router.router_site else None
str(subscription.router.router_site.site_tier), if not fqdn or not site_tier:
) msg = f"FQDN and/or Site tier missing in router subscription {subscription.subscription_id}!"
raise ValueError(msg)
NetboxClient().create_device(fqdn, site_tier)
return {"subscription": subscription} return {"subscription": subscription}
@step("Verify IPAM resources for loopback interface") @step("Verify IPAM resources for loopback interface")
def verify_ipam_loopback(subscription: RouterProvisioning) -> State: def verify_ipam_loopback(subscription: RouterInactive) -> State:
"""Validate the :term:`IPAM` resources for the loopback interface.""" """Validate the :term:`IPAM` resources for the loopback interface."""
host_record = infoblox.find_host_by_fqdn(f"lo0.{subscription.router.router_fqdn}") host_record = infoblox.find_host_by_fqdn(f"lo0.{subscription.router.router_fqdn}")
if not host_record or str(subscription.subscription_id) not in host_record.comment: if not host_record or str(subscription.subscription_id) not in host_record.comment:
...@@ -147,17 +151,21 @@ def verify_ipam_loopback(subscription: RouterProvisioning) -> State: ...@@ -147,17 +151,21 @@ def verify_ipam_loopback(subscription: RouterProvisioning) -> State:
@inputstep("Prompt to reboot", assignee=Assignee.SYSTEM) @inputstep("Prompt to reboot", assignee=Assignee.SYSTEM)
def prompt_reboot_router(subscription: RouterProvisioning) -> FormGenerator: def prompt_reboot_router(subscription: RouterInactive) -> FormGenerator:
"""Wait for confirmation from an operator that the router has been rebooted.""" """Wait for confirmation from an operator that the router has been rebooted."""
class RebootPrompt(FormPage): class RebootPrompt(FormPage):
class Config: class Config:
title = "Please reboot before continuing" title = "Please reboot before continuing"
info_label_1: Label = ( if subscription.router.router_site and subscription.router.router_site.site_ts_address:
f"Base config has been deployed. Please log in via the console using https://" # type: ignore[assignment] info_label_1: Label = (
f"{subscription.router.router_site.site_ts_address}." f"Base config has been deployed. Please log in via the console using https://" # type: ignore[assignment]
) f"{subscription.router.router_site.site_ts_address}."
)
else:
info_label_1 = "Base config has been deployed. Please log in via the console." # type: ignore[assignment]
info_label_2: Label = "Reboot the router, and once it is up again, press submit to continue the workflow." # type: ignore[assignment] info_label_2: Label = "Reboot the router, and once it is up again, press submit to continue the workflow." # type: ignore[assignment]
yield RebootPrompt yield RebootPrompt
......
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