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
Select Git revision

Target

Select target project
  • goat/gap/geant-service-orchestrator
1 result
Select Git revision
Show changes
Commits on Source (8)
"""Add IP Trunk migration workflow.
Revision ID: e68720f2ec32
Revises: a6eefd32c4f7
Create Date: 2023-08-16 14:48:00.227803
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = 'e68720f2ec32'
down_revision = 'a6eefd32c4f7'
branch_labels = None
depends_on = None
from orchestrator.migrations.helpers import create_workflow, delete_workflow
new_workflows = [
{
"name": "migrate_iptrunk",
"target": "MODIFY",
"description": "Migrate an IP Trunk",
"product_type": "Iptrunk"
}
]
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"])
"""Update IP trunk model.
Revision ID: 01e42c100448
Revises: e68720f2ec32
Create Date: 2023-08-23 16:56:04.762211
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '01e42c100448'
down_revision = 'e68720f2ec32'
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_geant_a_sid'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_geant_a_sid'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members_description'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members_description'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_geant_a_sid'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_geant_a_sid'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members_description'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_members_description'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_iface'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideB_ae_iface'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_iface'))
""")
conn.execute("""
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 ('IptrunkBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_iface'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))
""")
conn.execute("""
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 ('iptrunk_sideA_ae_members', 'iptrunk_sideB_ae_geant_a_sid', 'iptrunk_sideB_ae_members', 'iptrunk_sideA_ae_members_description', 'iptrunk_sideA_ae_geant_a_sid', 'iptrunk_sideB_ae_members_description', 'iptrunk_sideB_ae_iface', 'iptrunk_sideA_ae_iface'))
""")
conn.execute("""
DELETE FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_sideA_ae_members', 'iptrunk_sideB_ae_geant_a_sid', 'iptrunk_sideB_ae_members', 'iptrunk_sideA_ae_members_description', 'iptrunk_sideA_ae_geant_a_sid', 'iptrunk_sideB_ae_members_description', 'iptrunk_sideB_ae_iface', 'iptrunk_sideA_ae_iface')
""")
conn.execute("""
INSERT INTO product_blocks (name, description, tag, status) VALUES ('IptrunkSideBlock', 'IP Trunk side', 'IPTSIDE', 'active') RETURNING product_blocks.product_block_id
""")
conn.execute("""
INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_members_description', 'LAG member descriptions') RETURNING resource_types.resource_type_id
""")
conn.execute("""
INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_iface', 'LAG interfaces') RETURNING resource_types.resource_type_id
""")
conn.execute("""
INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_members', 'LAG interface names') RETURNING resource_types.resource_type_id
""")
conn.execute("""
INSERT INTO resource_types (resource_type, description) VALUES ('iptrunk_side_ae_geant_a_sid', 'GÉANT SID') RETURNING resource_types.resource_type_id
""")
conn.execute("""
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 ('IptrunkSideBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock')))
""")
conn.execute("""
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 ('IptrunkBlock')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')))
""")
conn.execute("""
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 ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description')))
""")
conn.execute("""
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 ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_iface')))
""")
conn.execute("""
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 ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members')))
""")
conn.execute("""
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 ('IptrunkSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_geant_a_sid')))
""")
conn.execute("""
INSERT INTO subscription_instances (subscription_id, product_block_id) VALUES ('76af1125-9374-4653-bce2-e213419cdae5', (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))), ('f69f3d25-929c-4e41-98e6-49f1bd89e70f', (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')))
""")
conn.execute("""
INSERT INTO subscription_instance_relations (in_use_by_id, depends_on_id, order_id) VALUES ('eaa4cf58-358f-4c34-82a1-d248dad43b9a', (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND subscription_instances.subscription_id = '76af1125-9374-4653-bce2-e213419cdae5' LIMIT 1), 0), ('9794538d-d7a4-42c9-8fbe-f2c88f6e3e12', (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')) AND subscription_instances.subscription_id = 'f69f3d25-929c-4e41-98e6-49f1bd89e70f' LIMIT 1), 0)
""")
conn.execute("""
WITH subscription_instance_ids AS (
SELECT subscription_instances.subscription_instance_id
FROM subscription_instances
WHERE subscription_instances.product_block_id IN (
SELECT product_blocks.product_block_id
FROM product_blocks
WHERE product_blocks.name = 'IptrunkSideBlock'
)
)
INSERT INTO
subscription_instance_values (subscription_instance_id, resource_type_id, value)
SELECT
subscription_instance_ids.subscription_instance_id,
resource_types.resource_type_id,
'null'
FROM resource_types
CROSS JOIN subscription_instance_ids
WHERE resource_types.resource_type = 'iptrunk_side_ae_members_description'
""")
conn.execute("""
WITH subscription_instance_ids AS (
SELECT subscription_instances.subscription_instance_id
FROM subscription_instances
WHERE subscription_instances.product_block_id IN (
SELECT product_blocks.product_block_id
FROM product_blocks
WHERE product_blocks.name = 'IptrunkSideBlock'
)
)
INSERT INTO
subscription_instance_values (subscription_instance_id, resource_type_id, value)
SELECT
subscription_instance_ids.subscription_instance_id,
resource_types.resource_type_id,
'null'
FROM resource_types
CROSS JOIN subscription_instance_ids
WHERE resource_types.resource_type = 'iptrunk_side_ae_iface'
""")
conn.execute("""
WITH subscription_instance_ids AS (
SELECT subscription_instances.subscription_instance_id
FROM subscription_instances
WHERE subscription_instances.product_block_id IN (
SELECT product_blocks.product_block_id
FROM product_blocks
WHERE product_blocks.name = 'IptrunkSideBlock'
)
)
INSERT INTO
subscription_instance_values (subscription_instance_id, resource_type_id, value)
SELECT
subscription_instance_ids.subscription_instance_id,
resource_types.resource_type_id,
'null'
FROM resource_types
CROSS JOIN subscription_instance_ids
WHERE resource_types.resource_type = 'iptrunk_side_ae_members'
""")
conn.execute("""
WITH subscription_instance_ids AS (
SELECT subscription_instances.subscription_instance_id
FROM subscription_instances
WHERE subscription_instances.product_block_id IN (
SELECT product_blocks.product_block_id
FROM product_blocks
WHERE product_blocks.name = 'IptrunkSideBlock'
)
)
INSERT INTO
subscription_instance_values (subscription_instance_id, resource_type_id, value)
SELECT
subscription_instance_ids.subscription_instance_id,
resource_types.resource_type_id,
'null'
FROM resource_types
CROSS JOIN subscription_instance_ids
WHERE resource_types.resource_type = 'iptrunk_side_ae_geant_a_sid'
""")
def downgrade() -> None:
conn = op.get_bind()
conn.execute("""
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 ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description'))
""")
conn.execute("""
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 ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description'))
""")
conn.execute("""
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 ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_iface'))
""")
conn.execute("""
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 ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_iface'))
""")
conn.execute("""
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 ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members'))
""")
conn.execute("""
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 ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members'))
""")
conn.execute("""
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 ('IptrunkSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_geant_a_sid'))
""")
conn.execute("""
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 ('IptrunkSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_geant_a_sid'))
""")
conn.execute("""
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 ('iptrunk_side_ae_members_description', 'iptrunk_side_ae_iface', 'iptrunk_side_ae_members', 'iptrunk_side_ae_geant_a_sid'))
""")
conn.execute("""
DELETE FROM resource_types WHERE resource_types.resource_type IN ('iptrunk_side_ae_members_description', 'iptrunk_side_ae_iface', 'iptrunk_side_ae_members', 'iptrunk_side_ae_geant_a_sid')
""")
conn.execute("""
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 ('IptrunkSideBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('RouterBlock'))
""")
conn.execute("""
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 ('IptrunkBlock')) AND product_block_relations.depends_on_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock'))
""")
conn.execute("""
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 ('IptrunkSideBlock'))
""")
conn.execute("""
DELETE FROM product_blocks WHERE product_blocks.name IN ('IptrunkSideBlock')
""")
"""IP trunk product block that has all parameters of a subscription throughout its lifecycle.""" """IP trunk product block that has all parameters of a subscription throughout its lifecycle."""
import ipaddress import ipaddress
from typing import Optional from typing import Optional, TypeVar
from orchestrator.domain.base import ProductBlockModel from orchestrator.domain.base import ProductBlockModel
from orchestrator.forms.validators import UniqueConstrainedList
from orchestrator.types import SubscriptionLifecycle, strEnum from orchestrator.types import SubscriptionLifecycle, strEnum
from pydantic import Field from pydantic import Field
...@@ -15,6 +16,40 @@ class IptrunkType(strEnum): ...@@ -15,6 +16,40 @@ class IptrunkType(strEnum):
LEASED = "Leased" LEASED = "Leased"
T = TypeVar("T", covariant=True)
class IptrunkSides(UniqueConstrainedList[T]): # type: ignore
min_items = 2
max_items = 2
class IptrunkSideBlockInactive(
ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="IptrunkSideBlock"
):
iptrunk_side_node: RouterBlockInactive
iptrunk_side_ae_iface: Optional[str] = None
iptrunk_side_ae_geant_a_sid: Optional[str] = None
iptrunk_side_ae_members: list[str] = Field(default_factory=list)
iptrunk_side_ae_members_description: list[str] = Field(default_factory=list)
class IptrunkSideBlockProvisioning(IptrunkSideBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
iptrunk_side_node: RouterBlockProvisioning
iptrunk_side_ae_iface: Optional[str] = None
iptrunk_side_ae_geant_a_sid: Optional[str] = None
iptrunk_side_ae_members: list[str] = Field(default_factory=list)
iptrunk_side_ae_members_description: list[str] = Field(default_factory=list)
class IptrunkSideBlock(IptrunkSideBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
iptrunk_side_node: RouterBlock
iptrunk_side_ae_iface: Optional[str] = None
iptrunk_side_ae_geant_a_sid: Optional[str] = None
iptrunk_side_ae_members: list[str] = Field(default_factory=list)
iptrunk_side_ae_members_description: list[str] = Field(default_factory=list)
class IptrunkBlockInactive( class IptrunkBlockInactive(
ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="IptrunkBlock" ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="IptrunkBlock"
): ):
...@@ -29,17 +64,7 @@ class IptrunkBlockInactive( ...@@ -29,17 +64,7 @@ class IptrunkBlockInactive(
iptrunk_ipv4_network: Optional[ipaddress.IPv4Network] = None iptrunk_ipv4_network: Optional[ipaddress.IPv4Network] = None
iptrunk_ipv6_network: Optional[ipaddress.IPv6Network] = None iptrunk_ipv6_network: Optional[ipaddress.IPv6Network] = None
# #
iptrunk_sideA_node: RouterBlockInactive iptrunk_sides: IptrunkSides[IptrunkSideBlockInactive]
iptrunk_sideA_ae_iface: Optional[str] = None
iptrunk_sideA_ae_geant_a_sid: Optional[str] = None
iptrunk_sideA_ae_members: list[str] = Field(default_factory=list)
iptrunk_sideA_ae_members_description: list[str] = Field(default_factory=list)
#
iptrunk_sideB_node: RouterBlockInactive
iptrunk_sideB_ae_iface: Optional[str] = None
iptrunk_sideB_ae_geant_a_sid: Optional[str] = None
iptrunk_sideB_ae_members: list[str] = Field(default_factory=list)
iptrunk_sideB_ae_members_description: list[str] = Field(default_factory=list)
class IptrunkBlockProvisioning(IptrunkBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): class IptrunkBlockProvisioning(IptrunkBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
...@@ -54,17 +79,7 @@ class IptrunkBlockProvisioning(IptrunkBlockInactive, lifecycle=[SubscriptionLife ...@@ -54,17 +79,7 @@ class IptrunkBlockProvisioning(IptrunkBlockInactive, lifecycle=[SubscriptionLife
iptrunk_ipv4_network: Optional[ipaddress.IPv4Network] = None iptrunk_ipv4_network: Optional[ipaddress.IPv4Network] = None
iptrunk_ipv6_network: Optional[ipaddress.IPv6Network] = None iptrunk_ipv6_network: Optional[ipaddress.IPv6Network] = None
# #
iptrunk_sideA_node: RouterBlockProvisioning iptrunk_sides: IptrunkSides[IptrunkSideBlockProvisioning]
iptrunk_sideA_ae_iface: Optional[str] = None
iptrunk_sideA_ae_geant_a_sid: Optional[str] = None
iptrunk_sideA_ae_members: list[str] = Field(default_factory=list)
iptrunk_sideA_ae_members_description: list[str] = Field(default_factory=list)
#
iptrunk_sideB_node: RouterBlockProvisioning
iptrunk_sideB_ae_iface: Optional[str] = None
iptrunk_sideB_ae_geant_a_sid: Optional[str] = None
iptrunk_sideB_ae_members: list[str] = Field(default_factory=list)
iptrunk_sideB_ae_members_description: list[str] = Field(default_factory=list)
class IptrunkBlock(IptrunkBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class IptrunkBlock(IptrunkBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
...@@ -86,22 +101,4 @@ class IptrunkBlock(IptrunkBlockProvisioning, lifecycle=[SubscriptionLifecycle.AC ...@@ -86,22 +101,4 @@ class IptrunkBlock(IptrunkBlockProvisioning, lifecycle=[SubscriptionLifecycle.AC
"""The IPv4 network used for this trunk.""" """The IPv4 network used for this trunk."""
iptrunk_ipv6_network: ipaddress.IPv6Network iptrunk_ipv6_network: ipaddress.IPv6Network
"""The IPv6 network used for this trunk.""" """The IPv6 network used for this trunk."""
# iptrunk_sides: IptrunkSides[IptrunkSideBlock]
iptrunk_sideA_node: RouterBlock
"""The router that hosts the A side of the trunk."""
iptrunk_sideA_ae_iface: str
"""The name of the interface on which the trunk connects."""
iptrunk_sideA_ae_geant_a_sid: str
"""The service ID of the interface."""
iptrunk_sideA_ae_members: list[str] = Field(default_factory=list)
"""A list of interface members that make up the aggregated Ethernet interface."""
iptrunk_sideA_ae_members_description: list[str] = Field(default_factory=list)
"""The list of descriptions that describe the list of interface members."""
#
iptrunk_sideB_node: RouterBlock
"""The router that hosts the B side of the trunk. It possesses the same attributes as the A-side, including the
interfaces and its descriptions."""
iptrunk_sideB_ae_iface: str
iptrunk_sideB_ae_geant_a_sid: str
iptrunk_sideB_ae_members: list[str] = Field(default_factory=list)
iptrunk_sideB_ae_members_description: list[str] = Field(default_factory=list)
...@@ -19,12 +19,11 @@ from pydantic import validator ...@@ -19,12 +19,11 @@ from pydantic import validator
from gso import settings from gso import settings
from gso.products.product_types.iptrunk import Iptrunk, IptrunkProvisioning from gso.products.product_types.iptrunk import Iptrunk, IptrunkProvisioning
from gso.products.product_types.router import RouterProvisioning from gso.products.product_types.router import Router, RouterProvisioning
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
"""{class}`logging.Logger` instance."""
DEFAULT_LABEL = "Provisioning proxy is running. Please come back later for the results." DEFAULT_LABEL = "Provisioning proxy is running. Please come back later for the results."
"""The default label displayed when the provisioning proxy is running.""" """The default label displayed when the provisioning proxy is running, in case no custom label is provided."""
class CUDOperation(strEnum): class CUDOperation(strEnum):
...@@ -159,6 +158,52 @@ def deprovision_ip_trunk(subscription: Iptrunk, process_id: UUIDstr, dry_run: bo ...@@ -159,6 +158,52 @@ def deprovision_ip_trunk(subscription: Iptrunk, process_id: UUIDstr, dry_run: bo
_send_request("ip_trunk", parameters, process_id, CUDOperation.DELETE) _send_request("ip_trunk", parameters, process_id, CUDOperation.DELETE)
def migrate_ip_trunk(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
verb: str,
dry_run: bool = True,
) -> None:
"""Migrate an IP trunk service using {term}`LSO`.
:param subscription: The subscription object that's to be migrated.
:type subscription: {class}`Iptrunk`
:param new_node: The new node that is being migrated to
:type new_node: {class}`Router`
:param new_lag_interface: The name of the new aggregated Ethernet interface
:type new_lag_interface: str
:param new_lag_member_interfaces: The new list of interfaces that are part of the LAG
:type new_lag_member_interfaces: list[str]
:param replace_index: The index of the side that is going to be replaced as part of the existing trunk,
can be `0` or `1`.
:type replace_index: int
:param process_id: The related process ID, used for callback.
:type process_id: UUIDstr
:param verb: The verb that is passed to the executed playbook
:type verb: str
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`.
:type dry_run: bool
:rtype: None
"""
parameters = {
"subscription": json.loads(json_dumps(subscription)),
"new_side": {
"new_node": json.loads(json_dumps(new_node)),
"new_lag_interface": new_lag_interface,
"new_lag_member_interfaces": new_lag_member_interfaces,
"replace_index": replace_index,
},
"verb": verb,
"dry_run": dry_run,
}
_send_request("ip_trunk/migrate", parameters, process_id, CUDOperation.POST)
@inputstep("Await provisioning proxy results", assignee=Assignee("SYSTEM")) @inputstep("Await provisioning proxy results", assignee=Assignee("SYSTEM"))
def _await_pp_results(subscription: SubscriptionModel, label_text: str = DEFAULT_LABEL) -> FormGenerator: def _await_pp_results(subscription: SubscriptionModel, label_text: str = DEFAULT_LABEL) -> FormGenerator:
"""Input step that forces the workflow to go into a `SUSPENDED` state. """Input step that forces the workflow to go into a `SUSPENDED` state.
......
...@@ -30,13 +30,15 @@ ...@@ -30,13 +30,15 @@
"iptrunk_sideB_ae_geant_a_sid": "GÉANT A-SID", "iptrunk_sideB_ae_geant_a_sid": "GÉANT A-SID",
"iptrunk_sideB_ae_members": "Aggregated Ethernet member interface names", "iptrunk_sideB_ae_members": "Aggregated Ethernet member interface names",
"iptrunk_sideB_ae_members_descriptions": "Aggregated Ethernet member interface descriptions", "iptrunk_sideB_ae_members_descriptions": "Aggregated Ethernet member interface descriptions",
"migrate_to_different_site": "Migrating to a different Site",
"remove_configuration": "Remove configuration from the router", "remove_configuration": "Remove configuration from the router",
"clean_up_ipam": "Clean up related entries in IPAM" "clean_up_ipam": "Clean up related entries in IPAM"
} }
}, },
"workflow": { "workflow": {
"modify_isis_metric": "Modify the ISIS metric", "modify_isis_metric": "Modify the ISIS metric",
"modify_trunk_interface": "Modify IP Trunk interface", "modify_trunk_interface": "Modify IP Trunk interface",
"confirm_info": "Please verify this form looks correct." "migrate_iptrunk": "Migrate IP Trunk",
"confirm_info": "Please verify this form looks correct."
} }
} }
"""Initialisation class that imports all workflows into {term}`GSO`.""" """Initialisation class that imports all workflows into {term}`GSO`."""
from orchestrator.workflows import LazyWorkflowInstance from orchestrator.workflows import LazyWorkflowInstance
LazyWorkflowInstance("gso.workflows.router.create_router", "create_router")
LazyWorkflowInstance("gso.workflows.router.terminate_router", "terminate_router")
LazyWorkflowInstance("gso.workflows.iptrunk.create_iptrunk", "create_iptrunk") LazyWorkflowInstance("gso.workflows.iptrunk.create_iptrunk", "create_iptrunk")
LazyWorkflowInstance("gso.workflows.iptrunk.modify_isis_metric", "modify_isis_metric")
LazyWorkflowInstance("gso.workflows.iptrunk.modify_trunk_interface", "modify_trunk_interface") LazyWorkflowInstance("gso.workflows.iptrunk.modify_trunk_interface", "modify_trunk_interface")
LazyWorkflowInstance("gso.workflows.iptrunk.migrate_iptrunk", "migrate_iptrunk")
LazyWorkflowInstance("gso.workflows.iptrunk.terminate_iptrunk", "terminate_iptrunk") LazyWorkflowInstance("gso.workflows.iptrunk.terminate_iptrunk", "terminate_iptrunk")
LazyWorkflowInstance("gso.workflows.iptrunk.modify_isis_metric", "modify_isis_metric") LazyWorkflowInstance("gso.workflows.router.create_router", "create_router")
LazyWorkflowInstance("gso.workflows.router.terminate_router", "terminate_router")
LazyWorkflowInstance("gso.workflows.site.create_site", "create_site") LazyWorkflowInstance("gso.workflows.site.create_site", "create_site")
LazyWorkflowInstance("gso.workflows.tasks.import_site", "import_site") LazyWorkflowInstance("gso.workflows.tasks.import_site", "import_site")
LazyWorkflowInstance("gso.workflows.tasks.import_router", "import_router") LazyWorkflowInstance("gso.workflows.tasks.import_router", "import_router")
......
from logging import getLogger
from orchestrator import step
from orchestrator.types import State
from products import Iptrunk
logger = getLogger(__name__)
@step("Set ISIS metric to 9000")
def set_isis_to_9000(subscription: Iptrunk) -> State:
old_isis_metric = subscription.iptrunk.iptrunk_isis_metric
subscription.iptrunk.iptrunk_isis_metric = 90000
logger.warning("ISIS metric is only updated in the subscription, not in the real world.")
return {"subscription": subscription, "old_isis_metric": old_isis_metric}
@step("Restore ISIS metric to original value")
def restore_isis_metric(subscription: Iptrunk, old_isis_metric: int) -> State:
subscription.iptrunk.iptrunk_isis_metric = old_isis_metric
logger.warning("ISIS metric is only updated in the subscription, not in the real world.")
return {"subscription": subscription}
from orchestrator.db.models import ProductTable, SubscriptionTable
from orchestrator.forms import FormPage from orchestrator.forms import FormPage
from orchestrator.forms.validators import Choice, UniqueConstrainedList from orchestrator.forms.validators import Choice, UniqueConstrainedList
from orchestrator.targets import Target from orchestrator.targets import Target
...@@ -128,17 +129,17 @@ def initialize_subscription( ...@@ -128,17 +129,17 @@ def initialize_subscription(
subscription.iptrunk.iptrunk_isis_metric = 9000 subscription.iptrunk.iptrunk_isis_metric = 9000
subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links
subscription.iptrunk.iptrunk_sideA_node = Router.from_subscription(iptrunk_sideA_node_id).router subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node = Router.from_subscription(iptrunk_sideA_node_id).router
subscription.iptrunk.iptrunk_sideA_ae_iface = iptrunk_sideA_ae_iface subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface = iptrunk_sideA_ae_iface
subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid = iptrunk_sideA_ae_geant_a_sid subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid = iptrunk_sideA_ae_geant_a_sid
subscription.iptrunk.iptrunk_sideA_ae_members = iptrunk_sideA_ae_members subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members = iptrunk_sideA_ae_members
subscription.iptrunk.iptrunk_sideA_ae_members_description = iptrunk_sideA_ae_members_descriptions subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members_description = iptrunk_sideA_ae_members_descriptions
subscription.iptrunk.iptrunk_sideB_node = Router.from_subscription(iptrunk_sideB_node_id).router subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node = Router.from_subscription(iptrunk_sideB_node_id).router
subscription.iptrunk.iptrunk_sideB_ae_iface = iptrunk_sideB_ae_iface subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface = iptrunk_sideB_ae_iface
subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid = iptrunk_sideB_ae_geant_a_sid subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid = iptrunk_sideB_ae_geant_a_sid
subscription.iptrunk.iptrunk_sideB_ae_members = iptrunk_sideB_ae_members subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members = iptrunk_sideB_ae_members
subscription.iptrunk.iptrunk_sideB_ae_members_description = iptrunk_sideB_ae_members_descriptions subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members_description = iptrunk_sideB_ae_members_descriptions
subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}" subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}"
subscription = IptrunkProvisioning.from_other_lifecycle(subscription, SubscriptionLifecycle.PROVISIONING) subscription = IptrunkProvisioning.from_other_lifecycle(subscription, SubscriptionLifecycle.PROVISIONING)
...@@ -202,7 +203,7 @@ def check_ip_trunk_isis(subscription: IptrunkProvisioning, process_id: UUIDstr) ...@@ -202,7 +203,7 @@ def check_ip_trunk_isis(subscription: IptrunkProvisioning, process_id: UUIDstr)
return { return {
"subscription": subscription, "subscription": subscription,
"label_text": "Checking ISIS adjacencies, please refresh to get the results of the playbook.", "label_text": "Checking ISIS adjacency, please refresh to get the results of the playbook.",
} }
...@@ -226,26 +227,6 @@ def provision_ip_trunk_ldp_iface_real(subscription: IptrunkProvisioning, process ...@@ -226,26 +227,6 @@ def provision_ip_trunk_ldp_iface_real(subscription: IptrunkProvisioning, process
} }
@step("Provision IP trunk LLDP interface [DRY RUN]")
def provision_ip_trunk_lldp_iface_dry(subscription: IptrunkProvisioning, process_id: UUIDstr) -> State:
provisioning_proxy.provision_ip_trunk(subscription, process_id, "lldp_interface")
return {
"subscription": subscription,
"label_text": "[DRY RUN] Provisioning LLDP interface, please refresh to get the results of the playbook.",
}
@step("Provision IP trunk LLDP interface [FOR REAL]")
def provision_ip_trunk_lldp_iface_real(subscription: IptrunkProvisioning, process_id: UUIDstr) -> State:
provisioning_proxy.provision_ip_trunk(subscription, process_id, "lldp_interface", False)
return {
"subscription": subscription,
"label_text": "Provisioning LLDP interface, please refresh to get the results of the playbook.",
}
@workflow( @workflow(
"Create IP trunk", "Create IP trunk",
initial_input_form=wrap_create_initial_input_form(initial_input_form_generator), initial_input_form=wrap_create_initial_input_form(initial_input_form_generator),
...@@ -264,8 +245,6 @@ def create_iptrunk() -> StepList: ...@@ -264,8 +245,6 @@ def create_iptrunk() -> StepList:
>> pp_interaction(provision_ip_trunk_isis_iface_dry, 3) >> pp_interaction(provision_ip_trunk_isis_iface_dry, 3)
>> pp_interaction(provision_ip_trunk_isis_iface_real, 3) >> pp_interaction(provision_ip_trunk_isis_iface_real, 3)
>> pp_interaction(check_ip_trunk_isis, 2) >> pp_interaction(check_ip_trunk_isis, 2)
>> pp_interaction(provision_ip_trunk_lldp_iface_dry, 3)
>> pp_interaction(provision_ip_trunk_lldp_iface_real, 3)
>> set_status(SubscriptionLifecycle.ACTIVE) >> set_status(SubscriptionLifecycle.ACTIVE)
>> resync >> resync
>> done >> done
......
import re
from logging import getLogger
from typing import NoReturn, Optional
from orchestrator import step, workflow
from orchestrator.config.assignee import Assignee
from orchestrator.db import ProductTable, SubscriptionTable
from orchestrator.forms import FormPage
from orchestrator.forms.validators import Choice, Label, UniqueConstrainedList
from orchestrator.targets import Target
from orchestrator.types import FormGenerator, State, UUIDstr
from orchestrator.workflow import StepList, done, init, inputstep
from orchestrator.workflows.steps import resync, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form
from products import Iptrunk, Router
from pydantic import validator
from services import provisioning_proxy
from services.provisioning_proxy import pp_interaction
from workflows.iptrunk import restore_isis_metric, set_isis_to_9000
logger = getLogger(__name__)
def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
subscription = Iptrunk.from_subscription(subscription_id)
sides_dict = {
str(side.iptrunk_side_node.subscription.subscription_id): side.iptrunk_side_node.subscription.description
for side in subscription.iptrunk.iptrunk_sides
}
ReplacedSide = Choice(
"Select the side of the IP trunk to be replaced", zip(sides_dict.keys(), sides_dict.items()) # type: ignore
)
class OldSideIptrunkForm(FormPage):
class Config:
title = (
f"Subscription {subscription.iptrunk.geant_s_sid} from "
f"{subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn} to "
f"{subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn}"
)
replace_side: ReplacedSide # type: ignore
warning_label: Label = "Are we moving to a different Site?" # type: ignore
migrate_to_different_site: Optional[bool] = False
old_side_input = yield OldSideIptrunkForm
routers = {}
for router_id, router_description in (
SubscriptionTable.query.join(ProductTable)
.filter(
ProductTable.product_type == "Router",
SubscriptionTable.status == "active",
)
.with_entities(SubscriptionTable.subscription_id, SubscriptionTable.description)
.all()
):
if router_id not in [
subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.subscription.subscription_id,
subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.subscription.subscription_id,
]:
current_router = Router.from_subscription(router_id)
old_side_site_id = Router.from_subscription(old_side_input.replace_side).router.router_site
if (
not old_side_input.migrate_to_different_site
and current_router.router.router_site.subscription.subscription_id != old_side_site_id
):
continue
routers[str(router_id)] = router_description
NewRouterEnum = Choice("Select a new router", zip(routers.keys(), routers.items())) # type: ignore
class LagMemberList(UniqueConstrainedList[str]):
min_items = len(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members)
max_items = len(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members)
class NewSideIptrunkForm(FormPage):
class Config:
title = (
f"Subscription {subscription.iptrunk.geant_s_sid} from "
f"{subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn} to "
f"{subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn}"
)
new_node: NewRouterEnum # type: ignore
new_lag_interface: str
new_lag_member_interfaces: LagMemberList
@validator("new_lag_interface", allow_reuse=True, pre=True, always=True)
def lag_interface_proper_name(cls, new_lag_name: str) -> str | NoReturn:
nokia_lag_re = re.compile("^lag-\\d+$")
juniper_lag_re = re.compile("^ae\\d{1,2}$")
if nokia_lag_re.match(new_lag_name) or juniper_lag_re.match(new_lag_name):
return new_lag_name
raise ValueError("Invalid LAG name, please try again.")
new_side_input = yield NewSideIptrunkForm
def _find_updated_side_of_trunk(trunk: Iptrunk, new_side: str) -> int:
sides = trunk.iptrunk.iptrunk_sides
if str(sides[0].iptrunk_side_node.subscription.subscription_id) == new_side:
return 0
elif str(sides[1].iptrunk_side_node.subscription.subscription_id) == new_side: # noqa: RET505
return 1
raise ValueError("Invalid Router id provided to be replaced!")
replace_index = _find_updated_side_of_trunk(subscription, old_side_input.replace_side)
return old_side_input.dict() | new_side_input.dict() | {"replace_index": replace_index}
@inputstep("Wait for confirmation", assignee=Assignee.SYSTEM)
def confirm_continue() -> FormGenerator:
class ProvisioningResultPage(FormPage):
class Config:
title = "Please confirm before continuing"
info_label: Label = (
"ISIS metric has been set to 9000, please confirm to continue the workflow when ready." # type: ignore
)
yield ProvisioningResultPage
return {}
@step("[DRY RUN] Disable configuration on old router")
def disable_old_config_dry(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"VERB NEEDS TO BE UPDATED",
)
return {
"subscription": subscription,
"label_text": "[DRY RUN] Migrating old trunk interface, please refresh to get the results of the playbook.",
}
@step("[REAL] Disable configuration on old router")
def disable_old_config_real(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"VERB NEEDS TO BE UPDATED",
False,
)
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "Migrating old trunk interface, please refresh to get the results of the playbook.",
}
@step("[DRY RUN] Deploy configuration on new router")
def deploy_new_config_dry(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"VERB NEEDS TO BE UPDATED",
)
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "[DRY RUN] Deploying new trunk interface, please refresh to get the results of the playbook.",
}
@step("Deploy configuration on new router")
def deploy_new_config_real(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"VERB NEEDS TO BE UPDATED",
False,
)
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "Deploying new trunk interface, please refresh to get the results of the playbook.",
}
@step("Run interface checks")
def run_interface_checks(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"MIGRATION_INTERFACE_CHECK",
)
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "Running checks on the new trunk interface, please refresh to get the results of the playbook.",
}
@step("Deploy configuration on new router")
def deploy_new_isis(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"VERB NEEDS TO BE UPDATED",
False,
)
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "Updating new ISIS metric, please refresh to get the results of the playbook.",
}
@step("Check ISIS metric")
def check_isis(subscription: Iptrunk, process_id: UUIDstr) -> State:
provisioning_proxy.check_ip_trunk(subscription, process_id, "VERB NEEDS TO BE UPDATED")
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "Checking ISIS functionality, please refresh to get the results of the playbook.",
}
@step("[DRY RUN] Delete configuration on old router")
def delete_old_config_dry(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"VERB NEEDS TO BE UPDATED",
)
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "[DRY RUN] Removing configuration from old router,"
"please refresh to get the results of the playbook.",
}
@step("Delete configuration on old router")
def delete_old_config_real(
subscription: Iptrunk,
new_node: Router,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
replace_index: int,
process_id: UUIDstr,
) -> State:
provisioning_proxy.migrate_ip_trunk(
subscription,
new_node,
new_lag_interface,
new_lag_member_interfaces,
replace_index,
process_id,
"VERB NEEDS TO BE UPDATED",
False,
)
logger.warning("Playbook verb is not yet properly set.")
return {
"subscription": subscription,
"label_text": "Removing configuration from old router, please refresh to get the results of the playbook.",
}
@step("Update IPAM")
def update_ipam(subscription: Iptrunk) -> State:
pass
return {"subscription": subscription}
@step("Update subscription model")
def update_subscription_model(
subscription: Iptrunk,
replace_index: int,
new_node: UUIDstr,
new_lag_interface: str,
new_lag_member_interfaces: list[str],
) -> State:
subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_node = Router.from_subscription(new_node).router
subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_iface = new_lag_interface
subscription.iptrunk.iptrunk_sides[replace_index].iptrunk_side_ae_members = new_lag_member_interfaces
return {"subscription": subscription}
@workflow(
"Migrate an IP Trunk",
initial_input_form=wrap_modify_initial_input_form(initial_input_form_generator),
target=Target.MODIFY,
)
def migrate_iptrunk() -> StepList:
return (
init
>> store_process_subscription(Target.MODIFY)
>> unsync
>> set_isis_to_9000
>> confirm_continue
>> pp_interaction(disable_old_config_dry, 3)
>> pp_interaction(disable_old_config_real, 3)
>> pp_interaction(deploy_new_config_dry, 3)
>> pp_interaction(deploy_new_config_real, 3)
>> confirm_continue
>> pp_interaction(run_interface_checks, 3)
>> pp_interaction(deploy_new_isis, 3)
>> pp_interaction(check_isis, 3)
>> confirm_continue
>> restore_isis_metric
>> pp_interaction(delete_old_config_dry, 3)
>> pp_interaction(delete_old_config_real, 3)
>> update_ipam
>> update_subscription_model
>> resync
>> done
)
...@@ -37,13 +37,13 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: ...@@ -37,13 +37,13 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
class Config: class Config:
title = "Provide subscription details for side A of the trunk." title = "Provide subscription details for side A of the trunk."
iptrunk_sideA_node: str = ReadOnlyField(subscription.iptrunk.iptrunk_sideA_node.router_fqdn) iptrunk_sideA_node: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn)
iptrunk_sideA_ae_iface: str = ReadOnlyField(subscription.iptrunk.iptrunk_sideA_ae_iface) iptrunk_sideA_ae_iface: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[0].iptrunk_ae_iface)
iptrunk_sideA_ae_geant_a_sid: str = subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid iptrunk_sideA_ae_geant_a_sid: str = subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid
iptrunk_sideA_ae_members: AeMembersListA = subscription.iptrunk.iptrunk_sideA_ae_members # type: ignore iptrunk_sideA_ae_members: AeMembersListA = subscription.iptrunk.iptrunk_sideA_ae_members # type: ignore
iptrunk_sideA_ae_members_descriptions: AeMembersListA = ( iptrunk_sideA_ae_members_descriptions: AeMembersListA = subscription.iptrunk.iptrunk_sides[
subscription.iptrunk.iptrunk_sideA_ae_members_description # type: ignore 0
) ].iptrunk_side_ae_members_description
user_input_side_a = yield ModifyIptrunkSideAForm user_input_side_a = yield ModifyIptrunkSideAForm
...@@ -55,13 +55,13 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: ...@@ -55,13 +55,13 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
class Config: class Config:
title = "Provide subscription details for side B of the trunk." title = "Provide subscription details for side B of the trunk."
iptrunk_sideB_node: str = ReadOnlyField(subscription.iptrunk.iptrunk_sideB_node.router_fqdn) iptrunk_sideB_node: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn)
iptrunk_sideB_ae_iface: str = ReadOnlyField(subscription.iptrunk.iptrunk_sideB_ae_iface) iptrunk_sideB_ae_iface: str = ReadOnlyField(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface)
iptrunk_sideB_ae_geant_a_sid: str = subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid iptrunk_sideB_ae_geant_a_sid: str = subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid
iptrunk_sideB_ae_members: AeMembersListB = subscription.iptrunk.iptrunk_sideB_ae_members # type: ignore iptrunk_sideB_ae_members: AeMembersListB = subscription.iptrunk.iptrunk_sideB_ae_members # type: ignore
iptrunk_sideB_ae_members_descriptions: AeMembersListB = ( iptrunk_sideB_ae_members_descriptions: AeMembersListB = subscription.iptrunk.iptrunk_sides[
subscription.iptrunk.iptrunk_sideB_ae_members_description # type: ignore 1
) ].iptrunk_side_ae_members_description
user_input_side_b = yield ModifyIptrunkSideBForm user_input_side_b = yield ModifyIptrunkSideBForm
...@@ -89,13 +89,13 @@ def modify_iptrunk_subscription( ...@@ -89,13 +89,13 @@ def modify_iptrunk_subscription(
subscription.iptrunk.iptrunk_speed = iptrunk_speed subscription.iptrunk.iptrunk_speed = iptrunk_speed
subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links
subscription.iptrunk.iptrunk_sideA_ae_geant_a_sid = iptrunk_sideA_ae_geant_a_sid subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid = iptrunk_sideA_ae_geant_a_sid
subscription.iptrunk.iptrunk_sideA_ae_members = iptrunk_sideA_ae_members subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members = iptrunk_sideA_ae_members
subscription.iptrunk.iptrunk_sideA_ae_members_description = iptrunk_sideA_ae_members_descriptions subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members_description = iptrunk_sideA_ae_members_descriptions
subscription.iptrunk.iptrunk_sideB_ae_geant_a_sid = iptrunk_sideB_ae_geant_a_sid subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid = iptrunk_sideB_ae_geant_a_sid
subscription.iptrunk.iptrunk_sideB_ae_members = iptrunk_sideB_ae_members subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members = iptrunk_sideB_ae_members
subscription.iptrunk.iptrunk_sideB_ae_members_description = iptrunk_sideB_ae_members_descriptions subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members_description = iptrunk_sideB_ae_members_descriptions
subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}" subscription.description = f"IP trunk, geant_s_sid:{geant_s_sid}"
......
...@@ -7,6 +7,7 @@ from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUID ...@@ -7,6 +7,7 @@ from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUID
from orchestrator.workflow import StepList, conditional, done, init, step, workflow from orchestrator.workflow import StepList, conditional, done, init, step, workflow
from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync
from orchestrator.workflows.utils import wrap_modify_initial_input_form from orchestrator.workflows.utils import wrap_modify_initial_input_form
from workflows.iptrunk import set_isis_to_9000
from gso.products.product_types.iptrunk import Iptrunk from gso.products.product_types.iptrunk import Iptrunk
from gso.services import ipam, provisioning_proxy from gso.services import ipam, provisioning_proxy
...@@ -27,22 +28,13 @@ def initial_input_form_generator() -> FormGenerator: ...@@ -27,22 +28,13 @@ def initial_input_form_generator() -> FormGenerator:
return user_input.dict() return user_input.dict()
@step("Set iptrunk ISIS metric to 9000")
def update_isis_metric(subscription: Iptrunk) -> State:
subscription.iptrunk.iptrunk_isis_metric = 9000
return {"subscription": subscription}
@step("Drain traffic from trunk") @step("Drain traffic from trunk")
def drain_traffic_from_ip_trunk(subscription: Iptrunk, process_id: UUIDstr) -> State: def drain_traffic_from_ip_trunk(subscription: Iptrunk, process_id: UUIDstr) -> State:
provisioning_proxy.provision_ip_trunk(subscription, process_id, "isis_interface", False) provisioning_proxy.provision_ip_trunk(subscription, process_id, "isis_interface", False)
return { return {
"subscription": subscription, "subscription": subscription,
"label_text": "This is setting the ISIS metric of the trunk to 9000" "label_text": "This is setting the ISIS metric of the trunk to 9000. Press refresh to get the results."
"trunk. " "When traffic is drained, confirm to continue.",
"Press refresh to get the results\n"
"When traffic is drained, confirm to continue",
} }
...@@ -94,7 +86,7 @@ def terminate_iptrunk() -> StepList: ...@@ -94,7 +86,7 @@ def terminate_iptrunk() -> StepList:
run_ipam_steps = conditional(lambda state: state.get("clean_up_ipam", True)) run_ipam_steps = conditional(lambda state: state.get("clean_up_ipam", True))
config_steps = ( config_steps = (
StepList([update_isis_metric]) StepList([set_isis_to_9000])
>> pp_interaction(drain_traffic_from_ip_trunk, 3) >> pp_interaction(drain_traffic_from_ip_trunk, 3)
>> pp_interaction(deprovision_ip_trunk_dry, 3) >> pp_interaction(deprovision_ip_trunk_dry, 3)
>> pp_interaction(deprovision_ip_trunk_real, 3) >> pp_interaction(deprovision_ip_trunk_real, 3)
......