diff --git a/Changelog.md b/Changelog.md
index 371dcf4f9723110ce3b7f9d8da4bfb293a815e4b..a5131efa7c62f51f243fb36b935dd50ee8028323 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## [2.23] - 2024-11-05
+- Added new workflows and updated the products of Swich and LAN Swith Interconnect
+- Upgraded orchestrator-core to 2.8.0 
+
 ## [2.22] - 2024-10-31
 - Added EdgePort, IAS and GEANT IP products and required workflows
 - Refactored pydantic models for maintainability
diff --git a/docs/source/module/workflows/lan_switch_interconnect/create_imported_lan_switch_interconnect.rst b/docs/source/module/workflows/lan_switch_interconnect/create_imported_lan_switch_interconnect.rst
new file mode 100644
index 0000000000000000000000000000000000000000..6900a2f8f6ee4ccb34ded8dc28d94a7f86091759
--- /dev/null
+++ b/docs/source/module/workflows/lan_switch_interconnect/create_imported_lan_switch_interconnect.rst
@@ -0,0 +1,6 @@
+``gso.workflows.lan_switch_interconnect.create_imported_lan_switch_interconnect``
+=================================================================================
+
+.. automodule:: gso.workflows.lan_switch_interconnect.create_imported_lan_switch_interconnect
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/lan_switch_interconnect/create_lan_switch_interconnect.rst b/docs/source/module/workflows/lan_switch_interconnect/create_lan_switch_interconnect.rst
new file mode 100644
index 0000000000000000000000000000000000000000..9e1e9ce47de6bc5de2b1fc71eb1df168479db1f7
--- /dev/null
+++ b/docs/source/module/workflows/lan_switch_interconnect/create_lan_switch_interconnect.rst
@@ -0,0 +1,6 @@
+``gso.workflows.lan_switch_interconnect.create_lan_switch_interconnect``
+========================================================================
+
+.. automodule:: gso.workflows.lan_switch_interconnect.create_lan_switch_interconnect
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/lan_switch_interconnect/import_lan_switch_interconnect.rst b/docs/source/module/workflows/lan_switch_interconnect/import_lan_switch_interconnect.rst
new file mode 100644
index 0000000000000000000000000000000000000000..230944df9445c9a94b7a4d26a56eded75acc5dee
--- /dev/null
+++ b/docs/source/module/workflows/lan_switch_interconnect/import_lan_switch_interconnect.rst
@@ -0,0 +1,6 @@
+``gso.workflows.lan_switch_interconnect.import_lan_switch_interconnect``
+========================================================================
+
+.. automodule:: gso.workflows.lan_switch_interconnect.import_lan_switch_interconnect
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/lan_switch_interconnect/index.rst b/docs/source/module/workflows/lan_switch_interconnect/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..f8a8b4f8e7d185c300dd77ac382accdf8db462eb
--- /dev/null
+++ b/docs/source/module/workflows/lan_switch_interconnect/index.rst
@@ -0,0 +1,19 @@
+``gso.workflows.lan_switch_interconnect``
+=========================================
+
+.. automodule:: gso.workflows.lan_switch_interconnect
+   :members:
+   :show-inheritance:
+
+Submodules
+----------
+
+.. toctree::
+   :maxdepth: 2
+   :titlesonly:
+
+   create_imported_lan_switch_interconnect
+   create_lan_switch_interconnect
+   import_lan_switch_interconnect
+   terminate_lan_switch_interconnect
+   validate_lan_switch_interconnect
diff --git a/docs/source/module/workflows/lan_switch_interconnect/terminate_lan_switch_interconnect.rst b/docs/source/module/workflows/lan_switch_interconnect/terminate_lan_switch_interconnect.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7575a60fe18911455a00e79081bd62ddfe97383e
--- /dev/null
+++ b/docs/source/module/workflows/lan_switch_interconnect/terminate_lan_switch_interconnect.rst
@@ -0,0 +1,6 @@
+``gso.workflows.lan_switch_interconnect.terminate_lan_switch_interconnect``
+===========================================================================
+
+.. automodule:: gso.workflows.lan_switch_interconnect.terminate_lan_switch_interconnect
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/lan_switch_interconnect/validate_lan_switch_interconnect.rst b/docs/source/module/workflows/lan_switch_interconnect/validate_lan_switch_interconnect.rst
new file mode 100644
index 0000000000000000000000000000000000000000..17530cf9e81819770c478b64b06c1284a91cb4b3
--- /dev/null
+++ b/docs/source/module/workflows/lan_switch_interconnect/validate_lan_switch_interconnect.rst
@@ -0,0 +1,6 @@
+``gso.workflows.lan_switch_interconnect.validate_lan_switch_interconnect``
+==========================================================================
+
+.. automodule:: gso.workflows.lan_switch_interconnect.validate_lan_switch_interconnect
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/switch/activate_switch.rst b/docs/source/module/workflows/switch/activate_switch.rst
new file mode 100644
index 0000000000000000000000000000000000000000..dc850fa583c452c1e47bd9a5c45dd0633e2cec78
--- /dev/null
+++ b/docs/source/module/workflows/switch/activate_switch.rst
@@ -0,0 +1,6 @@
+``gso.workflows.switch.activate_switch``
+========================================
+
+.. automodule:: gso.workflows.switch.activate_switch
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/switch/create_imported_switch.rst b/docs/source/module/workflows/switch/create_imported_switch.rst
new file mode 100644
index 0000000000000000000000000000000000000000..2dcd76641d8489becc4dd9e209e1035343b413fd
--- /dev/null
+++ b/docs/source/module/workflows/switch/create_imported_switch.rst
@@ -0,0 +1,6 @@
+``gso.workflows.switch.create_imported_switch``
+===============================================
+
+.. automodule:: gso.workflows.switch.create_imported_switch
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/switch/create_switch.rst b/docs/source/module/workflows/switch/create_switch.rst
new file mode 100644
index 0000000000000000000000000000000000000000..c2c8d19563bb59c00d4053e0f3f6e0454777158f
--- /dev/null
+++ b/docs/source/module/workflows/switch/create_switch.rst
@@ -0,0 +1,6 @@
+``gso.workflows.switch.create_switch``
+======================================
+
+.. automodule:: gso.workflows.switch.create_switch
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/switch/import_switch.rst b/docs/source/module/workflows/switch/import_switch.rst
new file mode 100644
index 0000000000000000000000000000000000000000..82f140766a082f4d31a825c973b00d74790c2fbf
--- /dev/null
+++ b/docs/source/module/workflows/switch/import_switch.rst
@@ -0,0 +1,6 @@
+``gso.workflows.switch.import_switch``
+======================================
+
+.. automodule:: gso.workflows.switch.import_switch
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/switch/index.rst b/docs/source/module/workflows/switch/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..160939de0474626ddb2c47778f959d3d0f5ce2e7
--- /dev/null
+++ b/docs/source/module/workflows/switch/index.rst
@@ -0,0 +1,20 @@
+``gso.workflows.switch``
+========================
+
+.. automodule:: gso.workflows.switch
+   :members:
+   :show-inheritance:
+
+Submodules
+----------
+
+.. toctree::
+   :maxdepth: 2
+   :titlesonly:
+
+   activate_switch
+   create_imported_switch
+   create_switch
+   import_switch
+   terminate_switch
+   validate_switch
diff --git a/docs/source/module/workflows/switch/terminate_switch.rst b/docs/source/module/workflows/switch/terminate_switch.rst
new file mode 100644
index 0000000000000000000000000000000000000000..15d3336f7f37c265c1ad21c0ae5c96f656853c37
--- /dev/null
+++ b/docs/source/module/workflows/switch/terminate_switch.rst
@@ -0,0 +1,6 @@
+``gso.workflows.switch.terminate_switch``
+=========================================
+
+.. automodule:: gso.workflows.switch.terminate_switch
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/switch/validate_switch.rst b/docs/source/module/workflows/switch/validate_switch.rst
new file mode 100644
index 0000000000000000000000000000000000000000..40bbbf30d8a2ccea4924f7d9512bd162ef720b28
--- /dev/null
+++ b/docs/source/module/workflows/switch/validate_switch.rst
@@ -0,0 +1,6 @@
+``gso.workflows.switch.validate_switch``
+========================================
+
+.. automodule:: gso.workflows.switch.validate_switch
+   :members:
+   :show-inheritance:
diff --git a/gso/cli/imports.py b/gso/cli/imports.py
index f1553d222d34c974584c45ef15cff56dfa55c371..cd2e5998dd39ea965f1c476357c1738afeaae372 100644
--- a/gso/cli/imports.py
+++ b/gso/cli/imports.py
@@ -12,7 +12,7 @@ import typer
 import yaml
 from orchestrator.db import db
 from orchestrator.services.processes import start_process
-from orchestrator.types import SubscriptionLifecycle
+from orchestrator.types import SubscriptionLifecycle, UUIDstr
 from pydantic import BaseModel, ValidationError, field_validator, model_validator
 from sqlalchemy.exc import SQLAlchemyError
 
@@ -23,6 +23,7 @@ from gso.products.product_blocks.edge_port import EdgePortType, EncapsulationTyp
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_blocks.router import RouterRole
 from gso.products.product_blocks.service_binding_port import VLAN_ID
+from gso.products.product_blocks.switch import SwitchModel
 from gso.products.product_types.nren_l3_core_service import NRENL3CoreServiceType
 from gso.services.partners import (
     PartnerEmail,
@@ -39,7 +40,16 @@ from gso.services.subscriptions import (
 from gso.utils.shared_enums import SBPType, Vendor
 from gso.utils.types.base_site import BaseSiteValidatorModel
 from gso.utils.types.interfaces import LAGMember, LAGMemberList, PhysicalPortCapacity
-from gso.utils.types.ip_address import IPAddress, IPv4AddressType, IPV4Netmask, IPv6AddressType, IPV6Netmask, PortNumber
+from gso.utils.types.ip_address import (
+    AddressSpace,
+    IPAddress,
+    IPv4AddressType,
+    IPV4Netmask,
+    IPv4NetworkType,
+    IPv6AddressType,
+    IPV6Netmask,
+    PortNumber,
+)
 
 app: typer.Typer = typer.Typer()
 
@@ -69,6 +79,16 @@ class RouterImportModel(BaseModel):
     router_lo_iso_address: str
 
 
+class SwitchImportModel(BaseModel):
+    """Required fields for importing an existing :class:`gso.product.product_types.switch`."""
+
+    fqdn: str
+    ts_port: PortNumber
+    site: UUIDstr
+    switch_vendor: Vendor
+    switch_model: SwitchModel
+
+
 class SuperPopSwitchImportModel(BaseModel):
     """Required fields for importing an existing :class:`gso.product.product_types.super_pop_switch`."""
 
@@ -278,16 +298,47 @@ class NRENL3CoreServiceImportModel(BaseModel):
         return value
 
 
+class LanSwitchInterconnectRouterSideImportModel(BaseModel):
+    """Import LAN Switch Interconnect Router side model."""
+
+    node: UUIDstr
+    ae_iface: str
+    ae_members: LAGMemberList[LAGMember]
+    ipv4_address: IPv4AddressType
+
+
+class LanSwitchInterconnectSwitchSideImportModel(BaseModel):
+    """Import LAN Switch Interconnect Switch side model."""
+
+    switch: UUIDstr
+    ae_iface: str
+    ae_members: LAGMemberList[LAGMember]
+    ipv4_address: IPv4AddressType
+
+
+class LanSwitchInterconnectImportModel(BaseModel):
+    """Import LAN Switch Interconnect model."""
+
+    lan_switch_interconnect_description: str
+    lan_switch_interconnect_ip_network: IPv4NetworkType | None
+    address_space: AddressSpace
+    minimum_links: int
+    router_side: LanSwitchInterconnectRouterSideImportModel
+    switch_side: LanSwitchInterconnectSwitchSideImportModel
+
+
 T = TypeVar(
     "T",
     SiteImportModel,
     RouterImportModel,
+    SwitchImportModel,
     IptrunkImportModel,
     SuperPopSwitchImportModel,
     OfficeRouterImportModel,
     OpenGearImportModel,
     EdgePortImportModel,
     NRENL3CoreServiceImportModel,
+    LanSwitchInterconnectImportModel,
 )
 
 common_filepath_option = typer.Option(
@@ -380,6 +431,12 @@ def import_routers(filepath: str = common_filepath_option) -> None:
     _generic_import_product(Path(filepath), ProductType.IMPORTED_ROUTER, "router", "hostname", RouterImportModel)
 
 
+@app.command()
+def import_switches(filepath: str = common_filepath_option) -> None:
+    """Import switches into GSO."""
+    _generic_import_product(Path(filepath), ProductType.IMPORTED_SWITCH, "switch", "fqdn", SwitchImportModel)
+
+
 @app.command()
 def import_super_pop_switches(filepath: str = common_filepath_option) -> None:
     """Import Super PoP Switches into GSO."""
@@ -581,3 +638,15 @@ def import_nren_l3_core_service(filepath: str = common_filepath_option) -> None:
         typer.echo("Successfully created imported NREN L3 Core Services:")
         for item in successfully_imported_data:
             typer.echo(f"- {item}")
+
+
+@app.command()
+def import_lan_switch_interconnect(filepath: str = common_filepath_option) -> None:
+    """Import :term:`LAN` Switch Interconnect services into :term:`GSO`."""
+    _generic_import_product(
+        Path(filepath),
+        ProductType.IMPORTED_LAN_SWITCH_INTERCONNECT,
+        "lan_switch_interconnect",
+        "lan_switch_interconnect_description",
+        LanSwitchInterconnectImportModel,
+    )
diff --git a/gso/migrations/versions/2024-08-29_0e7e7d749617_add_switch_workflows.py b/gso/migrations/versions/2024-08-29_0e7e7d749617_add_switch_workflows.py
new file mode 100644
index 0000000000000000000000000000000000000000..8807ad742a497397f293389a53a587fd0b79eb3a
--- /dev/null
+++ b/gso/migrations/versions/2024-08-29_0e7e7d749617_add_switch_workflows.py
@@ -0,0 +1,105 @@
+"""Add switch workflows.
+
+Revision ID: 0e7e7d749617
+Revises: 94d9de9246fe
+Create Date: 2024-08-29 15:45:57.581710
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = '0e7e7d749617'
+down_revision = '94d9de9246fe'
+branch_labels = None
+depends_on = None
+
+
+from orchestrator.migrations.helpers import create_workflow, delete_workflow
+
+new_workflows = [
+    {
+        "name": "create_switch",
+        "target": "CREATE",
+        "description": "Create Switch",
+        "product_type": "Switch"
+    },
+    {
+        "name": "activate_switch",
+        "target": "MODIFY",
+        "description": "Activate switch",
+        "product_type": "Switch"
+    },
+    {
+        "name": "terminate_switch",
+        "target": "TERMINATE",
+        "description": "Terminate switch",
+        "product_type": "Switch"
+    },
+    {
+        "name": "validate_switch",
+        "target": "SYSTEM",
+        "description": "Validate switch subscription",
+        "product_type": "Switch"
+    },
+    {
+        "name": "create_imported_switch",
+        "target": "CREATE",
+        "description": "Create Imported Switch",
+        "product_type": "ImportedSwitch"
+    },
+    {
+        "name": "import_switch",
+        "target": "MODIFY",
+        "description": "Import Switch",
+        "product_type": "ImportedSwitch"
+    },
+    {
+        "name": "create_lan_switch_interconnect",
+        "target": "CREATE",
+        "description": "Create LAN Switch Interconnect",
+        "product_type": "LanSwitchInterconnect"
+    },
+    {
+        "name": "terminate_lan_switch_interconnect",
+        "target": "TERMINATE",
+        "description": "Terminate LAN Switch Interconnect",
+        "product_type": "LanSwitchInterconnect"
+    },
+    {
+        "name": "validate_lan_switch_interconnect",
+        "target": "SYSTEM",
+        "description": "Validate LAN Switch Interconnect",
+        "product_type": "LanSwitchInterconnect"
+    },
+    {
+        "name": "validate_lan_switch_interconnect",
+        "target": "SYSTEM",
+        "description": "Validate LAN Switch Interconnect",
+        "product_type": "LanSwitchInterconnect"
+    },
+    {
+        "name": "create_imported_lan_switch_interconnect",
+        "target": "CREATE",
+        "description": "Create Imported LAN Switch Interconnect",
+        "product_type": "ImportedLanSwitchInterconnect"
+    },
+    {
+        "name": "import_lan_switch_interconnect",
+        "target": "MODIFY",
+        "description": "Import LAN Switch Interconnect",
+        "product_type": "ImportedLanSwitchInterconnect"
+    }
+]
+
+
+def upgrade() -> None:
+    conn = op.get_bind()
+    for workflow in new_workflows:
+        create_workflow(conn, workflow)
+
+
+def downgrade() -> None:
+    conn = op.get_bind()
+    for workflow in new_workflows:
+        delete_workflow(conn, workflow["name"])
diff --git a/gso/migrations/versions/2024-10-29_94d9de9246fe_add_imported_switches_update_domain_.py b/gso/migrations/versions/2024-10-29_94d9de9246fe_add_imported_switches_update_domain_.py
new file mode 100644
index 0000000000000000000000000000000000000000..9a835eab838625f4bb2d5f383f3678c225cb678d
--- /dev/null
+++ b/gso/migrations/versions/2024-10-29_94d9de9246fe_add_imported_switches_update_domain_.py
@@ -0,0 +1,110 @@
+"""Add Imported Switches, update domain models.
+
+Revision ID: 94d9de9246fe
+Revises: 7412c5b7ebe4
+Create Date: 2024-10-29 15:45:28.294699
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = '94d9de9246fe'
+down_revision = '7412c5b7ebe4'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='ts_port' WHERE resource_types.resource_type = 'switch_ts_port'
+    """))
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='fqdn' WHERE resource_types.resource_type = 'switch_hostname'
+    """))
+    conn.execute(sa.text("""
+INSERT INTO products (name, description, product_type, tag, status) VALUES ('Imported Switch', 'An existing Switch that is imported into the subscription database', 'ImportedSwitch', 'IMP_SWITCH', 'active') RETURNING products.product_id
+    """))
+    conn.execute(sa.text("""
+INSERT INTO resource_types (resource_type, description) VALUES ('lan_switch_interconnect_ip_network', 'IP resources for a LAN Switch interconnect') RETURNING resource_types.resource_type_id
+    """))
+    conn.execute(sa.text("""
+INSERT INTO product_product_blocks (product_id, product_block_id) VALUES ((SELECT products.product_id FROM products WHERE products.name IN ('Imported Switch')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SwitchBlock')))
+    """))
+    conn.execute(sa.text("""
+INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('lan_switch_interconnect_ip_network')))
+    """))
+    conn.execute(sa.text("""
+INSERT INTO products (name, description, product_type, tag, status) VALUES ('Imported LAN Switch Interconnect', 'An existing LAN Switch Interconnect that is imported into the subscription database', 'ImportedLanSwitchInterconnect', 'IMP_LSI', 'active') RETURNING products.product_id
+    """))
+    conn.execute(sa.text("""
+INSERT INTO product_product_blocks (product_id, product_block_id) VALUES ((SELECT products.product_id FROM products WHERE products.name IN ('Imported LAN Switch Interconnect')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectBlock')))
+    """))
+    conn.execute(sa.text("""
+INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectSwitchSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ipv4_address'))), ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectRouterSideBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ipv4_address')))
+    """))
+
+
+def downgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+    DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectSwitchSideBlock', 'LanSwitchInterconnectRouterSideBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ipv4_address'))
+        """))
+    conn.execute(sa.text("""
+    DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectSwitchSideBlock', 'LanSwitchInterconnectRouterSideBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('ipv4_address'))
+        """))
+    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 ('Imported LAN Switch Interconnect')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectBlock'))
+        """))
+    conn.execute(sa.text("""
+    DELETE FROM processes WHERE processes.pid IN (SELECT processes_subscriptions.pid FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported LAN Switch Interconnect'))))
+        """))
+    conn.execute(sa.text("""
+    DELETE FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported LAN Switch Interconnect')))
+        """))
+    conn.execute(sa.text("""
+    DELETE FROM subscription_instances WHERE subscription_instances.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported LAN Switch Interconnect')))
+        """))
+    conn.execute(sa.text("""
+    DELETE FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported LAN Switch Interconnect'))
+        """))
+    conn.execute(sa.text("""
+    DELETE FROM products WHERE products.name IN ('Imported LAN Switch Interconnect')
+        """))
+    conn.execute(sa.text("""
+DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('lan_switch_interconnect_ip_network'))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('LanSwitchInterconnectBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('lan_switch_interconnect_ip_network'))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('lan_switch_interconnect_ip_network'))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM resource_types WHERE resource_types.resource_type IN ('lan_switch_interconnect_ip_network')
+    """))
+    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 ('Imported Switch')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('SwitchBlock'))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM processes WHERE processes.pid IN (SELECT processes_subscriptions.pid FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported Switch'))))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM processes_subscriptions WHERE processes_subscriptions.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported Switch')))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM subscription_instances WHERE subscription_instances.subscription_id IN (SELECT subscriptions.subscription_id FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported Switch')))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported Switch'))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM products WHERE products.name IN ('Imported Switch')
+    """))
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='switch_ts_port' WHERE resource_types.resource_type = 'ts_port'
+    """))
+    conn.execute(sa.text("""
+UPDATE resource_types SET resource_type='switch_hostname' WHERE resource_types.resource_type = 'fqdn'
+    """))
diff --git a/gso/products/__init__.py b/gso/products/__init__.py
index ad3c2d2a7be2d9c863541d38d950100b0acb59a8..457a86ed3601e66ffb728f5ac00fdc3937907612 100644
--- a/gso/products/__init__.py
+++ b/gso/products/__init__.py
@@ -10,7 +10,7 @@ from pydantic_forms.types import strEnum
 
 from gso.products.product_types.edge_port import EdgePort, ImportedEdgePort
 from gso.products.product_types.iptrunk import ImportedIptrunk, Iptrunk
