Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • goat/gap/geant-service-orchestrator
1 result
Show changes
Commits on Source (44)
Showing
with 692 additions and 22 deletions
``gso.workflows.l2_circuit.create_imported_layer_2_circuit``
============================================================
.. automodule:: gso.workflows.l2_circuit.create_imported_layer_2_circuit
:members:
:show-inheritance:
``gso.workflows.l2_circuit.create_layer_2_circuit``
===================================================
.. automodule:: gso.workflows.l2_circuit.create_layer_2_circuit
:members:
:show-inheritance:
``gso.workflows.l2_circuit.import_layer_2_circuit``
===================================================
.. automodule:: gso.workflows.l2_circuit.import_layer_2_circuit
:members:
:show-inheritance:
``gso.workflows.L2_circuit
==========================
.. automodule:: gso.workflows.L2_circuit
:members:
:show-inheritance:
Submodules
----------
.. toctree::
:maxdepth: 2
:titlesonly:
create_layer_2_circuit
modify_layer_2_circuit
terminate_layer_2_circuit
create_imported_layer_2_circuit
import_layer_2_circuit
``gso.workflows.l2_circuit.modify_layer_2_circuit``
===================================================
.. automodule:: gso.workflows.l2_circuit.modify_layer_2_circuit
:members:
:show-inheritance:
......@@ -21,10 +21,11 @@ from gso.products import ProductType
from gso.products.product_blocks.bgp_session import IPFamily
from gso.products.product_blocks.edge_port import EdgePortType, EncapsulationType
from gso.products.product_blocks.iptrunk import IptrunkType
from gso.products.product_blocks.layer_2_circuit import Layer2CircuitType
from gso.products.product_blocks.router import RouterRole
from gso.products.product_blocks.service_binding_port import VLAN_ID
from gso.products.product_blocks.switch import SwitchModel
from gso.products.product_types.nren_l3_core_service import NRENL3CoreServiceType
from gso.products.product_types.edge_port import EdgePort
from gso.products.product_types.layer_2_circuit import Layer2CircuitServiceType
from gso.services.partners import (
PartnerEmail,
PartnerName,
......@@ -39,7 +40,7 @@ from gso.services.subscriptions import (
)
from gso.utils.shared_enums import SBPType, Vendor
from gso.utils.types.base_site import BaseSiteValidatorModel
from gso.utils.types.interfaces import LAGMember, LAGMemberList, PhysicalPortCapacity
from gso.utils.types.interfaces import BandwidthString, LAGMember, LAGMemberList, PhysicalPortCapacity
from gso.utils.types.ip_address import (
AddressSpace,
IPAddress,
......@@ -50,6 +51,7 @@ from gso.utils.types.ip_address import (
IPV6Netmask,
PortNumber,
)
from gso.utils.types.virtual_identifiers import VC_ID, VLAN_ID
app: typer.Typer = typer.Typer()
......@@ -327,6 +329,49 @@ class LanSwitchInterconnectImportModel(BaseModel):
switch_side: LanSwitchInterconnectSwitchSideImportModel
class Layer2CircuitServiceImportModel(BaseModel):
"""Import Layer 2 Circuit Service model."""
class ServiceBindingPortInput(BaseModel):
"""Service Binding Port model."""
edge_port: UUIDstr
vlan_id: VLAN_ID
service_type: Layer2CircuitServiceType
partner: str
geant_sid: str
vc_id: VC_ID
layer_2_circuit_side_a: ServiceBindingPortInput
layer_2_circuit_side_b: ServiceBindingPortInput
layer_2_circuit_type: Layer2CircuitType
vlan_range_lower_bound: VLAN_ID | None = None
vlan_range_upper_bound: VLAN_ID | None = None
policer_enabled: bool = False
policer_bandwidth: BandwidthString | None = None
policer_burst_rate: BandwidthString | None = None
@field_validator("partner")
def check_if_partner_exists(cls, value: str) -> str:
"""Validate that the partner exists."""
try:
get_partner_by_name(value)
except PartnerNotFoundError as e:
msg = f"Partner {value} not found"
raise ValueError(msg) from e
return value
@model_validator(mode="after")
def check_if_edge_ports_exist(self) -> Self:
"""Check if the edge ports exist."""
for side in [self.layer_2_circuit_side_a, self.layer_2_circuit_side_b]:
if not EdgePort.from_subscription(side.edge_port):
msg = f"Edge Port {side.edge_port} not found"
raise ValueError(msg)
return self
T = TypeVar(
"T",
SiteImportModel,
......@@ -339,6 +384,7 @@ T = TypeVar(
EdgePortImportModel,
NRENL3CoreServiceImportModel,
LanSwitchInterconnectImportModel,
Layer2CircuitServiceImportModel,
)
common_filepath_option = typer.Option(
......@@ -608,7 +654,7 @@ def import_nren_l3_core_service(filepath: str = common_filepath_option) -> None:
for nren_l3_core_service in nren_l3_core_service_list:
partner = nren_l3_core_service["partner"]
service_type = NRENL3CoreServiceType(nren_l3_core_service["service_type"])
service_type = nren_l3_core_service["service_type"]
typer.echo(f"Creating imported {service_type} for {partner}")
try:
......@@ -650,3 +696,44 @@ def import_lan_switch_interconnect(filepath: str = common_filepath_option) -> No
"lan_switch_interconnect_description",
LanSwitchInterconnectImportModel,
)
@app.command()
def import_layer_2_circuit_service(filepath: str = common_filepath_option) -> None:
"""Import Layer 2 Circuit services into GSO."""
successfully_imported_data = []
layer_2_circuit_service_list = _read_data(Path(filepath))
for layer_2_circuit_service in layer_2_circuit_service_list:
partner = layer_2_circuit_service["partner"]
service_type = Layer2CircuitServiceType(layer_2_circuit_service["service_type"])
typer.echo(f"Creating imported {service_type} for {partner}")
try:
initial_data = Layer2CircuitServiceImportModel(**layer_2_circuit_service)
start_process("create_imported_layer_2_circuit", [initial_data.model_dump()])
successfully_imported_data.append(initial_data.vc_id)
typer.echo(
f"Successfully created imported {service_type} with virtual circuit ID {initial_data.vc_id}"
f" for {partner}"
)
except ValidationError as e:
typer.echo(f"Validation error: {e}")
typer.echo("Waiting for the dust to settle before importing new products...")
time.sleep(1)
# Migrate new products from imported to "full" counterpart.
imported_products = get_subscriptions(
product_types=[ProductType.IMPORTED_EXPRESSROUTE, ProductType.IMPORTED_GEANT_PLUS],
lifecycles=[SubscriptionLifecycle.ACTIVE],
includes=["subscription_id"],
)
for subscription_id in imported_products:
typer.echo(f"Importing {subscription_id}")
start_process("import_layer_2_circuit", [subscription_id])
if successfully_imported_data:
typer.echo("Successfully created imported Layer 2 Circuit services:")
for item in successfully_imported_data:
typer.echo(f"- {item}")
"""Add Layer 2 Cricuits services domain models..
Revision ID: 5132c463214d
Revises: 0e7e7d749617
Create Date: 2024-10-29 13:34:39.234303
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '5132c463214d'
down_revision = '0e7e7d749617'
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
conn.execute(sa.text("""
INSERT INTO products (name, description, product_type, tag, status) VALUES ('GÉANT Plus', 'GÉANT Plus', 'Layer2Circuit', 'G_PLUS', 'active') RETURNING products.product_id
"""))
conn.execute(sa.text("""
INSERT INTO products (name, description, product_type, tag, status) VALUES ('Imported GÉANT Plus', 'Imported GEANT Plus', 'ImportedLayer2Circuit', 'IMP_G_PLUS', 'active') RETURNING products.product_id
"""))
conn.execute(sa.text("""
INSERT INTO products (name, description, product_type, tag, status) VALUES ('Azure ExpressRoute', 'Azure ExpressRoute product', 'Layer2Circuit', 'ER', 'active') RETURNING products.product_id
"""))
conn.execute(sa.text("""
INSERT INTO products (name, description, product_type, tag, status) VALUES ('Imported Azure ExpressRoute', 'Imported Azure ExpressRoute', 'ImportedLayer2Circuit', 'IMP_ER', 'active') RETURNING products.product_id
"""))
conn.execute(sa.text("""
INSERT INTO fixed_inputs (name, value, product_id) VALUES ('layer_2_circuit_service_type', 'Azure ExpressRoute', (SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute'))), ('layer_2_circuit_service_type', 'Imported Azure ExpressRoute', (SELECT products.product_id FROM products WHERE products.name IN ('Imported Azure ExpressRoute'))), ('layer_2_circuit_service_type', 'Imported GÉANT Plus', (SELECT products.product_id FROM products WHERE products.name IN ('Imported GÉANT Plus'))), ('layer_2_circuit_service_type', 'GÉANT Plus', (SELECT products.product_id FROM products WHERE products.name IN ('GÉANT Plus')))
"""))
conn.execute(sa.text("""
INSERT INTO product_blocks (name, description, tag, status) VALUES ('Layer2CircuitBlock', 'Layer 2 Circuit product block', 'L2_C_BLOCK', 'active') RETURNING product_blocks.product_block_id
"""))
conn.execute(sa.text("""
INSERT INTO product_blocks (name, description, tag, status) VALUES ('Layer2CircuitSideBlock', 'Layer 2 Circuit side product block', 'L2_C_SIDE_BLOCK', 'active') RETURNING product_blocks.product_block_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('policer_enabled', 'Whether this Layer 2 Circuit is policed.') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('bandwidth', 'If policed, the bandwidth of the policer is stored.') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('vlan_range_upper_bound', 'VLAN upper bound range') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('vlan_range_lower_bound', 'VLAN lower bound range') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('virtual_circuit_id', 'Virtual Circuit ID of this Layer 2 Circuit.') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('layer_2_circuit_type', 'The type of circuit, can be tagged or untagged.') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO product_product_blocks (product_id, product_block_id) VALUES ((SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))), ((SELECT products.product_id FROM products WHERE products.name IN ('Imported Azure ExpressRoute')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))), ((SELECT products.product_id FROM products WHERE products.name IN ('Imported GÉANT Plus')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))), ((SELECT products.product_id FROM products WHERE products.name IN ('GÉANT Plus')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_relations (in_use_by_id, depends_on_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitSideBlock')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_relations (in_use_by_id, depends_on_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitSideBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('ServiceBindingPort')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('virtual_circuit_id')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('layer_2_circuit_type')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('vlan_range_lower_bound')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('vlan_range_upper_bound')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_enabled')))
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('bandwidth')))
"""))
conn.execute(sa.text("""
INSERT INTO resource_types (resource_type, description) VALUES ('policer_burst_rate', 'Max burst rate of a policer') RETURNING resource_types.resource_type_id
"""))
conn.execute(sa.text("""
INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_burst_rate')))
"""))
def downgrade() -> None:
conn = op.get_bind()
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_burst_rate'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_burst_rate'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_burst_rate'))
"""))
conn.execute(sa.text("""
DELETE FROM resource_types WHERE resource_types.resource_type IN ('policer_burst_rate')
"""))
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('virtual_circuit_id'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('virtual_circuit_id'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('layer_2_circuit_type'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('layer_2_circuit_type'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('vlan_range_lower_bound'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('vlan_range_lower_bound'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('vlan_range_upper_bound'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('vlan_range_upper_bound'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_enabled'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_enabled'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('bandwidth'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('bandwidth'))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('policer_enabled', 'bandwidth', 'vlan_range_upper_bound', 'vlan_range_lower_bound', 'virtual_circuit_id', 'layer_2_circuit_type'))
"""))
conn.execute(sa.text("""
DELETE FROM resource_types WHERE resource_types.resource_type IN ('policer_enabled', 'bandwidth', 'vlan_range_upper_bound', 'vlan_range_lower_bound', 'virtual_circuit_id', 'layer_2_circuit_type')
"""))
conn.execute(sa.text("""
DELETE FROM product_product_blocks WHERE product_product_blocks.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute', 'Imported Azure ExpressRoute', 'Imported GÉANT Plus', 'GÉANT Plus')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitSideBlock'))
"""))
conn.execute(sa.text("""
DELETE FROM product_block_relations WHERE product_block_relations.in_use_by_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitSideBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('ServiceBindingPort'))
"""))
conn.execute(sa.text("""
DELETE FROM fixed_inputs WHERE fixed_inputs.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute', 'Imported Azure ExpressRoute', 'Imported GÉANT Plus', 'GÉANT Plus')) AND fixed_inputs.name = 'layer_2_circuit_service_type'
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instances WHERE subscription_instances.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitSideBlock', 'Layer2CircuitBlock'))
"""))
conn.execute(sa.text("""
DELETE FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitSideBlock', 'Layer2CircuitBlock')
"""))
conn.execute(sa.text("""
DELETE FROM processes WHERE processes.pid IN (SELECT processes_subscriptions.pid FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute', 'Imported Azure ExpressRoute', 'Imported GÉANT Plus', 'GÉANT Plus'))))
"""))
conn.execute(sa.text("""
DELETE FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute', 'Imported Azure ExpressRoute', 'Imported GÉANT Plus', 'GÉANT Plus')))
"""))
conn.execute(sa.text("""
DELETE FROM subscription_instances WHERE subscription_instances.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute', 'Imported Azure ExpressRoute', 'Imported GÉANT Plus', 'GÉANT Plus')))
"""))
conn.execute(sa.text("""
DELETE FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Azure ExpressRoute', 'Imported Azure ExpressRoute', 'Imported GÉANT Plus', 'GÉANT Plus'))
"""))
conn.execute(sa.text("""
DELETE FROM products WHERE products.name IN ('Azure ExpressRoute', 'Imported Azure ExpressRoute', 'Imported GÉANT Plus', 'GÉANT Plus')
"""))
"""Add L2Circuit workflows..
Revision ID: 72a4f7aa499d
Revises: 5132c463214d
Create Date: 2024-10-29 14:04:29.807253
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '72a4f7aa499d'
down_revision = '5132c463214d'
branch_labels = None
depends_on = None
from orchestrator.migrations.helpers import create_workflow, delete_workflow
new_workflows = [
{
"name": "create_layer_2_circuit",
"target": "CREATE",
"description": "Create Layer 2 Circuit Service",
"product_type": "Layer2Circuit"
},
{
"name": "modify_layer_2_circuit",
"target": "MODIFY",
"description": "Modify Layer 2 Circuit Service",
"product_type": "Layer2Circuit"
},
{
"name": "terminate_layer_2_circuit",
"target": "TERMINATE",
"description": "Terminate Layer 2 Circuit Service",
"product_type": "Layer2Circuit"
},
{
"name": "create_imported_layer_2_circuit",
"target": "CREATE",
"description": "Create imported Layer 2 Circuit",
"product_type": "ImportedLayer2Circuit"
},
{
"name": "import_layer_2_circuit",
"target": "MODIFY",
"description": "Import Layer 2 Circuit",
"product_type": "ImportedLayer2Circuit"
},
]
def upgrade() -> None:
conn = op.get_bind()
for workflow in new_workflows:
create_workflow(conn, workflow)
def downgrade() -> None:
conn = op.get_bind()
for workflow in new_workflows:
delete_workflow(conn, workflow["name"])
......@@ -11,6 +11,7 @@ from pydantic_forms.types import strEnum
from gso.products.product_types.edge_port import EdgePort, ImportedEdgePort
from gso.products.product_types.iptrunk import ImportedIptrunk, Iptrunk
from gso.products.product_types.lan_switch_interconnect import ImportedLanSwitchInterconnect, LanSwitchInterconnect
from gso.products.product_types.layer_2_circuit import ImportedLayer2Circuit, Layer2Circuit, Layer2CircuitServiceType
from gso.products.product_types.nren_l3_core_service import ImportedNRENL3CoreService, NRENL3CoreService
from gso.products.product_types.office_router import ImportedOfficeRouter, OfficeRouter
from gso.products.product_types.opengear import ImportedOpengear, Opengear
......@@ -47,6 +48,10 @@ class ProductName(strEnum):
IMPORTED_GEANT_IP = "Imported GÉANT IP"
IAS = "IAS"
IMPORTED_IAS = "Imported IAS"
GEANT_PLUS = Layer2CircuitServiceType.GEANT_PLUS
IMPORTED_GEANT_PLUS = Layer2CircuitServiceType.IMPORTED_GEANT_PLUS
EXPRESSROUTE = Layer2CircuitServiceType.EXPRESSROUTE
IMPORTED_EXPRESSROUTE = Layer2CircuitServiceType.IMPORTED_EXPRESSROUTE
class ProductType(strEnum):
......@@ -75,6 +80,10 @@ class ProductType(strEnum):
IMPORTED_GEANT_IP = ImportedNRENL3CoreService.__name__
IAS = NRENL3CoreService.__name__
IMPORTED_IAS = ImportedNRENL3CoreService.__name__
GEANT_PLUS = Layer2Circuit.__name__
IMPORTED_GEANT_PLUS = ImportedLayer2Circuit.__name__
EXPRESSROUTE = Layer2Circuit.__name__
IMPORTED_EXPRESSROUTE = ImportedLayer2Circuit.__name__
SUBSCRIPTION_MODEL_REGISTRY.update(
......@@ -102,5 +111,11 @@ SUBSCRIPTION_MODEL_REGISTRY.update(
ProductName.IMPORTED_GEANT_IP.value: ImportedNRENL3CoreService,
ProductName.IAS.value: NRENL3CoreService,
ProductName.IMPORTED_IAS.value: ImportedNRENL3CoreService,
ProductName.GEANT_PLUS.value: Layer2Circuit,
ProductName.IMPORTED_GEANT_PLUS.value: ImportedLayer2Circuit,
ProductName.EXPRESSROUTE.value: Layer2Circuit,
ProductName.IMPORTED_EXPRESSROUTE.value: ImportedLayer2Circuit,
},
)
__all__ = ["ProductName", "ProductType"]
"""Layer 2 Circuit product block."""
from collections.abc import Sequence
from typing import Annotated, TypeVar
from annotated_types import Len
from orchestrator.domain.base import ProductBlockModel
from orchestrator.types import SubscriptionLifecycle
from pydantic import AfterValidator
from pydantic_forms.types import strEnum
from pydantic_forms.validators import validate_unique_list
from typing_extensions import Doc
from gso.products.product_blocks.service_binding_port import (
ServiceBindingPort,
ServiceBindingPortInactive,
ServiceBindingPortProvisioning,
)
from gso.utils.types.interfaces import BandwidthString
from gso.utils.types.virtual_identifiers import VC_ID, VLAN_ID
class Layer2CircuitSideBlockInactive(
ProductBlockModel,
lifecycle=[SubscriptionLifecycle.INITIAL],
product_block_name="Layer2CircuitSideBlock",
):
"""One inactive side of a Layer 2 Circuit."""
sbp: ServiceBindingPortInactive
class Layer2CircuitSideBlockProvisioning(
Layer2CircuitSideBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]
):
"""One provisioning side of a Layer 2 Circuit."""
sbp: ServiceBindingPortProvisioning
class Layer2CircuitSideBlock(Layer2CircuitSideBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""One side of a Layer 2 Circuit."""
sbp: ServiceBindingPort
Layer2CircuitSideBlockType = TypeVar(
"Layer2CircuitSideBlockType",
"Layer2CircuitSideBlockInactive",
"Layer2CircuitSideBlockProvisioning",
"Layer2CircuitSideBlock",
)
Layer2CircuitSides = Annotated[
Sequence[Layer2CircuitSideBlockType],
AfterValidator(validate_unique_list),
Len(min_length=2, max_length=2),
Doc("A list of two Layer 2 Circuit sides."),
]
class Layer2CircuitType(strEnum):
"""The two types of Layer 2 Circuit."""
TAGGED = "TAGGED"
UNTAGGED = "UNTAGGED"
class Layer2CircuitBlockInactive(
ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="Layer2CircuitBlock"
):
"""An inactive Layer 2 Circuit, see :class:`Layer2CircuitBlock`."""
layer_2_circuit_sides: Layer2CircuitSides[Layer2CircuitSideBlockInactive]
virtual_circuit_id: VC_ID | None = None
layer_2_circuit_type: Layer2CircuitType | None = None
vlan_range_lower_bound: VLAN_ID | None = None
vlan_range_upper_bound: VLAN_ID | None = None
policer_enabled: bool | None = None
policer_burst_rate: BandwidthString | None = None
bandwidth: BandwidthString | None = None
class Layer2CircuitBlockProvisioning(Layer2CircuitBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
"""A provisioning Layer 2 Circuit, see :class:`Layer2CircuitBlock`."""
layer_2_circuit_sides: Layer2CircuitSides[Layer2CircuitSideBlockProvisioning]
virtual_circuit_id: VC_ID
layer_2_circuit_type: Layer2CircuitType
vlan_range_lower_bound: VLAN_ID | None
vlan_range_upper_bound: VLAN_ID | None
policer_enabled: bool
policer_burst_rate: BandwidthString | None
bandwidth: BandwidthString | None
class Layer2CircuitBlock(Layer2CircuitBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""An active Layer 2 Circuit."""
#: The two sides that the Layer 2 Circuit is connected to.
layer_2_circuit_sides: Layer2CircuitSides[Layer2CircuitSideBlock]
#: Virtual Circuit ID of this Layer 2 Circuit.
virtual_circuit_id: VC_ID
#: The type of circuit, can be tagged or untagged.
layer_2_circuit_type: Layer2CircuitType
#: If tagged, the lower and upper bounds will set the :term:`VLAN` range.
vlan_range_lower_bound: VLAN_ID | None
#: Lower and Upper bounds are including.
vlan_range_upper_bound: VLAN_ID | None
#: Whether this Layer 2 Circuit is policed.
policer_enabled: bool
#: If policed, the burst rate of the policer
policer_burst_rate: BandwidthString | None
#: If policed, the bandwidth of the policer is stored.
bandwidth: BandwidthString | None
......@@ -3,8 +3,6 @@
A service binding port is used to logically attach an edge port to a customer service using a :term:`VLAN`.
"""
from typing import Annotated
from orchestrator.domain.base import ProductBlockModel
from orchestrator.types import SubscriptionLifecycle
from pydantic import Field
......@@ -13,8 +11,7 @@ from gso.products.product_blocks.bgp_session import BGPSession, BGPSessionInacti
from gso.products.product_blocks.edge_port import EdgePortBlock, EdgePortBlockInactive, EdgePortBlockProvisioning
from gso.utils.shared_enums import SBPType
from gso.utils.types.ip_address import IPv4AddressType, IPV4Netmask, IPv6AddressType, IPV6Netmask
VLAN_ID = Annotated[int, Field(gt=0, lt=4096)]
from gso.utils.types.virtual_identifiers import VLAN_ID
class ServiceBindingPortInactive(
......
"""Product type for a Layer 2 circuit."""
from orchestrator.domain.base import SubscriptionModel
from orchestrator.types import SubscriptionLifecycle
from pydantic_forms.types import strEnum
from gso.products.product_blocks.layer_2_circuit import (
Layer2CircuitBlock,
Layer2CircuitBlockInactive,
Layer2CircuitBlockProvisioning,
)
class Layer2CircuitServiceType(strEnum):
"""Available types of Layer 2 Circuit services."""
GEANT_PLUS = "GÉANT Plus"
IMPORTED_GEANT_PLUS = "Imported GÉANT Plus"
EXPRESSROUTE = "Azure ExpressRoute"
IMPORTED_EXPRESSROUTE = "Imported Azure ExpressRoute"
class Layer2CircuitInactive(SubscriptionModel, is_base=True):
"""An inactive Layer 2 Circuit."""
layer_2_circuit_service_type: Layer2CircuitServiceType
layer_2_circuit: Layer2CircuitBlockInactive
class Layer2CircuitProvisioning(Layer2CircuitInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
"""A Layer 2 Circuit that is provisioning."""
layer_2_circuit_service_type: Layer2CircuitServiceType
layer_2_circuit: Layer2CircuitBlockProvisioning
class Layer2Circuit(Layer2CircuitProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""An active Layer 2 Circuit."""
layer_2_circuit_service_type: Layer2CircuitServiceType
layer_2_circuit: Layer2CircuitBlock
class ImportedLayer2CircuitInactive(SubscriptionModel, is_base=True):
"""An imported, inactive Layer 2 Circuit."""
layer_2_circuit_service_type: Layer2CircuitServiceType
layer_2_circuit: Layer2CircuitBlockInactive
class ImportedLayer2Circuit(
ImportedLayer2CircuitInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE]
):
"""An imported Layer 2 Circuit."""
layer_2_circuit_service_type: Layer2CircuitServiceType
layer_2_circuit: Layer2CircuitBlock
......@@ -10,11 +10,11 @@ from typing import Any, Literal, TypedDict
import requests
from orchestrator import step
from orchestrator.config.assignee import Assignee
from orchestrator.forms import FormPage
from orchestrator.types import State
from orchestrator.utils.errors import ProcessFailureError
from orchestrator.workflow import Step, StepList, begin, callback_step, conditional, inputstep
from pydantic import ConfigDict
from pydantic_forms.core import FormPage
from pydantic_forms.types import FormGenerator
from pydantic_forms.validators import Label, LongText, ReadOnlyField
......
......@@ -287,3 +287,25 @@ def get_all_active_sites() -> list[dict[str, Any]]:
}
for subscription in get_active_site_subscriptions(includes=["subscription_id"])
]
def is_virtual_circuit_id_available(virtual_circuit_id: str) -> bool:
"""Check if the given virtual circuit ID is unique in the database.
This function verifies if the specified virtual circuit ID is not already
present in the core database.
:param virtual_circuit_id: The virtual circuit ID to check.
:type virtual_circuit_id: str
:return: True if the virtual circuit ID is unique (not found), False if it exists.
:rtype: bool
"""
exists = (
ResourceTypeTable.query.join(SubscriptionInstanceValueTable)
.filter(
ResourceTypeTable.resource_type == "virtual_circuit_id",
SubscriptionInstanceValueTable.value == virtual_circuit_id,
)
.scalar()
)
return exists is None
......@@ -103,6 +103,11 @@
"task_modify_partners": "Modify partner task",
"task_delete_partners": "Delete partner task",
"task_clean_old_tasks": "Remove old cleanup tasks",
"promote_p_to_pe": "Promote P to PE"
"promote_p_to_pe": "Promote P to PE",
"create_layer_2_circuit": "Create Layer 2 Circuit",
"modify_layer_2_circuit": "Modify Layer 2 Circuit",
"terminate_layer_2_circuit": "Terminate Layer 2 Circuit",
"create_imported_layer_2_circuit": "NOT FOR HUMANS -- Import existing Layer 2 Circuit",
"import_layer_2_circuit": "NOT FOR HUMANS -- Finalize import into a Layer 2 Circuit product"
}
}
"""Helper methods that are used across :term:`GSO`."""
import random
import re
from typing import TYPE_CHECKING
from uuid import UUID
from orchestrator.types import SubscriptionLifecycle
from pydantic_forms.types import UUIDstr
from pydantic_forms.validators import Choice
......@@ -13,9 +15,11 @@ from gso.products.product_types.router import Router
from gso.services import subscriptions
from gso.services.netbox_client import NetboxClient
from gso.services.partners import get_all_partners
from gso.services.subscriptions import is_virtual_circuit_id_available
from gso.utils.shared_enums import Vendor
from gso.utils.types.interfaces import PhysicalPortCapacity
from gso.utils.types.ip_address import IPv4AddressType
from gso.utils.types.virtual_identifiers import VC_ID
if TYPE_CHECKING:
from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock
......@@ -119,10 +123,12 @@ def generate_fqdn(hostname: str, site_name: str, country_code: str) -> str:
return f"{hostname}.{site_name.lower()}.{country_code.lower()}{oss.IPAM.LO.domain_name}"
def generate_inventory_for_active_routers(
def generate_inventory_for_routers(
router_role: RouterRole,
exclude_routers: list[str] | None = None,
router_vendor: Vendor | None = None,
*,
include_provisioning_routers: bool = True,
) -> dict:
"""Generate an Ansible-compatible inventory for executing playbooks.
......@@ -131,11 +137,18 @@ def generate_inventory_for_active_routers(
:param RouterRole router_role: The role of the routers to include in the inventory.
:param list exclude_routers: List of routers to exclude from the inventory.
:param Vendor router_vendor: The vendor of the routers to include in the inventory.
:param bool include_provisioning_routers: Include routers that are in a ``PROVISIONING`` state.
:return: A dictionary representing the inventory of active routers.
:rtype: dict[str, Any]
"""
lifecycles = (
[SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE]
if include_provisioning_routers
else [SubscriptionLifecycle.ACTIVE]
)
all_routers = [
Router.from_subscription(r["subscription_id"]) for r in subscriptions.get_active_router_subscriptions()
Router.from_subscription(r["subscription_id"])
for r in subscriptions.get_router_subscriptions(lifecycles=lifecycles)
]
exclude_routers = exclude_routers or []
......@@ -248,3 +261,28 @@ def validate_edge_port_number_of_members_based_on_lacp(*, number_of_members: int
if number_of_members > 1 and not enable_lacp:
err_msg = "Number of members must be 1 if LACP is disabled."
raise ValueError(err_msg)
def generate_unique_vc_id(max_attempts: int = 100) -> VC_ID | None:
"""Generate a unique 8-digit VC_ID starting with '11'.
This function attempts to generate an 8-digit VC_ID beginning with '11',
checking its uniqueness before returning it. A maximum attempt limit is
set to prevent infinite loops in case the ID space is saturated.
:param max_attempts: The maximum number of attempts to generate a unique ID.
:type max_attempts: int
:return: A unique VC_ID instance if successful, None if no unique ID is found.
:rtype: Optional[VC_ID]
"""
def create_vc_id() -> str:
"""Generate an 8-digit VC_ID starting with '11'."""
return f"11{random.randint(100000, 999999)}" # noqa: S311
for _ in range(max_attempts):
vc_id = create_vc_id()
if is_virtual_circuit_id_available(vc_id):
return VC_ID(vc_id)
return None
......@@ -100,3 +100,26 @@ class PhysicalPortCapacity(strEnum):
TEN_GIGABIT_PER_SECOND = "10G"
HUNDRED_GIGABIT_PER_SECOND = "100G"
FOUR_HUNDRED_GIGABIT_PER_SECOND = "400G"
def bandwidth_string_is_valid(bandwidth_string: str) -> str:
"""Expect a bandwidth definition to follow the pattern of an int followed by a single letter.
If this string does not consist of a number followed by a single
"""
msg = f"Expected a network capacity, e.g. 40G or 200M. Got: {bandwidth_string}"
if len(bandwidth_string) < 2: # noqa: PLR2004 not a magic value
raise ValueError(msg)
if bandwidth_string[-1:] not in "K" "M" "G" "T":
raise ValueError(msg)
try:
int(bandwidth_string[:-1]) # Try parsing the bandwidth number
except ValueError as e:
raise ValueError(msg) from e
return bandwidth_string
BandwidthString = Annotated[str, AfterValidator(bandwidth_string_is_valid)]
"""Annotated types for virtual identifiers such as :term:`VLAN` ID or Virtual Circuit ID."""
from typing import Annotated
from pydantic import Field
from typing_extensions import Doc
VLAN_ID = Annotated[int, Field(gt=0, lt=4096)]
VC_ID = Annotated[
int,
Field(gt=0, le=2147483648),
Doc(
"A Virtual Circuit ID, the upper limit comes from the highest number that a service ID could be in Nokia srOS."
),
]
......@@ -5,12 +5,12 @@ from typing import Any
from orchestrator import inputstep, step
from orchestrator.config.assignee import Assignee
from orchestrator.forms import FormPage
from orchestrator.types import State, UUIDstr
from orchestrator.utils.errors import ProcessFailureError
from orchestrator.utils.json import json_dumps
from orchestrator.workflow import StepList, conditional
from pydantic import ConfigDict
from pydantic_forms.core import FormPage
from pydantic_forms.types import FormGenerator
from pydantic_forms.validators import Label
......@@ -19,7 +19,7 @@ from gso.products.product_types.iptrunk import Iptrunk
from gso.services.kentik_client import KentikClient, NewKentikDevice
from gso.services.lso_client import LSOState, indifferent_lso_interaction
from gso.settings import load_oss_params
from gso.utils.helpers import generate_inventory_for_active_routers
from gso.utils.helpers import generate_inventory_for_routers
from gso.utils.shared_enums import Vendor
......@@ -51,7 +51,7 @@ def _update_sdp_mesh(
*,
dry_run: bool,
) -> LSOState:
inventory = generate_inventory_for_active_routers(
inventory = generate_inventory_for_routers(
router_role=RouterRole.PE, router_vendor=Vendor.NOKIA, exclude_routers=[subscription["router"]["router_fqdn"]]
)
......@@ -89,7 +89,7 @@ def _update_sdp_single_pe(
"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(
"pe_router_list": generate_inventory_for_routers(
router_role=RouterRole.PE,
exclude_routers=[subscription["router"]["router_fqdn"]],
)["all"]["hosts"],
......@@ -122,7 +122,7 @@ def _add_pe_mesh_to_pe(
"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(
"pe_router_list": generate_inventory_for_routers(
router_role=RouterRole.PE, exclude_routers=[subscription["router"]["router_fqdn"]]
)["all"]["hosts"],
}
......@@ -148,7 +148,7 @@ def _add_pe_to_pe_mesh(
*,
dry_run: bool,
) -> LSOState:
inventory = generate_inventory_for_active_routers(
inventory = generate_inventory_for_routers(
router_role=RouterRole.PE, exclude_routers=[subscription["router"]["router_fqdn"]]
)
extra_vars = {
......@@ -178,7 +178,7 @@ def _add_all_p_to_pe(
"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(
"p_router_list": generate_inventory_for_routers(
router_role=RouterRole.P, exclude_routers=[subscription["router"]["router_fqdn"]]
)["all"]["hosts"],
}
......@@ -204,7 +204,7 @@ def _add_pe_to_all_p(
*,
dry_run: bool,
) -> LSOState:
inventory = generate_inventory_for_active_routers(
inventory = generate_inventory_for_routers(
router_role=RouterRole.P, exclude_routers=[subscription["router"]["router_fqdn"]]
)
extra_vars = {
......@@ -417,11 +417,11 @@ def stop_moodi() -> StepList:
host = load_oss_params().MOODI.host
@step("Stop Moodi")
def _stop_moodi() -> LSOState:
def _stop_moodi(subscription: dict[str, Any]) -> LSOState:
return {
"playbook_name": "moodi_telemetry/playbooks/stop_moodi.yaml",
"inventory": {"all": {"hosts": {host: None}}},
"extra_vars": None,
"extra_vars": {"subscription": subscription},
}
return _is_moodi_enabled(indifferent_lso_interaction(_stop_moodi))
......
......@@ -124,3 +124,10 @@ LazyWorkflowInstance(
)
LazyWorkflowInstance("gso.workflows.nren_l3_core_service.import_nren_l3_core_service", "import_nren_l3_core_service")
LazyWorkflowInstance("gso.workflows.nren_l3_core_service.migrate_nren_l3_core_service", "migrate_nren_l3_core_service")
# Layer 2 Circuit workflows
LazyWorkflowInstance("gso.workflows.l2_circuit.create_layer_2_circuit", "create_layer_2_circuit")
LazyWorkflowInstance("gso.workflows.l2_circuit.modify_layer_2_circuit", "modify_layer_2_circuit")
LazyWorkflowInstance("gso.workflows.l2_circuit.terminate_layer_2_circuit", "terminate_layer_2_circuit")
LazyWorkflowInstance("gso.workflows.l2_circuit.create_imported_layer_2_circuit", "create_imported_layer_2_circuit")
LazyWorkflowInstance("gso.workflows.l2_circuit.import_layer_2_circuit", "import_layer_2_circuit")