From 7660911a849ffa8fcbccb993d378d35191618ccf Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Wed, 4 Dec 2024 15:40:47 +0100
Subject: [PATCH 01/20] Add migration for removing additional products.

---
 ...4cc835c615fc_remove_additional_products.py | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 gso/migrations/versions/2024-12-04_4cc835c615fc_remove_additional_products.py

diff --git a/gso/migrations/versions/2024-12-04_4cc835c615fc_remove_additional_products.py b/gso/migrations/versions/2024-12-04_4cc835c615fc_remove_additional_products.py
new file mode 100644
index 00000000..969e1e0f
--- /dev/null
+++ b/gso/migrations/versions/2024-12-04_4cc835c615fc_remove_additional_products.py
@@ -0,0 +1,33 @@
+"""remove additional products.
+
+Revision ID: 4cc835c615fc
+Revises: 28c1723c6a00
+Create Date: 2024-12-04 14:54:22.167158
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = '4cc835c615fc'
+down_revision = '28c1723c6a00'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+    conn = op.get_bind()
+    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 ('IAS', 'Imported IAS', 'Imported GÉANT IP', 'GÉANT IP')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('NRENL3CoreServiceBlock'))
+    """))
+    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 ('NRENAccessPort', 'NRENL3CoreServiceBlock'))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM product_blocks WHERE product_blocks.name IN ('NRENAccessPort', 'NRENL3CoreServiceBlock')
+    """))
+
+
+def downgrade() -> None:
+    conn = op.get_bind()
+
-- 
GitLab


From 486239cc39ea4dacac654d5b187159967f8157ef Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Wed, 4 Dec 2024 15:49:18 +0100
Subject: [PATCH 02/20] Rename Service IDs to GS or GA id.

---
 ...ename_iptrunk_and_iptrunk_side_sid_and_.py | 35 ++++++++++++++
 ...5c_rename_edgeport_and_sbp_gs_and_ga_id.py | 47 +++++++++++++++++++
 gso/products/product_blocks/edge_port.py      |  6 +--
 gso/products/product_blocks/iptrunk.py        | 12 ++---
 .../product_blocks/service_binding_port.py    |  6 +--
 5 files changed, 94 insertions(+), 12 deletions(-)
 create mode 100644 gso/migrations/versions/2024-12-04_e358efe9ab03_rename_iptrunk_and_iptrunk_side_sid_and_.py
 create mode 100644 gso/migrations/versions/2024-12-04_e36b3bd8a45c_rename_edgeport_and_sbp_gs_and_ga_id.py

diff --git a/gso/migrations/versions/2024-12-04_e358efe9ab03_rename_iptrunk_and_iptrunk_side_sid_and_.py b/gso/migrations/versions/2024-12-04_e358efe9ab03_rename_iptrunk_and_iptrunk_side_sid_and_.py
new file mode 100644
index 00000000..63bc63a7
--- /dev/null
+++ b/gso/migrations/versions/2024-12-04_e358efe9ab03_rename_iptrunk_and_iptrunk_side_sid_and_.py
@@ -0,0 +1,35 @@
+"""Rename iptrunk and iptrunk side sid and gid.
+
+Revision ID: e358efe9ab03
+Revises: 4cc835c615fc
+Create Date: 2024-12-04 15:05:46.356709
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = 'e358efe9ab03'
+down_revision = '4cc835c615fc'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='ga_id' WHERE resource_types.resource_type = 'iptrunk_side_ae_geant_a_sid'
+    """))
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='gs_id' WHERE resource_types.resource_type = 'geant_s_sid'
+    """))
+
+
+def downgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='iptrunk_side_ae_geant_a_sid' WHERE resource_types.resource_type = 'ga_id'
+    """))
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='geant_s_sid' WHERE resource_types.resource_type = 'gs_id'
+    """))
diff --git a/gso/migrations/versions/2024-12-04_e36b3bd8a45c_rename_edgeport_and_sbp_gs_and_ga_id.py b/gso/migrations/versions/2024-12-04_e36b3bd8a45c_rename_edgeport_and_sbp_gs_and_ga_id.py
new file mode 100644
index 00000000..180c97ee
--- /dev/null
+++ b/gso/migrations/versions/2024-12-04_e36b3bd8a45c_rename_edgeport_and_sbp_gs_and_ga_id.py
@@ -0,0 +1,47 @@
+"""Rename edgeport and sbp gs and ga id.
+
+Revision ID: e36b3bd8a45c
+Revises: e358efe9ab03
+Create Date: 2024-12-04 15:08:30.512126
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = 'e36b3bd8a45c'
+down_revision = 'e358efe9ab03'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+UPDATE product_block_resource_types SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ga_id')) WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('EdgePortBlock')) AND product_block_resource_types.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_ga_id'))
+    """))
+    conn.execute(sa.text("""
+UPDATE product_block_resource_types SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('gs_id')) WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('ServiceBindingPort')) AND product_block_resource_types.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_sid'))
+    """))
+    conn.execute(sa.text("""
+UPDATE subscription_instance_values SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ga_id')) WHERE subscription_instance_values.subscription_instance_id IN (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 ('EdgePortBlock'))) AND subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_ga_id'))
+    """))
+    conn.execute(sa.text("""
+UPDATE subscription_instance_values SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('gs_id')) WHERE subscription_instance_values.subscription_instance_id IN (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 ('ServiceBindingPort'))) AND subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_sid'))
+    """))
+
+
+def downgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+UPDATE product_block_resource_types SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_ga_id')) WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('EdgePortBlock')) AND product_block_resource_types.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ga_id'))
+    """))
+    conn.execute(sa.text("""
+UPDATE product_block_resource_types SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_sid')) WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('ServiceBindingPort')) AND product_block_resource_types.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('gs_id'))
+    """))
+    conn.execute(sa.text("""
+UPDATE subscription_instance_values SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_ga_id')) WHERE subscription_instance_values.subscription_instance_id IN (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 ('EdgePortBlock'))) AND subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ga_id'))
+    """))
+    conn.execute(sa.text("""
+UPDATE subscription_instance_values SET resource_type_id=(SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('geant_sid')) WHERE subscription_instance_values.subscription_instance_id IN (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 ('ServiceBindingPort'))) AND subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('gs_id'))
+    """))
diff --git a/gso/products/product_blocks/edge_port.py b/gso/products/product_blocks/edge_port.py
index b3400e0f..8f5c4bb1 100644
--- a/gso/products/product_blocks/edge_port.py
+++ b/gso/products/product_blocks/edge_port.py
@@ -72,7 +72,7 @@ class EdgePortBlockInactive(
     minimum_links: int | None = None
     edge_port_type: EdgePortType | None = None
     ignore_if_down: bool = False
-    geant_ga_id: str | None = None
+    ga_id: str | None = None
     edge_port_ae_members: LAGMemberList[EdgePortAEMemberBlockInactive]
 
 
@@ -89,7 +89,7 @@ class EdgePortBlockProvisioning(EdgePortBlockInactive, lifecycle=[SubscriptionLi
     minimum_links: int | None = None
     edge_port_type: EdgePortType
     ignore_if_down: bool = False
-    geant_ga_id: str | None = None
+    ga_id: str | None = None
     edge_port_ae_members: LAGMemberList[EdgePortAEMemberBlockProvisioning]  # type: ignore[assignment]
 
 
@@ -117,6 +117,6 @@ class EdgePortBlock(EdgePortBlockProvisioning, lifecycle=[SubscriptionLifecycle.
     #: If set to True, the edge port will be ignored if it is down.
     ignore_if_down: bool = False
     #: The GEANT GA ID associated with this edge port, if any.
-    geant_ga_id: str | None = None
+    ga_id: str | None = None
     #: A list of LAG members associated with this edge port.
     edge_port_ae_members: LAGMemberList[EdgePortAEMemberBlock]  # type: ignore[assignment]
diff --git a/gso/products/product_blocks/iptrunk.py b/gso/products/product_blocks/iptrunk.py
index e68911dd..9ffaa788 100644
--- a/gso/products/product_blocks/iptrunk.py
+++ b/gso/products/product_blocks/iptrunk.py
@@ -67,7 +67,7 @@ class IptrunkSideBlockInactive(
 
     iptrunk_side_node: RouterBlockInactive
     iptrunk_side_ae_iface: str | None = None
-    iptrunk_side_ae_geant_a_sid: str | None = None
+    ga_id: str | None = None
     iptrunk_side_ae_members: LAGMemberList[IptrunkInterfaceBlockInactive]
 
 
@@ -76,7 +76,7 @@ class IptrunkSideBlockProvisioning(IptrunkSideBlockInactive, lifecycle=[Subscrip
 
     iptrunk_side_node: RouterBlockProvisioning
     iptrunk_side_ae_iface: str
-    iptrunk_side_ae_geant_a_sid: str | None = None
+    ga_id: str | None = None
     iptrunk_side_ae_members: LAGMemberList[IptrunkInterfaceBlockProvisioning]  # type: ignore[assignment]
 
 
@@ -85,7 +85,7 @@ class IptrunkSideBlock(IptrunkSideBlockProvisioning, lifecycle=[SubscriptionLife
 
     iptrunk_side_node: RouterBlock
     iptrunk_side_ae_iface: str
-    iptrunk_side_ae_geant_a_sid: str | None = None
+    ga_id: str | None = None
     iptrunk_side_ae_members: LAGMemberList[IptrunkInterfaceBlock]  # type: ignore[assignment]
 
 
@@ -96,7 +96,7 @@ class IptrunkBlockInactive(
 ):
     """A trunk that's currently inactive, see ``IptrunkBlock``."""
 
-    geant_s_sid: str | None = None
+    gs_id: str | None = None
     iptrunk_description: str | None = None
     iptrunk_type: IptrunkType | None = None
     iptrunk_speed: PhysicalPortCapacity | None = None