-from gso.products.product_types.lan_switch_interconnect import LanSwitchInterconnect
+from gso.products.product_types.lan_switch_interconnect import ImportedLanSwitchInterconnect, LanSwitchInterconnect
 from gso.products.product_types.nren_l3_core_service import ImportedNRENL3CoreService, NRENL3CoreService
 from gso.products.product_types.office_router import ImportedOfficeRouter, OfficeRouter
 from gso.products.product_types.opengear import ImportedOpengear, Opengear
@@ -18,7 +18,7 @@ from gso.products.product_types.pop_vlan import PopVlan
 from gso.products.product_types.router import ImportedRouter, Router
 from gso.products.product_types.site import ImportedSite, Site
 from gso.products.product_types.super_pop_switch import ImportedSuperPopSwitch, SuperPopSwitch
-from gso.products.product_types.switch import Switch
+from gso.products.product_types.switch import ImportedSwitch, Switch
 
 
 class ProductName(strEnum):
@@ -30,7 +30,9 @@ class ProductName(strEnum):
     SUPER_POP_SWITCH = "Super PoP switch"
     OFFICE_ROUTER = "Office router"
     SWITCH = "Switch"
+    IMPORTED_SWITCH = "Imported Switch"
     LAN_SWITCH_INTERCONNECT = "LAN Switch Interconnect"
+    IMPORTED_LAN_SWITCH_INTERCONNECT = "Imported LAN Switch Interconnect"
     POP_VLAN = "Pop VLAN"
     IMPORTED_IP_TRUNK = "Imported IP trunk"
     IMPORTED_ROUTER = "Imported router"
@@ -56,7 +58,9 @@ class ProductType(strEnum):
     SUPER_POP_SWITCH = SuperPopSwitch.__name__
     OFFICE_ROUTER = OfficeRouter.__name__
     SWITCH = Switch.__name__
+    IMPORTED_SWITCH = ImportedSwitch.__name__
     LAN_SWITCH_INTERCONNECT = LanSwitchInterconnect.__name__
+    IMPORTED_LAN_SWITCH_INTERCONNECT = ImportedLanSwitchInterconnect.__name__
     POP_VLAN = PopVlan.__name__
     IMPORTED_IP_TRUNK = ImportedIptrunk.__name__
     IMPORTED_ROUTER = ImportedRouter.__name__
@@ -81,7 +85,9 @@ SUBSCRIPTION_MODEL_REGISTRY.update(
         ProductName.SUPER_POP_SWITCH.value: SuperPopSwitch,
         ProductName.OFFICE_ROUTER.value: OfficeRouter,
         ProductName.SWITCH.value: Switch,
+        ProductName.IMPORTED_SWITCH.value: ImportedSwitch,
         ProductName.LAN_SWITCH_INTERCONNECT.value: LanSwitchInterconnect,
+        ProductName.IMPORTED_LAN_SWITCH_INTERCONNECT.value: ImportedLanSwitchInterconnect,
         ProductName.POP_VLAN.value: PopVlan,
         ProductName.IMPORTED_IP_TRUNK.value: ImportedIptrunk,
         ProductName.IMPORTED_ROUTER.value: ImportedRouter,
diff --git a/gso/products/product_blocks/lan_switch_interconnect.py b/gso/products/product_blocks/lan_switch_interconnect.py
index e2626de5c680bb983454ed32b523e61f1b78ad6d..945efc5a14ffb6f8e58b60aa375b91165f19616b 100644
--- a/gso/products/product_blocks/lan_switch_interconnect.py
+++ b/gso/products/product_blocks/lan_switch_interconnect.py
@@ -1,18 +1,12 @@
 """LAN Switch Interconnect product block that has all parameters of a subscription throughout its lifecycle."""
 
 from orchestrator.domain.base import ProductBlockModel
-from orchestrator.types import SubscriptionLifecycle, strEnum
+from orchestrator.types import SubscriptionLifecycle
 
 from gso.products.product_blocks.router import RouterBlock, RouterBlockInactive, RouterBlockProvisioning
 from gso.products.product_blocks.switch import SwitchBlock, SwitchBlockInactive, SwitchBlockProvisioning
 from gso.utils.types.interfaces import LAGMemberList
-
-
-class LanSwitchInterconnectAddressSpace(strEnum):
-    """Types of LAN Switch Interconnect. Can be private or public."""
-
-    PRIVATE = "Private"
-    PUBLIC = "Public"
+from gso.utils.types.ip_address import AddressSpace, IPv4AddressType, IPv4NetworkType
 
 
 class LanSwitchInterconnectInterfaceBlockInactive(
@@ -20,7 +14,7 @@ class LanSwitchInterconnectInterfaceBlockInactive(
     lifecycle=[SubscriptionLifecycle.INITIAL],
     product_block_name="LanSwitchInterconnectInterfaceBlock",
 ):
-    """An inactive LAN Switch Interconnect interface."""
+    """An inactive :term:`LAN` Switch Interconnect interface."""
 
     interface_name: str | None = None
     interface_description: str | None = None
@@ -29,7 +23,7 @@ class LanSwitchInterconnectInterfaceBlockInactive(
 class LanSwitchInterconnectInterfaceBlockProvisioning(
     LanSwitchInterconnectInterfaceBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]
 ):
-    """A LAN Switch Interconnect interface that is being provisioned."""
+    """A :term:`LAN` Switch Interconnect interface that is being provisioned."""
 
     interface_name: str
     interface_description: str
@@ -49,31 +43,34 @@ class LanSwitchInterconnectRouterSideBlockInactive(
     lifecycle=[SubscriptionLifecycle.INITIAL],
     product_block_name="LanSwitchInterconnectRouterSideBlock",
 ):
-    """An inactive LAN Switch Interconnect router side."""
+    """An inactive :term:`LAN` Switch Interconnect router side."""
 
     node: RouterBlockInactive
     ae_iface: str | None = None
     ae_members: LAGMemberList[LanSwitchInterconnectInterfaceBlockInactive]
+    ipv4_address: IPv4AddressType | None = None
 
 
 class LanSwitchInterconnectRouterSideBlockProvisioning(
     LanSwitchInterconnectRouterSideBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]
 ):
-    """An LAN Switch Interconnect router side that is being provisioned."""
+    """A :term:`LAN` Switch Interconnect router side that is being provisioned."""
 
     node: RouterBlockProvisioning
     ae_iface: str | None = None
     ae_members: LAGMemberList[LanSwitchInterconnectInterfaceBlockProvisioning]  # type: ignore[assignment]
+    ipv4_address: IPv4AddressType | None
 
 
 class LanSwitchInterconnectRouterSideBlock(
     LanSwitchInterconnectRouterSideBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]
 ):
-    """An active LAN Switch Interconnect router side."""
+    """An active :term:`LAN` Switch Interconnect router side."""
 
     node: RouterBlock
     ae_iface: str
     ae_members: LAGMemberList[LanSwitchInterconnectInterfaceBlock]  # type: ignore[assignment]
+    ipv4_address: IPv4AddressType | None
 
 
 class LanSwitchInterconnectSwitchSideBlockInactive(
@@ -81,31 +78,34 @@ class LanSwitchInterconnectSwitchSideBlockInactive(
     lifecycle=[SubscriptionLifecycle.INITIAL],
     product_block_name="LanSwitchInterconnectSwitchSideBlock",
 ):
-    """An inactive LAN Switch Interconnect switch side."""
+    """An inactive :term:`LAN` Switch Interconnect switch side."""
 
-    node: SwitchBlockInactive
+    switch: SwitchBlockInactive
     ae_iface: str | None = None
     ae_members: LAGMemberList[LanSwitchInterconnectInterfaceBlockInactive]
+    ipv4_address: IPv4AddressType | None = None
 
 
 class LanSwitchInterconnectSwitchSideBlockProvisioning(
     LanSwitchInterconnectSwitchSideBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]
 ):
-    """An LAN Switch Interconnect switch side that is being provisioned."""
+    """A :term:`LAN` Switch Interconnect switch side that is being provisioned."""
 
-    node: SwitchBlockProvisioning
+    switch: SwitchBlockProvisioning
     ae_iface: str | None = None
     ae_members: LAGMemberList[LanSwitchInterconnectInterfaceBlockProvisioning]  # type: ignore[assignment]
+    ipv4_address: IPv4AddressType | None
 
 
 class LanSwitchInterconnectSwitchSideBlock(
     LanSwitchInterconnectSwitchSideBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]
 ):
-    """An active LAN Switch Interconnect switch side."""
+    """An active :term:`LAN` Switch Interconnect switch side."""
 
-    node: SwitchBlock
+    switch: SwitchBlock
     ae_iface: str
     ae_members: LAGMemberList[LanSwitchInterconnectInterfaceBlock]  # type: ignore[assignment]