@@ -110,7 +110,7 @@ class IptrunkBlockInactive(
 class IptrunkBlockProvisioning(IptrunkBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
     """A trunk that's currently being provisioned, see ``IptrunkBlock``."""
 
-    geant_s_sid: str | None = None
+    gs_id: str | None = None
     iptrunk_description: str | None = None
     iptrunk_type: IptrunkType | None = None
     iptrunk_speed: PhysicalPortCapacity | None = None
@@ -125,7 +125,7 @@ class IptrunkBlock(IptrunkBlockProvisioning, lifecycle=[SubscriptionLifecycle.AC
     """A trunk that's currently deployed in the network."""
 
     #:  GÉANT service ID associated with this trunk.
-    geant_s_sid: str | None = None
+    gs_id: str | None = None
     #:  A human-readable description of this trunk.
     iptrunk_description: str | None = None
     #:  The type of trunk, can be either dark fibre or leased capacity.
diff --git a/gso/products/product_blocks/service_binding_port.py b/gso/products/product_blocks/service_binding_port.py
index 6fd7467c..5f10b33c 100644
--- a/gso/products/product_blocks/service_binding_port.py
+++ b/gso/products/product_blocks/service_binding_port.py
@@ -64,7 +64,7 @@ class ServiceBindingPortInactive(
     ipv6_address: IPv6AddressType | None = None
     ipv6_mask: IPV6Netmask | None = None
     custom_firewall_filters: bool | None = None
-    geant_sid: str | None = None
+    gs_id: str | None = None
     bgp_session_list: list[BGPSessionInactive] = Field(default_factory=list)
     edge_port: EdgePortBlockInactive | None = None
     v4_bfd_settings: BFDSettingsInactive
@@ -82,7 +82,7 @@ class ServiceBindingPortProvisioning(ServiceBindingPortInactive, lifecycle=[Subs
     ipv6_address: IPv6AddressType | None = None
     ipv6_mask: IPV6Netmask | None = None
     custom_firewall_filters: bool
-    geant_sid: str
+    gs_id: str
     bgp_session_list: list[BGPSessionProvisioning]  # type: ignore[assignment]
     edge_port: EdgePortBlockProvisioning
     v4_bfd_settings: BFDSettingsProvisioning
@@ -109,7 +109,7 @@ class ServiceBindingPort(ServiceBindingPortProvisioning, lifecycle=[Subscription
     #: Any custom firewall filters that the partner may require.
     custom_firewall_filters: bool
     #: The GÉANT service ID of this binding port.
-    geant_sid: str
+    gs_id: str
     #: The BGP sessions associated with this service binding port.
     bgp_session_list: list[BGPSession]  # type: ignore[assignment]
     #: The Edge Port on which this SBP resides.
-- 
GitLab


From 72e450c8c948c629ee56720bb2190f25132fe399 Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Wed, 4 Dec 2024 15:50:01 +0100
Subject: [PATCH 03/20] Rename IPtrunk geant_s_id to gs_id in the entire
 project.

---
 gso/api/v1/network.py                         |  4 ++--
 gso/cli/imports.py                            |  4 ++--
 gso/utils/workflow_steps.py                   |  2 +-
 .../iptrunk/create_imported_iptrunk.py        |  8 +++----
 gso/workflows/iptrunk/create_iptrunk.py       | 20 ++++++++---------
 gso/workflows/iptrunk/migrate_iptrunk.py      | 22 +++++++++----------
 gso/workflows/iptrunk/modify_isis_metric.py   |  4 ++--
 .../iptrunk/modify_trunk_interface.py         | 12 +++++-----
 gso/workflows/iptrunk/terminate_iptrunk.py    |  4 ++--
 test/fixtures/iptrunk_fixtures.py             |  6 ++---
 .../iptrunk/test_create_imported_iptrunk.py   |  2 +-
 test/workflows/iptrunk/test_create_iptrunk.py |  4 ++--
 .../iptrunk/test_modify_trunk_interface.py    |  8 +++----
 13 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/gso/api/v1/network.py b/gso/api/v1/network.py
index e4a19de9..81a209b7 100644
--- a/gso/api/v1/network.py
+++ b/gso/api/v1/network.py
@@ -64,7 +64,7 @@ class IptrunkBlock(OrchestratorBaseModel):
     iptrunk_capacity: str
     iptrunk_isis_metric: int
     iptrunk_sides: list[IptrunkSideBlock]
-    geant_s_sid: str
+    gs_id: str
 
 
 class IptrunkSchema(OrchestratorBaseModel):
@@ -109,7 +109,7 @@ def network_topology() -> NetworkTopologyDomainModelSchema:
                 "iptrunk_capacity": _calculate_iptrunk_capacity(
                     extended_model["iptrunk"]["iptrunk_sides"], extended_model["iptrunk"]["iptrunk_speed"]
                 ),
-                "geant_s_sid": extended_model["iptrunk"]["geant_s_sid"],
+                "gs_id": extended_model["iptrunk"]["gs_id"],
                 "iptrunk_sides": [
                     {
                         "subscription_instance_id": side["subscription_instance_id"],
diff --git a/gso/cli/imports.py b/gso/cli/imports.py
index 14a45ad0..9903d186 100644
--- a/gso/cli/imports.py
+++ b/gso/cli/imports.py
@@ -116,7 +116,7 @@ class IptrunkImportModel(BaseModel):
     """Required fields for importing an existing ``gso.products.product_types.iptrunk``."""
 
     partner: str
-    geant_s_sid: str | None
+    gs_id: str | None
     iptrunk_type: IptrunkType
     iptrunk_description: str | None = None
     iptrunk_speed: PhysicalPortCapacity
@@ -592,7 +592,7 @@ def import_iptrunks(filepath: str = common_filepath_option) -> None:
         try:
             initial_data = IptrunkImportModel(
                 partner="GEANT",
-                geant_s_sid=trunk["id"],
+                gs_id=trunk["id"],
                 iptrunk_type=trunk["config"]["common"]["type"],
                 iptrunk_description=trunk["config"]["common"].get("description", ""),
                 iptrunk_speed=trunk["config"]["common"]["link_speed"],
diff --git a/gso/utils/workflow_steps.py b/gso/utils/workflow_steps.py
index 721e1845..0250eb8c 100644
--- a/gso/utils/workflow_steps.py
+++ b/gso/utils/workflow_steps.py
@@ -318,7 +318,7 @@ def set_isis_to_max(subscription: Iptrunk, process_id: UUIDstr, tt_number: str)
         "verb": "deploy",
         "config_object": "isis_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
diff --git a/gso/workflows/iptrunk/create_imported_iptrunk.py b/gso/workflows/iptrunk/create_imported_iptrunk.py
index 5cf9c5f8..77774049 100644
--- a/gso/workflows/iptrunk/create_imported_iptrunk.py
+++ b/gso/workflows/iptrunk/create_imported_iptrunk.py
@@ -30,7 +30,7 @@ def initial_input_form_generator() -> FormGenerator:
         model_config = ConfigDict(title="Import Iptrunk")
 
         partner: str
-        geant_s_sid: str | None = None
+        gs_id: str | None = None
         iptrunk_description: str | None = None
         iptrunk_type: IptrunkType
         iptrunk_speed: PhysicalPortCapacity
@@ -71,7 +71,7 @@ def create_subscription(partner: str) -> State:
 @step("Initialize subscription")
 def initialize_subscription(
     subscription: ImportedIptrunkInactive,
-    geant_s_sid: str | None,
+    gs_id: str | None,
     iptrunk_type: IptrunkType,
     iptrunk_description: str,
     iptrunk_speed: PhysicalPortCapacity,
@@ -87,7 +87,7 @@ def initialize_subscription(
     side_b_ae_members: LAGMemberList,
 ) -> State:
     """Take all input from the user, and store it in the database."""
-    subscription.iptrunk.geant_s_sid = geant_s_sid
+    subscription.iptrunk.gs_id = gs_id
     subscription.iptrunk.iptrunk_description = iptrunk_description
     subscription.iptrunk.iptrunk_type = iptrunk_type
     subscription.iptrunk.iptrunk_speed = iptrunk_speed
@@ -113,7 +113,7 @@ def initialize_subscription(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{geant_s_sid}"
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{gs_id}"
     return {"subscription": subscription}
 
 
diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index f8b54c61..c786f847 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -86,7 +86,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
 
         tt_number: TTNumber
         partner: ReadOnlyField("GEANT", default_type=str)  # type: ignore[valid-type]
-        geant_s_sid: str | None = None
+        gs_id: str | None = None
         iptrunk_description: str | None = None
         iptrunk_type: IptrunkType
         iptrunk_speed: PhysicalPortCapacity
@@ -196,7 +196,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
     )
     summary_form_data = input_forms_data | {"side_a_node": router_a_fqdn, "side_b_node": router_b_fqdn}
     summary_fields = [
-        "geant_s_sid",
+        "gs_id",
         "iptrunk_type",
         "iptrunk_speed",
         "iptrunk_description",
@@ -322,7 +322,7 @@ def ping_all_hosts_v6(new_ipv6_network: str) -> State:
 @step("Initialize subscription")
 def initialize_subscription(
     subscription: IptrunkInactive,
-    geant_s_sid: str | None,
+    gs_id: str | None,
     iptrunk_type: IptrunkType,
     iptrunk_description: str | None,
     iptrunk_speed: PhysicalPortCapacity,
@@ -340,7 +340,7 @@ def initialize_subscription(
     oss_params = load_oss_params()
     side_a = Router.from_subscription(side_a_node_id).router
     side_b = Router.from_subscription(side_b_node_id).router
-    subscription.iptrunk.geant_s_sid = geant_s_sid
+    subscription.iptrunk.gs_id = gs_id
     subscription.iptrunk.iptrunk_description = iptrunk_description
     subscription.iptrunk.iptrunk_type = iptrunk_type
     subscription.iptrunk.iptrunk_speed = iptrunk_speed
@@ -363,7 +363,7 @@ def initialize_subscription(
             IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member),
         )
     side_names = sorted([side_a.router_site.site_name, side_b.router_site.site_name])
-    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{geant_s_sid}"
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{gs_id}"
 
     return {"subscription": subscription}
 
@@ -377,7 +377,7 @@ def provision_ip_trunk_iface_dry(subscription: IptrunkInactive, process_id: UUID
         "verb": "deploy",
         "config_object": "trunk_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -403,7 +403,7 @@ def provision_ip_trunk_iface_real(subscription: IptrunkInactive, process_id: UUI
         "verb": "deploy",
         "config_object": "trunk_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -441,7 +441,7 @@ def provision_ip_trunk_isis_iface_dry(subscription: IptrunkInactive, process_id:
         "verb": "deploy",
         "config_object": "isis_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -467,7 +467,7 @@ def provision_ip_trunk_isis_iface_real(subscription: IptrunkInactive, process_id
         "verb": "deploy",
         "config_object": "isis_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -574,7 +574,7 @@ def create_new_sharepoint_checklist(subscription: IptrunkProvisioning, tt_number
     new_list_item_url = SharePointClient().add_list_item(
         list_name="ip_trunk",
         fields={
-            "Title": f"{subscription.description} - {subscription.iptrunk.geant_s_sid}",
+            "Title": f"{subscription.description} - {subscription.iptrunk.gs_id}",
             "TT_NUMBER": tt_number,
             "GAP_PROCESS_URL": f"{load_oss_params().GENERAL.public_hostname}/workflows/{process_id}",
             "ACTIVITY_TYPE": "Creation",
diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py
index 5684dd2d..e0a42d19 100644
--- a/gso/workflows/iptrunk/migrate_iptrunk.py
+++ b/gso/workflows/iptrunk/migrate_iptrunk.py
@@ -50,7 +50,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
     """Gather input from the operator on the new router that the IP trunk should connect to."""
     subscription = Iptrunk.from_subscription(subscription_id)
     form_title = (
-        f"Subscription {subscription.iptrunk.geant_s_sid} "
+        f"Subscription {subscription.iptrunk.gs_id} "
         f" from {subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn}"
         f" to {subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn}"
     )
@@ -298,7 +298,7 @@ def disable_old_config_dry(
         "config_object": "deactivate",
         "dry_run": True,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Deploy config for {subscription.iptrunk.geant_s_sid}",
+        f"- Deploy config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -337,7 +337,7 @@ def disable_old_config_real(
         "config_object": "deactivate",
         "dry_run": False,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Deploy config for {subscription.iptrunk.geant_s_sid}",
+        f"- Deploy config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -376,7 +376,7 @@ def deploy_new_config_dry(
         "config_object": "trunk_interface",
         "dry_run": True,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Deploy config for {subscription.iptrunk.geant_s_sid}",
+        f"- Deploy config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -415,7 +415,7 @@ def deploy_new_config_real(
         "config_object": "trunk_interface",
         "dry_run": False,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Deploy config for {subscription.iptrunk.geant_s_sid}",
+        f"- Deploy config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -564,7 +564,7 @@ def deploy_new_isis(
         "config_object": "isis_interface",
         "dry_run": False,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Deploy config for {subscription.iptrunk.geant_s_sid}",
+        f"- Deploy config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -629,7 +629,7 @@ def restore_isis_metric(
         "verb": "deploy",
         "config_object": "isis_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -668,7 +668,7 @@ def delete_old_config_dry(
         "config_object": "delete",
         "dry_run": True,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Deploy config for {subscription.iptrunk.geant_s_sid}",
+        f"- Deploy config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -707,7 +707,7 @@ def delete_old_config_real(
         "config_object": "delete",
         "dry_run": False,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Deploy config for {subscription.iptrunk.geant_s_sid}",
+        f"- Deploy config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -770,7 +770,7 @@ def update_subscription_model(
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
     subscription.description = (
-        f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{subscription.iptrunk.geant_s_sid}"
+        f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{subscription.iptrunk.gs_id}"
     )
 
     return {"subscription": subscription}
@@ -816,7 +816,7 @@ def create_new_sharepoint_checklist(subscription: Iptrunk, tt_number: str, proce
     new_list_item_url = SharePointClient().add_list_item(
         list_name="ip_trunk",
         fields={
-            "Title": f"{subscription.description} - {subscription.iptrunk.geant_s_sid}",
+            "Title": f"{subscription.description} - {subscription.iptrunk.gs_id}",
             "TT_NUMBER": tt_number,
             "GAP_PROCESS_URL": f"{load_oss_params().GENERAL.public_hostname}/workflows/{process_id}",
             "ACTIVITY_TYPE": "Migration",
diff --git a/gso/workflows/iptrunk/modify_isis_metric.py b/gso/workflows/iptrunk/modify_isis_metric.py
index 61d2f090..80d97531 100644
--- a/gso/workflows/iptrunk/modify_isis_metric.py
+++ b/gso/workflows/iptrunk/modify_isis_metric.py
@@ -53,7 +53,7 @@ def provision_ip_trunk_isis_iface_dry(subscription: Iptrunk, process_id: UUIDstr
         "verb": "deploy",
         "config_object": "isis_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -79,7 +79,7 @@ def provision_ip_trunk_isis_iface_real(subscription: Iptrunk, process_id: UUIDst
         "verb": "deploy",
         "config_object": "isis_interface",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py
index 9c1be5cd..723a3246 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -86,7 +86,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
 
     class ModifyIptrunkForm(FormPage):
         tt_number: TTNumber
-        geant_s_sid: str | None = subscription.iptrunk.geant_s_sid
+        gs_id: str | None = subscription.iptrunk.gs_id
         iptrunk_description: str | None = subscription.iptrunk.iptrunk_description
         iptrunk_type: IptrunkType = subscription.iptrunk.iptrunk_type
         warning_label: Label = (
@@ -254,7 +254,7 @@ def update_side_members(subscription: Iptrunk, side_index: int, new_members: lis
 @step("Update subscription")
 def modify_iptrunk_subscription(
     subscription: Iptrunk,
-    geant_s_sid: str | None,
+    gs_id: str | None,
     iptrunk_type: IptrunkType,
     iptrunk_description: str | None,
     iptrunk_speed: PhysicalPortCapacity,
@@ -287,7 +287,7 @@ def modify_iptrunk_subscription(
             if ae_member["interface_name"] not in [m["interface_name"] for m in current_members]
         ])
     # Update the subscription
-    subscription.iptrunk.geant_s_sid = geant_s_sid
+    subscription.iptrunk.gs_id = gs_id
     subscription.iptrunk.iptrunk_description = iptrunk_description
     subscription.iptrunk.iptrunk_type = iptrunk_type
     subscription.iptrunk.iptrunk_speed = iptrunk_speed
@@ -302,7 +302,7 @@ def modify_iptrunk_subscription(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{geant_s_sid}"
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{gs_id}"
 
     return {
         "subscription": subscription,
@@ -323,7 +323,7 @@ def provision_ip_trunk_iface_dry(
         "config_object": "trunk_interface",
         "removed_ae_members": removed_ae_members,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -352,7 +352,7 @@ def provision_ip_trunk_iface_real(
         "config_object": "trunk_interface",
         "removed_ae_members": removed_ae_members,
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy config for "
-        f"{subscription.iptrunk.geant_s_sid}",
+        f"{subscription.iptrunk.gs_id}",
     }
 
     return {
diff --git a/gso/workflows/iptrunk/terminate_iptrunk.py b/gso/workflows/iptrunk/terminate_iptrunk.py
index d008ad88..24cb4271 100644
--- a/gso/workflows/iptrunk/terminate_iptrunk.py
+++ b/gso/workflows/iptrunk/terminate_iptrunk.py
@@ -70,7 +70,7 @@ def deprovision_ip_trunk_dry(subscription: Iptrunk, process_id: UUIDstr, tt_numb
         "verb": "terminate",
         "config_object": "trunk_deprovision",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Remove config for {subscription.iptrunk.geant_s_sid}",
+        f"- Remove config for {subscription.iptrunk.gs_id}",
     }
 
     return {
@@ -96,7 +96,7 @@ def deprovision_ip_trunk_real(subscription: Iptrunk, process_id: UUIDstr, tt_num
         "verb": "terminate",
         "config_object": "trunk_deprovision",
         "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} "
-        f"- Remove config for {subscription.iptrunk.geant_s_sid}",
+        f"- Remove config for {subscription.iptrunk.gs_id}",
     }
 
     return {
diff --git a/test/fixtures/iptrunk_fixtures.py b/test/fixtures/iptrunk_fixtures.py
index 5044a2e5..b297d07e 100644
--- a/test/fixtures/iptrunk_fixtures.py
+++ b/test/fixtures/iptrunk_fixtures.py
@@ -56,7 +56,7 @@ def iptrunk_subscription_factory(iptrunk_side_subscription_factory, faker, geant
     def subscription_create(
         description=None,
         start_date="2023-05-24T00:00:00+00:00",
-        geant_s_sid=None,
+        gs_id=None,
         iptrunk_description=None,
         iptrunk_type=IptrunkType.LEASED,
         iptrunk_speed=PhysicalPortCapacity.ONE_GIGABIT_PER_SECOND,
@@ -84,7 +84,7 @@ def iptrunk_subscription_factory(iptrunk_side_subscription_factory, faker, geant
             )
 
         description = description or faker.sentence()
-        geant_s_sid = geant_s_sid or faker.geant_sid()
+        gs_id = gs_id or faker.geant_sid()
         iptrunk_description = iptrunk_description or faker.sentence()
         iptrunk_isis_metric = iptrunk_isis_metric or faker.pyint()
         iptrunk_ipv4_network = iptrunk_ipv4_network or faker.ipv4_network(max_subnet=31)
@@ -94,7 +94,7 @@ def iptrunk_subscription_factory(iptrunk_side_subscription_factory, faker, geant
         iptrunk_side_b = iptrunk_side_subscription_factory()
         iptrunk_sides = iptrunk_sides or [iptrunk_side_a, iptrunk_side_b]
 
-        iptrunk_subscription.iptrunk.geant_s_sid = geant_s_sid
+        iptrunk_subscription.iptrunk.gs_id = gs_id
         iptrunk_subscription.iptrunk.iptrunk_description = iptrunk_description
         iptrunk_subscription.iptrunk.iptrunk_type = iptrunk_type
         iptrunk_subscription.iptrunk.iptrunk_speed = iptrunk_speed
diff --git a/test/workflows/iptrunk/test_create_imported_iptrunk.py b/test/workflows/iptrunk/test_create_imported_iptrunk.py
index 25d68d8f..2e18e4bb 100644
--- a/test/workflows/iptrunk/test_create_imported_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_imported_iptrunk.py
@@ -16,7 +16,7 @@ from test.workflows import (
 def workflow_input_data(faker, router_subscription_factory):
     return {
         "partner": "GEANT",
-        "geant_s_sid": faker.geant_sid(),
+        "gs_id": faker.geant_sid(),
         "iptrunk_description": faker.sentence(),
         "iptrunk_type": IptrunkType.DARK_FIBER,
         "iptrunk_speed": PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND,
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index cac63729..6345237f 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -65,7 +65,7 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
 
     create_ip_trunk_step = {
         "tt_number": faker.tt_number(),
-        "geant_s_sid": faker.geant_sid(),
+        "gs_id": faker.geant_sid(),
         "iptrunk_type": IptrunkType.DARK_FIBER,
         "iptrunk_description": faker.sentence(),
         "iptrunk_speed": PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND,
@@ -154,7 +154,7 @@ def test_successful_iptrunk_creation_with_standard_lso_result(
     ])
     assert subscription.status == "provisioning"
     assert subscription.description == (
-        f"IP trunk {sorted_sides[0]} {sorted_sides[1]}, geant_s_sid:{input_form_wizard_data[0]["geant_s_sid"]}"
+        f"IP trunk {sorted_sides[0]} {sorted_sides[1]}, gs_id:{input_form_wizard_data[0]["gs_id"]}"
     )
 
     assert mock_execute_playbook.call_count == 6
diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py
index 2dcb23e2..ef3325fa 100644
--- a/test/workflows/iptrunk/test_modify_trunk_interface.py
+++ b/test/workflows/iptrunk/test_modify_trunk_interface.py
@@ -66,7 +66,7 @@ def input_form_iptrunk_data(
         {"subscription_id": product_id},
         {
             "tt_number": faker.tt_number(),
-            "geant_s_sid": new_sid,
+            "gs_id": new_sid,
             "iptrunk_description": new_description,
             "iptrunk_type": new_type,
             "iptrunk_speed": new_speed,
@@ -135,7 +135,7 @@ def test_iptrunk_modify_trunk_interface_success(
     assert subscription.status == "active"
     assert mock_provision_ip_trunk.call_count == lso_interaction_count
     # Assert all Netbox calls have been made
-    new_sid = input_form_iptrunk_data[1]["geant_s_sid"]
+    new_sid = input_form_iptrunk_data[1]["gs_id"]
     new_side_a_sid = input_form_iptrunk_data[3]["side_a_ae_geant_a_sid"]
     new_side_a_ae_members = input_form_iptrunk_data[3]["side_a_ae_members"]
     new_side_b_sid = input_form_iptrunk_data[4]["side_b_ae_geant_a_sid"]
@@ -164,8 +164,8 @@ def test_iptrunk_modify_trunk_interface_success(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    assert subscription.description == f"IP trunk {side_names[0]} {side_names[1]}, geant_s_sid:{new_sid}"
-    assert subscription.iptrunk.geant_s_sid == input_form_iptrunk_data[1]["geant_s_sid"]
+    assert subscription.description == f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{new_sid}"
+    assert subscription.iptrunk.gs_id == input_form_iptrunk_data[1]["gs_id"]
     assert subscription.iptrunk.iptrunk_description == input_form_iptrunk_data[1]["iptrunk_description"]
     assert subscription.iptrunk.iptrunk_type == input_form_iptrunk_data[1]["iptrunk_type"]
     assert subscription.iptrunk.iptrunk_speed == input_form_iptrunk_data[1]["iptrunk_speed"]
-- 
GitLab


From b2ea69cb45a3bf5de90ea11bf76301f93890dd6b Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Wed, 4 Dec 2024 16:04:40 +0100
Subject: [PATCH 04/20] Rename IPtrunk side iptrunk_side_ae_geant_a_sid to
 ga_id

---
 gso/workflows/iptrunk/create_imported_iptrunk.py | 12 ++++++------
 gso/workflows/iptrunk/create_iptrunk.py          | 16 ++++++++--------
 gso/workflows/iptrunk/modify_trunk_interface.py  | 12 ++++++------
 test/fixtures/iptrunk_fixtures.py                |  4 ++--
 .../iptrunk/test_modify_trunk_interface.py       | 16 ++++++++--------
 5 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/gso/workflows/iptrunk/create_imported_iptrunk.py b/gso/workflows/iptrunk/create_imported_iptrunk.py
index 77774049..db88b2b8 100644
--- a/gso/workflows/iptrunk/create_imported_iptrunk.py
+++ b/gso/workflows/iptrunk/create_imported_iptrunk.py
@@ -39,12 +39,12 @@ def initial_input_form_generator() -> FormGenerator:
 
         side_a_node_id: active_router_selector()  # type: ignore[valid-type]
         side_a_ae_iface: str
-        side_a_ae_geant_a_sid: str | None = None
+        side_a_ga_id: str | None = None
         side_a_ae_members: Annotated[list[LAGMember], AfterValidator(validate_unique_list)]
 
         side_b_node_id: active_router_selector()  # type: ignore[valid-type]
         side_b_ae_iface: str
-        side_b_ae_geant_a_sid: str | None = None
+        side_b_ga_id: str | None = None
         side_b_ae_members: Annotated[list[LAGMember], AfterValidator(validate_unique_list)]
 
         iptrunk_ipv4_network: ipaddress.IPv4Network
@@ -79,11 +79,11 @@ def initialize_subscription(
     iptrunk_isis_metric: int,
     side_a_node_id: str,
     side_a_ae_iface: str,
-    side_a_ae_geant_a_sid: str | None,
+    side_a_ga_id: str | None,
     side_a_ae_members: LAGMemberList,
     side_b_node_id: str,
     side_b_ae_iface: str,
-    side_b_ae_geant_a_sid: str | None,
+    side_b_ga_id: str | None,
     side_b_ae_members: LAGMemberList,
 ) -> State:
     """Take all input from the user, and store it in the database."""
@@ -96,7 +96,7 @@ def initialize_subscription(
 
     subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node = Router.from_subscription(side_a_node_id).router
     subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface = side_a_ae_iface
-    subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid = side_a_ae_geant_a_sid
+    subscription.iptrunk.iptrunk_sides[0].ga_id = side_a_ga_id
     for member in side_a_ae_members:
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members.append(
             IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member),
@@ -104,7 +104,7 @@ def initialize_subscription(
 
     subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node = Router.from_subscription(side_b_node_id).router
     subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface = side_b_ae_iface
-    subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid = side_b_ae_geant_a_sid
+    subscription.iptrunk.iptrunk_sides[1].ga_id = side_b_ga_id
     for member in side_b_ae_members:
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members.append(
             IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member),
diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index c786f847..eefcd46c 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -144,7 +144,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         model_config = ConfigDict(title=f"Provide subscription details for side A of the trunk. ({router_a_fqdn})")
 
         side_a_ae_iface: available_lags_choices(router_a) or str  # type: ignore[valid-type]
-        side_a_ae_geant_a_sid: str | None
+        side_a_ga_id: str | None
         side_a_ae_members: ae_members_side_a_type
 
     user_input_side_a = yield CreateIptrunkSideAForm
@@ -182,7 +182,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         model_config = ConfigDict(title=f"Provide subscription details for side B of the trunk. ({router_b_fqdn})")
 
         side_b_ae_iface: available_lags_choices(router_b) or str  # type: ignore[valid-type]
-        side_b_ae_geant_a_sid: str | None
+        side_b_ga_id: str | None
         side_b_ae_members: ae_members_side_b
 
     user_input_side_b = yield CreateIptrunkSideBForm
@@ -204,11 +204,11 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         "side_a_node",
         "side_a_ae_iface",
         "side_a_ae_members",
-        "side_a_ae_geant_a_sid",
+        "side_a_ga_id",
         "side_b_node",
         "side_b_ae_iface",
         "side_b_ae_members",
-        "side_b_ae_geant_a_sid",
+        "side_b_ga_id",
     ]
     yield from create_summary_form(summary_form_data, product_name, summary_fields)
 
@@ -329,11 +329,11 @@ def initialize_subscription(
     iptrunk_minimum_links: int,
     side_a_node_id: str,
     side_a_ae_iface: str,
-    side_a_ae_geant_a_sid: str | None,
+    side_a_ga_id: str | None,
     side_a_ae_members: list[dict],
     side_b_node_id: str,
     side_b_ae_iface: str,
-    side_b_ae_geant_a_sid: str | None,
+    side_b_ga_id: str | None,
     side_b_ae_members: list[dict],
 ) -> State:
     """Take all input from the user, and store it in the database."""
@@ -349,7 +349,7 @@ def initialize_subscription(
 
     subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node = side_a
     subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface = side_a_ae_iface
-    subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid = side_a_ae_geant_a_sid
+    subscription.iptrunk.iptrunk_sides[0].ga_id = side_a_ga_id
     for member in side_a_ae_members:
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members.append(
             IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member),
@@ -357,7 +357,7 @@ def initialize_subscription(
 
     subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node = side_b
     subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface = side_b_ae_iface
-    subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid = side_b_ae_geant_a_sid
+    subscription.iptrunk.iptrunk_sides[1].ga_id = side_b_ga_id
     for member in side_b_ae_members:
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members.append(
             IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member),
diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py
index 723a3246..65fa452b 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -125,7 +125,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
             subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_fqdn, default_type=str
         )
         side_a_ae_iface: ReadOnlyField(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface, default_type=str)  # type: ignore[valid-type]
-        side_a_ae_geant_a_sid: str | None = subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid
+        side_a_ga_id: str | None = subscription.iptrunk.iptrunk_sides[0].ga_id
         side_a_ae_members: ae_members_side_a = (  # type: ignore[valid-type]
             subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members
             if initial_user_input.iptrunk_speed == subscription.iptrunk.iptrunk_speed
@@ -142,7 +142,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
             subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_fqdn, default_type=str
         )
         side_b_ae_iface: ReadOnlyField(subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface, default_type=str)  # type: ignore[valid-type]
-        side_b_ae_geant_a_sid: str | None = subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid
+        side_b_ga_id: str | None = subscription.iptrunk.iptrunk_sides[1].ga_id
         side_b_ae_members: ae_members_side_b = (  # type: ignore[valid-type]
             subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members
             if initial_user_input.iptrunk_speed == subscription.iptrunk.iptrunk_speed
@@ -259,9 +259,9 @@ def modify_iptrunk_subscription(
     iptrunk_description: str | None,
     iptrunk_speed: PhysicalPortCapacity,
     iptrunk_minimum_links: int,
-    side_a_ae_geant_a_sid: str | None,
+    side_a_ga_id: str | None,
     side_a_ae_members: list[dict],
-    side_b_ae_geant_a_sid: str | None,
+    side_b_ga_id: str | None,
     side_b_ae_members: list[dict],
 ) -> State:
     """Modify the subscription in the service database, reflecting the changes to the newly selected interfaces."""
@@ -293,9 +293,9 @@ def modify_iptrunk_subscription(
     subscription.iptrunk.iptrunk_speed = iptrunk_speed
     subscription.iptrunk.iptrunk_minimum_links = iptrunk_minimum_links
 
-    subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid = side_a_ae_geant_a_sid
+    subscription.iptrunk.iptrunk_sides[0].ga_id = side_a_ga_id
     update_side_members(subscription, 0, side_a_ae_members)
-    subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid = side_b_ae_geant_a_sid
+    subscription.iptrunk.iptrunk_sides[1].ga_id = side_b_ga_id
     update_side_members(subscription, 1, side_b_ae_members)
 
     side_names = sorted([
diff --git a/test/fixtures/iptrunk_fixtures.py b/test/fixtures/iptrunk_fixtures.py
index b297d07e..17715ebe 100644
--- a/test/fixtures/iptrunk_fixtures.py
+++ b/test/fixtures/iptrunk_fixtures.py
@@ -21,7 +21,7 @@ def iptrunk_side_subscription_factory(router_subscription_factory, faker):
     def subscription_create(
         iptrunk_side_node=None,
         iptrunk_side_ae_iface=None,
-        iptrunk_side_ae_geant_a_sid=None,
+        ga_id=None,
         iptrunk_side_ae_members=None,
         iptrunk_side_ae_members_description=None,
     ) -> IptrunkSideBlock:
@@ -31,7 +31,7 @@ def iptrunk_side_subscription_factory(router_subscription_factory, faker):
                 iptrunk_side_node or router_subscription_factory(vendor=Vendor.NOKIA)
             ).router,
             iptrunk_side_ae_iface=iptrunk_side_ae_iface or faker.pystr(),
-            iptrunk_side_ae_geant_a_sid=iptrunk_side_ae_geant_a_sid or faker.geant_sid(),
+            ga_id=ga_id or faker.geant_gid(),
             iptrunk_side_ae_members=iptrunk_side_ae_members
             or [
                 IptrunkInterfaceBlock.new(
diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py
index ef3325fa..d88d805d 100644
--- a/test/workflows/iptrunk/test_modify_trunk_interface.py
+++ b/test/workflows/iptrunk/test_modify_trunk_interface.py
@@ -58,9 +58,9 @@ def input_form_iptrunk_data(
     new_speed = PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND
     new_link_count = 2
 
-    new_side_a_sid = faker.geant_sid()
+    new_side_a_gid = faker.geant_gid()
 
-    new_side_b_sid = faker.geant_sid()
+    new_side_b_gid = faker.geant_gid()
 
     return [
         {"subscription_id": product_id},
@@ -74,11 +74,11 @@ def input_form_iptrunk_data(
         },
         {},
         {
-            "side_a_ae_geant_a_sid": new_side_a_sid,
+            "side_a_ae_geant_a_sid": new_side_a_gid,
             "side_a_ae_members": new_side_a_ae_members,
         },
         {
-            "side_b_ae_geant_a_sid": new_side_b_sid,
+            "side_b_ae_geant_a_sid": new_side_b_gid,
             "side_b_ae_members": new_side_b_ae_members,
         },
     ]
@@ -136,9 +136,9 @@ def test_iptrunk_modify_trunk_interface_success(
     assert mock_provision_ip_trunk.call_count == lso_interaction_count
     # Assert all Netbox calls have been made
     new_sid = input_form_iptrunk_data[1]["gs_id"]
-    new_side_a_sid = input_form_iptrunk_data[3]["side_a_ae_geant_a_sid"]
+    new_side_a_gid = input_form_iptrunk_data[3]["side_a_ae_geant_a_sid"]
     new_side_a_ae_members = input_form_iptrunk_data[3]["side_a_ae_members"]
-    new_side_b_sid = input_form_iptrunk_data[4]["side_b_ae_geant_a_sid"]
+    new_side_b_gid = input_form_iptrunk_data[4]["side_b_ae_geant_a_sid"]
     new_side_b_ae_members = input_form_iptrunk_data[4]["side_b_ae_members"]
 
     # Only Nokia interfaces are checked
@@ -170,7 +170,7 @@ def test_iptrunk_modify_trunk_interface_success(
     assert subscription.iptrunk.iptrunk_type == input_form_iptrunk_data[1]["iptrunk_type"]
     assert subscription.iptrunk.iptrunk_speed == input_form_iptrunk_data[1]["iptrunk_speed"]
     assert subscription.iptrunk.iptrunk_minimum_links == input_form_iptrunk_data[1]["iptrunk_number_of_members"] - 1
-    assert subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_geant_a_sid == new_side_a_sid
+    assert subscription.iptrunk.iptrunk_sides[0].ga_id == new_side_a_gid
 
     def _find_interface_by_name(interfaces: LAGMemberList, name: str):
         for interface in interfaces:
@@ -185,7 +185,7 @@ def test_iptrunk_modify_trunk_interface_success(
             == _find_interface_by_name(new_side_a_ae_members, member.interface_name).interface_description
         )
 
-    assert subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_geant_a_sid == new_side_b_sid
+    assert subscription.iptrunk.iptrunk_sides[1].ga_id == new_side_b_gid
 
     for member in subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members:
         assert (
-- 
GitLab


From bd9fc75c9472cbf423ec59566f9d15c19aee0c99 Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Wed, 4 Dec 2024 16:09:13 +0100
Subject: [PATCH 05/20] Rename EdgePort geant_ga_id to ga_id

---
 gso/cli/imports.py                                     |  2 +-
 gso/translations/en-GB.json                            |  2 +-
 gso/workflows/edge_port/create_edge_port.py            | 10 +++++-----
 gso/workflows/edge_port/create_imported_edge_port.py   |  8 ++++----
 gso/workflows/edge_port/modify_edge_port.py            |  8 ++++----
 test/cli/test_imports.py                               |  2 +-
 test/fixtures/edge_port_fixtures.py                    |  4 ++--
 test/workflows/edge_port/test_create_edge_port.py      |  4 ++--
 .../edge_port/test_create_imported_edge_port.py        |  2 +-
 test/workflows/edge_port/test_modify_edge_port.py      |  8 ++++----
 10 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/gso/cli/imports.py b/gso/cli/imports.py
index 9903d186..72fe0d38 100644
--- a/gso/cli/imports.py
+++ b/gso/cli/imports.py
@@ -197,7 +197,7 @@ class EdgePortImportModel(BaseModel):
     encapsulation: EncapsulationType
     name: str
     minimum_links: int
-    geant_ga_id: str | None
+    ga_id: str | None
     mac_address: str | None
     partner: str
     enable_lacp: bool
diff --git a/gso/translations/en-GB.json b/gso/translations/en-GB.json
index f1f66f07..2328bba2 100644
--- a/gso/translations/en-GB.json
+++ b/gso/translations/en-GB.json
@@ -40,7 +40,7 @@
 
             "enable_lacp": "Enable LACP",
             "mac_address": "MAC address",
-            "geant_ga_id": "GÉANT GA-ID"
+            "ga_id": "GÉANT GA-ID"
         }
     },
     "workflow": {
diff --git a/gso/workflows/edge_port/create_edge_port.py b/gso/workflows/edge_port/create_edge_port.py
index 2005d7c2..ccd022f6 100644
--- a/gso/workflows/edge_port/create_edge_port.py
+++ b/gso/workflows/edge_port/create_edge_port.py
@@ -52,7 +52,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         minimum_links: int
         mac_address: str | None = None
         ignore_if_down: bool = False
-        geant_ga_id: str | None = None
+        ga_id: str | None = None
 
         @model_validator(mode="after")
         def validate_number_of_members(self) -> Self:
@@ -104,7 +104,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         "minimum_links",
         "mac_address",
         "ignore_if_down",
-        "geant_ga_id",
+        "ga_id",
         "enable_lacp",
         "edge_port_name",
         "edge_port_description",
@@ -134,7 +134,7 @@ def initialize_subscription(
     encapsulation: EncapsulationType,
     name: str,
     minimum_links: int,
-    geant_ga_id: str | None,
+    ga_id: str | None,
     mac_address: str | None,
     partner: str,
     enable_lacp: bool,  # noqa: FBT001
@@ -152,10 +152,10 @@ def initialize_subscription(
     subscription.edge_port.edge_port_name = name
     subscription.edge_port.minimum_links = minimum_links
     subscription.edge_port.ignore_if_down = ignore_if_down
-    subscription.edge_port.geant_ga_id = geant_ga_id
+    subscription.edge_port.ga_id = ga_id
     subscription.edge_port.mac_address = mac_address
     partner_name = get_partner_by_id(partner).name
-    subscription.description = f"Edge Port {name} on {router.router_fqdn}, " f"{partner_name}, {geant_ga_id or ""}"
+    subscription.description = f"Edge Port {name} on {router.router_fqdn}, " f"{partner_name}, {ga_id or ""}"
     subscription.edge_port.edge_port_description = description
     for member in ae_members:
         subscription.edge_port.edge_port_ae_members.append(
diff --git a/gso/workflows/edge_port/create_imported_edge_port.py b/gso/workflows/edge_port/create_imported_edge_port.py
index 867965c7..07d4abf3 100644
--- a/gso/workflows/edge_port/create_imported_edge_port.py
+++ b/gso/workflows/edge_port/create_imported_edge_port.py
@@ -48,7 +48,7 @@ def initial_input_form_generator() -> FormGenerator:
         minimum_links: int
         mac_address: str | None = None
         ignore_if_down: bool = False
-        geant_ga_id: str | None = None
+        ga_id: str | None = None
         description: str | None = None
         name: str
         ae_members: Annotated[list[LAGMember], AfterValidator(validate_unique_list)]
@@ -67,7 +67,7 @@ def initialize_subscription(
     encapsulation: EncapsulationType,
     name: str,
     minimum_links: int,
-    geant_ga_id: str | None,
+    ga_id: str | None,
     mac_address: str | None,
     partner: str,
     enable_lacp: bool,  # noqa: FBT001
@@ -87,8 +87,8 @@ def initialize_subscription(
     subscription.edge_port.minimum_links = minimum_links
     subscription.edge_port.edge_port_type = service_type
     subscription.edge_port.ignore_if_down = ignore_if_down
-    subscription.edge_port.geant_ga_id = geant_ga_id
-    subscription.description = f"Edge Port {name} on {router.router_fqdn}, {partner}, {geant_ga_id or ""}"
+    subscription.edge_port.ga_id = ga_id
+    subscription.description = f"Edge Port {name} on {router.router_fqdn}, {partner}, {ga_id or ""}"
     for member in ae_members:
         subscription.edge_port.edge_port_ae_members.append(
             EdgePortAEMemberBlockInactive.new(subscription_id=uuid4(), **member)
diff --git a/gso/workflows/edge_port/modify_edge_port.py b/gso/workflows/edge_port/modify_edge_port.py
index bce56c74..94388984 100644
--- a/gso/workflows/edge_port/modify_edge_port.py
+++ b/gso/workflows/edge_port/modify_edge_port.py
@@ -43,7 +43,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
         minimum_links: int | None = subscription.edge_port.minimum_links or None
         mac_address: str | None = subscription.edge_port.mac_address or None
         ignore_if_down: bool = subscription.edge_port.ignore_if_down
-        geant_ga_id: str | None = subscription.edge_port.geant_ga_id or None
+        ga_id: str | None = subscription.edge_port.ga_id or None
 
         @model_validator(mode="after")
         def validate_number_of_members(self) -> Self:
@@ -117,7 +117,7 @@ def modify_edge_port_subscription(
     encapsulation: EncapsulationType,
     minimum_links: int,
     mac_address: str | None,
-    geant_ga_id: str | None,
+    ga_id: str | None,
     enable_lacp: bool,  # noqa: FBT001
     ae_members: list[dict[str, str]],
     ignore_if_down: bool,  # noqa: FBT001
@@ -138,12 +138,12 @@ def modify_edge_port_subscription(
     subscription.edge_port.minimum_links = minimum_links
     subscription.edge_port.mac_address = mac_address
     subscription.edge_port.ignore_if_down = ignore_if_down
-    subscription.edge_port.geant_ga_id = geant_ga_id
+    subscription.edge_port.ga_id = ga_id
     subscription.edge_port.edge_port_description = description
     subscription.description = (
         f"Edge Port {subscription.edge_port.edge_port_name} on"
         f" {subscription.edge_port.node.router_fqdn},"
-        f" {get_partner_by_id(subscription.customer_id).name}, {geant_ga_id or ""}"
+        f" {get_partner_by_id(subscription.customer_id).name}, {ga_id or ""}"
     )
     subscription.edge_port.edge_port_ae_members.clear()
     partner_name = get_partner_by_id(subscription.customer_id).name
diff --git a/test/cli/test_imports.py b/test/cli/test_imports.py
index fa378703..60c8acee 100644
--- a/test/cli/test_imports.py
+++ b/test/cli/test_imports.py
@@ -270,7 +270,7 @@ def edge_port_data(temp_file, faker, router_subscription_factory, partner_factor
             "encapsulation": EncapsulationType.DOT1Q,
             "name": "lag34",
             "minimum_links": 2,
-            "geant_ga_id": faker.geant_gid(),
+            "ga_id": faker.geant_gid(),
             "mac_address": faker.mac_address(),
             "partner": partner_factory()["name"],
             "enable_lacp": True,
diff --git a/test/fixtures/edge_port_fixtures.py b/test/fixtures/edge_port_fixtures.py
index 669d42ff..7ea6b8b9 100644
--- a/test/fixtures/edge_port_fixtures.py
+++ b/test/fixtures/edge_port_fixtures.py
@@ -30,7 +30,7 @@ def edge_port_subscription_factory(faker, partner_factory, router_subscription_f
         member_speed=PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND,
         minimum_links=None,
         edge_port_type=EdgePortType.PUBLIC,
-        geant_ga_id=None,
+        ga_id=None,
         edge_port_ae_members=None,
         status: SubscriptionLifecycle | None = None,
         *,
@@ -52,7 +52,7 @@ def edge_port_subscription_factory(faker, partner_factory, router_subscription_f
             )
 
         edge_port_subscription.edge_port.edge_port_description = description or faker.text(max_nb_chars=30)
-        edge_port_subscription.edge_port.geant_ga_id = geant_ga_id or faker.geant_sid()
+        edge_port_subscription.edge_port.ga_id = ga_id or faker.geant_gid()
         edge_port_subscription.edge_port.node = node or node
         edge_port_subscription.edge_port.edge_port_name = name or f"lag-{faker.pyint(21, 50)}"
         edge_port_subscription.edge_port.edge_port_description = edge_port_description or faker.sentence()
diff --git a/test/workflows/edge_port/test_create_edge_port.py b/test/workflows/edge_port/test_create_edge_port.py
index 8066c5e0..35cf2613 100644
--- a/test/workflows/edge_port/test_create_edge_port.py
+++ b/test/workflows/edge_port/test_create_edge_port.py
@@ -50,7 +50,7 @@ def input_form_wizard_data(request, router_subscription_factory, partner_factory
         "node": router_subscription_factory(vendor=Vendor.NOKIA),
         "partner": partner_factory(name="GAAR", email=faker.email())["partner_id"],
         "service_type": EdgePortType.PUBLIC,
-        "geant_ga_id": faker.geant_gid(),
+        "ga_id": faker.geant_gid(),
         "enable_lacp": True,
         "speed": PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND,
         "encapsulation": EncapsulationType.DOT1Q,
@@ -101,7 +101,7 @@ def test_successful_edge_port_creation(
     subscription = EdgePort.from_subscription(subscription_id)
 
     assert subscription.status == "active"
-    ga_id = input_form_wizard_data[0]["geant_ga_id"]
+    ga_id = input_form_wizard_data[0]["ga_id"]
     router_fqdn = Router.from_subscription(input_form_wizard_data[0]["node"]).router.router_fqdn
     assert subscription.description == f"Edge Port lag-21 on {router_fqdn}, GAAR, {ga_id}"
     assert len(subscription.edge_port.edge_port_ae_members) == 2
diff --git a/test/workflows/edge_port/test_create_imported_edge_port.py b/test/workflows/edge_port/test_create_imported_edge_port.py
index c5590fe4..838d330d 100644
--- a/test/workflows/edge_port/test_create_imported_edge_port.py
+++ b/test/workflows/edge_port/test_create_imported_edge_port.py
@@ -17,7 +17,7 @@ def imported_edge_port_creation_input_form_data(router_subscription_factory, par
         "encapsulation": EncapsulationType.DOT1Q,
         "name": "lag34",
         "minimum_links": 2,
-        "geant_ga_id": faker.geant_gid(),
+        "ga_id": faker.geant_gid(),
         "mac_address": faker.mac_address(),
         "partner": partner_factory()["name"],
         "enable_lacp": True,
diff --git a/test/workflows/edge_port/test_modify_edge_port.py b/test/workflows/edge_port/test_modify_edge_port.py
index a7c82428..6e16f73a 100644
--- a/test/workflows/edge_port/test_modify_edge_port.py
+++ b/test/workflows/edge_port/test_modify_edge_port.py
@@ -21,7 +21,7 @@ def input_form_wizard_data(request, faker, edge_port_subscription_factory, partn
         {"subscription_id": subscription_id},
         {
             "tt_number": faker.tt_number(),
-            "geant_ga_id": faker.geant_gid(),
+            "ga_id": faker.geant_gid(),
             "member_speed": PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND,
             "number_of_members": 1,
         },
@@ -89,7 +89,7 @@ def test_modify_edge_port_with_changing_capacity(
     assert mocked_attach_interface_to_lag.call_count == 1
     assert mocked_free_interface.call_count == 2
     assert mocked_detach_interfaces_from_lag.call_count == 1
-    assert subscription.edge_port.geant_ga_id == input_form_wizard_data[1]["geant_ga_id"]
+    assert subscription.edge_port.ga_id == input_form_wizard_data[1]["ga_id"]
     assert len(subscription.edge_port.edge_port_ae_members) == 1
 
 
@@ -100,7 +100,7 @@ def input_form_wizard_without_changing_capacity(request, faker, edge_port_subscr
 
     return [
         {"subscription_id": subscription_id},
-        {"tt_number": faker.tt_number(), "geant_ga_id": faker.geant_gid()},
+        {"tt_number": faker.tt_number(), "ga_id": faker.geant_gid()},
         {
             "description": faker.sentence(),
             "ae_members": [
@@ -163,6 +163,6 @@ def test_modify_edge_port_without_changing_capacity(
     assert mocked_free_interface.call_count == 0
     assert mocked_detach_interfaces_from_lag.call_count == 0
 
-    assert subscription.edge_port.geant_ga_id == input_form_wizard_without_changing_capacity[1]["geant_ga_id"]
+    assert subscription.edge_port.ga_id == input_form_wizard_without_changing_capacity[1]["ga_id"]
     assert len(subscription.edge_port.edge_port_ae_members) == 2
     assert subscription.edge_port.edge_port_description == input_form_wizard_without_changing_capacity[2]["description"]
-- 
GitLab


From 7ef7177783f895474121f64a32415d5613bf4915 Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Wed, 4 Dec 2024 16:44:16 +0100
Subject: [PATCH 06/20] IPTrunk side ga id renaming.

---
 test/workflows/iptrunk/test_create_imported_iptrunk.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/workflows/iptrunk/test_create_imported_iptrunk.py b/test/workflows/iptrunk/test_create_imported_iptrunk.py
index 2e18e4bb..8b9c5d4d 100644
--- a/test/workflows/iptrunk/test_create_imported_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_imported_iptrunk.py
@@ -24,13 +24,13 @@ def workflow_input_data(faker, router_subscription_factory):
         "iptrunk_isis_metric": 10000,
         "side_a_node_id": router_subscription_factory(),
         "side_a_ae_iface": faker.network_interface(),
-        "side_a_ae_geant_a_sid": faker.geant_sid(),
+        "side_a_ga_id": faker.geant_gid(),
         "side_a_ae_members": [
             {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} for _ in range(3)
         ],
         "side_b_node_id": router_subscription_factory(),
         "side_b_ae_iface": faker.network_interface(),
-        "side_b_ae_geant_a_sid": faker.geant_sid(),
+        "side_b_ga_id": faker.geant_gid(),
         "side_b_ae_members": [
             {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} for _ in range(3)
         ],
-- 
GitLab


From e746c51f67e41b9c9b7fb635e1e5f6a3af1eac99 Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Wed, 4 Dec 2024 16:47:29 +0100
Subject: [PATCH 07/20] IPTrunk side ga id renaming.

---
 test/workflows/iptrunk/test_modify_trunk_interface.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py
index d88d805d..801ce865 100644
--- a/test/workflows/iptrunk/test_modify_trunk_interface.py
+++ b/test/workflows/iptrunk/test_modify_trunk_interface.py
@@ -74,11 +74,11 @@ def input_form_iptrunk_data(
         },
         {},
         {
-            "side_a_ae_geant_a_sid": new_side_a_gid,
+            "side_a_ga_id": new_side_a_gid,
             "side_a_ae_members": new_side_a_ae_members,
         },
         {
-            "side_b_ae_geant_a_sid": new_side_b_gid,
+            "side_b_ga_id": new_side_b_gid,
             "side_b_ae_members": new_side_b_ae_members,
         },
     ]
@@ -136,9 +136,9 @@ def test_iptrunk_modify_trunk_interface_success(
     assert mock_provision_ip_trunk.call_count == lso_interaction_count
     # Assert all Netbox calls have been made
     new_sid = input_form_iptrunk_data[1]["gs_id"]
-    new_side_a_gid = input_form_iptrunk_data[3]["side_a_ae_geant_a_sid"]
+    new_side_a_gid = input_form_iptrunk_data[3]["side_a_ga_id"]
     new_side_a_ae_members = input_form_iptrunk_data[3]["side_a_ae_members"]
-    new_side_b_gid = input_form_iptrunk_data[4]["side_b_ae_geant_a_sid"]
+    new_side_b_gid = input_form_iptrunk_data[4]["side_b_ga_id"]
     new_side_b_ae_members = input_form_iptrunk_data[4]["side_b_ae_members"]
 
     # Only Nokia interfaces are checked
-- 
GitLab


From 6a7a47c61d9eb5dd8e87a4bef123973acd8822ed Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 09:45:22 +0100
Subject: [PATCH 08/20] Replace geant_sid with gs_id

---
 gso/cli/imports.py                                 | 12 ++++++------
 .../l2_circuit/create_imported_layer_2_circuit.py  |  6 +++---
 gso/workflows/l2_circuit/create_layer_2_circuit.py |  6 +++---
 .../create_imported_l3_core_service.py             |  2 +-
 .../l3_core_service/create_l3_core_service.py      |  2 +-
 .../l3_core_service/modify_l3_core_service.py      |  6 +++---
 test/cli/test_imports.py                           | 14 +++++++-------
 test/fixtures/l3_core_service_fixtures.py          |  4 ++--
 test/fixtures/layer_2_circuit_fixtures.py          |  4 ++--
 test/workflows/iptrunk/test_create_iptrunk.py      |  4 ++--
 .../test_create_imported_layer_2_circuit.py        |  4 ++--
 .../l2_circuit/test_create_layer_2_circuit.py      |  6 +++---
 .../test_create_imported_l3_core_service.py        |  2 +-
 .../l3_core_service/test_create_l3_core_service.py |  2 +-
 .../l3_core_service/test_modify_l3_core_service.py |  6 +++---
 15 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/gso/cli/imports.py b/gso/cli/imports.py
index 72fe0d38..ba33565e 100644
--- a/gso/cli/imports.py
+++ b/gso/cli/imports.py
@@ -124,11 +124,11 @@ class IptrunkImportModel(BaseModel):
     iptrunk_isis_metric: int
     side_a_node_id: str
     side_a_ae_iface: str
-    side_a_ae_geant_a_sid: str | None
+    side_a_ga_id: str | None
     side_a_ae_members: LAGMemberList[LAGMember]
     side_b_node_id: str
     side_b_ae_iface: str
-    side_b_ae_geant_a_sid: str | None
+    side_b_ga_id: str | None
     side_b_ae_members: LAGMemberList[LAGMember]
 
     iptrunk_ipv4_network: ipaddress.IPv4Network
@@ -269,7 +269,7 @@ class L3CoreServiceImportModel(BaseModel):
 
         edge_port: str
         ap_type: str
-        geant_sid: str
+        gs_id: str
         sbp_type: SBPType = SBPType.L3
         is_tagged: bool = False
         vlan_id: VLAN_ID
@@ -349,7 +349,7 @@ class Layer2CircuitServiceImportModel(BaseModel):
 
     service_type: Layer2CircuitServiceType
     partner: str
-    geant_sid: str
+    gs_id: str
     vc_id: VC_ID
     layer_2_circuit_side_a: ServiceBindingPortInput
     layer_2_circuit_side_b: ServiceBindingPortInput
@@ -600,11 +600,11 @@ def import_iptrunks(filepath: str = common_filepath_option) -> None:
                 iptrunk_isis_metric=trunk["config"]["common"]["isis_metric"],
                 side_a_node_id=_get_router_subscription_id(trunk["config"]["nodeA"]["name"]) or "",
                 side_a_ae_iface=trunk["config"]["nodeA"]["ae_name"],
-                side_a_ae_geant_a_sid=trunk["config"]["nodeA"]["port_sid"],
+                side_a_ga_id=trunk["config"]["nodeA"]["port_ga_id"],
                 side_a_ae_members=trunk["config"]["nodeA"]["members"],
                 side_b_node_id=_get_router_subscription_id(trunk["config"]["nodeB"]["name"]) or "",
                 side_b_ae_iface=trunk["config"]["nodeB"]["ae_name"],
-                side_b_ae_geant_a_sid=trunk["config"]["nodeB"]["port_sid"],
+                side_b_ga_id=trunk["config"]["nodeB"]["port_ga_id"],
                 side_b_ae_members=trunk["config"]["nodeB"]["members"],
                 iptrunk_ipv4_network=iptrunk_ipv4_network,
                 iptrunk_ipv6_network=iptrunk_ipv6_network,
diff --git a/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py b/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py
index a0fc39cb..6102d86d 100644
--- a/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py
+++ b/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py
@@ -39,7 +39,7 @@ def initial_input_form_generator() -> FormGenerator:
 
         service_type: Layer2CircuitServiceType
         partner: str
-        geant_sid: str
+        gs_id: str
         vc_id: VC_ID
         layer_2_circuit_side_a: ServiceBindingPortInput
         layer_2_circuit_side_b: ServiceBindingPortInput
@@ -91,7 +91,7 @@ def create_subscription(partner: str, service_type: Layer2CircuitServiceType) ->
 @step("Initialize subscription")
 def initialize_subscription(
     subscription: ImportedLayer2CircuitInactive,
-    geant_sid: str,
+    gs_id: str,
     layer_2_circuit_side_a: dict[str, Any],
     layer_2_circuit_side_b: dict[str, Any],
     layer_2_circuit_type: Layer2CircuitType,
@@ -110,7 +110,7 @@ def initialize_subscription(
             edge_port=EdgePort.from_subscription(subscription_id=circuit_side_data["edge_port"]).edge_port,
             sbp_type=SBPType.L2,
             vlan_id=circuit_side_data["vlan_id"],
-            geant_sid=geant_sid,
+            gs_id=gs_id,
             is_tagged=layer_2_circuit_type == Layer2CircuitType.TAGGED,
             custom_firewall_filters=False,
         )
diff --git a/gso/workflows/l2_circuit/create_layer_2_circuit.py b/gso/workflows/l2_circuit/create_layer_2_circuit.py
index 0a15fceb..7959a30b 100644
--- a/gso/workflows/l2_circuit/create_layer_2_circuit.py
+++ b/gso/workflows/l2_circuit/create_layer_2_circuit.py
@@ -69,7 +69,7 @@ def initial_input_generator(product_name: str) -> FormGenerator:
         vlan_divider: Divider = Field(None, exclude=True)
         policer_bandwidth: _policer_field(policer_enabled=initial_user_input.policer_enabled)  # type: ignore[valid-type]
         policer_burst_rate: _policer_field(policer_enabled=initial_user_input.policer_enabled)  # type: ignore[valid-type]
-        geant_sid: str
+        gs_id: str
         layer_2_circuit_side_a: Layer2CircuitSideSelection
         side_divider: Divider = Field(None, exclude=True)
         layer_2_circuit_side_b: Layer2CircuitSideSelection
@@ -105,7 +105,7 @@ def initialize_subscription(
     policer_enabled: bool,  # noqa: FBT001
     policer_bandwidth: BandwidthString | None,
     policer_burst_rate: BandwidthString | None,
-    geant_sid: str,
+    gs_id: str,
 ) -> State:
     """Build a subscription object from all user input."""
     layer_2_circuit_sides = []
@@ -115,7 +115,7 @@ def initialize_subscription(
             edge_port=EdgePort.from_subscription(subscription_id=circuit_side_data["edge_port"]).edge_port,
             sbp_type=SBPType.L2,
             vlan_id=circuit_side_data["vlan_id"],
-            geant_sid=geant_sid,
+            gs_id=gs_id,
             is_tagged=layer_2_circuit_type == Layer2CircuitType.TAGGED,
             custom_firewall_filters=False,
         )
diff --git a/gso/workflows/l3_core_service/create_imported_l3_core_service.py b/gso/workflows/l3_core_service/create_imported_l3_core_service.py
index dd77021b..7862a47f 100644
--- a/gso/workflows/l3_core_service/create_imported_l3_core_service.py
+++ b/gso/workflows/l3_core_service/create_imported_l3_core_service.py
@@ -50,7 +50,7 @@ def initial_input_form_generator() -> FormGenerator:
     class ServiceBindingPort(BaseModel):
         edge_port: UUIDstr
         ap_type: str
-        geant_sid: str
+        gs_id: str
         sbp_type: SBPType = SBPType.L3
         is_tagged: bool = False
         vlan_id: VLAN_ID
diff --git a/gso/workflows/l3_core_service/create_l3_core_service.py b/gso/workflows/l3_core_service/create_l3_core_service.py
index d4b085c1..04edd53f 100644
--- a/gso/workflows/l3_core_service/create_l3_core_service.py
+++ b/gso/workflows/l3_core_service/create_l3_core_service.py
@@ -113,7 +113,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
             exclude=True,
         )
 
-        geant_sid: str
+        gs_id: str
         is_tagged: bool = False
         vlan_id: VLAN_ID
         custom_firewall_filters: bool = False
diff --git a/gso/workflows/l3_core_service/modify_l3_core_service.py b/gso/workflows/l3_core_service/modify_l3_core_service.py
index 7dbeb486..24b408ab 100644
--- a/gso/workflows/l3_core_service/modify_l3_core_service.py
+++ b/gso/workflows/l3_core_service/modify_l3_core_service.py
@@ -152,7 +152,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
                 exclude=True,
             )
 
-            geant_sid: str = current_sbp.geant_sid
+            gs_id: str = current_sbp.gs_id
             is_tagged: bool = current_sbp.is_tagged
             # The SBP model does not require these five fields, but in the case of GÉANT IP or IAS this will never
             # occur since it's a layer 3 service. The ignore statements are there to put our type checker at ease.
@@ -212,7 +212,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
                 exclude=True,
             )
 
-            geant_sid: str
+            gs_id: str
             is_tagged: bool = False
             vlan_id: VLAN_ID
             ipv4_address: IPv4AddressType
@@ -279,7 +279,7 @@ def modify_existing_sbp_blocks(subscription: L3CoreService, modified_sbp_list: l
 
         current_sbp.bgp_session_list = [v4_peer, v6_peer]
         current_sbp.vlan_id = modified_sbp_data["vlan_id"]
-        current_sbp.geant_sid = modified_sbp_data["geant_sid"]
+        current_sbp.gs_id = modified_sbp_data["gs_id"]
         current_sbp.is_tagged = modified_sbp_data["is_tagged"]
         current_sbp.ipv4_address = modified_sbp_data["ipv4_address"]
         current_sbp.ipv6_address = modified_sbp_data["ipv6_address"]
diff --git a/test/cli/test_imports.py b/test/cli/test_imports.py
index 60c8acee..475492a4 100644
--- a/test/cli/test_imports.py
+++ b/test/cli/test_imports.py
@@ -73,7 +73,7 @@ def iptrunk_data(temp_file, router_subscription_factory, faker) -> (Path, dict):
                 "nodeA": {
                     "name": side_a_node or Router.from_subscription(router_side_a).router.router_fqdn,
                     "ae_name": side_a_ae_name or faker.network_interface(),
-                    "port_sid": faker.geant_sid(),
+                    "port_ga_id": faker.geant_gid(),
                     "members": side_a_members
                     or [
                         {
@@ -88,7 +88,7 @@ def iptrunk_data(temp_file, router_subscription_factory, faker) -> (Path, dict):
                 "nodeB": {
                     "name": side_b_node or Router.from_subscription(router_side_b).router.router_fqdn,
                     "ae_name": side_b_ae_name or faker.network_interface(),
-                    "port_sid": faker.geant_sid(),
+                    "port_ga_id": faker.geant_gid(),
                     "members": side_b_members
                     or [
                         {
@@ -305,7 +305,7 @@ def l3_core_service_data(temp_file, faker, partner_factory, edge_port_subscripti
                 {
                     "edge_port": edge_port_subscription_factory(),
                     "ap_type": "PRIMARY",
-                    "geant_sid": faker.geant_sid(),
+                    "gs_id": faker.geant_sid(),
                     "vlan_id": faker.vlan_id(),
                     "ipv4_address": faker.ipv4(),
                     "ipv4_mask": faker.ipv4_netmask(),
@@ -353,7 +353,7 @@ def l3_core_service_data(temp_file, faker, partner_factory, edge_port_subscripti
                 {
                     "edge_port": edge_port_subscription_factory(),
                     "ap_type": "BACKUP",
-                    "geant_sid": faker.geant_sid(),
+                    "gs_id": faker.geant_sid(),
                     "vlan_id": faker.vlan_id(),
                     "ipv4_address": faker.ipv4(),
                     "ipv4_mask": faker.ipv4_netmask(),
@@ -414,7 +414,7 @@ def layer_2_circuit_data(temp_file, faker, partner_factory, edge_port_subscripti
         layer_2_circuit_input_data = {
             "partner": partner_factory()["name"],
             "service_type": Layer2CircuitServiceType.GEANT_PLUS,
-            "geant_sid": faker.geant_sid(),
+            "gs_id": faker.geant_sid(),
             "vc_id": generate_unique_vc_id(),
             "layer_2_circuit_side_a": {
                 "edge_port": edge_port_subscription_factory(),
@@ -697,7 +697,7 @@ def test_import_l3_core_service_with_invalid_edge_port(
             {
                 "edge_port": fake_uuid,
                 "ap_type": "PRIMARY",
-                "geant_sid": faker.geant_sid(),
+                "gs_id": faker.geant_sid(),
                 "vlan_id": faker.vlan_id(),
                 "ipv4_address": faker.ipv4(),
                 "ipv4_mask": faker.ipv4_netmask(),
@@ -737,7 +737,7 @@ def test_import_l3_core_service_with_invalid_edge_port(
             {
                 "edge_port": edge_port_subscription_factory(),
                 "ap_type": "BACKUP",
-                "geant_sid": faker.geant_sid(),
+                "gs_id": faker.geant_sid(),
                 "vlan_id": faker.vlan_id(),
                 "ipv4_address": faker.ipv4(),
                 "ipv4_mask": faker.ipv4_netmask(),
diff --git a/test/fixtures/l3_core_service_fixtures.py b/test/fixtures/l3_core_service_fixtures.py
index da94298e..493ddc1c 100644
--- a/test/fixtures/l3_core_service_fixtures.py
+++ b/test/fixtures/l3_core_service_fixtures.py
@@ -84,7 +84,7 @@ def service_binding_port_factory(
 ):
     def create_service_binding_port(
         bgp_session_list: list[BGPSession] | None = None,
-        geant_sid: str | None = None,
+        gs_id: str | None = None,
         sbp_type: SBPType = SBPType.L3,
         ipv4_address: str | None = None,
         ipv4_mask: int | None = None,
@@ -108,7 +108,7 @@ def service_binding_port_factory(
             ipv6_address=ipv6_address or faker.ipv6(),
             ipv6_mask=ipv6_mask or faker.ipv6_netmask(),
             custom_firewall_filters=custom_firewall_filters,
-            geant_sid=geant_sid or faker.geant_sid(),
+            gs_id=gs_id or faker.geant_sid(),
             bgp_session_list=bgp_session_list
             or [
                 bgp_session_subscription_factory(families=[IPFamily.V4UNICAST]),
diff --git a/test/fixtures/layer_2_circuit_fixtures.py b/test/fixtures/layer_2_circuit_fixtures.py
index 28fd88ae..e7c8c468 100644
--- a/test/fixtures/layer_2_circuit_fixtures.py
+++ b/test/fixtures/layer_2_circuit_fixtures.py
@@ -38,7 +38,7 @@ def layer_2_circuit_subscription_factory(faker, geant_partner, edge_port_subscri
         vlan_id_side_a: VLAN_ID | None = None,
         layer_2_circuit_side_b_edgeport: UUIDstr | None = None,
         vlan_id_side_b: VLAN_ID | None = None,
-        geant_sid: str | None = None,
+        gs_id: str | None = None,
         *,
         policer_enabled: bool = False,
     ) -> UUIDstr:
@@ -82,7 +82,7 @@ def layer_2_circuit_subscription_factory(faker, geant_partner, edge_port_subscri
                 edge_port=EdgePort.from_subscription(edge_port).edge_port,
                 sbp_type=SBPType.L2,
                 vlan_id=vlan_id,
-                geant_sid=geant_sid or faker.geant_sid(),
+                gs_id=gs_id or faker.geant_sid(),
                 is_tagged=layer_2_circuit_type == Layer2CircuitType.TAGGED,
                 custom_firewall_filters=False,
             )
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index 6345237f..17c37388 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -75,7 +75,7 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
     create_ip_trunk_side_a_router_name = {"side_a_node_id": router_side_a}
     create_ip_trunk_side_a_step = {
         "side_a_ae_iface": "lag-1",
-        "side_a_ae_geant_a_sid": None,
+        "side_a_ga_id": None,
         "side_a_ae_members": [
             {
                 "interface_name": f"Interface{interface}",
@@ -87,7 +87,7 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
     create_ip_trunk_side_b_router_name = {"side_b_node_id": router_side_b}
     create_ip_trunk_side_b_step = {
         "side_b_ae_iface": "lag-4",
-        "side_b_ae_geant_a_sid": faker.geant_sid(),
+        "side_b_ga_id": faker.geant_sid(),
         "side_b_ae_members": side_b_members,
     }
     summary_view_step = {}
diff --git a/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py b/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
index 0e4e857e..1bc9884a 100644
--- a/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
@@ -28,7 +28,7 @@ def test_create_imported_layer_2_circuit_success(
             "vc_id": generate_unique_vc_id(),
             "policer_bandwidth": faker.bandwidth() if policer_enabled else None,
             "policer_burst_rate": faker.bandwidth() if policer_enabled else None,
-            "geant_sid": faker.geant_sid(),
+            "gs_id": faker.geant_sid(),
             "layer_2_circuit_side_a": {"edge_port": edge_port_a, "vlan_id": faker.vlan_id()},
             "layer_2_circuit_side_b": {"edge_port": edge_port_b, "vlan_id": faker.vlan_id()},
         }
@@ -44,7 +44,7 @@ def test_create_imported_layer_2_circuit_success(
     assert len(subscription.layer_2_circuit.layer_2_circuit_sides) == 2
     assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.is_tagged is True
     assert (
-        subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.geant_sid == creation_form_input_data[0]["geant_sid"]
+        subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.gs_id == creation_form_input_data[0]["gs_id"]
     )
     assert (
         str(subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.edge_port.owner_subscription_id)
diff --git a/test/workflows/l2_circuit/test_create_layer_2_circuit.py b/test/workflows/l2_circuit/test_create_layer_2_circuit.py
index c0d1b2df..edfab4dd 100644
--- a/test/workflows/l2_circuit/test_create_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_create_layer_2_circuit.py
@@ -28,7 +28,7 @@ def layer_2_circuit_input(faker, partner_factory, edge_port_subscription_factory
             "vlan_range_upper_bound": faker.vlan_id(),
             "policer_bandwidth": faker.bandwidth() if policer_enabled else None,
             "policer_burst_rate": faker.bandwidth() if policer_enabled else None,
-            "geant_sid": faker.geant_sid(),
+            "gs_id": faker.geant_sid(),
             "layer_2_circuit_side_a": {"edge_port": edge_port_a, "vlan_id": faker.vlan_id()},
             "layer_2_circuit_side_b": {"edge_port": edge_port_b, "vlan_id": faker.vlan_id()},
         },
@@ -56,13 +56,13 @@ def test_create_layer_2_circuit_success(
         == layer_2_circuit_input[2]["layer_2_circuit_side_a"]["edge_port"]
     )
     assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.is_tagged is True
-    assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.geant_sid == layer_2_circuit_input[2]["geant_sid"]
+    assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.gs_id == layer_2_circuit_input[2]["gs_id"]
     assert (
         str(subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.edge_port.owner_subscription_id)
         == layer_2_circuit_input[2]["layer_2_circuit_side_b"]["edge_port"]
     )
     assert subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.is_tagged is True
-    assert subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.geant_sid == layer_2_circuit_input[2]["geant_sid"]
+    assert subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.gs_id == layer_2_circuit_input[2]["gs_id"]
     assert subscription.layer_2_circuit.layer_2_circuit_type == Layer2CircuitType.TAGGED
     assert subscription.layer_2_circuit.vlan_range_lower_bound == layer_2_circuit_input[2]["vlan_range_lower_bound"]
     assert subscription.layer_2_circuit.vlan_range_upper_bound == layer_2_circuit_input[2]["vlan_range_upper_bound"]
diff --git a/test/workflows/l3_core_service/test_create_imported_l3_core_service.py b/test/workflows/l3_core_service/test_create_imported_l3_core_service.py
index 626c6237..0580bb5c 100644
--- a/test/workflows/l3_core_service/test_create_imported_l3_core_service.py
+++ b/test/workflows/l3_core_service/test_create_imported_l3_core_service.py
@@ -27,7 +27,7 @@ def test_create_imported_l3_core_service_success(
             {
                 "edge_port": edge_port_subscription_factory(),
                 "ap_type": "PRIMARY",
-                "geant_sid": faker.geant_sid(),
+                "gs_id": faker.geant_sid(),
                 "sbp_type": SBPType.L3,
                 "is_tagged": faker.boolean(),
                 "vlan_id": faker.vlan_id(),
diff --git a/test/workflows/l3_core_service/test_create_l3_core_service.py b/test/workflows/l3_core_service/test_create_l3_core_service.py
index 149fdf20..2295e362 100644
--- a/test/workflows/l3_core_service/test_create_l3_core_service.py
+++ b/test/workflows/l3_core_service/test_create_l3_core_service.py
@@ -49,7 +49,7 @@ def test_create_l3_core_service_success(
         {"tt_number": faker.tt_number(), "partner": partner["partner_id"]},
         {"edge_port": {"edge_port": edge_port_a, "ap_type": APType.PRIMARY}},
         {
-            "geant_sid": faker.geant_sid(),
+            "gs_id": faker.geant_sid(),
             "is_tagged": faker.boolean(),
             "vlan_id": faker.vlan_id(),
             "ipv4_address": faker.ipv4(),
diff --git a/test/workflows/l3_core_service/test_modify_l3_core_service.py b/test/workflows/l3_core_service/test_modify_l3_core_service.py
index 67ff8880..333fc670 100644
--- a/test/workflows/l3_core_service/test_modify_l3_core_service.py
+++ b/test/workflows/l3_core_service/test_modify_l3_core_service.py
@@ -84,7 +84,7 @@ def test_modify_l3_core_service_add_new_edge_port_success(
         {},  # The existing SBPs are unchanged
         {},
         {  # Adding configuration for the new SBP
-            "geant_sid": faker.geant_sid(),
+            "gs_id": faker.geant_sid(),
             "vlan_id": faker.vlan_id(),
             "ipv4_address": faker.ipv4(),
             "ipv6_address": faker.ipv6(),
@@ -115,7 +115,7 @@ def test_modify_l3_core_service_add_new_edge_port_success(
 def sbp_input_form_data(faker):
     def _generate_form_data():
         return {
-            "geant_sid": faker.geant_sid(),
+            "gs_id": faker.geant_sid(),
             "is_tagged": True,
             "vlan_id": faker.vlan_id(),
             "ipv4_address": faker.ipv4(),
@@ -198,7 +198,7 @@ def test_modify_l3_core_service_modify_edge_port_success(
     assert len(subscription.l3_core_service.ap_list) == 2
 
     for i in range(2):
-        assert subscription.l3_core_service.ap_list[i].sbp.geant_sid == new_sbp_data[i]["geant_sid"]
+        assert subscription.l3_core_service.ap_list[i].sbp.gs_id == new_sbp_data[i]["gs_id"]
         assert subscription.l3_core_service.ap_list[i].sbp.is_tagged == new_sbp_data[i]["is_tagged"]
         assert subscription.l3_core_service.ap_list[i].sbp.vlan_id == new_sbp_data[i]["vlan_id"]
         assert str(subscription.l3_core_service.ap_list[i].sbp.ipv4_address) == new_sbp_data[i]["ipv4_address"]
-- 
GitLab


From f064efed78be7b3b53c4df4b578f9d079fa0d2ae Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 09:53:45 +0100
Subject: [PATCH 09/20] Make ruff happy

---
 gso/workflows/iptrunk/migrate_iptrunk.py                      | 4 +---
 .../l2_circuit/test_create_imported_layer_2_circuit.py        | 4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py
index e0a42d19..03ee4465 100644
--- a/gso/workflows/iptrunk/migrate_iptrunk.py
+++ b/gso/workflows/iptrunk/migrate_iptrunk.py
@@ -769,9 +769,7 @@ def update_subscription_model(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    subscription.description = (
-        f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{subscription.iptrunk.gs_id}"
-    )
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{subscription.iptrunk.gs_id}"
 
     return {"subscription": subscription}
 
diff --git a/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py b/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
index 1bc9884a..2d4ed7a2 100644
--- a/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
@@ -43,9 +43,7 @@ def test_create_imported_layer_2_circuit_success(
     assert subscription.layer_2_circuit.virtual_circuit_id == creation_form_input_data[0]["vc_id"]
     assert len(subscription.layer_2_circuit.layer_2_circuit_sides) == 2
     assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.is_tagged is True
-    assert (
-        subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.gs_id == creation_form_input_data[0]["gs_id"]
-    )
+    assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.gs_id == creation_form_input_data[0]["gs_id"]
     assert (
         str(subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.edge_port.owner_subscription_id)
         == creation_form_input_data[0]["layer_2_circuit_side_a"]["edge_port"]
-- 
GitLab


From 6f9601271f35c3ebd50c194aa40564792b0c5cee Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 12:43:25 +0100
Subject: [PATCH 10/20] Add the GA_ID and GS_ID sequence to manage automatic
 creation of GA and GS ids

---
 ...05_79192e72131c_add_gs_and_ga_sequences.py | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 gso/migrations/versions/2024-12-05_79192e72131c_add_gs_and_ga_sequences.py

diff --git a/gso/migrations/versions/2024-12-05_79192e72131c_add_gs_and_ga_sequences.py b/gso/migrations/versions/2024-12-05_79192e72131c_add_gs_and_ga_sequences.py
new file mode 100644
index 00000000..2fb7fc2d
--- /dev/null
+++ b/gso/migrations/versions/2024-12-05_79192e72131c_add_gs_and_ga_sequences.py
@@ -0,0 +1,42 @@
+"""Add GS and GA sequences.
+
+Revision ID: 79192e72131c
+Revises: e36b3bd8a45c
+Create Date: 2024-12-05 11:11:41.048264
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = '79192e72131c'
+down_revision = 'e36b3bd8a45c'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+    # Create GS ID sequence
+    op.execute("""
+    CREATE SEQUENCE gs_id_seq
+        START WITH 50000
+        INCREMENT BY 1
+        MINVALUE 50000
+        MAXVALUE 99999
+        NO CYCLE;
+    """)
+
+    # Create GA ID sequence
+    op.execute("""
+    CREATE SEQUENCE ga_id_seq
+        START WITH 50000
+        INCREMENT BY 1
+        MINVALUE 50000
+        MAXVALUE 99999
+        NO CYCLE;
+    """)
+
+
+def downgrade() -> None:
+    op.execute("DROP SEQUENCE gs_id_seq")
+    op.execute("DROP SEQUENCE ga_id_seq")
-- 
GitLab


From 28a66dea05e975e1eb1110a88bfaf96f7dc36cfa Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 12:46:13 +0100
Subject: [PATCH 11/20] Make GA and GS unique ids functionality

---
 gso/services/subscriptions.py | 38 +++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/gso/services/subscriptions.py b/gso/services/subscriptions.py
index 9185265c..e5b3c8e7 100644
--- a/gso/services/subscriptions.py
+++ b/gso/services/subscriptions.py
@@ -19,6 +19,8 @@ from orchestrator.db import (
 from orchestrator.domain import SubscriptionModel
 from orchestrator.services.subscriptions import query_in_use_by_subscriptions
 from orchestrator.types import SubscriptionLifecycle, UUIDstr
+from sqlalchemy import text
+from sqlalchemy.exc import SQLAlchemyError
 
 from gso.products import ProductName, ProductType
 from gso.products.product_types.site import Site
@@ -329,3 +331,39 @@ def is_virtual_circuit_id_available(virtual_circuit_id: str) -> bool:
         True if the virtual circuit ID is unique (not found), False if it exists.
     """
     return is_resource_type_value_unique("virtual_circuit_id", virtual_circuit_id)
+
+
+def make_unique_gs_id() -> str:
+    """Generate a unique GS ID using the gs_id_seq database sequence.
+
+    Returns:
+        str: A unique GS ID in the format `GS-<number>`.
+
+    Raises:
+        ValueError: If there is an error generating the ID.
+    """
+    try:
+        new_id = db.session.execute(text("SELECT nextval('gs_id_seq')")).scalar_one()
+    except SQLAlchemyError as exc:
+        error_message = f"Error generating GS ID: {exc}"
+        raise ValueError(error_message) from exc
+    else:
+        return f"GS-{new_id}"
+
+
+def make_unique_ga_id() -> str:
+    """Generate a unique GA ID using the ga_id_seq database sequence.
+
+    Returns:
+        str: A unique GA ID in the format `GA<number>`.
+
+    Raises:
+        ValueError: If there is an error generating the ID.
+    """
+    try:
+        new_id = db.session.execute(text("SELECT nextval('ga_id_seq')")).scalar_one()
+    except SQLAlchemyError as exc:
+        error_message = f"Error generating GA ID: {exc}"
+        raise ValueError(error_message) from exc
+    else:
+        return f"GA-{new_id}"
-- 
GitLab


From c0b3a84142bdc913fab4d862fd84b1fa62ad537d Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 12:48:19 +0100
Subject: [PATCH 12/20] Update create EdgePort WF

---
 gso/workflows/edge_port/create_edge_port.py       | 5 ++---
 test/workflows/edge_port/test_create_edge_port.py | 5 ++---
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/gso/workflows/edge_port/create_edge_port.py b/gso/workflows/edge_port/create_edge_port.py
index ccd022f6..a3ff763c 100644
--- a/gso/workflows/edge_port/create_edge_port.py
+++ b/gso/workflows/edge_port/create_edge_port.py
@@ -22,6 +22,7 @@ from gso.products.product_types.router import Router
 from gso.services.lso_client import LSOState, lso_interaction
 from gso.services.netbox_client import NetboxClient
 from gso.services.partners import get_partner_by_id
+from gso.services.subscriptions import make_unique_ga_id
 from gso.utils.helpers import (
     active_pe_router_selector,
     available_interfaces_choices,
@@ -52,7 +53,6 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         minimum_links: int
         mac_address: str | None = None
         ignore_if_down: bool = False
-        ga_id: str | None = None
 
         @model_validator(mode="after")
         def validate_number_of_members(self) -> Self:
@@ -104,7 +104,6 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         "minimum_links",
         "mac_address",
         "ignore_if_down",
-        "ga_id",
         "enable_lacp",
         "edge_port_name",
         "edge_port_description",
@@ -134,7 +133,6 @@ def initialize_subscription(
     encapsulation: EncapsulationType,
     name: str,
     minimum_links: int,
-    ga_id: str | None,
     mac_address: str | None,
     partner: str,
     enable_lacp: bool,  # noqa: FBT001
@@ -152,6 +150,7 @@ def initialize_subscription(
     subscription.edge_port.edge_port_name = name
     subscription.edge_port.minimum_links = minimum_links
     subscription.edge_port.ignore_if_down = ignore_if_down
+    ga_id = make_unique_ga_id()
     subscription.edge_port.ga_id = ga_id
     subscription.edge_port.mac_address = mac_address
     partner_name = get_partner_by_id(partner).name
diff --git a/test/workflows/edge_port/test_create_edge_port.py b/test/workflows/edge_port/test_create_edge_port.py
index 35cf2613..107dab95 100644
--- a/test/workflows/edge_port/test_create_edge_port.py
+++ b/test/workflows/edge_port/test_create_edge_port.py
@@ -50,7 +50,6 @@ def input_form_wizard_data(request, router_subscription_factory, partner_factory
         "node": router_subscription_factory(vendor=Vendor.NOKIA),
         "partner": partner_factory(name="GAAR", email=faker.email())["partner_id"],
         "service_type": EdgePortType.PUBLIC,
-        "ga_id": faker.geant_gid(),
         "enable_lacp": True,
         "speed": PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND,
         "encapsulation": EncapsulationType.DOT1Q,
@@ -101,9 +100,9 @@ def test_successful_edge_port_creation(
     subscription = EdgePort.from_subscription(subscription_id)
 
     assert subscription.status == "active"
-    ga_id = input_form_wizard_data[0]["ga_id"]
     router_fqdn = Router.from_subscription(input_form_wizard_data[0]["node"]).router.router_fqdn
-    assert subscription.description == f"Edge Port lag-21 on {router_fqdn}, GAAR, {ga_id}"
+    assert subscription.edge_port.ga_id is not None
+    assert subscription.description == f"Edge Port lag-21 on {router_fqdn}, GAAR, {subscription.edge_port.ga_id}"
     assert len(subscription.edge_port.edge_port_ae_members) == 2
     assert mock_execute_playbook.call_count == 2
 
-- 
GitLab


From 66bf227e8ca3c510e855bb65ba67d96b07b436df Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 12:52:39 +0100
Subject: [PATCH 13/20] Update create EdgePort WF and rename generating GA and
 GS ids function

---
 gso/services/subscriptions.py               | 4 ++--
 gso/workflows/edge_port/create_edge_port.py | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gso/services/subscriptions.py b/gso/services/subscriptions.py
index e5b3c8e7..e6781244 100644
--- a/gso/services/subscriptions.py
+++ b/gso/services/subscriptions.py
@@ -333,7 +333,7 @@ def is_virtual_circuit_id_available(virtual_circuit_id: str) -> bool:
     return is_resource_type_value_unique("virtual_circuit_id", virtual_circuit_id)
 
 
-def make_unique_gs_id() -> str:
+def generate_unique_gs_id() -> str:
     """Generate a unique GS ID using the gs_id_seq database sequence.
 
     Returns:
@@ -351,7 +351,7 @@ def make_unique_gs_id() -> str:
         return f"GS-{new_id}"
 
 
-def make_unique_ga_id() -> str:
+def generate_unique_ga_id() -> str:
     """Generate a unique GA ID using the ga_id_seq database sequence.
 
     Returns:
diff --git a/gso/workflows/edge_port/create_edge_port.py b/gso/workflows/edge_port/create_edge_port.py
index a3ff763c..a62c7147 100644
--- a/gso/workflows/edge_port/create_edge_port.py
+++ b/gso/workflows/edge_port/create_edge_port.py
@@ -22,7 +22,7 @@ from gso.products.product_types.router import Router
 from gso.services.lso_client import LSOState, lso_interaction
 from gso.services.netbox_client import NetboxClient
 from gso.services.partners import get_partner_by_id
-from gso.services.subscriptions import make_unique_ga_id
+from gso.services.subscriptions import generate_unique_ga_id
 from gso.utils.helpers import (
     active_pe_router_selector,
     available_interfaces_choices,
@@ -150,7 +150,7 @@ def initialize_subscription(
     subscription.edge_port.edge_port_name = name
     subscription.edge_port.minimum_links = minimum_links
     subscription.edge_port.ignore_if_down = ignore_if_down
-    ga_id = make_unique_ga_id()
+    ga_id = generate_unique_ga_id()
     subscription.edge_port.ga_id = ga_id
     subscription.edge_port.mac_address = mac_address
     partner_name = get_partner_by_id(partner).name
-- 
GitLab


From f11acd44d7dd6acc52571187376875e307248a7f Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 13:25:32 +0100
Subject: [PATCH 14/20] Update create Iptrunk WF

---
 gso/workflows/iptrunk/create_iptrunk.py       | 18 ++++++++----------
 test/workflows/iptrunk/test_create_iptrunk.py |  6 ++----
 2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index eefcd46c..8f24e333 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -57,7 +57,11 @@ from gso.services.lso_client import LSOState, lso_interaction
 from gso.services.netbox_client import NetboxClient
 from gso.services.partners import get_partner_by_name
 from gso.services.sharepoint import SharePointClient
-from gso.services.subscriptions import get_non_terminated_iptrunk_subscriptions
+from gso.services.subscriptions import (
+    generate_unique_ga_id,
+    generate_unique_gs_id,
+    get_non_terminated_iptrunk_subscriptions,
+)
 from gso.settings import load_oss_params
 from gso.utils.helpers import (
     available_interfaces_choices,
@@ -86,7 +90,6 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
 
         tt_number: TTNumber
         partner: ReadOnlyField("GEANT", default_type=str)  # type: ignore[valid-type]
-        gs_id: str | None = None
         iptrunk_description: str | None = None
         iptrunk_type: IptrunkType
         iptrunk_speed: PhysicalPortCapacity
@@ -144,7 +147,6 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         model_config = ConfigDict(title=f"Provide subscription details for side A of the trunk. ({router_a_fqdn})")
 
         side_a_ae_iface: available_lags_choices(router_a) or str  # type: ignore[valid-type]
-        side_a_ga_id: str | None
         side_a_ae_members: ae_members_side_a_type
 
     user_input_side_a = yield CreateIptrunkSideAForm
@@ -182,7 +184,6 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         model_config = ConfigDict(title=f"Provide subscription details for side B of the trunk. ({router_b_fqdn})")
 
         side_b_ae_iface: available_lags_choices(router_b) or str  # type: ignore[valid-type]
-        side_b_ga_id: str | None
         side_b_ae_members: ae_members_side_b
 
     user_input_side_b = yield CreateIptrunkSideBForm
@@ -196,7 +197,6 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
     )
     summary_form_data = input_forms_data | {"side_a_node": router_a_fqdn, "side_b_node": router_b_fqdn}
     summary_fields = [
-        "gs_id",
         "iptrunk_type",
         "iptrunk_speed",
         "iptrunk_description",
@@ -204,11 +204,9 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
         "side_a_node",
         "side_a_ae_iface",
         "side_a_ae_members",
-        "side_a_ga_id",
         "side_b_node",
         "side_b_ae_iface",
         "side_b_ae_members",
-        "side_b_ga_id",
     ]
     yield from create_summary_form(summary_form_data, product_name, summary_fields)
 
@@ -322,24 +320,22 @@ def ping_all_hosts_v6(new_ipv6_network: str) -> State:
 @step("Initialize subscription")
 def initialize_subscription(
     subscription: IptrunkInactive,
-    gs_id: str | None,
     iptrunk_type: IptrunkType,
     iptrunk_description: str | None,
     iptrunk_speed: PhysicalPortCapacity,
     iptrunk_minimum_links: int,
     side_a_node_id: str,
     side_a_ae_iface: str,
-    side_a_ga_id: str | None,
     side_a_ae_members: list[dict],
     side_b_node_id: str,
     side_b_ae_iface: str,
-    side_b_ga_id: str | None,
     side_b_ae_members: list[dict],
 ) -> State:
     """Take all input from the user, and store it in the database."""
     oss_params = load_oss_params()
     side_a = Router.from_subscription(side_a_node_id).router
     side_b = Router.from_subscription(side_b_node_id).router
+    gs_id = generate_unique_gs_id()
     subscription.iptrunk.gs_id = gs_id
     subscription.iptrunk.iptrunk_description = iptrunk_description
     subscription.iptrunk.iptrunk_type = iptrunk_type
@@ -349,6 +345,7 @@ def initialize_subscription(
 
     subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node = side_a
     subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface = side_a_ae_iface
+    side_a_ga_id = generate_unique_ga_id()
     subscription.iptrunk.iptrunk_sides[0].ga_id = side_a_ga_id
     for member in side_a_ae_members:
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members.append(
@@ -357,6 +354,7 @@ def initialize_subscription(
 
     subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node = side_b
     subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_iface = side_b_ae_iface
+    side_b_ga_id = generate_unique_ga_id()
     subscription.iptrunk.iptrunk_sides[1].ga_id = side_b_ga_id
     for member in side_b_ae_members:
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_ae_members.append(
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index 17c37388..a45f3bf1 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -65,7 +65,6 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
 
     create_ip_trunk_step = {
         "tt_number": faker.tt_number(),
-        "gs_id": faker.geant_sid(),
         "iptrunk_type": IptrunkType.DARK_FIBER,
         "iptrunk_description": faker.sentence(),
         "iptrunk_speed": PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND,
@@ -75,7 +74,6 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
     create_ip_trunk_side_a_router_name = {"side_a_node_id": router_side_a}
     create_ip_trunk_side_a_step = {
         "side_a_ae_iface": "lag-1",
-        "side_a_ga_id": None,
         "side_a_ae_members": [
             {
                 "interface_name": f"Interface{interface}",
@@ -87,7 +85,6 @@ def input_form_wizard_data(request, router_subscription_factory, faker):
     create_ip_trunk_side_b_router_name = {"side_b_node_id": router_side_b}
     create_ip_trunk_side_b_step = {
         "side_b_ae_iface": "lag-4",
-        "side_b_ga_id": faker.geant_sid(),
         "side_b_ae_members": side_b_members,
     }
     summary_view_step = {}
@@ -153,8 +150,9 @@ def test_successful_iptrunk_creation_with_standard_lso_result(
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
     assert subscription.status == "provisioning"
+    assert subscription.iptrunk.gs_id is not None
     assert subscription.description == (
-        f"IP trunk {sorted_sides[0]} {sorted_sides[1]}, gs_id:{input_form_wizard_data[0]["gs_id"]}"
+        f"IP trunk {sorted_sides[0]} {sorted_sides[1]}, gs_id:{subscription.iptrunk.gs_id}"
     )
 
     assert mock_execute_playbook.call_count == 6
-- 
GitLab


From f4f004921d653d0568bef3173e4fb1226e59c06e Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 13:41:11 +0100
Subject: [PATCH 15/20] Update create L3 core service and L2 Circuit WFs

---
 gso/workflows/l2_circuit/create_layer_2_circuit.py         | 4 ++--
 gso/workflows/l3_core_service/create_l3_core_service.py    | 4 +++-
 test/workflows/l2_circuit/test_create_layer_2_circuit.py   | 7 ++++---
 .../l3_core_service/test_create_l3_core_service.py         | 1 -
 4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/gso/workflows/l2_circuit/create_layer_2_circuit.py b/gso/workflows/l2_circuit/create_layer_2_circuit.py
index 7959a30b..acf5beef 100644
--- a/gso/workflows/l2_circuit/create_layer_2_circuit.py
+++ b/gso/workflows/l2_circuit/create_layer_2_circuit.py
@@ -19,6 +19,7 @@ from gso.products.product_blocks.service_binding_port import ServiceBindingPortI
 from gso.products.product_types.edge_port import EdgePort
 from gso.products.product_types.layer_2_circuit import Layer2Circuit, Layer2CircuitInactive
 from gso.services.partners import get_partner_by_name
+from gso.services.subscriptions import generate_unique_gs_id
 from gso.utils.helpers import active_edge_port_selector, generate_unique_vc_id, partner_choice
 from gso.utils.shared_enums import SBPType
 from gso.utils.types.interfaces import BandwidthString
@@ -69,7 +70,6 @@ def initial_input_generator(product_name: str) -> FormGenerator:
         vlan_divider: Divider = Field(None, exclude=True)
         policer_bandwidth: _policer_field(policer_enabled=initial_user_input.policer_enabled)  # type: ignore[valid-type]
         policer_burst_rate: _policer_field(policer_enabled=initial_user_input.policer_enabled)  # type: ignore[valid-type]
-        gs_id: str
         layer_2_circuit_side_a: Layer2CircuitSideSelection
         side_divider: Divider = Field(None, exclude=True)
         layer_2_circuit_side_b: Layer2CircuitSideSelection
@@ -105,10 +105,10 @@ def initialize_subscription(
     policer_enabled: bool,  # noqa: FBT001
     policer_bandwidth: BandwidthString | None,
     policer_burst_rate: BandwidthString | None,
-    gs_id: str,
 ) -> State:
     """Build a subscription object from all user input."""
     layer_2_circuit_sides = []
+    gs_id = generate_unique_gs_id()
     for circuit_side_data in [layer_2_circuit_side_a, layer_2_circuit_side_b]:
         sbp = ServiceBindingPortInactive.new(
             uuid4(),
diff --git a/gso/workflows/l3_core_service/create_l3_core_service.py b/gso/workflows/l3_core_service/create_l3_core_service.py
index 04edd53f..cd42c761 100644
--- a/gso/workflows/l3_core_service/create_l3_core_service.py
+++ b/gso/workflows/l3_core_service/create_l3_core_service.py
@@ -20,6 +20,7 @@ from gso.products.product_types.edge_port import EdgePort
 from gso.products.product_types.l3_core_service import L3CoreService, L3CoreServiceInactive
 from gso.services.lso_client import LSOState, lso_interaction
 from gso.services.partners import get_partner_by_id
+from gso.services.subscriptions import generate_unique_gs_id
 from gso.utils.helpers import (
     active_edge_port_selector,
     partner_choice,
@@ -113,7 +114,6 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
             exclude=True,
         )
 
-        gs_id: str
         is_tagged: bool = False
         vlan_id: VLAN_ID
         custom_firewall_filters: bool = False
@@ -165,6 +165,7 @@ def initialize_subscription(
         BGPSession.new(subscription_id=uuid4(), rtbh_enabled=True, is_multi_hop=True, **session)
         for session in binding_port_input["bgp_peers"]
     ]
+    sbp_gs_id = generate_unique_gs_id()
     service_binding_port = ServiceBindingPortInactive.new(
         subscription_id=uuid4(),
         v4_bfd_settings=BFDSettings.new(subscription_id=uuid4(), **(binding_port_input.pop("v4_bfd_settings"))),
@@ -173,6 +174,7 @@ def initialize_subscription(
         bgp_session_list=sbp_bgp_session_list,
         sbp_type=SBPType.L3,
         edge_port=edge_port_subscription.edge_port,
+        gs_id=sbp_gs_id,
     )
     subscription.l3_core_service.ap_list.append(
         AccessPortInactive.new(
diff --git a/test/workflows/l2_circuit/test_create_layer_2_circuit.py b/test/workflows/l2_circuit/test_create_layer_2_circuit.py
index edfab4dd..c14ab121 100644
--- a/test/workflows/l2_circuit/test_create_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_create_layer_2_circuit.py
@@ -28,7 +28,6 @@ def layer_2_circuit_input(faker, partner_factory, edge_port_subscription_factory
             "vlan_range_upper_bound": faker.vlan_id(),
             "policer_bandwidth": faker.bandwidth() if policer_enabled else None,
             "policer_burst_rate": faker.bandwidth() if policer_enabled else None,
-            "gs_id": faker.geant_sid(),
             "layer_2_circuit_side_a": {"edge_port": edge_port_a, "vlan_id": faker.vlan_id()},
             "layer_2_circuit_side_b": {"edge_port": edge_port_b, "vlan_id": faker.vlan_id()},
         },
@@ -56,13 +55,15 @@ def test_create_layer_2_circuit_success(
         == layer_2_circuit_input[2]["layer_2_circuit_side_a"]["edge_port"]
     )
     assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.is_tagged is True
-    assert subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.gs_id == layer_2_circuit_input[2]["gs_id"]
+    assert (
+        subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.gs_id
+        == subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.gs_id
+    )
     assert (
         str(subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.edge_port.owner_subscription_id)
         == layer_2_circuit_input[2]["layer_2_circuit_side_b"]["edge_port"]
     )
     assert subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.is_tagged is True
-    assert subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.gs_id == layer_2_circuit_input[2]["gs_id"]
     assert subscription.layer_2_circuit.layer_2_circuit_type == Layer2CircuitType.TAGGED
     assert subscription.layer_2_circuit.vlan_range_lower_bound == layer_2_circuit_input[2]["vlan_range_lower_bound"]
     assert subscription.layer_2_circuit.vlan_range_upper_bound == layer_2_circuit_input[2]["vlan_range_upper_bound"]
diff --git a/test/workflows/l3_core_service/test_create_l3_core_service.py b/test/workflows/l3_core_service/test_create_l3_core_service.py
index 2295e362..c26e6494 100644
--- a/test/workflows/l3_core_service/test_create_l3_core_service.py
+++ b/test/workflows/l3_core_service/test_create_l3_core_service.py
@@ -49,7 +49,6 @@ def test_create_l3_core_service_success(
         {"tt_number": faker.tt_number(), "partner": partner["partner_id"]},
         {"edge_port": {"edge_port": edge_port_a, "ap_type": APType.PRIMARY}},
         {
-            "gs_id": faker.geant_sid(),
             "is_tagged": faker.boolean(),
             "vlan_id": faker.vlan_id(),
             "ipv4_address": faker.ipv4(),
-- 
GitLab


From 4208ca006232bb368739e0c724c6ccf1424aeb6c Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 15:58:34 +0100
Subject: [PATCH 16/20] Update the relevant import WF

---
 gso/cli/imports.py                            | 13 ++---
 gso/utils/types/geant_ids.py                  | 49 +++++++++++++++++++
 .../edge_port/create_imported_edge_port.py    |  5 +-
 .../iptrunk/create_imported_iptrunk.py        | 13 ++---
 test/cli/test_imports.py                      | 18 +++----
 test/conftest.py                              | 18 +++++--
 test/fixtures/edge_port_fixtures.py           |  2 +-
 test/fixtures/iptrunk_fixtures.py             |  4 +-
 test/fixtures/l3_core_service_fixtures.py     |  2 +-
 test/fixtures/layer_2_circuit_fixtures.py     |  2 +-
 .../test_create_imported_edge_port.py         |  2 +-
 .../edge_port/test_modify_edge_port.py        |  4 +-
 .../iptrunk/test_create_imported_iptrunk.py   |  6 +--
 .../iptrunk/test_modify_trunk_interface.py    |  6 +--
 .../test_create_imported_layer_2_circuit.py   |  2 +-
 .../test_create_imported_l3_core_service.py   |  2 +-
 .../test_modify_l3_core_service.py            |  4 +-
 17 files changed, 107 insertions(+), 45 deletions(-)
 create mode 100644 gso/utils/types/geant_ids.py

diff --git a/gso/cli/imports.py b/gso/cli/imports.py
index ba33565e..4c973ace 100644
--- a/gso/cli/imports.py
+++ b/gso/cli/imports.py
@@ -40,6 +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.geant_ids import IMPORTED_GA_ID, IMPORTED_GS_ID
 from gso.utils.types.interfaces import BandwidthString, LAGMember, LAGMemberList, PhysicalPortCapacity
 from gso.utils.types.ip_address import (
     AddressSpace,
@@ -116,7 +117,7 @@ class IptrunkImportModel(BaseModel):
     """Required fields for importing an existing ``gso.products.product_types.iptrunk``."""
 
     partner: str
-    gs_id: str | None
+    gs_id: IMPORTED_GS_ID | None
     iptrunk_type: IptrunkType
     iptrunk_description: str | None = None
     iptrunk_speed: PhysicalPortCapacity
@@ -124,11 +125,11 @@ class IptrunkImportModel(BaseModel):
     iptrunk_isis_metric: int
     side_a_node_id: str
     side_a_ae_iface: str
-    side_a_ga_id: str | None
+    side_a_ga_id: IMPORTED_GA_ID | None
     side_a_ae_members: LAGMemberList[LAGMember]
     side_b_node_id: str
     side_b_ae_iface: str
-    side_b_ga_id: str | None
+    side_b_ga_id: IMPORTED_GA_ID | None
     side_b_ae_members: LAGMemberList[LAGMember]
 
     iptrunk_ipv4_network: ipaddress.IPv4Network
@@ -197,7 +198,7 @@ class EdgePortImportModel(BaseModel):
     encapsulation: EncapsulationType
     name: str
     minimum_links: int
-    ga_id: str | None
+    ga_id: IMPORTED_GA_ID | None
     mac_address: str | None
     partner: str
     enable_lacp: bool
@@ -269,7 +270,7 @@ class L3CoreServiceImportModel(BaseModel):
 
         edge_port: str
         ap_type: str
-        gs_id: str
+        gs_id: IMPORTED_GS_ID
         sbp_type: SBPType = SBPType.L3
         is_tagged: bool = False
         vlan_id: VLAN_ID
@@ -349,7 +350,7 @@ class Layer2CircuitServiceImportModel(BaseModel):
 
     service_type: Layer2CircuitServiceType
     partner: str
-    gs_id: str
+    gs_id: IMPORTED_GS_ID
     vc_id: VC_ID
     layer_2_circuit_side_a: ServiceBindingPortInput
     layer_2_circuit_side_b: ServiceBindingPortInput
diff --git a/gso/utils/types/geant_ids.py b/gso/utils/types/geant_ids.py
new file mode 100644
index 00000000..adc3b19c
--- /dev/null
+++ b/gso/utils/types/geant_ids.py
@@ -0,0 +1,49 @@
+"""Type definitions for the GA and GS IDs."""
+
+from functools import partial
+from typing import Annotated
+
+from pydantic import AfterValidator
+
+from gso.services.subscriptions import is_resource_type_value_unique
+
+
+def validate_id(value: str, prefix: str, field_name: str) -> str:
+    """Validate that the ID is unique, has the correct prefix, and is within valid constraints.
+
+    Args:
+        value (str): The ID value to validate.
+        prefix (str): The required prefix for the ID (e.g., "GA-" or "GS-").
+        field_name (str): The database field name to check for uniqueness (e.g., "ga_id" or "gs_id").
+
+    Raises:
+        ValueError: If the ID is not valid.
+
+    Returns:
+        str: The validated ID.
+    """
+    min_range = 50000
+    max_range = 99999
+    if not value.startswith(prefix):
+        err = f"{field_name} must start with the prefix '{prefix}'."
+        raise ValueError(err)
+
+    try:
+        numeric_part = int(value[len(prefix) :])
+    except ValueError:
+        err = f"{field_name} must have a numeric part after the prefix '{prefix}'."
+        raise ValueError(err) from ValueError
+
+    if min_range <= numeric_part < max_range:
+        err = f"{field_name} must not have a numeric part between 50000 and 99999."
+        raise ValueError(err)
+
+    if not is_resource_type_value_unique(field_name, value):
+        err = f"{field_name} must be unique."
+        raise ValueError(err)
+
+    return value
+
+
+IMPORTED_GA_ID = Annotated[str, AfterValidator(partial(validate_id, prefix="GA-", field_name="ga_id"))]
+IMPORTED_GS_ID = Annotated[str, AfterValidator(partial(validate_id, prefix="GS-", field_name="gs_id"))]
diff --git a/gso/workflows/edge_port/create_imported_edge_port.py b/gso/workflows/edge_port/create_imported_edge_port.py
index 07d4abf3..cd5f7a7b 100644
--- a/gso/workflows/edge_port/create_imported_edge_port.py
+++ b/gso/workflows/edge_port/create_imported_edge_port.py
@@ -20,6 +20,7 @@ from gso.products.product_types.router import Router
 from gso.services.partners import get_partner_by_name
 from gso.services.subscriptions import get_product_id_by_name
 from gso.utils.helpers import active_pe_router_selector
+from gso.utils.types.geant_ids import IMPORTED_GA_ID
 from gso.utils.types.interfaces import LAGMember, PhysicalPortCapacity
 
 
@@ -48,7 +49,7 @@ def initial_input_form_generator() -> FormGenerator:
         minimum_links: int
         mac_address: str | None = None
         ignore_if_down: bool = False
-        ga_id: str | None = None
+        ga_id: IMPORTED_GA_ID | None = None
         description: str | None = None
         name: str
         ae_members: Annotated[list[LAGMember], AfterValidator(validate_unique_list)]
@@ -67,7 +68,7 @@ def initialize_subscription(
     encapsulation: EncapsulationType,
     name: str,
     minimum_links: int,
-    ga_id: str | None,
+    ga_id: IMPORTED_GA_ID | None,
     mac_address: str | None,
     partner: str,
     enable_lacp: bool,  # noqa: FBT001
diff --git a/gso/workflows/iptrunk/create_imported_iptrunk.py b/gso/workflows/iptrunk/create_imported_iptrunk.py
index db88b2b8..1feec505 100644
--- a/gso/workflows/iptrunk/create_imported_iptrunk.py
+++ b/gso/workflows/iptrunk/create_imported_iptrunk.py
@@ -20,6 +20,7 @@ from gso.products.product_types.router import Router
 from gso.services import subscriptions
 from gso.services.partners import get_partner_by_name
 from gso.utils.helpers import active_router_selector
+from gso.utils.types.geant_ids import IMPORTED_GA_ID, IMPORTED_GS_ID
 from gso.utils.types.interfaces import LAGMember, LAGMemberList, PhysicalPortCapacity
 
 
@@ -30,7 +31,7 @@ def initial_input_form_generator() -> FormGenerator:
         model_config = ConfigDict(title="Import Iptrunk")
 
         partner: str
-        gs_id: str | None = None
+        gs_id: IMPORTED_GS_ID | None = None
         iptrunk_description: str | None = None
         iptrunk_type: IptrunkType
         iptrunk_speed: PhysicalPortCapacity
@@ -39,12 +40,12 @@ def initial_input_form_generator() -> FormGenerator:
 
         side_a_node_id: active_router_selector()  # type: ignore[valid-type]
         side_a_ae_iface: str
-        side_a_ga_id: str | None = None
+        side_a_ga_id: IMPORTED_GA_ID | None = None
         side_a_ae_members: Annotated[list[LAGMember], AfterValidator(validate_unique_list)]
 
         side_b_node_id: active_router_selector()  # type: ignore[valid-type]
         side_b_ae_iface: str
-        side_b_ga_id: str | None = None
+        side_b_ga_id: IMPORTED_GA_ID | None = None
         side_b_ae_members: Annotated[list[LAGMember], AfterValidator(validate_unique_list)]
 
         iptrunk_ipv4_network: ipaddress.IPv4Network
@@ -71,7 +72,7 @@ def create_subscription(partner: str) -> State:
 @step("Initialize subscription")
 def initialize_subscription(
     subscription: ImportedIptrunkInactive,
-    gs_id: str | None,
+    gs_id: IMPORTED_GS_ID | None,
     iptrunk_type: IptrunkType,
     iptrunk_description: str,
     iptrunk_speed: PhysicalPortCapacity,
@@ -79,11 +80,11 @@ def initialize_subscription(
     iptrunk_isis_metric: int,
     side_a_node_id: str,
     side_a_ae_iface: str,
-    side_a_ga_id: str | None,
+    side_a_ga_id: IMPORTED_GA_ID | None,
     side_a_ae_members: LAGMemberList,
     side_b_node_id: str,
     side_b_ae_iface: str,
-    side_b_ga_id: str | None,
+    side_b_ga_id: IMPORTED_GA_ID | None,
     side_b_ae_members: LAGMemberList,
 ) -> State:
     """Take all input from the user, and store it in the database."""
diff --git a/test/cli/test_imports.py b/test/cli/test_imports.py
index 475492a4..571e64b6 100644
--- a/test/cli/test_imports.py
+++ b/test/cli/test_imports.py
@@ -62,7 +62,7 @@ def iptrunk_data(temp_file, router_subscription_factory, faker) -> (Path, dict):
         ipv6_network = ipv6_network or str(faker.ipv6_network(max_subnet=126))
 
         iptrunk_data = {
-            "id": faker.geant_sid(),
+            "id": faker.imported_gs_id(),
             "config": {
                 "common": {
                     "link_speed": PhysicalPortCapacity.HUNDRED_GIGABIT_PER_SECOND,
@@ -73,7 +73,7 @@ def iptrunk_data(temp_file, router_subscription_factory, faker) -> (Path, dict):
                 "nodeA": {
                     "name": side_a_node or Router.from_subscription(router_side_a).router.router_fqdn,
                     "ae_name": side_a_ae_name or faker.network_interface(),
-                    "port_ga_id": faker.geant_gid(),
+                    "port_ga_id": faker.imported_ga_id(),
                     "members": side_a_members
                     or [
                         {
@@ -88,7 +88,7 @@ def iptrunk_data(temp_file, router_subscription_factory, faker) -> (Path, dict):
                 "nodeB": {
                     "name": side_b_node or Router.from_subscription(router_side_b).router.router_fqdn,
                     "ae_name": side_b_ae_name or faker.network_interface(),
-                    "port_ga_id": faker.geant_gid(),
+                    "port_ga_id": faker.imported_ga_id(),
                     "members": side_b_members
                     or [
                         {
@@ -270,7 +270,7 @@ def edge_port_data(temp_file, faker, router_subscription_factory, partner_factor
             "encapsulation": EncapsulationType.DOT1Q,
             "name": "lag34",
             "minimum_links": 2,
-            "ga_id": faker.geant_gid(),
+            "ga_id": faker.imported_ga_id(),
             "mac_address": faker.mac_address(),
             "partner": partner_factory()["name"],
             "enable_lacp": True,
@@ -305,7 +305,7 @@ def l3_core_service_data(temp_file, faker, partner_factory, edge_port_subscripti
                 {
                     "edge_port": edge_port_subscription_factory(),
                     "ap_type": "PRIMARY",
-                    "gs_id": faker.geant_sid(),
+                    "gs_id": faker.imported_gs_id(),
                     "vlan_id": faker.vlan_id(),
                     "ipv4_address": faker.ipv4(),
                     "ipv4_mask": faker.ipv4_netmask(),
@@ -353,7 +353,7 @@ def l3_core_service_data(temp_file, faker, partner_factory, edge_port_subscripti
                 {
                     "edge_port": edge_port_subscription_factory(),
                     "ap_type": "BACKUP",
-                    "gs_id": faker.geant_sid(),
+                    "gs_id": faker.imported_gs_id(),
                     "vlan_id": faker.vlan_id(),
                     "ipv4_address": faker.ipv4(),
                     "ipv4_mask": faker.ipv4_netmask(),
@@ -414,7 +414,7 @@ def layer_2_circuit_data(temp_file, faker, partner_factory, edge_port_subscripti
         layer_2_circuit_input_data = {
             "partner": partner_factory()["name"],
             "service_type": Layer2CircuitServiceType.GEANT_PLUS,
-            "gs_id": faker.geant_sid(),
+            "gs_id": faker.imported_gs_id(),
             "vc_id": generate_unique_vc_id(),
             "layer_2_circuit_side_a": {
                 "edge_port": edge_port_subscription_factory(),
@@ -697,7 +697,7 @@ def test_import_l3_core_service_with_invalid_edge_port(
             {
                 "edge_port": fake_uuid,
                 "ap_type": "PRIMARY",
-                "gs_id": faker.geant_sid(),
+                "gs_id": faker.imported_gs_id(),
                 "vlan_id": faker.vlan_id(),
                 "ipv4_address": faker.ipv4(),
                 "ipv4_mask": faker.ipv4_netmask(),
@@ -737,7 +737,7 @@ def test_import_l3_core_service_with_invalid_edge_port(
             {
                 "edge_port": edge_port_subscription_factory(),
                 "ap_type": "BACKUP",
-                "gs_id": faker.geant_sid(),
+                "gs_id": faker.imported_gs_id(),
                 "vlan_id": faker.vlan_id(),
                 "ipv4_address": faker.ipv4(),
                 "ipv4_mask": faker.ipv4_netmask(),
diff --git a/test/conftest.py b/test/conftest.py
index da558c8a..4548fe0f 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -73,11 +73,21 @@ class FakerProvider(BaseProvider):
 
         return f"TT#{random_date}{random_int}"
 
-    def geant_gid(self) -> str:
-        return self.generator.numerify("GID-#####")
+    def ga_id(self) -> str:
+        random_int = self.generator.random_int(min=50000, max=99999)
+        return f"GA-{random_int}"
 
-    def geant_sid(self) -> str:
-        return self.generator.numerify("SID-#####")
+    def gs_id(self) -> str:
+        random_int = self.generator.random_int(min=50000, max=99999)
+        return f"GS-{random_int}"
+
+    def imported_ga_id(self) -> str:
+        random_int = self.generator.random_int(min=00000, max=50000)
+        return f"GA-{random_int}"
+
+    def imported_gs_id(self) -> str:
+        random_int = self.generator.random_int(min=00000, max=50000)
+        return f"GS-{random_int}"
 
     def site_name(self) -> str:
         site_name = "".join(self.generator.random_letter().upper() for _ in range(3))
diff --git a/test/fixtures/edge_port_fixtures.py b/test/fixtures/edge_port_fixtures.py
index 7ea6b8b9..0ea87449 100644
--- a/test/fixtures/edge_port_fixtures.py
+++ b/test/fixtures/edge_port_fixtures.py
@@ -52,7 +52,7 @@ def edge_port_subscription_factory(faker, partner_factory, router_subscription_f
             )
 
         edge_port_subscription.edge_port.edge_port_description = description or faker.text(max_nb_chars=30)
-        edge_port_subscription.edge_port.ga_id = ga_id or faker.geant_gid()
+        edge_port_subscription.edge_port.ga_id = ga_id or faker.ga_id()
         edge_port_subscription.edge_port.node = node or node
         edge_port_subscription.edge_port.edge_port_name = name or f"lag-{faker.pyint(21, 50)}"
         edge_port_subscription.edge_port.edge_port_description = edge_port_description or faker.sentence()
diff --git a/test/fixtures/iptrunk_fixtures.py b/test/fixtures/iptrunk_fixtures.py
index 17715ebe..742e974a 100644
--- a/test/fixtures/iptrunk_fixtures.py
+++ b/test/fixtures/iptrunk_fixtures.py
@@ -31,7 +31,7 @@ def iptrunk_side_subscription_factory(router_subscription_factory, faker):
                 iptrunk_side_node or router_subscription_factory(vendor=Vendor.NOKIA)
             ).router,
             iptrunk_side_ae_iface=iptrunk_side_ae_iface or faker.pystr(),
-            ga_id=ga_id or faker.geant_gid(),
+            ga_id=ga_id or faker.ga_id(),
             iptrunk_side_ae_members=iptrunk_side_ae_members
             or [
                 IptrunkInterfaceBlock.new(
@@ -84,7 +84,7 @@ def iptrunk_subscription_factory(iptrunk_side_subscription_factory, faker, geant
             )
 
         description = description or faker.sentence()
-        gs_id = gs_id or faker.geant_sid()
+        gs_id = gs_id or faker.gs_id()
         iptrunk_description = iptrunk_description or faker.sentence()
         iptrunk_isis_metric = iptrunk_isis_metric or faker.pyint()
         iptrunk_ipv4_network = iptrunk_ipv4_network or faker.ipv4_network(max_subnet=31)
diff --git a/test/fixtures/l3_core_service_fixtures.py b/test/fixtures/l3_core_service_fixtures.py
index 493ddc1c..21ea6379 100644
--- a/test/fixtures/l3_core_service_fixtures.py
+++ b/test/fixtures/l3_core_service_fixtures.py
@@ -108,7 +108,7 @@ def service_binding_port_factory(
             ipv6_address=ipv6_address or faker.ipv6(),
             ipv6_mask=ipv6_mask or faker.ipv6_netmask(),
             custom_firewall_filters=custom_firewall_filters,
-            gs_id=gs_id or faker.geant_sid(),
+            gs_id=gs_id or faker.gs_id(),
             bgp_session_list=bgp_session_list
             or [
                 bgp_session_subscription_factory(families=[IPFamily.V4UNICAST]),
diff --git a/test/fixtures/layer_2_circuit_fixtures.py b/test/fixtures/layer_2_circuit_fixtures.py
index e7c8c468..2b93a370 100644
--- a/test/fixtures/layer_2_circuit_fixtures.py
+++ b/test/fixtures/layer_2_circuit_fixtures.py
@@ -82,7 +82,7 @@ def layer_2_circuit_subscription_factory(faker, geant_partner, edge_port_subscri
                 edge_port=EdgePort.from_subscription(edge_port).edge_port,
                 sbp_type=SBPType.L2,
                 vlan_id=vlan_id,
-                gs_id=gs_id or faker.geant_sid(),
+                gs_id=gs_id or faker.gs_id(),
                 is_tagged=layer_2_circuit_type == Layer2CircuitType.TAGGED,
                 custom_firewall_filters=False,
             )
diff --git a/test/workflows/edge_port/test_create_imported_edge_port.py b/test/workflows/edge_port/test_create_imported_edge_port.py
index 838d330d..ea5b024e 100644
--- a/test/workflows/edge_port/test_create_imported_edge_port.py
+++ b/test/workflows/edge_port/test_create_imported_edge_port.py
@@ -17,7 +17,7 @@ def imported_edge_port_creation_input_form_data(router_subscription_factory, par
         "encapsulation": EncapsulationType.DOT1Q,
         "name": "lag34",
         "minimum_links": 2,
-        "ga_id": faker.geant_gid(),
+        "ga_id": faker.imported_ga_id(),
         "mac_address": faker.mac_address(),
         "partner": partner_factory()["name"],
         "enable_lacp": True,
diff --git a/test/workflows/edge_port/test_modify_edge_port.py b/test/workflows/edge_port/test_modify_edge_port.py
index 6e16f73a..25adcd85 100644
--- a/test/workflows/edge_port/test_modify_edge_port.py
+++ b/test/workflows/edge_port/test_modify_edge_port.py
@@ -21,7 +21,7 @@ def input_form_wizard_data(request, faker, edge_port_subscription_factory, partn
         {"subscription_id": subscription_id},
         {
             "tt_number": faker.tt_number(),
-            "ga_id": faker.geant_gid(),
+            "ga_id": faker.ga_id(),
             "member_speed": PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND,
             "number_of_members": 1,
         },
@@ -100,7 +100,7 @@ def input_form_wizard_without_changing_capacity(request, faker, edge_port_subscr
 
     return [
         {"subscription_id": subscription_id},
-        {"tt_number": faker.tt_number(), "ga_id": faker.geant_gid()},
+        {"tt_number": faker.tt_number(), "ga_id": faker.ga_id()},
         {
             "description": faker.sentence(),
             "ae_members": [
diff --git a/test/workflows/iptrunk/test_create_imported_iptrunk.py b/test/workflows/iptrunk/test_create_imported_iptrunk.py
index 8b9c5d4d..deaa2ddd 100644
--- a/test/workflows/iptrunk/test_create_imported_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_imported_iptrunk.py
@@ -16,7 +16,7 @@ from test.workflows import (
 def workflow_input_data(faker, router_subscription_factory):
     return {
         "partner": "GEANT",
-        "gs_id": faker.geant_sid(),
+        "gs_id": faker.imported_gs_id(),
         "iptrunk_description": faker.sentence(),
         "iptrunk_type": IptrunkType.DARK_FIBER,
         "iptrunk_speed": PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND,
@@ -24,13 +24,13 @@ def workflow_input_data(faker, router_subscription_factory):
         "iptrunk_isis_metric": 10000,
         "side_a_node_id": router_subscription_factory(),
         "side_a_ae_iface": faker.network_interface(),
-        "side_a_ga_id": faker.geant_gid(),
+        "side_a_ga_id": faker.imported_ga_id(),
         "side_a_ae_members": [
             {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} for _ in range(3)
         ],
         "side_b_node_id": router_subscription_factory(),
         "side_b_ae_iface": faker.network_interface(),
-        "side_b_ga_id": faker.geant_gid(),
+        "side_b_ga_id": faker.imported_ga_id(),
         "side_b_ae_members": [
             {"interface_name": faker.network_interface(), "interface_description": faker.sentence()} for _ in range(3)
         ],
diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py
index 801ce865..12f49b90 100644
--- a/test/workflows/iptrunk/test_modify_trunk_interface.py
+++ b/test/workflows/iptrunk/test_modify_trunk_interface.py
@@ -52,15 +52,15 @@ def input_form_iptrunk_data(
 
     product_id = iptrunk_subscription_factory(iptrunk_sides=[side_a_node, side_b_node])
 
-    new_sid = faker.geant_sid()
+    new_sid = faker.gs_id()
     new_description = faker.sentence()
     new_type = IptrunkType.LEASED
     new_speed = PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND
     new_link_count = 2
 
-    new_side_a_gid = faker.geant_gid()
+    new_side_a_gid = faker.ga_id()
 
-    new_side_b_gid = faker.geant_gid()
+    new_side_b_gid = faker.ga_id()
 
     return [
         {"subscription_id": product_id},
diff --git a/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py b/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
index 2d4ed7a2..3d0e7870 100644
--- a/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
+++ b/test/workflows/l2_circuit/test_create_imported_layer_2_circuit.py
@@ -28,7 +28,7 @@ def test_create_imported_layer_2_circuit_success(
             "vc_id": generate_unique_vc_id(),
             "policer_bandwidth": faker.bandwidth() if policer_enabled else None,
             "policer_burst_rate": faker.bandwidth() if policer_enabled else None,
-            "gs_id": faker.geant_sid(),
+            "gs_id": faker.imported_gs_id(),
             "layer_2_circuit_side_a": {"edge_port": edge_port_a, "vlan_id": faker.vlan_id()},
             "layer_2_circuit_side_b": {"edge_port": edge_port_b, "vlan_id": faker.vlan_id()},
         }
diff --git a/test/workflows/l3_core_service/test_create_imported_l3_core_service.py b/test/workflows/l3_core_service/test_create_imported_l3_core_service.py
index 0580bb5c..48ac4b54 100644
--- a/test/workflows/l3_core_service/test_create_imported_l3_core_service.py
+++ b/test/workflows/l3_core_service/test_create_imported_l3_core_service.py
@@ -27,7 +27,7 @@ def test_create_imported_l3_core_service_success(
             {
                 "edge_port": edge_port_subscription_factory(),
                 "ap_type": "PRIMARY",
-                "gs_id": faker.geant_sid(),
+                "gs_id": faker.imported_gs_id(),
                 "sbp_type": SBPType.L3,
                 "is_tagged": faker.boolean(),
                 "vlan_id": faker.vlan_id(),
diff --git a/test/workflows/l3_core_service/test_modify_l3_core_service.py b/test/workflows/l3_core_service/test_modify_l3_core_service.py
index 333fc670..dc7f3a51 100644
--- a/test/workflows/l3_core_service/test_modify_l3_core_service.py
+++ b/test/workflows/l3_core_service/test_modify_l3_core_service.py
@@ -84,7 +84,7 @@ def test_modify_l3_core_service_add_new_edge_port_success(
         {},  # The existing SBPs are unchanged
         {},
         {  # Adding configuration for the new SBP
-            "gs_id": faker.geant_sid(),
+            "gs_id": faker.gs_id(),
             "vlan_id": faker.vlan_id(),
             "ipv4_address": faker.ipv4(),
             "ipv6_address": faker.ipv6(),
@@ -115,7 +115,7 @@ def test_modify_l3_core_service_add_new_edge_port_success(
 def sbp_input_form_data(faker):
     def _generate_form_data():
         return {
-            "gs_id": faker.geant_sid(),
+            "gs_id": faker.gs_id(),
             "is_tagged": True,
             "vlan_id": faker.vlan_id(),
             "ipv4_address": faker.ipv4(),
-- 
GitLab


From dc51292181fad87680d520e3104861692f5b7e3a Mon Sep 17 00:00:00 2001
From: Neda Moeini <neda.moeini@geant.org>
Date: Thu, 5 Dec 2024 16:05:37 +0100
Subject: [PATCH 17/20] Update the custom geant_ids

---
 gso/utils/types/geant_ids.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gso/utils/types/geant_ids.py b/gso/utils/types/geant_ids.py
index adc3b19c..194f57b0 100644
--- a/gso/utils/types/geant_ids.py
+++ b/gso/utils/types/geant_ids.py
@@ -34,7 +34,7 @@ def validate_id(value: str, prefix: str, field_name: str) -> str:
         err = f"{field_name} must have a numeric part after the prefix '{prefix}'."
         raise ValueError(err) from ValueError
 
-    if min_range <= numeric_part < max_range:
+    if min_range <= numeric_part <= max_range:
         err = f"{field_name} must not have a numeric part between 50000 and 99999."
         raise ValueError(err)
 
-- 
GitLab


From 7fdced2db5abb26a81fcbd2c8290ff2771097ec3 Mon Sep 17 00:00:00 2001
From: Karel van Klink <karel.vanklink@geant.org>
Date: Wed, 11 Dec 2024 10:08:05 +0100
Subject: [PATCH 18/20] Add input validation to modification workflows that
 contain GA- and GS-IDs

---
 gso/services/subscriptions.py                 |  2 +-
 gso/workflows/edge_port/modify_edge_port.py   | 11 +++++++++--
 .../iptrunk/create_imported_iptrunk.py        |  2 +-
 gso/workflows/iptrunk/create_iptrunk.py       |  2 +-
 gso/workflows/iptrunk/migrate_iptrunk.py      |  2 +-
 .../iptrunk/modify_trunk_interface.py         | 13 ++++++++++---
 .../create_imported_layer_2_circuit.py        |  3 ++-
 .../create_imported_l3_core_service.py        |  3 ++-
 .../edge_port/test_modify_edge_port.py        | 17 +++++++++++++++++
 test/workflows/iptrunk/test_create_iptrunk.py |  4 +---
 .../iptrunk/test_modify_trunk_interface.py    | 19 ++++++++++++++++++-
 11 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/gso/services/subscriptions.py b/gso/services/subscriptions.py
index e6781244..83d88751 100644
--- a/gso/services/subscriptions.py
+++ b/gso/services/subscriptions.py
@@ -355,7 +355,7 @@ def generate_unique_ga_id() -> str:
     """Generate a unique GA ID using the ga_id_seq database sequence.
 
     Returns:
-        str: A unique GA ID in the format `GA<number>`.
+        str: A unique GA ID in the format `GA-<number>`.
 
     Raises:
         ValueError: If there is an error generating the ID.
diff --git a/gso/workflows/edge_port/modify_edge_port.py b/gso/workflows/edge_port/modify_edge_port.py
index 94388984..b176eafc 100644
--- a/gso/workflows/edge_port/modify_edge_port.py
+++ b/gso/workflows/edge_port/modify_edge_port.py
@@ -1,5 +1,6 @@
 """Modify an existing edge port subscription."""
 
+from functools import partial
 from typing import Annotated, Any, Self
 from uuid import uuid4
 
@@ -10,7 +11,7 @@ from orchestrator.targets import Target
 from orchestrator.workflow import StepList, begin, conditional, done, step
 from orchestrator.workflows.steps import resync, store_process_subscription, unsync
 from orchestrator.workflows.utils import wrap_modify_initial_input_form
-from pydantic import AfterValidator, ConfigDict, model_validator
+from pydantic import AfterValidator, ConfigDict, Field, model_validator
 from pydantic_forms.types import FormGenerator, State, UUIDstr
 from pydantic_forms.validators import ReadOnlyField, validate_unique_list
 
@@ -26,6 +27,7 @@ from gso.utils.helpers import (
 )
 from gso.utils.types.interfaces import LAGMember, PhysicalPortCapacity
 from gso.utils.types.tt_number import TTNumber
+from gso.utils.types.unique_field import validate_field_is_unique
 
 
 def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
@@ -43,7 +45,12 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
         minimum_links: int | None = subscription.edge_port.minimum_links or None
         mac_address: str | None = subscription.edge_port.mac_address or None
         ignore_if_down: bool = subscription.edge_port.ignore_if_down
-        ga_id: str | None = subscription.edge_port.ga_id or None
+        ga_id: (
+            Annotated[
+                str, AfterValidator(partial(validate_field_is_unique, subscription_id)), Field(pattern=r"^GA-\d{5}$")
+            ]
+            | None
+        ) = subscription.edge_port.ga_id or None
 
         @model_validator(mode="after")
         def validate_number_of_members(self) -> Self:
diff --git a/gso/workflows/iptrunk/create_imported_iptrunk.py b/gso/workflows/iptrunk/create_imported_iptrunk.py
index 1feec505..722121fe 100644
--- a/gso/workflows/iptrunk/create_imported_iptrunk.py
+++ b/gso/workflows/iptrunk/create_imported_iptrunk.py
@@ -114,7 +114,7 @@ def initialize_subscription(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{gs_id}"
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, {gs_id}"
     return {"subscription": subscription}
 
 
diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index 8f24e333..962cc5d0 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -361,7 +361,7 @@ def initialize_subscription(
             IptrunkInterfaceBlockInactive.new(subscription_id=uuid4(), **member),
         )
     side_names = sorted([side_a.router_site.site_name, side_b.router_site.site_name])
-    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{gs_id}"
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, {gs_id}"
 
     return {"subscription": subscription}
 
diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py
index 03ee4465..7e7f32b4 100644
--- a/gso/workflows/iptrunk/migrate_iptrunk.py
+++ b/gso/workflows/iptrunk/migrate_iptrunk.py
@@ -769,7 +769,7 @@ def update_subscription_model(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{subscription.iptrunk.gs_id}"
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, {subscription.iptrunk.gs_id}"
 
     return {"subscription": subscription}
 
diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py
index 65fa452b..ea2309e4 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -7,6 +7,7 @@ necessary modifications will be applied.
 """
 
 import json
+from functools import partial
 from typing import Annotated
 from uuid import UUID, uuid4
 
@@ -18,7 +19,7 @@ from orchestrator.utils.json import json_dumps
 from orchestrator.workflow import StepList, begin, conditional, done, step, workflow
 from orchestrator.workflows.steps import resync, store_process_subscription, unsync
 from orchestrator.workflows.utils import wrap_modify_initial_input_form
-from pydantic import ConfigDict
+from pydantic import AfterValidator, ConfigDict, Field
 from pydantic_forms.validators import Label, ReadOnlyField
 
 from gso.products.product_blocks.iptrunk import (
@@ -39,6 +40,7 @@ from gso.utils.shared_enums import Vendor
 from gso.utils.types.interfaces import JuniperLAGMember, LAGMember, LAGMemberList, PhysicalPortCapacity
 from gso.utils.types.ip_address import IPv4AddressType, IPv6AddressType
 from gso.utils.types.tt_number import TTNumber
+from gso.utils.types.unique_field import validate_field_is_unique
 from gso.workflows.iptrunk.migrate_iptrunk import check_ip_trunk_optical_levels_pre
 from gso.workflows.iptrunk.validate_iptrunk import check_ip_trunk_isis
 
@@ -86,7 +88,12 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
 
     class ModifyIptrunkForm(FormPage):
         tt_number: TTNumber
-        gs_id: str | None = subscription.iptrunk.gs_id
+        gs_id: (
+            Annotated[
+                str, AfterValidator(partial(validate_field_is_unique, subscription_id)), Field(pattern=r"^GS-\d{5}$")
+            ]
+            | None
+        ) = subscription.iptrunk.gs_id
         iptrunk_description: str | None = subscription.iptrunk.iptrunk_description
         iptrunk_type: IptrunkType = subscription.iptrunk.iptrunk_type
         warning_label: Label = (
@@ -302,7 +309,7 @@ def modify_iptrunk_subscription(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{gs_id}"
+    subscription.description = f"IP trunk {side_names[0]} {side_names[1]}, {gs_id}"
 
     return {
         "subscription": subscription,
diff --git a/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py b/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py
index 6102d86d..3e5e97c9 100644
--- a/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py
+++ b/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py
@@ -23,6 +23,7 @@ from gso.products.product_types.layer_2_circuit import (
 from gso.services.partners import get_partner_by_name
 from gso.services.subscriptions import get_product_id_by_name
 from gso.utils.shared_enums import SBPType
+from gso.utils.types.geant_ids import IMPORTED_GS_ID
 from gso.utils.types.interfaces import BandwidthString
 from gso.utils.types.virtual_identifiers import VC_ID, VLAN_ID
 
@@ -39,7 +40,7 @@ def initial_input_form_generator() -> FormGenerator:
 
         service_type: Layer2CircuitServiceType
         partner: str
-        gs_id: str
+        gs_id: IMPORTED_GS_ID
         vc_id: VC_ID
         layer_2_circuit_side_a: ServiceBindingPortInput
         layer_2_circuit_side_b: ServiceBindingPortInput
diff --git a/gso/workflows/l3_core_service/create_imported_l3_core_service.py b/gso/workflows/l3_core_service/create_imported_l3_core_service.py
index 7862a47f..7280a225 100644
--- a/gso/workflows/l3_core_service/create_imported_l3_core_service.py
+++ b/gso/workflows/l3_core_service/create_imported_l3_core_service.py
@@ -21,6 +21,7 @@ from gso.products.product_types.l3_core_service import ImportedL3CoreServiceInac
 from gso.services.partners import get_partner_by_name
 from gso.services.subscriptions import get_product_id_by_name
 from gso.utils.shared_enums import SBPType
+from gso.utils.types.geant_ids import IMPORTED_GS_ID
 from gso.utils.types.ip_address import IPAddress, IPv4AddressType, IPV4Netmask, IPv6AddressType, IPV6Netmask
 from gso.utils.types.virtual_identifiers import VLAN_ID
 
@@ -50,7 +51,7 @@ def initial_input_form_generator() -> FormGenerator:
     class ServiceBindingPort(BaseModel):
         edge_port: UUIDstr
         ap_type: str
-        gs_id: str
+        gs_id: IMPORTED_GS_ID
         sbp_type: SBPType = SBPType.L3
         is_tagged: bool = False
         vlan_id: VLAN_ID
diff --git a/test/workflows/edge_port/test_modify_edge_port.py b/test/workflows/edge_port/test_modify_edge_port.py
index 25adcd85..0f7ed140 100644
--- a/test/workflows/edge_port/test_modify_edge_port.py
+++ b/test/workflows/edge_port/test_modify_edge_port.py
@@ -1,6 +1,7 @@
 from unittest.mock import patch
 
 import pytest
+from pydantic_forms.exceptions import FormValidationError
 
 from gso.products.product_types.edge_port import EdgePort
 from gso.utils.types.interfaces import PhysicalPortCapacity
@@ -37,6 +38,22 @@ def input_form_wizard_data(request, faker, edge_port_subscription_factory, partn
     ]
 
 
+@pytest.mark.workflow()
+@pytest.mark.parametrize("invalid_ga_id", ["GS-11111", "GA-1234", "GA_12345", "GA-100000"])
+def test_modify_edge_port_with_invalid_ga_id(
+    input_form_wizard_data, faker, invalid_ga_id, iptrunk_side_subscription_factory, iptrunk_subscription_factory
+):
+    input_data = input_form_wizard_data
+    input_data[1]["ga_id"] = invalid_ga_id
+    iptrunk_subscription_factory(
+        iptrunk_sides=[iptrunk_side_subscription_factory(ga_id="GA-11111"), iptrunk_side_subscription_factory()]
+    )
+
+    #  Run workflow
+    with pytest.raises(FormValidationError):
+        run_workflow("modify_edge_port", input_data)
+
+
 @pytest.mark.workflow()
 @patch("gso.services.lso_client._send_request")
 @patch("gso.services.netbox_client.NetboxClient.get_available_interfaces")
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index a45f3bf1..d0f9cfa5 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -151,9 +151,7 @@ def test_successful_iptrunk_creation_with_standard_lso_result(
     ])
     assert subscription.status == "provisioning"
     assert subscription.iptrunk.gs_id is not None
-    assert subscription.description == (
-        f"IP trunk {sorted_sides[0]} {sorted_sides[1]}, gs_id:{subscription.iptrunk.gs_id}"
-    )
+    assert subscription.description == f"IP trunk {sorted_sides[0]} {sorted_sides[1]}, {subscription.iptrunk.gs_id}"
 
     assert mock_execute_playbook.call_count == 6
     #  We search for 6 hosts in total, 2 in a /31 and 4 in a /126
diff --git a/test/workflows/iptrunk/test_modify_trunk_interface.py b/test/workflows/iptrunk/test_modify_trunk_interface.py
index 12f49b90..d8a96588 100644
--- a/test/workflows/iptrunk/test_modify_trunk_interface.py
+++ b/test/workflows/iptrunk/test_modify_trunk_interface.py
@@ -1,6 +1,7 @@
 from unittest.mock import patch
 
 import pytest
+from pydantic_forms.exceptions import FormValidationError
 
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_types.iptrunk import Iptrunk
@@ -164,7 +165,7 @@ def test_iptrunk_modify_trunk_interface_success(
         subscription.iptrunk.iptrunk_sides[0].iptrunk_side_node.router_site.site_name,
         subscription.iptrunk.iptrunk_sides[1].iptrunk_side_node.router_site.site_name,
     ])
-    assert subscription.description == f"IP trunk {side_names[0]} {side_names[1]}, gs_id:{new_sid}"
+    assert subscription.description == f"IP trunk {side_names[0]} {side_names[1]}, {new_sid}"
     assert subscription.iptrunk.gs_id == input_form_iptrunk_data[1]["gs_id"]
     assert subscription.iptrunk.iptrunk_description == input_form_iptrunk_data[1]["iptrunk_description"]
     assert subscription.iptrunk.iptrunk_type == input_form_iptrunk_data[1]["iptrunk_type"]
@@ -192,3 +193,19 @@ def test_iptrunk_modify_trunk_interface_success(
             member.interface_description
             == _find_interface_by_name(new_side_b_ae_members, member.interface_name).interface_description
         )
+
+
+@pytest.mark.workflow()
+@pytest.mark.parametrize("invalid_ga_id", ["GA-11111", "GS-1234", "GS_12345", "GS-100000"])
+def test_modify_iptrunk_interface_with_invalid_ga_id(
+    input_form_iptrunk_data, faker, invalid_ga_id, iptrunk_side_subscription_factory, iptrunk_subscription_factory
+):
+    input_data = input_form_iptrunk_data
+    input_data[3]["side_a_ga_id"] = invalid_ga_id
+    iptrunk_subscription_factory(
+        iptrunk_sides=[iptrunk_side_subscription_factory(ga_id="GA-11111"), iptrunk_side_subscription_factory()]
+    )
+
+    #  Run workflow
+    with pytest.raises(FormValidationError):
+        run_workflow("modify_edge_port", input_data)
-- 
GitLab


From 73d830911ef348e49430fd7d2311aaf61ff44309 Mon Sep 17 00:00:00 2001
From: Karel van Klink <karel.vanklink@geant.org>
Date: Wed, 11 Dec 2024 12:09:44 +0100
Subject: [PATCH 19/20] Update typing of ga and gs id validation method

---
 gso/utils/types/geant_ids.py | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/gso/utils/types/geant_ids.py b/gso/utils/types/geant_ids.py
index 194f57b0..ec728bc0 100644
--- a/gso/utils/types/geant_ids.py
+++ b/gso/utils/types/geant_ids.py
@@ -1,20 +1,20 @@
 """Type definitions for the GA and GS IDs."""
 
 from functools import partial
-from typing import Annotated
+from typing import Annotated, Literal
 
 from pydantic import AfterValidator
 
 from gso.services.subscriptions import is_resource_type_value_unique
 
 
-def validate_id(value: str, prefix: str, field_name: str) -> str:
+def validate_id(value: str, prefix: Literal["GA", "GS"], field_name: str) -> str:
     """Validate that the ID is unique, has the correct prefix, and is within valid constraints.
 
     Args:
-        value (str): The ID value to validate.
-        prefix (str): The required prefix for the ID (e.g., "GA-" or "GS-").
-        field_name (str): The database field name to check for uniqueness (e.g., "ga_id" or "gs_id").
+        value: The ID value to validate.
+        prefix: The required prefix for the ID.
+        field_name: The database field name to check for uniqueness.
 
     Raises:
         ValueError: If the ID is not valid.
@@ -29,21 +29,21 @@ def validate_id(value: str, prefix: str, field_name: str) -> str:
         raise ValueError(err)
 
     try:
-        numeric_part = int(value[len(prefix) :])
+        numeric_part = int(value.split("-")[-1])
     except ValueError:
         err = f"{field_name} must have a numeric part after the prefix '{prefix}'."
         raise ValueError(err) from ValueError
 
     if min_range <= numeric_part <= max_range:
-        err = f"{field_name} must not have a numeric part between 50000 and 99999."
+        err = f"{field_name} must not have a numeric part between 50000 and 99999, received {numeric_part}"
         raise ValueError(err)
 
     if not is_resource_type_value_unique(field_name, value):
-        err = f"{field_name} must be unique."
+        err = f"{field_name} must be unique, {value} is already in use."
         raise ValueError(err)
 
     return value
 
 
-IMPORTED_GA_ID = Annotated[str, AfterValidator(partial(validate_id, prefix="GA-", field_name="ga_id"))]
-IMPORTED_GS_ID = Annotated[str, AfterValidator(partial(validate_id, prefix="GS-", field_name="gs_id"))]
+IMPORTED_GA_ID = Annotated[str, AfterValidator(partial(validate_id, prefix="GA", field_name="ga_id"))]
+IMPORTED_GS_ID = Annotated[str, AfterValidator(partial(validate_id, prefix="GS", field_name="gs_id"))]
-- 
GitLab


From 96fa31fc046a516a04d22b7e0574ec2b8e677c32 Mon Sep 17 00:00:00 2001
From: Karel van Klink <karel.vanklink@geant.org>
Date: Wed, 11 Dec 2024 13:49:39 +0000
Subject: [PATCH 20/20] Apply 1 suggestion(s) to 1 file(s)

Co-authored-by: Mohammad Torkashvand <mohammad.torkashvand@geant.org>
---
 gso/utils/types/geant_ids.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gso/utils/types/geant_ids.py b/gso/utils/types/geant_ids.py
index ec728bc0..72afc7f4 100644
--- a/gso/utils/types/geant_ids.py
+++ b/gso/utils/types/geant_ids.py
@@ -35,7 +35,7 @@ def validate_id(value: str, prefix: Literal["GA", "GS"], field_name: str) -> str
         raise ValueError(err) from ValueError
 
     if min_range <= numeric_part <= max_range:
-        err = f"{field_name} must not have a numeric part between 50000 and 99999, received {numeric_part}"
+        err = f"{field_name} must not have a numeric part between {min_range} and {max_range}, received {numeric_part}"
         raise ValueError(err)
 
     if not is_resource_type_value_unique(field_name, value):
-- 
GitLab