+    ipv4_address: IPv4AddressType | None
 
 
 class LanSwitchInterconnectBlockInactive(
@@ -113,10 +113,11 @@ class LanSwitchInterconnectBlockInactive(
     lifecycle=[SubscriptionLifecycle.INITIAL],
     product_block_name="LanSwitchInterconnectBlock",
 ):
-    """A LAN Switch Interconnect that's currently inactive, see :class:`LanSwitchInterconnectBlock`."""
+    """A :term:`LAN` Switch Interconnect that's currently inactive, see :class:`LanSwitchInterconnectBlock`."""
 
     lan_switch_interconnect_description: str | None = None
-    address_space: LanSwitchInterconnectAddressSpace | None = None
+    lan_switch_interconnect_ip_network: IPv4NetworkType | None = None
+    address_space: AddressSpace | None = None
     minimum_links: int | None = None
     router_side: LanSwitchInterconnectRouterSideBlockInactive
     switch_side: LanSwitchInterconnectSwitchSideBlockInactive
@@ -125,25 +126,28 @@ class LanSwitchInterconnectBlockInactive(
 class LanSwitchInterconnectBlockProvisioning(
     LanSwitchInterconnectBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]
 ):
-    """A LAN Switch Interconnect that's currently being provisioned, see :class:`LanSwitchInterconnectBlock`."""
+    """A :term:`LAN` Switch Interconnect that's currently being provisioned, see :class:`LanSwitchInterconnectBlock`."""
 
     lan_switch_interconnect_description: str | None = None
-    address_space: LanSwitchInterconnectAddressSpace | None = None
+    lan_switch_interconnect_ip_network: IPv4NetworkType | None
+    address_space: AddressSpace | None = None
     minimum_links: int | None = None
     router_side: LanSwitchInterconnectRouterSideBlockProvisioning
     switch_side: LanSwitchInterconnectSwitchSideBlockProvisioning
 
 
 class LanSwitchInterconnectBlock(LanSwitchInterconnectBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
-    """A LAN Switch Interconnect that's currently deployed in the network."""
+    """A :term:`LAN` Switch Interconnect that's currently deployed in the network."""
 
-    #:  A human-readable description of this LAN Switch Interconnect.
+    #: A human-readable description of this :term:`LAN` Switch Interconnect.
     lan_switch_interconnect_description: str
-    #:  The address space of the VLAN Switch Interconnect. It can be private or public.
-    address_space: LanSwitchInterconnectAddressSpace
-    #:  The minimum amount of links the LAN Switch Interconnect should consist of.
+    #: The :term:`IP` resources for this :term:`VLAN` Switch Interconnect.
+    lan_switch_interconnect_ip_network: IPv4NetworkType | None
+    #: The address space of the :term:`VLAN` Switch Interconnect. It can be private or public.
+    address_space: AddressSpace
+    #: The minimum amount of links the :term:`LAN` Switch Interconnect should consist of.
     minimum_links: int
-    #:  The router side of the LAN Switch Interconnect.
+    #: The router side of the :term:`LAN` Switch Interconnect.
     router_side: LanSwitchInterconnectRouterSideBlock
-    #:  The switch side of the LAN Switch Interconnect.
+    #: The switch side of the :term:`LAN` Switch Interconnect.
     switch_side: LanSwitchInterconnectSwitchSideBlock
diff --git a/gso/products/product_blocks/pop_vlan.py b/gso/products/product_blocks/pop_vlan.py
index 191e7255951f24f9514a592989546774d17f2185..7e60aa2e2c762bd3d24977b3ddceae8a1b0f89f4 100644
--- a/gso/products/product_blocks/pop_vlan.py
+++ b/gso/products/product_blocks/pop_vlan.py
@@ -1,4 +1,4 @@
-"""Pop VLAN product block that has all parameters of a subscription throughout its lifecycle."""
+"""Pop :term:`VLAN` product block that has all parameters of a subscription throughout its lifecycle."""
 
 from ipaddress import IPv4Network, IPv6Network
 from typing import Annotated, TypeVar
@@ -32,7 +32,7 @@ PortList = Annotated[list[T], AfterValidator(validate_unique_list), Doc("A list
 class PopVlanPortBlockInactive(
     ProductBlockModel, lifecycle=[SubscriptionLifecycle.INITIAL], product_block_name="PopVlanPortBlock"
 ):
-    """An inactive Pop VLAN port."""
+    """An inactive Pop :term:`VLAN` port."""
 
     port_name: str | None = None
     port_description: str | None = None
@@ -40,15 +40,15 @@ class PopVlanPortBlockInactive(
 
 
 class PopVlanPortBlockProvisioning(PopVlanPortBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
-    """A Pop VLAN port that is being provisioned."""
+    """A Pop :term:`VLAN` port that is being provisioned."""
 
-    port_name: str | None = None
-    port_description: str | None = None
-    tagged: bool | None = None
+    port_name: str | None
+    port_description: str | None
+    tagged: bool | None
 
 
 class PopVlanPortBlock(PopVlanPortBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
-    """An active Pop VLAN port."""
+    """An active Pop :term:`VLAN` port."""
 
     port_name: str
     port_description: str
@@ -60,10 +60,10 @@ class PopVlanBlockInactive(
     lifecycle=[SubscriptionLifecycle.INITIAL],
     product_block_name="PopVlanBlock",
 ):
-    """A Pop VLAN that's currently inactive, see :class:`PopVlanBlock`."""
+    """A Pop :term:`VLAN` that's currently inactive, see :class:`PopVlanBlock`."""
 
     vlan_id: int
-    pop_vlan_description: str | None
+    pop_vlan_description: str | None = None
     lan_switch_interconnect: LanSwitchInterconnectBlockInactive
     ports: PortList[PopVlanPortBlockProvisioning]
     layer_preference: LayerPreference
@@ -72,31 +72,31 @@ class PopVlanBlockInactive(
 
 
 class PopVlanBlockProvisioning(PopVlanBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
-    """A Pop VLAN that's currently being provisioned, see :class:`PopVlanBlock`."""
+    """A Pop :term:`VLAN` that's currently being provisioned, see :class:`PopVlanBlock`."""
 
     vlan_id: int
-    pop_vlan_description: str | None = None
+    pop_vlan_description: str | None
     lan_switch_interconnect: LanSwitchInterconnectBlockProvisioning
     ports: PortList[PopVlanPortBlockProvisioning]
     layer_preference: LayerPreference
-    ipv4_network: IPv4Network | None = None
-    ipv6_network: IPv6Network | None = None
+    ipv4_network: IPv4Network | None
+    ipv6_network: IPv6Network | None
 
 
 class PopVlanBlock(PopVlanBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
-    """A Pop VLAN that's currently deployed in the network."""
+    """A Pop :term:`VLAN` that's currently deployed in the network."""
 
-    #: The VLAN ID of the Pop VLAN.
+    #: The :term:`VLAN` ID of the Pop :term:`VLAN`.
     vlan_id: int
-    #: The description of the Pop VLAN.
+    #: The description of the Pop :term:`VLAN`.
     pop_vlan_description: str
-    #: The LAN Switch Interconnect that this Pop VLAN is connected to.
+    #: The :term:`LAN` Switch Interconnect that this Pop :term:`VLAN` is connected to.
     lan_switch_interconnect: LanSwitchInterconnectBlock
-    #: The ports of the Pop VLAN.
+    #: The ports of the Pop :term:`VLAN`.
     ports: PortList[PopVlanPortBlock]  # type: ignore[assignment]
-    #: The level of the layer preference for the Pop VLAN (L2 or L3).
+    #: The level of the layer preference for the Pop :term:`VLAN` (L2 or L3).
     layer_preference: LayerPreference
-    #: IPv4 network for the Pop VLAN if layer preference is L3.
-    ipv4_network: IPv4Network | None = None
-    #: IPv6 network for the Pop VLAN if layer preference is L3.
-    ipv6_network: IPv6Network | None = None
+    #: IPv4 network for the Pop :term:`VLAN` if layer preference is L3.
+    ipv4_network: IPv4Network | None
+    #: IPv6 network for the Pop :term:`VLAN` if layer preference is L3.
+    ipv6_network: IPv6Network | None
diff --git a/gso/products/product_blocks/switch.py b/gso/products/product_blocks/switch.py
index bdf2b4657f8d8674a5c4e19c192f455ef1e31524..790807ad058c6dece6eb1cab7dd055ae9bac96fd 100644
--- a/gso/products/product_blocks/switch.py
+++ b/gso/products/product_blocks/switch.py
@@ -26,9 +26,9 @@ class SwitchBlockInactive(
 ):
     """A switch that's being currently inactive. See :class:`SwitchBlock`."""
 
-    switch_hostname: str | None = None
-    switch_ts_port: PortNumber | None = None
-    switch_site: SiteBlockInactive | None = None
+    fqdn: str | None = None
+    ts_port: PortNumber | None = None
+    site: SiteBlockInactive | None = None
     switch_vendor: Vendor | None = None
     switch_model: SwitchModel | None = None
 
@@ -36,23 +36,23 @@ class SwitchBlockInactive(
 class SwitchBlockProvisioning(SwitchBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
     """A switch that's being provisioned. See :class:`SwitchBlock`."""
 
-    switch_hostname: str
-    switch_ts_port: PortNumber
-    switch_site: SiteBlockProvisioning
+    fqdn: str
+    ts_port: PortNumber
+    site: SiteBlockProvisioning
     switch_vendor: Vendor
-    switch_model: SwitchModel | None = None
+    switch_model: SwitchModel
 
 
 class SwitchBlock(SwitchBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
     """A switch that's currently deployed in the network."""
 
-    #: The hostname of the switch.
-    switch_hostname: str
+    #: The :term:`FQDN` of the switch.
+    fqdn: str
     #:  The port of the terminal server that this switch is connected to. Used to offer out of band access.
-    switch_ts_port: PortNumber
+    ts_port: PortNumber
     #:  The :class:`Site` that this switch resides in. Both physically and computationally.
-    switch_site: SiteBlock
+    site: SiteBlock
     #: The vendor of the switch.
     switch_vendor: Vendor
     #: The model of the switch.
-    switch_model: SwitchModel | None = None
+    switch_model: SwitchModel
diff --git a/gso/products/product_types/lan_switch_interconnect.py b/gso/products/product_types/lan_switch_interconnect.py
index 32433c4694b0f097bcdc80df742ca9695a9dee53..0f83fe3714ac68bc605b77c498d56b51412d7873 100644
--- a/gso/products/product_types/lan_switch_interconnect.py
+++ b/gso/products/product_types/lan_switch_interconnect.py
@@ -26,3 +26,17 @@ class LanSwitchInterconnect(LanSwitchInterconnectProvisioning, lifecycle=[Subscr
     """An LAN Switch Interconnect that is active."""
 
     lan_switch_interconnect: LanSwitchInterconnectBlock
+
+
+class ImportedLanSwitchInterconnectInactive(SubscriptionModel, is_base=True):
+    """An imported, inactive :term:`LAN` Switch Interconnect."""
+
+    lan_switch_interconnect: LanSwitchInterconnectBlockInactive
+
+
+class ImportedLanSwitchInterconnect(
+    ImportedLanSwitchInterconnectInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE]
+):
+    """An imported :term:`LAN` Switch Interconnect."""
+
+    lan_switch_interconnect: LanSwitchInterconnectBlock
diff --git a/gso/products/product_types/switch.py b/gso/products/product_types/switch.py
index ef2eb05eac333628ba4ae5bef2424283adec3758..10cc9bb202754866a6b8646abdcd10d31f074f85 100644
--- a/gso/products/product_types/switch.py
+++ b/gso/products/product_types/switch.py
@@ -22,3 +22,17 @@ class Switch(SwitchProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
     """A switch that is currently active."""
 
     switch: SwitchBlock
+
+
+class ImportedSwitchInactive(SubscriptionModel, is_base=True):
+    """An imported, inactive switch."""
+
+    switch: SwitchBlockInactive
+
+
+class ImportedSwitch(
+    ImportedSwitchInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE]
+):
+    """An imported switch that is currently active."""
+
+    switch: SwitchBlock
diff --git a/gso/translations/en-GB.json b/gso/translations/en-GB.json
index ef3a1bdeae293d10fa74fbb80a550860c3792841..1858d04ece8f39a1bd1f83de8994e6c71633ba9a 100644
--- a/gso/translations/en-GB.json
+++ b/gso/translations/en-GB.json
@@ -53,6 +53,7 @@
         "create_switch": "Create Switch",
         "create_edge_port": "Create Edge Port",
         "create_nren_l3_core_service": "Create NREN L3 Core Service",
+        "create_lan_switch_interconnect": "Create LAN Switch Interconnect",
         "deploy_twamp": "Deploy TWAMP",
         "migrate_iptrunk": "Migrate IP Trunk",
         "migrate_nren_l3_core_service": "Migrate NREN L3 Core Service",
@@ -68,6 +69,7 @@
         "terminate_site": "Terminate Site",
         "terminate_switch": "Terminate Switch",
         "terminate_edge_port": "Terminate Edge Port",
+        "terminate_lan_switch_interconnect": "Terminate LAN Switch Interconnect",
         "redeploy_base_config": "Redeploy base config",
         "update_ibgp_mesh": "Update iBGP mesh",
         "create_imported_site": "NOT FOR HUMANS -- Import existing site",
@@ -78,6 +80,8 @@
         "create_imported_opengear": "NOT FOR HUMANS -- Import existing OpenGear",
         "create_imported_edge_port": "NOT FOR HUMANS -- Import existing Edge Port",
         "create_imported_nren_l3_core_service": "NOT FOR HUMANS -- Import existing NREN L3 Core Service",
+        "create_imported_switch": "NOT FOR HUMANS -- Import existing Switch",
+        "create_imported_lan_switch_interconnect": "NOT FOR HUMANS -- Import existing LAN Switch Interconnect",
         "import_site": "NOT FOR HUMANS -- Finalize import into a Site product",
         "import_router": "NOT FOR HUMANS -- Finalize import into a Router product",
         "import_iptrunk": "NOT FOR HUMANS -- Finalize import into an IP trunk product",
@@ -86,10 +90,13 @@
         "import_opengear": "NOT FOR HUMANS -- Finalize import into an OpenGear",
         "import_edge_port": "NOT FOR HUMANS -- Finalize import into an Edge Port",
         "import_nren_l3_core_service": "NOT FOR HUMANS -- Finalize import into a NREN L3 Core Service",
+        "import_switch": "NOT FOR HUMANS -- Finalize import into a Switch",
+        "import_lan_switch_interconnect": "NOT FOR HUMANS -- Finalize import into a LAN Switch Interconnect",
         "validate_iptrunk": "Validate IP Trunk configuration",
         "validate_router": "Validate Router configuration",
         "validate_switch": "Validate Switch configuration",
         "validate_edge_port": "Validate Edge Port",
+        "validate_lan_switch_interconnect": "Validate LAN Switch Interconnect",
         "task_validate_geant_products": "Validation task for GEANT products",
         "task_send_email_notifications": "Send email notifications for failed tasks",
         "task_create_partners": "Create partner task",
diff --git a/gso/utils/types/ip_address.py b/gso/utils/types/ip_address.py
index 6186a1f83d6a495aa591e1e96a6a2030794de7fd..3b91167fe978a863a133abe75c68b275a1b028fb 100644
--- a/gso/utils/types/ip_address.py
+++ b/gso/utils/types/ip_address.py
@@ -4,6 +4,7 @@ import ipaddress
 from typing import Annotated, Any
 
 from pydantic import AfterValidator, Field, PlainSerializer
+from pydantic_forms.types import strEnum
 from typing_extensions import Doc
 
 
@@ -52,3 +53,10 @@ PortNumber = Annotated[
         "and can therefore not be selected for permanent allocation."
     ),
 ]
+
+
+class AddressSpace(strEnum):
+    """Types of address space. Can be private or public."""
+
+    PRIVATE = "PRIVATE"
+    PUBLIC = "PUBLIC"
diff --git a/gso/workflows/__init__.py b/gso/workflows/__init__.py
index 5a6b9d082339add5f4890d54b3654228a989d7de..362f96ab161f8d15847185ebb8355a6df1a321e8 100644
--- a/gso/workflows/__init__.py
+++ b/gso/workflows/__init__.py
@@ -17,9 +17,12 @@ WF_USABLE_MAP.update({
     "deploy_twamp": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
     "modify_trunk_interface": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
     "activate_iptrunk": [SubscriptionLifecycle.PROVISIONING],
+    "activate_switch": [SubscriptionLifecycle.PROVISIONING],
     "terminate_site": ALL_ALIVE_STATES,
     "terminate_router": ALL_ALIVE_STATES,
     "terminate_iptrunk": ALL_ALIVE_STATES,
+    "terminate_switch": ALL_ALIVE_STATES,
+    "terminate_lan_switch_interconnect": ALL_ALIVE_STATES,
     "promote_p_to_pe": [SubscriptionLifecycle.ACTIVE],
     "validate_router": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
     "validate_iptrunk": [SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE],
@@ -50,6 +53,32 @@ LazyWorkflowInstance("gso.workflows.router.validate_router", "validate_router")
 LazyWorkflowInstance("gso.workflows.router.promote_p_to_pe", "promote_p_to_pe")
 LazyWorkflowInstance("gso.workflows.router.modify_kentik_license", "modify_router_kentik_license")
 
+#  Switch workflows
+LazyWorkflowInstance("gso.workflows.switch.create_switch", "create_switch")
+LazyWorkflowInstance("gso.workflows.switch.activate_switch", "activate_switch")
+LazyWorkflowInstance("gso.workflows.switch.terminate_switch", "terminate_switch")
+LazyWorkflowInstance("gso.workflows.switch.validate_switch", "validate_switch")
+LazyWorkflowInstance("gso.workflows.switch.create_imported_switch", "create_imported_switch")
+LazyWorkflowInstance("gso.workflows.switch.import_switch", "import_switch")
+
+#  LAN Switch Interconnect workflows
+LazyWorkflowInstance(
+    "gso.workflows.lan_switch_interconnect.create_lan_switch_interconnect", "create_lan_switch_interconnect"
+)
+LazyWorkflowInstance(
+    "gso.workflows.lan_switch_interconnect.terminate_lan_switch_interconnect", "terminate_lan_switch_interconnect"
+)
+LazyWorkflowInstance(
+    "gso.workflows.lan_switch_interconnect.validate_lan_switch_interconnect", "validate_lan_switch_interconnect"
+)
+LazyWorkflowInstance(
+    "gso.workflows.lan_switch_interconnect.create_imported_lan_switch_interconnect",
+    "create_imported_lan_switch_interconnect",
+)
+LazyWorkflowInstance(
+    "gso.workflows.lan_switch_interconnect.import_lan_switch_interconnect", "import_lan_switch_interconnect"
+)
+
 #  Site workflows
 LazyWorkflowInstance("gso.workflows.site.create_site", "create_site")
 LazyWorkflowInstance("gso.workflows.site.modify_site", "modify_site")
diff --git a/gso/workflows/lan_switch_interconnect/create_imported_lan_switch_interconnect.py b/gso/workflows/lan_switch_interconnect/create_imported_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..1439c2fe7572c7fe89cf0e2c9fb4fcc4164b5de2
--- /dev/null
+++ b/gso/workflows/lan_switch_interconnect/create_imported_lan_switch_interconnect.py
@@ -0,0 +1,100 @@
+"""Import an existing :term:`LAN` Switch Interconnect into the subscription database."""
+
+from uuid import uuid4
+
+from orchestrator import step, workflow
+from orchestrator.forms import FormPage
+from orchestrator.targets import Target
+from orchestrator.types import FormGenerator, State, SubscriptionLifecycle
+from orchestrator.workflow import StepList, begin, done
+from orchestrator.workflows.steps import resync, set_status, store_process_subscription
+
+from gso.cli.imports import LanSwitchInterconnectRouterSideImportModel, LanSwitchInterconnectSwitchSideImportModel
+from gso.products import ProductName
+from gso.products.product_blocks.lan_switch_interconnect import (
+    LanSwitchInterconnectInterfaceBlockInactive,
+    LanSwitchInterconnectRouterSideBlockInactive,
+    LanSwitchInterconnectSwitchSideBlockInactive,
+)
+from gso.products.product_types.lan_switch_interconnect import ImportedLanSwitchInterconnectInactive
+from gso.products.product_types.router import Router
+from gso.products.product_types.switch import Switch
+from gso.services.partners import get_partner_by_name
+from gso.services.subscriptions import get_product_id_by_name
+from gso.utils.types.ip_address import AddressSpace, IPv4NetworkType
+
+
+def _initial_input_form_generator() -> FormGenerator:
+    class ImportLanSwitchInterconnect(FormPage):
+        lan_switch_interconnect_description: str
+        lan_switch_interconnect_ip_network: IPv4NetworkType | None
+        address_space: AddressSpace
+        minimum_links: int
+        router_side: LanSwitchInterconnectRouterSideImportModel
+        switch_side: LanSwitchInterconnectSwitchSideImportModel
+
+    user_input = yield ImportLanSwitchInterconnect
+    return user_input.model_dump() | {"partner": "GEANT"}
+
+
+@step("Create subscription")
+def create_subscription(partner: str) -> State:
+    """Create a new subscription object."""
+    partner_id = get_partner_by_name(partner)["partner_id"]
+    product_id = get_product_id_by_name(ProductName.IMPORTED_LAN_SWITCH_INTERCONNECT)
+    subscription = ImportedLanSwitchInterconnectInactive.from_product_id(product_id, partner_id)
+
+    return {"subscription": subscription, "subscription_id": subscription.subscription_id}
+
+
+@step("Initialize subscription")
+def initialize_subscription(
+    subscription: ImportedLanSwitchInterconnectInactive,
+    lan_switch_interconnect_description: str,
+    lan_switch_interconnect_ip_network: IPv4NetworkType | None,
+    address_space: AddressSpace,
+    minimum_links: int,
+    router_side: dict,
+    switch_side: dict,
+) -> State:
+    """Initialize the subscription using input data."""
+    subscription.lan_switch_interconnect.lan_switch_interconnect_description = lan_switch_interconnect_description
+    subscription.lan_switch_interconnect.lan_switch_interconnect_ip_network = lan_switch_interconnect_ip_network
+    subscription.lan_switch_interconnect.address_space = address_space
+    subscription.lan_switch_interconnect.minimum_links = minimum_links
+
+    router_block = Router.from_subscription(router_side.pop("node")).router
+    router_side_interfaces = [
+        LanSwitchInterconnectInterfaceBlockInactive.new(uuid4(), **ae_member)
+        for ae_member in router_side.pop("ae_members")
+    ]
+    subscription.lan_switch_interconnect.router_side = LanSwitchInterconnectRouterSideBlockInactive.new(
+        uuid4(), **router_side, node=router_block, ae_members=router_side_interfaces
+    )
+
+    switch_block = Switch.from_subscription(switch_side.pop("switch")).switch
+    switch_side_interfaces = [
+        LanSwitchInterconnectInterfaceBlockInactive.new(uuid4(), **ae_member)
+        for ae_member in switch_side.pop("ae_members")
+    ]
+    subscription.lan_switch_interconnect.switch_side = LanSwitchInterconnectSwitchSideBlockInactive.new(
+        uuid4(), **switch_side, switch=switch_block, ae_members=switch_side_interfaces
+    )
+
+    return {"subscription": subscription}
+
+
+@workflow(
+    "Create Imported LAN Switch Interconnect", initial_input_form=_initial_input_form_generator, target=Target.CREATE
+)
+def create_imported_lan_switch_interconnect() -> StepList:
+    """Create an imported :term:`LAN` Switch Interconnect without provisioning it."""
+    return (
+        begin
+        >> create_subscription
+        >> store_process_subscription(Target.CREATE)
+        >> initialize_subscription
+        >> set_status(SubscriptionLifecycle.ACTIVE)
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py b/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py
index 973cf1d88495b4343e390c258d16c3c9f78f65c9..eeec84e17d08e53cf3bf9fcf3531f38314772c11 100644
--- a/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py
+++ b/gso/workflows/lan_switch_interconnect/create_lan_switch_interconnect.py
@@ -14,7 +14,6 @@ from pydantic import AfterValidator, ConfigDict
 from pydantic_forms.validators import Divider, ReadOnlyField
 
 from gso.products.product_blocks.lan_switch_interconnect import (
-    LanSwitchInterconnectAddressSpace,
     LanSwitchInterconnectInterfaceBlockInactive,
 )
 from gso.products.product_types.lan_switch_interconnect import LanSwitchInterconnectInactive
@@ -36,7 +35,9 @@ from gso.utils.types.interfaces import (
     PhysicalPortCapacity,
     validate_interface_names_are_unique,
 )
+from gso.utils.types.ip_address import AddressSpace
 from gso.utils.types.tt_number import TTNumber
+from gso.workflows.shared import create_summary_form
 
 
 def _initial_input_form(product_name: str) -> FormGenerator:
@@ -44,16 +45,17 @@ def _initial_input_form(product_name: str) -> FormGenerator:
         model_config = ConfigDict(title=product_name)
 
         tt_number: TTNumber
+        partner: ReadOnlyField("GEANT", default_type=str)  # type: ignore[valid-type]
         router_side: active_router_selector()  # type: ignore[valid-type]
         switch_side: active_switch_selector()  # type: ignore[valid-type]
-        address_space: LanSwitchInterconnectAddressSpace
+        address_space: AddressSpace
         description: str
         minimum_link_count: int
         divider: Divider
         vlan_id: ReadOnlyField(111, default_type=int)  # type: ignore[valid-type]
 
-    user_input = yield CreateLANSwitchInterconnectForm
-    router = Router.from_subscription(user_input.router_side)
+    initial_input = yield CreateLANSwitchInterconnectForm
+    router = Router.from_subscription(initial_input.router_side)
 
     if router.router.vendor == Vendor.NOKIA:
 
@@ -66,19 +68,19 @@ def _initial_input_form(product_name: str) -> FormGenerator:
         router_side_ae_member_list = Annotated[
             list[NokiaLAGMemberA],
             AfterValidator(validate_interface_names_are_unique),
-            Len(min_length=user_input.minimum_link_count),
+            Len(min_length=initial_input.minimum_link_count),
         ]
     else:
         router_side_ae_member_list = Annotated[  # type: ignore[assignment, misc]
             list[JuniperLAGMember],
             AfterValidator(validate_interface_names_are_unique),
-            Len(min_length=user_input.minimum_link_count),
+            Len(min_length=initial_input.minimum_link_count),
         ]
 
     class InterconnectRouterSideForm(FormPage):
         model_config = ConfigDict(title="Please enter interface names and descriptions for the router side.")
 
-        router_side_iface: available_lags_choices(user_input.router_side) or JuniperAEInterface  # type: ignore[valid-type]
+        router_side_iface: available_lags_choices(initial_input.router_side) or JuniperAEInterface or str  # type: ignore[valid-type]
         router_side_ae_members: router_side_ae_member_list
 
     router_side_input = yield InterconnectRouterSideForm
@@ -99,8 +101,24 @@ def _initial_input_form(product_name: str) -> FormGenerator:
         switch_side_ae_members: switch_side_ae_member_list
 
     switch_side_input = yield InterconnectSwitchSideForm
+    user_input = initial_input.model_dump() | router_side_input.model_dump() | switch_side_input.model_dump()
+    summary_fields = [
+        "tt_number",
+        "partner",
+        "router_side",
+        "switch_side",
+        "address_space",
+        "description",
+        "minimum_link_count",
+        "vlan_id",
+        "router_side_iface",
+        "router_side_ae_members",
+        "switch_side_iface",
+        "switch_side_ae_members",
+    ]
+    yield from create_summary_form(user_input, product_name, summary_fields)
 
-    return user_input.model_dump() | router_side_input.model_dump() | switch_side_input.model_dump()
+    return user_input
 
 
 @step("Create subscription")
@@ -108,14 +126,14 @@ def create_subscription(product: UUIDstr, partner: str) -> State:
     """Create a new subscription object in the database."""
     subscription = LanSwitchInterconnectInactive.from_product_id(product, get_partner_by_name(partner)["partner_id"])
 
-    return {"subscription": subscription}
+    return {"subscription": subscription, "subscription_id": subscription.subscription_id}
 
 
 @step("Initialize subscription")
 def initialize_subscription(
     subscription: LanSwitchInterconnectInactive,
     description: str,
-    address_space: LanSwitchInterconnectAddressSpace,
+    address_space: AddressSpace,
     minimum_link_count: int,
     router_side: UUIDstr,
     router_side_iface: JuniperPhyInterface,
@@ -134,7 +152,7 @@ def initialize_subscription(
         subscription.lan_switch_interconnect.router_side.ae_members.append(
             LanSwitchInterconnectInterfaceBlockInactive.new(subscription_id=uuid4(), **member)
         )
-    subscription.lan_switch_interconnect.switch_side.node = Switch.from_subscription(switch_side).switch
+    subscription.lan_switch_interconnect.switch_side.switch = Switch.from_subscription(switch_side).switch
     subscription.lan_switch_interconnect.switch_side.ae_iface = switch_side_iface
     for member in switch_side_ae_members:
         subscription.lan_switch_interconnect.switch_side.ae_members.append(
@@ -145,7 +163,7 @@ def initialize_subscription(
 
 
 @workflow(
-    "Create LAN switch interconnect",
+    "Create LAN Switch Interconnect",
     initial_input_form=wrap_create_initial_input_form(_initial_input_form),
     target=Target.CREATE,
 )
diff --git a/gso/workflows/lan_switch_interconnect/import_lan_switch_interconnect.py b/gso/workflows/lan_switch_interconnect/import_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0f247aa28d0578ec4e5898e32f316b22c449286
--- /dev/null
+++ b/gso/workflows/lan_switch_interconnect/import_lan_switch_interconnect.py
@@ -0,0 +1,37 @@
+"""Import an existing :term:`LAN` Switch Interconnect into the service database."""
+
+from orchestrator import step, workflow
+from orchestrator.targets import Target
+from orchestrator.types import State, UUIDstr
+from orchestrator.workflow import StepList, begin, done
+from orchestrator.workflows.steps import resync, store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+
+from gso.products import ProductName
+from gso.products.product_types.lan_switch_interconnect import ImportedLanSwitchInterconnect, LanSwitchInterconnect
+from gso.services.subscriptions import get_product_id_by_name
+
+
+@step("Create new switch subscription")
+def import_lan_switch_interconnect_subscription(subscription_id: UUIDstr) -> State:
+    """Take an imported subscription, and turn it into a full subscription."""
+    old_subscription = ImportedLanSwitchInterconnect.from_subscription(subscription_id)
+    new_subscription_id = get_product_id_by_name(ProductName.LAN_SWITCH_INTERCONNECT)
+    new_subscription = LanSwitchInterconnect.from_other_product(old_subscription, new_subscription_id)  # type: ignore[arg-type]
+
+    return {"subscription": new_subscription}
+
+
+@workflow(
+    "Import LAN Switch Interconnect", target=Target.MODIFY, initial_input_form=wrap_modify_initial_input_form(None)
+)
+def import_lan_switch_interconnect() -> StepList:
+    """Modify an ImportedLanSwitchInterconnect subscription into subscription to complete the import."""
+    return (
+        begin
+        >> store_process_subscription(Target.MODIFY)
+        >> unsync
+        >> import_lan_switch_interconnect_subscription
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/lan_switch_interconnect/terminate_lan_switch_interconnect.py b/gso/workflows/lan_switch_interconnect/terminate_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..9df06c9a08b046e6c8891b84ff88252b2fc0605a
--- /dev/null
+++ b/gso/workflows/lan_switch_interconnect/terminate_lan_switch_interconnect.py
@@ -0,0 +1,48 @@
+"""Workflow for terminating a LAN Switch interconnect."""
+
+from orchestrator import begin, workflow
+from orchestrator.forms import FormPage
+from orchestrator.targets import Target
+from orchestrator.types import SubscriptionLifecycle, UUIDstr
+from orchestrator.workflow import StepList, done
+from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+from pydantic_forms.types import FormGenerator
+from pydantic_forms.validators import Label
+
+from gso.products.product_types.lan_switch_interconnect import LanSwitchInterconnect
+from gso.utils.types.tt_number import TTNumber
+
+
+def _input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
+    lan_switch_interconnect = LanSwitchInterconnect.from_subscription(subscription_id)
+
+    class TerminateForm(FormPage):
+        if lan_switch_interconnect.status == SubscriptionLifecycle.INITIAL:
+            info_label: Label = (
+                "This will immediately mark the subscription as terminated, preventing any other workflows from "
+                "interacting with this product subscription."
+            )
+            info_label_2: Label = "ONLY EXECUTE THIS WORKFLOW WHEN YOU ARE ABSOLUTELY SURE WHAT YOU ARE DOING."
+
+        tt_number: TTNumber
+
+    yield TerminateForm
+    return {"subscription": lan_switch_interconnect}
+
+
+@workflow(
+    "Terminate LAN Switch Interconnect",
+    initial_input_form=wrap_modify_initial_input_form(_input_form_generator),
+    target=Target.TERMINATE,
+)
+def terminate_lan_switch_interconnect() -> StepList:
+    """Terminate a :term:`LAN` Switch Interconnect."""
+    return (
+        begin
+        >> store_process_subscription(Target.TERMINATE)
+        >> unsync
+        >> set_status(SubscriptionLifecycle.TERMINATED)
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/lan_switch_interconnect/validate_lan_switch_interconnect.py b/gso/workflows/lan_switch_interconnect/validate_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..f2a623dedb2a75716ec989b0c29795b4217541a2
--- /dev/null
+++ b/gso/workflows/lan_switch_interconnect/validate_lan_switch_interconnect.py
@@ -0,0 +1,40 @@
+"""Validation workflow for :term:`LAN` Switch Interconnect subscription objects."""
+
+from typing import Any
+
+from orchestrator.targets import Target
+from orchestrator.workflow import StepList, begin, done, step, workflow
+from orchestrator.workflows.steps import resync, store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+
+from gso.services.lso_client import LSOState, anonymous_lso_interaction
+
+
+@step("Check config for drift")
+def validate_config(subscription: dict[str, Any]) -> LSOState:
+    """Workflow step for running a playbook that checks whether config has drifted."""
+    return {
+        "playbook_name": "lan_switch_interconnect.yaml",
+        "inventory": {"all": {"hosts": {None: None}}},
+        "extra_vars": {
+            "subscription_json": subscription,
+            "verb": "deploy",
+            "dry_run": "true",
+            "is_verification_workflow": "true",
+        },
+    }
+
+
+@workflow(
+    "Validate LAN Switch Interconnect", target=Target.SYSTEM, initial_input_form=(wrap_modify_initial_input_form(None))
+)
+def validate_lan_switch_interconnect() -> StepList:
+    """Validate an existing :term:`LAN` Switch Interconnect."""
+    return (
+        begin
+        >> store_process_subscription(Target.SYSTEM)
+        >> unsync
+        >> anonymous_lso_interaction(validate_config)
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/router/create_imported_router.py b/gso/workflows/router/create_imported_router.py
index 12a71c79b51e0166d976a175d9833870300af1f5..cb729eb276c6a4734dd31c98ddd92bd1240b61cd 100644
--- a/gso/workflows/router/create_imported_router.py
+++ b/gso/workflows/router/create_imported_router.py
@@ -25,10 +25,7 @@ def create_subscription(partner: str) -> State:
     product_id = get_product_id_by_name(ProductName.IMPORTED_ROUTER)
     subscription = ImportedRouterInactive.from_product_id(product_id, partner_id)
 
-    return {
-        "subscription": subscription,
-        "subscription_id": subscription.subscription_id,
-    }
+    return {"subscription": subscription, "subscription_id": subscription.subscription_id}
 
 
 def initial_input_form_generator() -> FormGenerator:
diff --git a/gso/workflows/router/modify_kentik_license.py b/gso/workflows/router/modify_kentik_license.py
index bd97b9c04605ed475fb7800a6cf965b5c3c895a1..e1a87021483bbf05017be50129064c7d4ed78894 100644
--- a/gso/workflows/router/modify_kentik_license.py
+++ b/gso/workflows/router/modify_kentik_license.py
@@ -33,7 +33,7 @@ def _initial_input_form(subscription_id: UUIDstr) -> FormGenerator:
     )
 
     class ModifyKentikLicenseForm(FormPage):
-        new_plan_id: available_kentik_plans  # type: ignore[valid-type]
+        new_plan_id: available_kentik_plans or str  # type: ignore[valid-type]
 
         @model_validator(mode="before")
         def router_must_be_nokia_p(cls, data: Any) -> Any:
diff --git a/gso/workflows/switch/__init__.py b/gso/workflows/switch/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..acc604b8258770eaa9d31d3568811e5b7f81940e
--- /dev/null
+++ b/gso/workflows/switch/__init__.py
@@ -0,0 +1 @@
+"""Workflows for switches."""
diff --git a/gso/workflows/switch/activate_switch.py b/gso/workflows/switch/activate_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d0d7113764c4a2732526fd7c2123d85fe39675a
--- /dev/null
+++ b/gso/workflows/switch/activate_switch.py
@@ -0,0 +1,50 @@
+"""Workflow for activating a switch, making it available to other subscriptions."""
+
+from orchestrator.config.assignee import Assignee
+from orchestrator.forms import FormPage
+from orchestrator.forms.validators import Label
+from orchestrator.targets import Target
+from orchestrator.types import FormGenerator, SubscriptionLifecycle, UUIDstr
+from orchestrator.workflow import StepList, begin, done, inputstep, workflow
+from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+
+from gso.products.product_types.switch import Switch
+
+
+def _initial_input_form(subscription_id: UUIDstr) -> FormGenerator:
+    switch = Switch.from_subscription(subscription_id)
+
+    class ActivateSwitchForm(FormPage):
+        info_label: Label = "Start approval process for switch activation."
+
+    yield ActivateSwitchForm
+    return {"subscription": switch}
+
+
+@inputstep("Verify checklist completion", assignee=Assignee.SYSTEM)
+def verify_complete_checklist() -> FormGenerator:
+    """Ask the operator to provide a link to the completed checklist in SharePoint."""
+
+    class VerifyCompleteForm(FormPage):
+        info_label: Label = "Please enter URL to the completed checklist in SharePoint. Then continue this workflow."
+        checklist_url: str = ""
+
+    user_input = yield VerifyCompleteForm
+    return {"checklist_url": user_input.model_dump()["checklist_url"]}
+
+
+@workflow(
+    "Activate switch", initial_input_form=(wrap_modify_initial_input_form(_initial_input_form)), target=Target.MODIFY
+)
+def activate_switch() -> StepList:
+    """Take a switch and move it from a `PROVISIONING` to an `ACTIVE` state."""
+    return (
+        begin
+        >> store_process_subscription(Target.MODIFY)
+        >> unsync
+        >> verify_complete_checklist
+        >> set_status(SubscriptionLifecycle.ACTIVE)
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/switch/create_imported_switch.py b/gso/workflows/switch/create_imported_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..558e53b6e25fbac1b3c37df95b5dbdd45af5c517
--- /dev/null
+++ b/gso/workflows/switch/create_imported_switch.py
@@ -0,0 +1,72 @@
+"""A creation workflow that adds an existing switch to the service database."""
+
+from orchestrator import step, workflow
+from orchestrator.forms import FormPage
+from orchestrator.targets import Target
+from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUIDstr
+from orchestrator.workflow import StepList, begin, done
+from orchestrator.workflows.steps import resync, set_status, store_process_subscription
+
+from gso.products import ProductName
+from gso.products.product_blocks.switch import SwitchModel
+from gso.products.product_types.site import Site
+from gso.products.product_types.switch import ImportedSwitchInactive
+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 Vendor
+from gso.utils.types.ip_address import PortNumber
+
+
+def _initial_input_form_generator() -> FormGenerator:
+    class ImportSwitch(FormPage):
+        fqdn: str
+        ts_port: PortNumber
+        site: UUIDstr
+        switch_vendor: Vendor
+        switch_model: SwitchModel
+
+    user_input = yield ImportSwitch
+    return user_input.model_dump() | {"partner": "GEANT"}
+
+
+@step("Create subscription")
+def create_subscription(partner: str) -> State:
+    """Create a new subscription object."""
+    partner_id = get_partner_by_name(partner)["partner_id"]
+    product_id = get_product_id_by_name(ProductName.IMPORTED_SWITCH)
+    subscription = ImportedSwitchInactive.from_product_id(product_id, partner_id)
+
+    return {"subscription": subscription, "subscription_id": subscription.subscription_id}
+
+
+@step("Initialize subscription")
+def initialize_subscription(
+    subscription: ImportedSwitchInactive,
+    fqdn: str,
+    ts_port: PortNumber,
+    site: UUIDstr,
+    switch_vendor: Vendor,
+    switch_model: SwitchModel,
+) -> State:
+    """Initialize the switch subscription using input data."""
+    subscription.switch.fqdn = fqdn
+    subscription.switch.ts_port = ts_port
+    subscription.switch.site = Site.from_subscription(site).site
+    subscription.switch.switch_vendor = switch_vendor
+    subscription.switch.switch_model = switch_model
+
+    return {"subscription": subscription}
+
+
+@workflow("Create Imported Switch", initial_input_form=_initial_input_form_generator, target=Target.CREATE)
+def create_imported_switch() -> StepList:
+    """Create an imported switch without provisioning it."""
+    return (
+        begin
+        >> create_subscription
+        >> store_process_subscription(Target.CREATE)
+        >> initialize_subscription
+        >> set_status(SubscriptionLifecycle.ACTIVE)
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/switch/create_switch.py b/gso/workflows/switch/create_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..0074c8e4cc870a3afaffd8ac704759841dcf9a52
--- /dev/null
+++ b/gso/workflows/switch/create_switch.py
@@ -0,0 +1,219 @@
+"""A creation workflow for adding a new switch to the subscription database."""
+
+from typing import Self
+
+from orchestrator.config.assignee import Assignee
+from orchestrator.forms import FormPage
+from orchestrator.targets import Target
+from orchestrator.types import FormGenerator, State, SubscriptionLifecycle, UUIDstr
+from orchestrator.workflow import StepList, begin, done, inputstep, step, workflow
+from orchestrator.workflows.steps import resync, set_status, store_process_subscription
+from orchestrator.workflows.utils import wrap_create_initial_input_form
+from pydantic import ConfigDict, model_validator
+from pydantic_forms.validators import Label, ReadOnlyField
+
+from gso.products.product_blocks.switch import SwitchModel
+from gso.products.product_types.site import Site
+from gso.products.product_types.switch import SwitchInactive, SwitchProvisioning
+from gso.services import infoblox
+from gso.services.lso_client import LSOState, lso_interaction
+from gso.services.partners import get_partner_by_name
+from gso.services.sharepoint import SharePointClient
+from gso.settings import load_oss_params
+from gso.utils.helpers import active_site_selector, generate_fqdn
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import PortNumber
+from gso.utils.types.tt_number import TTNumber
+from gso.utils.workflow_steps import prompt_sharepoint_checklist_url
+from gso.workflows.shared import create_summary_form
+
+
+def _initial_input_form_generator(product_name: str) -> FormGenerator:
+    """Input form for creating a new Switch."""
+
+    class CreateSwitchForm(FormPage):
+        model_config = ConfigDict(title=product_name)
+
+        tt_number: TTNumber
+        partner: ReadOnlyField("GEANT", default_type=str)  # type: ignore[valid-type]
+        switch_site: active_site_selector() or str  # type: ignore[valid-type]
+        hostname: str
+        ts_port: PortNumber
+        vendor: ReadOnlyField(Vendor.JUNIPER, default_type=Vendor)  # type: ignore[valid-type]
+        model: ReadOnlyField(SwitchModel.EX3400, default_type=SwitchModel)  # type: ignore[valid-type]
+
+        @model_validator(mode="after")
+        def hostname_must_be_available(self) -> Self:
+            if not self.switch_site:
+                msg = "Please select a site before setting the hostname."
+                raise ValueError(msg)
+
+            selected_site = Site.from_subscription(self.switch_site).site
+            input_fqdn = generate_fqdn(self.hostname, selected_site.site_name, selected_site.site_country_code)
+            if not infoblox.hostname_available(input_fqdn):
+                msg = f'FQDN "{input_fqdn}" is not available.'
+                raise ValueError(msg)
+
+            return self
+
+    input_form = yield CreateSwitchForm
+    user_input = input_form.model_dump()
+    summary_fields = ["tt_number", "partner", "switch_site", "hostname", "ts_port", "vendor", "model"]
+    yield from create_summary_form(user_input, product_name, summary_fields)
+
+    return user_input
+
+
+@step("Create subscription")
+def create_subscription(product: UUIDstr, partner: str) -> State:
+    """Create a new subscription object."""
+    subscription = SwitchInactive.from_product_id(product, get_partner_by_name(partner)["partner_id"])
+
+    return {"subscription": subscription, "subscription_id": subscription.subscription_id}
+
+
+@step("Initialize subscription")
+def initialize_subscription(
+    subscription: SwitchInactive,
+    switch_site: str,
+    ts_port: PortNumber,
+    vendor: Vendor,
+    model: SwitchModel,
+    hostname: str,
+) -> State:
+    """Initialize the subscription with user input."""
+    subscription.switch.site = Site.from_subscription(switch_site).site
+    subscription.switch.fqdn = generate_fqdn(
+        hostname, subscription.switch.site.site_name, subscription.switch.site.site_country_code
+    )
+    subscription.switch.ts_port = ts_port
+    subscription.switch.switch_vendor = vendor
+    subscription.switch.switch_model = model
+    subscription.description = f"Switch {subscription.switch.fqdn}"
+
+    return {"subscription": subscription}
+
+
+@step("[DRY RUN] Deploy base config")
+def deploy_base_config_dry(subscription: dict, tt_number: str, process_id: UUIDstr) -> LSOState:
+    """Perform a dry run of provisioning base config on a switch."""
+    extra_vars = {
+        "subscription_json": subscription,
+        "dry_run": True,
+        "verb": "deploy",
+        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy base config",
+    }
+
+    return {
+        "playbook_name": "switch_base_config.yaml",
+        "extra_vars": extra_vars,
+        "inventory": {"all": {"hosts": {subscription["switch"]["fqdn"]: None}}},
+    }
+
+
+@step("[FOR REAL] Deploy base config")
+def deploy_base_config_real(subscription: dict, tt_number: str, process_id: UUIDstr) -> LSOState:
+    """Provision base config on a switch."""
+    extra_vars = {
+        "subscription_json": subscription,
+        "dry_run": False,
+        "verb": "deploy",
+        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} - Deploy base config",
+    }
+
+    return {
+        "playbook_name": "switch_base_config.yaml",
+        "extra_vars": extra_vars,
+        "inventory": {"all": {"hosts": {subscription["switch"]["fqdn"]: None}}},
+    }
+
+
+@inputstep("Prompt for console login", assignee=Assignee.SYSTEM)
+def prompt_console_login() -> FormGenerator:
+    """Wait for confirmation from an operator that console login is possible."""
+
+    class ConsoleLoginPage(FormPage):
+        model_config = ConfigDict(title="Please confirm before continuing")
+
+        info_label: Label = "Please confirm you are able to log in to the switch using out of band connectivity."
+
+    yield ConsoleLoginPage
+    return {}
+
+
+@inputstep("Prompt IMS insertion", assignee=Assignee.SYSTEM)
+def prompt_insert_in_ims() -> FormGenerator:
+    """Wait for confirmation from an operator that the switch has been inserted in IMS."""
+
+    class IMSPrompt(FormPage):
+        model_config = ConfigDict(title="Update IMS mediation server")
+
+        info_label_1: Label = "Insert the switch into IMS."
+        info_label_2: Label = "Once this is done, press submit to continue the workflow."
+
+    yield IMSPrompt
+    return {}
+
+
+@step("Create Netbox device")
+def create_netbox_device() -> State:
+    """Add the switch as a new device in Netbox."""
+    return {"netbox_device": "Not implemented."}
+
+
+@step("Run post-deployment checks")
+def run_post_deploy_checks(subscription: dict) -> LSOState:
+    """Workflow step for running checks after installing base config."""
+    return {
+        "playbook_name": "switch_base_config_checks.yaml",
+        "extra_vars": {"subscription_json": subscription},
+        "inventory": {"all": {"hosts": {subscription["switch"]["fqdn"]: None}}},
+    }
+
+
+@step("Create a new SharePoint checklist")
+def create_new_sharepoint_checklist(subscription: SwitchProvisioning, tt_number: str, process_id: UUIDstr) -> State:
+    """Create a new checklist in SharePoint for approving this router."""
+    new_list_item_url = SharePointClient().add_list_item(
+        list_name="switch",
+        fields={
+            "Title": subscription.switch.fqdn,
+            "TT_NUMBER": tt_number,
+            "GAP_PROCESS_URL": f"{load_oss_params().GENERAL.public_hostname}/workflows/{process_id}",
+        },
+    )
+
+    return {"checklist_url": new_list_item_url}
+
+
+@workflow(
+    "Create Switch",
+    initial_input_form=wrap_create_initial_input_form(_initial_input_form_generator),
+    target=Target.CREATE,
+)
+def create_switch() -> StepList:
+    """Create a new Switch.
+
+    * Create a subscription object in the service database
+    * Deploy base configuration on the switch
+    * Add the switch to Netbox
+    * Run a check playbook after deploying base configuration
+    * Create a new checklist in SharePoint
+    """
+    return (
+        begin
+        >> create_subscription
+        >> store_process_subscription(Target.CREATE)
+        >> initialize_subscription
+        >> lso_interaction(deploy_base_config_dry)
+        >> lso_interaction(deploy_base_config_real)
+        >> prompt_console_login
+        >> prompt_insert_in_ims
+        >> create_netbox_device
+        >> lso_interaction(run_post_deploy_checks)
+        >> set_status(SubscriptionLifecycle.PROVISIONING)
+        >> create_new_sharepoint_checklist
+        >> prompt_sharepoint_checklist_url
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/switch/import_switch.py b/gso/workflows/switch/import_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..8ecf2d43930b1e40f84d1866f2db0a7cf8115306
--- /dev/null
+++ b/gso/workflows/switch/import_switch.py
@@ -0,0 +1,28 @@
+"""Import an existing Switch into the service database."""
+
+from orchestrator import step, workflow
+from orchestrator.targets import Target
+from orchestrator.types import State, UUIDstr
+from orchestrator.workflow import StepList, begin, done
+from orchestrator.workflows.steps import resync, store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+
+from gso.products import ProductName
+from gso.products.product_types.switch import ImportedSwitch, Switch
+from gso.services.subscriptions import get_product_id_by_name
+
+
+@step("Create new switch subscription")
+def import_switch_subscription(subscription_id: UUIDstr) -> State:
+    """Take an ImportedSwitch subscription, and turn it into a switch subscription."""
+    old_switch = ImportedSwitch.from_subscription(subscription_id)
+    new_subscription_id = get_product_id_by_name(ProductName.SWITCH)
+    new_subscription = Switch.from_other_product(old_switch, new_subscription_id)  # type: ignore[arg-type]
+
+    return {"subscription": new_subscription}
+
+
+@workflow("Import Switch", target=Target.MODIFY, initial_input_form=wrap_modify_initial_input_form(None))
+def import_switch() -> StepList:
+    """Modify an ImportedSwitch subscription into a Switch subscription to complete the import."""
+    return begin >> store_process_subscription(Target.MODIFY) >> unsync >> import_switch_subscription >> resync >> done
diff --git a/gso/workflows/switch/terminate_switch.py b/gso/workflows/switch/terminate_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..da74b82cfa231f28b6c812cfcd852222bf343d73
--- /dev/null
+++ b/gso/workflows/switch/terminate_switch.py
@@ -0,0 +1,69 @@
+"""Workflow for terminating a switch."""
+
+from orchestrator import begin, done, workflow
+from orchestrator.forms import FormPage
+from orchestrator.targets import Target
+from orchestrator.types import SubscriptionLifecycle, UUIDstr
+from orchestrator.workflow import StepList, step
+from orchestrator.workflows.steps import resync, set_status, store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+from pydantic_forms.types import FormGenerator
+from pydantic_forms.validators import Label
+
+from gso.products.product_types.switch import Switch
+from gso.services.infoblox import delete_host_by_fqdn
+from gso.services.netbox_client import NetboxClient
+from gso.utils.types.tt_number import TTNumber
+
+
+def _input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
+    """Input form to confirm that this switch indeed must be terminated."""
+    switch = Switch.from_subscription(subscription_id)
+
+    class TerminateForm(FormPage):
+        if switch.status == SubscriptionLifecycle.INITIAL:
+            info_label: Label = (
+                "This will immediately mark the subscription as terminated, preventing any other workflows from "
+                "interacting with this product subscription."
+            )
+            info_label_2: Label = "ONLY EXECUTE THIS WORKFLOW WHEN YOU ARE ABSOLUTELY SURE WHAT YOU ARE DOING."
+
+        tt_number: TTNumber
+
+    yield TerminateForm
+    return {"subscription": switch}
+
+
+@step("Remove switch from Netbox")
+def remove_device_from_netbox(subscription: Switch) -> None:
+    """Remove the switch from Netbox."""
+    NetboxClient().delete_device(subscription.switch.fqdn)
+
+
+@step("Remove switch from IPAM")
+def remove_device_from_ipam(subscription: Switch) -> None:
+    """Remove the switch from :term:`IPAM`."""
+    delete_host_by_fqdn(subscription.switch.fqdn)
+
+
+@workflow(
+    "Terminate switch",
+    initial_input_form=wrap_modify_initial_input_form(_input_form_generator),
+    target=Target.TERMINATE,
+)
+def terminate_switch() -> StepList:
+    """Terminate a switch subscription.
+
+    * Remove the switch from Netbox
+    * Mark the service as terminated in the service database
+    """
+    return (
+        begin
+        >> store_process_subscription(Target.TERMINATE)
+        >> unsync
+        >> remove_device_from_netbox
+        >> remove_device_from_ipam
+        >> set_status(SubscriptionLifecycle.TERMINATED)
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/switch/validate_switch.py b/gso/workflows/switch/validate_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..17711d17188a293302d87acb9db957813b4c3739
--- /dev/null
+++ b/gso/workflows/switch/validate_switch.py
@@ -0,0 +1,49 @@
+"""Validation workflow for switch subscription objects."""
+
+from typing import Any
+
+from orchestrator.targets import Target
+from orchestrator.workflow import StepList, begin, done, step, workflow
+from orchestrator.workflows.steps import resync, store_process_subscription, unsync
+from orchestrator.workflows.utils import wrap_modify_initial_input_form
+
+from gso.products.product_types.switch import Switch
+from gso.services.lso_client import LSOState, anonymous_lso_interaction
+from gso.services.netbox_client import NetboxClient
+
+
+@step("Validate switch in Netbox")
+def check_netbox_device(subscription: Switch) -> None:
+    """Fetch the device in Netbox. Will raise an exception if it is not found."""
+    NetboxClient().get_device_by_name(subscription.switch.fqdn)
+
+
+@step("Check base config for drift")
+def verify_base_config(subscription: dict[str, Any]) -> LSOState:
+    """Workflow step for running a playbook that checks whether base config has drifted."""
+    return {
+        "playbook_name": "switch_base_config.yaml",
+        "inventory": {"all": {"hosts": {subscription["switch"]["fqdn"]: None}}},
+        "extra_vars": {
+            "subscription_json": subscription,
+            "verb": "deploy",
+            "dry_run": "true",
+            "is_verification_workflow": "true",
+        },
+    }
+
+
+@workflow(
+    "Validate switch subscription", target=Target.SYSTEM, initial_input_form=(wrap_modify_initial_input_form(None))
+)
+def validate_switch() -> StepList:
+    """Validate an existing, active switch subscription."""
+    return (
+        begin
+        >> store_process_subscription(Target.SYSTEM)
+        >> unsync
+        >> check_netbox_device
+        >> anonymous_lso_interaction(verify_base_config)
+        >> resync
+        >> done
+    )
diff --git a/requirements.txt b/requirements.txt
index 0ccb4d649c6ee9a30d3a633ab451747097e0d933..2488de134a518a88436df822e7a57e5519ee8935 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-orchestrator-core==2.7.6
+orchestrator-core==2.8.0
 requests==2.31.0
 infoblox-client~=0.6.0
 pycountry==23.12.11
diff --git a/setup.py b/setup.py
index 3ec7a018f534de6d21b39ba0c786eba2e04042ca..bf6eb267a561df5a72e8c986af8d7981bb40a616 100644
--- a/setup.py
+++ b/setup.py
@@ -4,14 +4,14 @@ from setuptools import find_packages, setup
 
 setup(
     name="geant-service-orchestrator",
-    version="2.22",
+    version="2.23",
     author="GÉANT Orchestration and Automation Team",
     author_email="goat@geant.org",
     description="GÉANT Service Orchestrator",
     url="https://gitlab.software.geant.org/goat/gap/geant-service-orchestrator",
     packages=find_packages(),
     install_requires=[
-        "orchestrator-core==2.7.6",
+        "orchestrator-core==2.8.0",
         "requests==2.31.0",
         "infoblox-client~=0.6.0",
         "pycountry==23.12.11",
diff --git a/test/cli/test_imports.py b/test/cli/test_imports.py
index 33ab32dd2acc6b1746322a1694528fa2323ee48d..62cf1a8d01ed5e0b41dc5f2eb518728f72b546b5 100644
--- a/test/cli/test_imports.py
+++ b/test/cli/test_imports.py
@@ -7,23 +7,27 @@ import pytest
 from gso.cli.imports import (
     import_edge_port,
     import_iptrunks,
+    import_lan_switch_interconnect,
     import_nren_l3_core_service,
     import_office_routers,
     import_opengear,
     import_routers,
     import_sites,
     import_super_pop_switches,
+    import_switches,
 )
 from gso.products.product_blocks.bgp_session import IPFamily
 from gso.products.product_blocks.edge_port import EdgePortType, EncapsulationType
 from gso.products.product_blocks.iptrunk import IptrunkType
 from gso.products.product_blocks.router import RouterRole
 from gso.products.product_blocks.site import SiteTier
+from gso.products.product_blocks.switch import SwitchModel
 from gso.products.product_types.router import Router
 from gso.products.product_types.site import Site
 from gso.utils.helpers import iso_from_ipv4
 from gso.utils.shared_enums import Vendor
 from gso.utils.types.interfaces import PhysicalPortCapacity
+from gso.utils.types.ip_address import AddressSpace
 
 
 ##############
@@ -200,6 +204,59 @@ def opengear_data(temp_file, faker, site_subscription_factory):
     return _opengear_data
 
 
+@pytest.fixture()
+def switch_data(temp_file, faker, site_subscription_factory):
+    def _switch_data(**kwargs):
+        switch_data = {
+            "fqdn": faker.domain_name(levels=4),
+            "ts_port": faker.port_number(is_user=True),
+            "site": site_subscription_factory(),
+            "switch_vendor": Vendor.JUNIPER,
+            "switch_model": SwitchModel.EX3400,
+        }
+        switch_data.update(**kwargs)
+
+        temp_file.write_text(json.dumps([switch_data]))
+        return {"path": str(temp_file), "data": switch_data}
+
+    return _switch_data
+
+
+@pytest.fixture()
+def lan_switch_interconnect_data(temp_file, faker, switch_subscription_factory, router_subscription_factory):
+    def _lan_switch_interconnect_data(**kwargs):
+        lan_switch_interconnect_data = {
+            "lan_switch_interconnect_description": faker.sentence(),
+            "lan_switch_interconnect_ip_network": str(faker.ipv4_network()),
+            "address_space": AddressSpace.PUBLIC,
+            "minimum_links": 1,
+            "router_side": {
+                "node": router_subscription_factory(),
+                "ae_iface": faker.nokia_lag_interface_name(),
+                "ae_members": [
+                    {"interface_name": faker.network_interface(), "interface_description": faker.sentence()}
+                    for _ in range(2)
+                ],
+                "ipv4_address": faker.ipv4(),
+            },
+            "switch_side": {
+                "switch": switch_subscription_factory(),
+                "ae_iface": faker.juniper_ae_interface_name(),
+                "ae_members": [
+                    {"interface_name": faker.network_interface(), "interface_description": faker.sentence()}
+                    for _ in range(2)
+                ],
+                "ipv4_address": faker.ipv4(),
+            },
+        }
+        lan_switch_interconnect_data.update(**kwargs)
+
+        temp_file.write_text(json.dumps([lan_switch_interconnect_data]))
+        return {"path": str(temp_file), "data": lan_switch_interconnect_data}
+
+    return _lan_switch_interconnect_data
+
+
 @pytest.fixture()
 def edge_port_data(temp_file, faker, router_subscription_factory, partner_factory):
     def _edge_port_data(**kwargs):
@@ -425,6 +482,20 @@ router_lo_ipv6_address
     assert mock_start_process.call_count == 0
 
 
+@patch("gso.cli.imports.time.sleep")
+@patch("gso.cli.imports.start_process")
+def test_import_switch_success(mock_start_process, mock_sleep, switch_data):
+    import_switches(switch_data()["path"])
+    assert mock_start_process.call_count == 1
+
+
+@patch("gso.cli.imports.time.sleep")
+@patch("gso.cli.imports.start_process")
+def test_import_lan_switch_interconnect(mock_start_process, mock_sleep, lan_switch_interconnect_data):
+    import_lan_switch_interconnect(lan_switch_interconnect_data()["path"])
+    assert mock_start_process.call_count == 1
+
+
 @patch("gso.cli.imports.time.sleep")
 @patch("gso.cli.imports.start_process")
 def test_import_iptrunk_successful(mock_start_process, mock_sleep, iptrunk_data):
diff --git a/test/conftest.py b/test/conftest.py
index 981768655dfde2eaf4700853488e2a2c6bedb049..8c8d246c5bd97c16ef7f8db09752c2dca0ffd804 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -40,6 +40,7 @@ from test.fixtures import (  # noqa: F401
     edge_port_subscription_factory,
     iptrunk_side_subscription_factory,
     iptrunk_subscription_factory,
+    lan_switch_interconnect_subscription_factory,
     nren_access_port_factory,
     nren_l3_core_service_subscription_factory,
     office_router_subscription_factory,
@@ -48,6 +49,7 @@ from test.fixtures import (  # noqa: F401
     service_binding_port_factory,
     site_subscription_factory,
     super_pop_switch_subscription_factory,
+    switch_subscription_factory,
 )
 
 logging.getLogger("faker.factory").setLevel(logging.WARNING)
@@ -108,7 +110,15 @@ class FakerProvider(BaseProvider):
         return self.generator.random_int(min=1, max=128)
 
     def network_interface(self) -> str:
-        return self.generator.numerify("ge-@#/@#/@#")
+        interface = self.generator.random_choices(elements=("ge", "et", "xe"))[0]
+        number = self.generator.numerify("-%/%/%")
+        return f"{interface}{number}"
+
+    def juniper_ae_interface_name(self) -> str:
+        return self.generator.numerify("ae@#")
+
+    def nokia_lag_interface_name(self) -> str:
+        return self.generator.numerify("lag-@#")
 
     def link_members_juniper(self) -> LAGMemberList[LAGMember]:
         iface_amount = self.generator.random_int(min=2, max=5)
diff --git a/test/fixtures/__init__.py b/test/fixtures/__init__.py
index 0b69c5fb506e854a84e6e0e908826fcc250ec08e..3f183fb2e8778f758d7bba96a459d1df29ac717b 100644
--- a/test/fixtures/__init__.py
+++ b/test/fixtures/__init__.py
@@ -1,5 +1,6 @@
 from test.fixtures.edge_port_fixtures import edge_port_subscription_factory
 from test.fixtures.iptrunk_fixtures import iptrunk_side_subscription_factory, iptrunk_subscription_factory
+from test.fixtures.lan_switch_interconnect_fixtures import lan_switch_interconnect_subscription_factory
 from test.fixtures.nren_l3_core_service_fixtures import (
     bgp_session_subscription_factory,
     nren_access_port_factory,
@@ -11,12 +12,14 @@ from test.fixtures.opengear_fixtures import opengear_subscription_factory
 from test.fixtures.router_fixtures import router_subscription_factory
 from test.fixtures.site_fixtures import site_subscription_factory
 from test.fixtures.super_pop_switch_fixtures import super_pop_switch_subscription_factory
+from test.fixtures.switch_fixtures import switch_subscription_factory
 
 __all__ = [
     "bgp_session_subscription_factory",
     "edge_port_subscription_factory",
     "iptrunk_side_subscription_factory",
     "iptrunk_subscription_factory",
+    "lan_switch_interconnect_subscription_factory",
     "nren_access_port_factory",
     "nren_l3_core_service_subscription_factory",
     "office_router_subscription_factory",
@@ -25,4 +28,5 @@ __all__ = [
     "service_binding_port_factory",
     "site_subscription_factory",
     "super_pop_switch_subscription_factory",
+    "switch_subscription_factory",
 ]
diff --git a/test/fixtures/lan_switch_interconnect_fixtures.py b/test/fixtures/lan_switch_interconnect_fixtures.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe0cb87f304b7eb04991bedcb5ad893d743b1483
--- /dev/null
+++ b/test/fixtures/lan_switch_interconnect_fixtures.py
@@ -0,0 +1,106 @@
+from uuid import uuid4
+
+import pytest
+from orchestrator.db import db
+from orchestrator.domain import SubscriptionModel
+from orchestrator.types import SubscriptionLifecycle, UUIDstr
+
+from gso.products import ProductName
+from gso.products.product_blocks.lan_switch_interconnect import (
+    LanSwitchInterconnectInterfaceBlockInactive,
+    LanSwitchInterconnectRouterSideBlockInactive,
+    LanSwitchInterconnectSwitchSideBlockInactive,
+)
+from gso.products.product_types.lan_switch_interconnect import (
+    ImportedLanSwitchInterconnectInactive,
+    LanSwitchInterconnectInactive,
+)
+from gso.products.product_types.router import Router
+from gso.products.product_types.switch import Switch
+from gso.services.subscriptions import get_product_id_by_name
+from gso.utils.types.ip_address import AddressSpace, IPv4AddressType, IPv4NetworkType
+
+
+@pytest.fixture()
+def lan_switch_interconnect_subscription_factory(
+    faker, geant_partner, router_subscription_factory, switch_subscription_factory
+):
+    def create_subscription(
+        description: str | None = None,
+        partner: dict | None = None,
+        status: SubscriptionLifecycle | None = None,
+        start_date: str | None = "2024-01-01T10:20:30+01:02",
+        lan_switch_interconnect_description: str | None = None,
+        lan_switch_interconnect_ip_network: IPv4NetworkType | None = None,
+        address_space: AddressSpace | None = None,
+        minimum_links: int | None = None,
+        router_side_node: UUIDstr | None = None,
+        router_side_ae_iface: str | None = None,
+        router_side_ae_members: list[dict[str, str]] | None = None,
+        router_side_ipv4_address: IPv4AddressType | None = None,
+        switch_side_switch: UUIDstr | None = None,
+        switch_side_ae_iface: str | None = None,
+        switch_side_ae_members: list[dict[str, str]] | None = None,
+        switch_side_ipv4_address: IPv4AddressType | None = None,
+        *,
+        is_imported: bool | None = True,
+    ) -> UUIDstr:
+        if partner is None:
+            partner = geant_partner
+        if is_imported:
+            product_id = get_product_id_by_name(ProductName.LAN_SWITCH_INTERCONNECT)
+            subscription = LanSwitchInterconnectInactive.from_product_id(product_id, partner["partner_id"])
+        else:
+            product_id = get_product_id_by_name(ProductName.IMPORTED_LAN_SWITCH_INTERCONNECT)
+            subscription = ImportedLanSwitchInterconnectInactive.from_product_id(product_id, partner["partner_id"])
+
+        router_side_ae_members = router_side_ae_members or [
+            LanSwitchInterconnectInterfaceBlockInactive.new(
+                uuid4(), interface_name=faker.network_interface(), interface_description=faker.sentence()
+            )
+            for _ in range(2)
+        ]
+        switch_side_ae_members = switch_side_ae_members or [
+            LanSwitchInterconnectInterfaceBlockInactive.new(
+                uuid4(), interface_name=faker.network_interface(), interface_description=faker.sentence()
+            )
+            for _ in range(2)
+        ]
+
+        subscription.lan_switch_interconnect.lan_switch_interconnect_description = (
+            lan_switch_interconnect_description or faker.sentence()
+        )
+        subscription.lan_switch_interconnect.lan_switch_interconnect_ip_network = (
+            lan_switch_interconnect_ip_network or faker.ipv4_network()
+        )
+        subscription.lan_switch_interconnect.address_space = address_space or AddressSpace.PRIVATE
+        subscription.lan_switch_interconnect.minimum_links = minimum_links or 1
+        subscription.lan_switch_interconnect.router_side = LanSwitchInterconnectRouterSideBlockInactive.new(
+            uuid4(),
+            node=router_side_node or Router.from_subscription(router_subscription_factory()).router,
+            ae_iface=router_side_ae_iface or faker.network_interface(),
+            ae_members=router_side_ae_members,
+            ipv4_address=router_side_ipv4_address or faker.ipv4(),
+        )
+        subscription.lan_switch_interconnect.switch_side = LanSwitchInterconnectSwitchSideBlockInactive.new(
+            uuid4(),
+            switch=switch_side_switch or Switch.from_subscription(switch_subscription_factory()).switch,
+            ae_iface=switch_side_ae_iface or faker.network_interface(),
+            ae_members=switch_side_ae_members,
+            ipv4_address=switch_side_ipv4_address or faker.ipv4(),
+        )
+
+        subscription = SubscriptionModel.from_other_lifecycle(subscription, SubscriptionLifecycle.ACTIVE)
+        subscription.insync = True
+        subscription.description = description or faker.sentence()
+        subscription.start_date = start_date
+
+        if status:
+            subscription.status = status
+
+        subscription.save()
+        db.session.commit()
+
+        return str(subscription.subscription_id)
+
+    return create_subscription
diff --git a/test/fixtures/switch_fixtures.py b/test/fixtures/switch_fixtures.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa7f34d60fd020398455312aed84402afcd7a0c4
--- /dev/null
+++ b/test/fixtures/switch_fixtures.py
@@ -0,0 +1,59 @@
+import pytest
+from orchestrator.db import db
+from orchestrator.domain import SubscriptionModel
+from orchestrator.types import SubscriptionLifecycle
+from pydantic_forms.types import UUIDstr
+
+from gso.products import ProductName
+from gso.products.product_blocks.switch import SwitchModel
+from gso.products.product_types.site import Site
+from gso.products.product_types.switch import ImportedSwitchInactive, SwitchInactive
+from gso.services.subscriptions import get_product_id_by_name
+from gso.utils.shared_enums import Vendor
+from gso.utils.types.ip_address import PortNumber
+
+
+@pytest.fixture()
+def switch_subscription_factory(faker, geant_partner, site_subscription_factory):
+    def subscription_create(
+        partner: dict | None = None,
+        description: str | None = None,
+        start_date: str | None = "2024-01-01T10:20:30+01:02",
+        fqdn: str | None = None,
+        ts_port: PortNumber | None = None,
+        site: UUIDstr | None = None,
+        switch_vendor: Vendor | None = None,
+        switch_model: SwitchModel | None = None,
+        status: SubscriptionLifecycle | None = None,
+        *,
+        is_imported: bool = True,
+    ) -> UUIDstr:
+        if partner is None:
+            partner = geant_partner
+        if is_imported:
+            product_id = get_product_id_by_name(ProductName.SWITCH)
+            switch_subscription = SwitchInactive.from_product_id(product_id, partner["partner_id"])
+        else:
+            product_id = get_product_id_by_name(ProductName.IMPORTED_SWITCH)
+            switch_subscription = ImportedSwitchInactive.from_product_id(product_id, partner["partner_id"])
+
+        switch_subscription.switch.fqdn = fqdn or faker.domain_name(levels=4)
+        switch_subscription.switch.ts_port = ts_port or faker.port_number(is_user=True)
+        switch_subscription.switch.site = site or Site.from_subscription(site_subscription_factory()).site
+        switch_subscription.switch.switch_vendor = switch_vendor or Vendor.JUNIPER
+        switch_subscription.switch.switch_model = switch_model or SwitchModel.EX3400
+
+        switch_subscription = SubscriptionModel.from_other_lifecycle(switch_subscription, SubscriptionLifecycle.ACTIVE)
+        switch_subscription.insync = True
+        switch_subscription.description = description or faker.sentence()
+        switch_subscription.start_date = start_date
+
+        if status:
+            switch_subscription.status = status
+
+        switch_subscription.save()
+        db.session.commit()
+
+        return str(switch_subscription.subscription_id)
+
+    return subscription_create
diff --git a/test/services/conftest.py b/test/services/conftest.py
index 3467d545d2c571e947c75022c8a574197394e723..ee0c59e1ea76e0e12a1ee69365cbe9e71109d0d6 100644
--- a/test/services/conftest.py
+++ b/test/services/conftest.py
@@ -64,6 +64,9 @@ class MockedNetboxClient:
     def delete_interface():
         return None
 
+    def get_available_lags_in_range(self):
+        return self.get_available_lags()
+
 
 class MockedSharePointClient:
     class BaseMockObject:
@@ -104,15 +107,18 @@ class MockedKentikClient:
 
     @staticmethod
     def get_plans() -> list[dict[str, Any]]:
-        return [{"id": 0, "plan_name": "kentik-plan-1"}, {"id": 1, "plan_name": "kentik-plan-2"}]
+        return [
+            {"id": 0, "name": "kentik-plan-1", "active": True, "devices": [], "max_devices": 9999},
+            {"id": 1, "name": "kentik-plan-2", "active": True, "devices": [], "max_devices": 9999},
+        ]
 
     @staticmethod
     def get_plan(plan_id: int) -> dict[str, Any]:
-        return {"id": plan_id, "plan_name": "kentik-mocked-plan"}
+        return {"id": plan_id, "name": "kentik-mocked-plan", "active": True, "devices": [], "max_devices": 9999}
 
     @staticmethod
     def get_plan_by_name(plan_name: str) -> dict[str, Any]:
-        return {"id": 0, "plan_name": plan_name}
+        return {"id": 0, "name": plan_name, "active": True, "devices": [], "max_devices": 9999}
 
     @staticmethod
     def create_device(device: NewKentikDevice) -> dict[str, Any]:
diff --git a/test/workflows/edge_port/test_create_edge_port.py b/test/workflows/edge_port/test_create_edge_port.py
index ad804c91f5143148098b7cc4fbfc427d99783d29..84c87b21cd08b0e9b2a0fb73d6f3e5f4a9b6171a 100644
--- a/test/workflows/edge_port/test_create_edge_port.py
+++ b/test/workflows/edge_port/test_create_edge_port.py
@@ -81,7 +81,6 @@ def input_form_wizard_data(request, router_subscription_factory, partner_factory
 @patch("gso.services.lso_client._send_request")
 def test_successful_edge_port_creation(
     mock_execute_playbook,
-    responses,
     input_form_wizard_data,
     faker,
     _netbox_client_mock,  # noqa: PT019
diff --git a/test/workflows/iptrunk/test_create_iptrunk.py b/test/workflows/iptrunk/test_create_iptrunk.py
index 7a38a234a7e0ba98dea56081b07e0bcc8be21c7e..cac63729ec0507232f904074c48bb7c8b5f203a1 100644
--- a/test/workflows/iptrunk/test_create_iptrunk.py
+++ b/test/workflows/iptrunk/test_create_iptrunk.py
@@ -119,7 +119,6 @@ def test_successful_iptrunk_creation_with_standard_lso_result(
     mock_allocate_v4_network,
     mock_allocate_v6_network,
     mock_execute_playbook,
-    responses,
     input_form_wizard_data,
     faker,
     _netbox_client_mock,  # noqa: PT019
@@ -176,7 +175,6 @@ def test_iptrunk_creation_fails_when_lso_return_code_is_one(
     mock_allocate_v4_network,
     mock_allocate_v6_network,
     mock_execute_playbook,
-    responses,
     input_form_wizard_data,
     faker,
     _netbox_client_mock,  # noqa: PT019
@@ -217,7 +215,6 @@ def test_successful_iptrunk_creation_with_juniper_interface_names(
     mock_allocate_v4_network,
     mock_allocate_v6_network,
     mock_execute_playbook,
-    responses,
     input_form_wizard_data,
     faker,
     data_config_filename: PathLike,
diff --git a/test/workflows/lan_switch_interconnect/__init__.py b/test/workflows/lan_switch_interconnect/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test/workflows/lan_switch_interconnect/test_create_imported_lan_switch_interconnect.py b/test/workflows/lan_switch_interconnect/test_create_imported_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..69349ae02c7d58dbbdc670aad70b855edb5f7a11
--- /dev/null
+++ b/test/workflows/lan_switch_interconnect/test_create_imported_lan_switch_interconnect.py
@@ -0,0 +1,44 @@
+import pytest
+from orchestrator.types import SubscriptionLifecycle
+
+from gso.products import ProductName
+from gso.products.product_types.lan_switch_interconnect import ImportedLanSwitchInterconnect
+from gso.utils.types.ip_address import AddressSpace
+from test.workflows import (
+    assert_complete,
+    extract_state,
+    run_workflow,
+)
+
+
+@pytest.fixture()
+def workflow_input_data(faker, router_subscription_factory, switch_subscription_factory):
+    return {
+        "lan_switch_interconnect_description": faker.sentence(),
+        "lan_switch_interconnect_ip_network": faker.ipv4_network(),
+        "address_space": AddressSpace.PUBLIC,
+        "minimum_links": 1,
+        "router_side": {
+            "node": router_subscription_factory(),
+            "ae_iface": faker.nokia_lag_interface_name(),
+            "ae_members": faker.link_members_nokia(),
+            "ipv4_address": faker.ipv4(),
+        },
+        "switch_side": {
+            "switch": switch_subscription_factory(),
+            "ae_iface": faker.juniper_ae_interface_name(),
+            "ae_members": faker.link_members_juniper(),
+            "ipv4_address": faker.ipv4(),
+        },
+    }
+
+
+@pytest.mark.workflow()
+def test_create_imported_lan_switch_interconnect_success(workflow_input_data):
+    result, _, _ = run_workflow("create_imported_lan_switch_interconnect", [workflow_input_data])
+    state = extract_state(result)
+    subscription = ImportedLanSwitchInterconnect.from_subscription(state["subscription_id"])
+
+    assert_complete(result)
+    assert subscription.product.name == ProductName.IMPORTED_LAN_SWITCH_INTERCONNECT
+    assert subscription.status == SubscriptionLifecycle.ACTIVE
diff --git a/test/workflows/lan_switch_interconnect/test_create_lan_switch_interconnect.py b/test/workflows/lan_switch_interconnect/test_create_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..2c6657d260a88b8871dcc843a8fb1e7a636685f4
--- /dev/null
+++ b/test/workflows/lan_switch_interconnect/test_create_lan_switch_interconnect.py
@@ -0,0 +1,74 @@
+from unittest.mock import patch
+
+import pytest
+from orchestrator.types import SubscriptionLifecycle
+
+from gso.products import ProductName
+from gso.products.product_types.lan_switch_interconnect import LanSwitchInterconnect
+from gso.services.subscriptions import get_product_id_by_name
+from gso.utils.types.ip_address import AddressSpace
+from test.services.conftest import MockedNetboxClient
+from test.workflows import assert_complete, extract_state, run_workflow
+
+
+@pytest.fixture()
+def _netbox_client_mock():
+    # Mock NetboxClient methods
+    with (
+        patch("gso.services.netbox_client.NetboxClient.get_device_by_name") as mock_get_device_by_name,
+        patch("gso.services.netbox_client.NetboxClient.get_available_interfaces") as mock_get_available_interfaces,
+        patch("gso.services.netbox_client.NetboxClient.get_available_lags_in_range") as mock_available_lags_in_range,
+    ):
+        mock_get_device_by_name.return_value = MockedNetboxClient().get_device_by_name()
+        mock_get_available_interfaces.return_value = MockedNetboxClient().get_available_interfaces()
+        mock_available_lags_in_range.return_value = MockedNetboxClient().get_available_lags_in_range()
+
+        yield
+
+
+@pytest.fixture()
+def input_form_data(faker, router_subscription_factory, switch_subscription_factory):
+    def _generate_form_data(address_space: AddressSpace):
+        return [
+            {
+                "product": get_product_id_by_name(ProductName.LAN_SWITCH_INTERCONNECT),
+            },
+            {
+                "tt_number": faker.tt_number(),
+                "router_side": router_subscription_factory(),
+                "switch_side": switch_subscription_factory(),
+                "address_space": address_space,
+                "description": faker.sentence(),
+                "minimum_link_count": 2,
+                "vlan_id": 111,  # VLAN ID for new interconnections is always 111
+            },
+            {
+                "router_side_iface": "lag-1",
+                "router_side_ae_members": faker.link_members_nokia()[:2],
+            },
+            {
+                "switch_side_iface": faker.network_interface(),
+                "switch_side_ae_members": faker.link_members_juniper()[:2],
+            },
+            {},
+        ]
+
+    return _generate_form_data
+
+
+@pytest.mark.parametrize("address_space", [AddressSpace.PRIVATE, AddressSpace.PUBLIC])
+@pytest.mark.workflow()
+def test_create_lan_switch_interconnect_success(
+    address_space,
+    input_form_data,
+    _netbox_client_mock,  # noqa: PT019
+):
+    initial_data = input_form_data(address_space)
+
+    result, _, _ = run_workflow("create_lan_switch_interconnect", initial_data)
+
+    assert_complete(result)
+    state = extract_state(result)
+    subscription_id = state["subscription_id"]
+    subscription = LanSwitchInterconnect.from_subscription(subscription_id)
+    assert subscription.status == SubscriptionLifecycle.ACTIVE
diff --git a/test/workflows/lan_switch_interconnect/test_import_lan_switch_interconnect.py b/test/workflows/lan_switch_interconnect/test_import_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..5808299f5de5f01fd001a39819f091cb716bca8b
--- /dev/null
+++ b/test/workflows/lan_switch_interconnect/test_import_lan_switch_interconnect.py
@@ -0,0 +1,20 @@
+import pytest
+from orchestrator.types import SubscriptionLifecycle
+
+from gso.products import ProductName
+from gso.products.product_types.lan_switch_interconnect import LanSwitchInterconnect
+from test.workflows import assert_complete, run_workflow
+
+
+@pytest.mark.workflow()
+def test_import_lan_switch_interconnect_success(lan_switch_interconnect_subscription_factory):
+    imported_lan_switch_interconnect = lan_switch_interconnect_subscription_factory(is_imported=False)
+    result, _, _ = run_workflow(
+        "import_lan_switch_interconnect", [{"subscription_id": imported_lan_switch_interconnect}]
+    )
+    subscription = LanSwitchInterconnect.from_subscription(imported_lan_switch_interconnect)
+
+    assert_complete(result)
+    assert subscription.product.name == ProductName.LAN_SWITCH_INTERCONNECT
+    assert subscription.status == SubscriptionLifecycle.ACTIVE
+    assert subscription.insync is True
diff --git a/test/workflows/lan_switch_interconnect/test_terminate_lan_switch_interconnect.py b/test/workflows/lan_switch_interconnect/test_terminate_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..6d5ae5383dd4559662f293535a3b3253d7123033
--- /dev/null
+++ b/test/workflows/lan_switch_interconnect/test_terminate_lan_switch_interconnect.py
@@ -0,0 +1,17 @@
+import pytest
+
+from gso.products.product_types.lan_switch_interconnect import LanSwitchInterconnect
+from test.workflows import assert_complete, extract_state, run_workflow
+
+
+@pytest.mark.workflow()
+def test_terminate_lan_switch_interconnect(lan_switch_interconnect_subscription_factory, faker):
+    subscription_id = lan_switch_interconnect_subscription_factory()
+    initial_lan_switch_interconnect_data = [{"subscription_id": subscription_id}, {"tt_number": faker.tt_number()}]
+    result, _, _ = run_workflow("terminate_lan_switch_interconnect", initial_lan_switch_interconnect_data)
+    assert_complete(result)
+
+    state = extract_state(result)
+    subscription_id = state["subscription_id"]
+    subscription = LanSwitchInterconnect.from_subscription(subscription_id)
+    assert subscription.status == "terminated"
diff --git a/test/workflows/lan_switch_interconnect/test_validate_lan_switch_interconnect.py b/test/workflows/lan_switch_interconnect/test_validate_lan_switch_interconnect.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py b/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py
index 1287bd01c9288d4f577512f8a832f565ed38a01a..d8eac84e705567a8ef1e5fb0add47457607751f3 100644
--- a/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py
+++ b/test/workflows/nren_l3_core_service/test_create_nren_l3_core_service.py
@@ -34,7 +34,6 @@ def base_bgp_peer_input(faker):
 def test_create_nren_l3_core_service_success(
     mock_lso_client,
     l3_core_type,
-    responses,
     faker,
     partner_factory,
     edge_port_subscription_factory,
diff --git a/test/workflows/router/test_modify_connection_strategy.py b/test/workflows/router/test_modify_connection_strategy.py
index fd3a01357a9fbb7558a38a0797d6ff55d23eeeb9..20f8f31a1780b4222705d17102e887b550b4771a 100644
--- a/test/workflows/router/test_modify_connection_strategy.py
+++ b/test/workflows/router/test_modify_connection_strategy.py
@@ -6,7 +6,7 @@ from test.workflows import assert_complete, run_workflow
 
 
 @pytest.mark.workflow()
-def test_modify_connection_strategy(responses, router_subscription_factory):
+def test_modify_connection_strategy(router_subscription_factory):
     subscription_id = router_subscription_factory(router_access_via_ts=True)
     subscription = Router.from_subscription(subscription_id)
     assert subscription.router.router_access_via_ts is True
diff --git a/test/workflows/router/test_modify_router_kentik_license.py b/test/workflows/router/test_modify_router_kentik_license.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d5352c515b25cc921622d7e1e58a1726fe499a1
--- /dev/null
+++ b/test/workflows/router/test_modify_router_kentik_license.py
@@ -0,0 +1,31 @@
+from unittest.mock import patch
+
+import pytest
+
+from gso.products.product_blocks.router import RouterRole
+from gso.products.product_types.router import Router
+from test.services.conftest import MockedKentikClient
+from test.workflows import assert_complete, extract_state, run_workflow
+
+
+@pytest.mark.workflow()
+@patch("gso.services.kentik_client.KentikClient")
+def test_modify_router_kentik_license_success(
+    mock_kentik_client,
+    router_subscription_factory,
+    faker,
+):
+    #  Set up mock return values
+    product_id = router_subscription_factory(router_role=RouterRole.PE)
+    mock_kentik_client.return_value = MockedKentikClient
+
+    #  Run workflow
+    initial_input_data = [{"subscription_id": product_id}, {"new_plan_id": "0"}]
+    result, _, _ = run_workflow("modify_router_kentik_license", initial_input_data)
+
+    assert_complete(result)
+
+    state = extract_state(result)
+    subscription_id = state["subscription_id"]
+    subscription = Router.from_subscription(subscription_id)
+    assert subscription.status == "active"
diff --git a/test/workflows/site/test_create_site.py b/test/workflows/site/test_create_site.py
index 112e078f39c78a1545ada8d14be18dbd61da7858..b744c2e049036c01df4c869ca43fd6ac68d43f71 100644
--- a/test/workflows/site/test_create_site.py
+++ b/test/workflows/site/test_create_site.py
@@ -9,7 +9,7 @@ from test.workflows import assert_complete, extract_state, run_workflow
 
 
 @pytest.mark.workflow()
-def test_create_site(responses, faker):
+def test_create_site(faker):
     product_id = get_product_id_by_name(ProductName.SITE)
     initial_site_data = [
         {"product": product_id},
@@ -41,7 +41,7 @@ def test_create_site(responses, faker):
 
 
 @pytest.mark.workflow()
-def test_site_name_is_incorrect(responses, faker):
+def test_site_name_is_incorrect(faker):
     """Test validate site name on site creation.
 
     The site name is a string with 3 upper case letter and one digit.
diff --git a/test/workflows/site/test_modify_site.py b/test/workflows/site/test_modify_site.py
index fb45a9576e6917e66af9370dab3a69435bdf20db..ff82fc7df2c5b759a57760dfac0a1480aa953eeb 100644
--- a/test/workflows/site/test_modify_site.py
+++ b/test/workflows/site/test_modify_site.py
@@ -6,7 +6,7 @@ from test.workflows import assert_complete, extract_state, run_workflow
 
 
 @pytest.mark.workflow()
-def test_modify_site(responses, site_subscription_factory, faker):
+def test_modify_site(site_subscription_factory, faker):
     subscription_id = site_subscription_factory()
     initial_site_data = [
         {"subscription_id": subscription_id},
diff --git a/test/workflows/site/test_terminate_site.py b/test/workflows/site/test_terminate_site.py
index 26cad9e28c90524bfc586bd6f628a9278923f726..93c1cd2141fe9f95cc21a168c447831d5447153f 100644
--- a/test/workflows/site/test_terminate_site.py
+++ b/test/workflows/site/test_terminate_site.py
@@ -5,7 +5,7 @@ from test.workflows import assert_complete, extract_state, run_workflow
 
 
 @pytest.mark.workflow()
-def test_terminate_site(responses, site_subscription_factory):
+def test_terminate_site(site_subscription_factory):
     subscription_id = site_subscription_factory()
     initial_site_data = [{"subscription_id": subscription_id}, {}]
     result, _, _ = run_workflow("terminate_site", initial_site_data)
diff --git a/test/workflows/switch/__init__.py b/test/workflows/switch/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test/workflows/switch/test_activate_switch.py b/test/workflows/switch/test_activate_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..52ffa94c4f16d6ae4b7d1c792eb64915583cb76f
--- /dev/null
+++ b/test/workflows/switch/test_activate_switch.py
@@ -0,0 +1,36 @@
+import pytest
+
+from gso.products.product_types.switch import Switch
+from test.workflows import (
+    assert_complete,
+    assert_suspended,
+    extract_state,
+    resume_workflow,
+    run_workflow,
+)
+
+
+@pytest.mark.workflow()
+def test_activate_switch_success(
+    switch_subscription_factory,
+    faker,
+):
+    #  Set up mock return values
+    product_id = switch_subscription_factory(status="provisioning")
+    #  Sanity check
+    assert Switch.from_subscription(product_id).status == "provisioning"
+
+    #  Run workflow
+    initial_input_data = [{"subscription_id": product_id}, {}]
+    result, process_stat, step_log = run_workflow("activate_switch", initial_input_data)
+
+    assert_suspended(result)
+    result, step_log = resume_workflow(process_stat, step_log, input_data=[{"checklist_url": "http://localhost"}])
+
+    assert_complete(result)
+
+    state = extract_state(result)
+    subscription_id = state["subscription_id"]
+    subscription = Switch.from_subscription(subscription_id)
+
+    assert subscription.status == "active"
diff --git a/test/workflows/switch/test_create_imported_switch.py b/test/workflows/switch/test_create_imported_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..76ad61c7a80615d4b88ae94add85c5ddabf3bcd8
--- /dev/null
+++ b/test/workflows/switch/test_create_imported_switch.py
@@ -0,0 +1,34 @@
+import pytest
+from orchestrator.types import SubscriptionLifecycle
+
+from gso.products import ProductName
+from gso.products.product_blocks.switch import SwitchModel
+from gso.products.product_types.switch import ImportedSwitch
+from gso.utils.shared_enums import Vendor
+from test.workflows import (
+    assert_complete,
+    extract_state,
+    run_workflow,
+)
+
+
+@pytest.fixture()
+def workflow_input_data(faker, site_subscription_factory):
+    return {
+        "fqdn": faker.domain_name(levels=4),
+        "ts_port": faker.port_number(is_user=True),
+        "site": site_subscription_factory(),
+        "switch_vendor": Vendor.JUNIPER,
+        "switch_model": SwitchModel.EX3400,
+    }
+
+
+@pytest.mark.workflow()
+def test_create_imported_switch_success(workflow_input_data):
+    result, _, _ = run_workflow("create_imported_switch", [workflow_input_data])
+    state = extract_state(result)
+    subscription = ImportedSwitch.from_subscription(state["subscription_id"])
+
+    assert_complete(result)
+    assert subscription.product.name == ProductName.IMPORTED_SWITCH
+    assert subscription.status == SubscriptionLifecycle.ACTIVE
diff --git a/test/workflows/switch/test_create_switch.py b/test/workflows/switch/test_create_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..c11edf80bc4f3059957c2e697be3d536ca7fdbd6
--- /dev/null
+++ b/test/workflows/switch/test_create_switch.py
@@ -0,0 +1,64 @@
+from unittest.mock import patch
+
+import pytest
+
+from gso.products import ProductName
+from gso.products.product_types.switch import Switch
+from gso.services.subscriptions import get_product_id_by_name
+from test import USER_CONFIRM_EMPTY_FORM
+from test.services.conftest import MockedSharePointClient
+from test.workflows import (
+    assert_complete,
+    assert_lso_interaction_success,
+    assert_suspended,
+    extract_state,
+    resume_workflow,
+    run_workflow,
+)
+
+
+@pytest.mark.workflow()
+@patch("gso.services.lso_client._send_request")
+@patch("gso.services.infoblox.hostname_available")
+@patch("gso.services.sharepoint.SharePointClient")
+def test_create_switch_success(
+    mock_sharepoint_client, mock_hostname_available, mock_execute_playbook, faker, site_subscription_factory
+):
+    product_id = get_product_id_by_name(ProductName.SWITCH)
+    initial_form_input = [
+        {"product": product_id},
+        {
+            "tt_number": faker.tt_number(),
+            "switch_site": site_subscription_factory(),
+            "hostname": faker.domain_word(),
+            "ts_port": faker.port_number(is_user=True),
+        },
+        {},
+    ]
+    mock_hostname_available.return_value = True
+    mock_sharepoint_client.return_value = MockedSharePointClient
+    result, process_stat, step_log = run_workflow("create_switch", initial_form_input)
+
+    # Two LSO interactions
+    for _ in range(2):
+        result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
+
+    # Two user prompts
+    for _ in range(2):
+        assert_suspended(result)
+        result, step_log = resume_workflow(process_stat, step_log, input_data=USER_CONFIRM_EMPTY_FORM)
+
+    # One LSO interaction
+    result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
+
+    # Sharepoint list created
+    assert_suspended(result)
+    result, step_log = resume_workflow(process_stat, step_log, input_data=USER_CONFIRM_EMPTY_FORM)
+
+    assert_complete(result)
+
+    state = extract_state(result)
+    subscription_id = state["subscription_id"]
+    subscription = Switch.from_subscription(subscription_id)
+    assert subscription.status == "provisioning"
+    assert mock_execute_playbook.call_count == 3
diff --git a/test/workflows/switch/test_import_switch.py b/test/workflows/switch/test_import_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..9bdd578d66553b9e5f06f09717aae2b35e633460
--- /dev/null
+++ b/test/workflows/switch/test_import_switch.py
@@ -0,0 +1,18 @@
+import pytest
+from orchestrator.types import SubscriptionLifecycle
+
+from gso.products import ProductName
+from gso.products.product_types.switch import Switch
+from test.workflows import assert_complete, run_workflow
+
+
+@pytest.mark.workflow()
+def test_import_switch_success(switch_subscription_factory):
+    imported_switch = switch_subscription_factory(is_imported=False)
+    result, _, _ = run_workflow("import_switch", [{"subscription_id": imported_switch}])
+    subscription = Switch.from_subscription(imported_switch)
+
+    assert_complete(result)
+    assert subscription.product.name == ProductName.SWITCH
+    assert subscription.status == SubscriptionLifecycle.ACTIVE
+    assert subscription.insync is True
diff --git a/test/workflows/switch/test_terminate_switch.py b/test/workflows/switch/test_terminate_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..4614789c98bf09b40a746f845def31098e93c16d
--- /dev/null
+++ b/test/workflows/switch/test_terminate_switch.py
@@ -0,0 +1,23 @@
+from unittest.mock import patch
+
+import pytest
+
+from gso.products.product_types.switch import Switch
+from test.workflows import assert_complete, extract_state, run_workflow
+
+
+@pytest.mark.workflow()
+@patch("gso.services.netbox_client.NetboxClient.delete_device")
+@patch("gso.services.infoblox.delete_host_by_fqdn")
+def test_terminate_switch(mock_delete_host_by_fqdn, mock_delete_device, switch_subscription_factory, faker):
+    subscription_id = switch_subscription_factory()
+    initial_switch_data = [{"subscription_id": subscription_id}, {"tt_number": faker.tt_number()}]
+    result, _, _ = run_workflow("terminate_switch", initial_switch_data)
+    assert_complete(result)
+
+    state = extract_state(result)
+    subscription_id = state["subscription_id"]
+    subscription = Switch.from_subscription(subscription_id)
+    assert subscription.status == "terminated"
+    assert mock_delete_device.call_count == 1
+    assert mock_delete_host_by_fqdn.call_count == 1
diff --git a/test/workflows/switch/test_validate_switch.py b/test/workflows/switch/test_validate_switch.py
new file mode 100644
index 0000000000000000000000000000000000000000..f4e449b0ca84b439193cc55825e43c0bce1cbfb1
--- /dev/null
+++ b/test/workflows/switch/test_validate_switch.py
@@ -0,0 +1,38 @@
+from unittest.mock import patch
+
+import pytest
+
+from gso.products.product_types.switch import Switch
+from test.workflows import (
+    assert_complete,
+    assert_lso_success,
+    extract_state,
+    run_workflow,
+)
+
+
+@pytest.mark.workflow()
+@patch("gso.services.lso_client._send_request")
+@patch("gso.services.netbox_client.NetboxClient.get_device_by_name")
+def test_validate_switch_success(
+    mock_get_device_by_name,
+    mock_execute_playbook,
+    switch_subscription_factory,
+    faker,
+    data_config_filename,
+    geant_partner,
+):
+    #  Run workflow
+    subscription_id = switch_subscription_factory()
+    initial_switch_data = [{"subscription_id": subscription_id}]
+    result, process_stat, step_log = run_workflow("validate_switch", initial_switch_data)
+
+    result, step_log = assert_lso_success(result, process_stat, step_log)
+
+    assert_complete(result)
+    state = extract_state(result)
+    subscription = Switch.from_subscription(state["subscription_id"])
+
+    assert subscription.status == "active"
+    assert mock_execute_playbook.call_count == 1
+    assert mock_get_device_by_name.call_count == 1
diff --git a/test/workflows/tasks/test_task_validate_products.py b/test/workflows/tasks/test_task_validate_products.py
index b12b3a4a6b0190f7d150faf54d9c61d466f4f8de..66853d257d838b423cd7595e2a8ee2b015d94ecf 100644
--- a/test/workflows/tasks/test_task_validate_products.py
+++ b/test/workflows/tasks/test_task_validate_products.py
@@ -4,7 +4,7 @@ from test.workflows import assert_complete, extract_state, run_workflow
 
 
 @pytest.mark.workflow()
-def test_task_validate_geant_products(responses):
+def test_task_validate_geant_products():
     result, _, _ = run_workflow("task_validate_geant_products", [{}])
     assert_complete(result)
     state = extract_state(result)