diff --git a/Changelog.md b/Changelog.md
index 999e99e0a464426f71a805a05cbd139ced1fe74d..c760ba0c8b4c4ef9e51d68fdd0ad0673895cefad 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,12 @@
 
 All notable changes to this project will be documented in this file.
 
+## [2.5] - 2024-07-16
+- Added import Opengear workflow.
+- NAT-616
+- NAT-617: Restored ISIS metric to new node
+- NAT-619: Fixed BFD update logic bug
+
 ## [2.4] - 2024-06-25
 - Fixed the issue with client_credentials grant type token in Authentication part.
 
diff --git a/docs/source/module/workflows/index.rst b/docs/source/module/workflows/index.rst
index 9ef57ae8414ab3e0d46154237f5aadc7b0817ede..d3f0d0a2eff42a8f3693d7c04f83e05ad2bdf6c1 100644
--- a/docs/source/module/workflows/index.rst
+++ b/docs/source/module/workflows/index.rst
@@ -17,3 +17,4 @@ Subpackages
    router/index
    site/index
    super_pop_switch/index
+   opengear/index
diff --git a/docs/source/module/workflows/opengear/create_imported_opengear.rst b/docs/source/module/workflows/opengear/create_imported_opengear.rst
new file mode 100644
index 0000000000000000000000000000000000000000..07765a76e09ca0923cd3466049798992672ba063
--- /dev/null
+++ b/docs/source/module/workflows/opengear/create_imported_opengear.rst
@@ -0,0 +1,6 @@
+``gso.workflows.opengear.create_imported_opengear``
+===================================================================
+
+.. automodule:: gso.workflows.opengear.create_imported_opengear
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/opengear/import_opengear.rst b/docs/source/module/workflows/opengear/import_opengear.rst
new file mode 100644
index 0000000000000000000000000000000000000000..9834c5b5303d40983b088a555d3a3051f58cb618
--- /dev/null
+++ b/docs/source/module/workflows/opengear/import_opengear.rst
@@ -0,0 +1,6 @@
+``gso.workflows.opengear.import_opengear``
+==========================================================
+
+.. automodule:: gso.workflows.opengear.import_opengear
+   :members:
+   :show-inheritance:
diff --git a/docs/source/module/workflows/opengear/index.rst b/docs/source/module/workflows/opengear/index.rst
new file mode 100644
index 0000000000000000000000000000000000000000..69acd4555a2f3c62880b7b799079b147922d0c95
--- /dev/null
+++ b/docs/source/module/workflows/opengear/index.rst
@@ -0,0 +1,16 @@
+``gso.workflows.opengear``
+==================================
+
+.. automodule:: gso.workflows.opengear
+   :members:
+   :show-inheritance:
+
+Submodules
+----------
+
+.. toctree::
+   :maxdepth: 2
+   :titlesonly:
+
+   create_imported_opengear
+   import_opengear
diff --git a/gso/cli/imports.py b/gso/cli/imports.py
index c4dc1adf2cd9080a4401ceb34415de674d1d561e..f9dc660bd9b26058099954a9ed03aa583cf27846 100644
--- a/gso/cli/imports.py
+++ b/gso/cli/imports.py
@@ -145,8 +145,25 @@ class IptrunkImportModel(BaseModel):
         return self
 
 
+class OpenGearImportModel(BaseModel):
+    """Required fields for importing an existing :class:`gso.products.product_types.opengear`."""
+
+    partner: str
+    opengear_site: str
+    opengear_hostname: str
+    opengear_wan_address: IPv4AddressType
+    opengear_wan_netmask: IPv4AddressType
+    opengear_wan_gateway: IPv4AddressType
+
+
 T = TypeVar(
-    "T", SiteImportModel, RouterImportModel, IptrunkImportModel, SuperPopSwitchImportModel, OfficeRouterImportModel
+    "T",
+    SiteImportModel,
+    RouterImportModel,
+    IptrunkImportModel,
+    SuperPopSwitchImportModel,
+    OfficeRouterImportModel,
+    OpenGearImportModel,
 )
 
 common_filepath_option = typer.Option(
@@ -263,6 +280,18 @@ def import_office_routers(filepath: str = common_filepath_option) -> None:
     )
 
 
+@app.command()
+def import_opengear(filepath: str = common_filepath_option) -> None:
+    """Import Opengear into GSO."""
+    _generic_import_product(
+        Path(filepath),
+        ProductType.IMPORTED_OPENGEAR,
+        "opengear",
+        "opengear_hostname",
+        OpenGearImportModel,
+    )
+
+
 @app.command()
 def import_iptrunks(filepath: str = common_filepath_option) -> None:
     """Import IP trunks into GSO."""
diff --git a/gso/main.py b/gso/main.py
old mode 100644
new mode 100755
diff --git a/gso/migrations/versions/2023-11-21_e8378fbcfbf3_add_initial_products.py b/gso/migrations/versions/2023-11-21_e8378fbcfbf3_add_initial_products.py
index d0c1a38893f1355a597a121cd39d553b6a847325..b91dfc6795d87f858dc9dde7fc097bc7215634e2 100644
--- a/gso/migrations/versions/2023-11-21_e8378fbcfbf3_add_initial_products.py
+++ b/gso/migrations/versions/2023-11-21_e8378fbcfbf3_add_initial_products.py
@@ -10,9 +10,9 @@ from alembic import op
 
 # revision identifiers, used by Alembic.
 revision = 'e8378fbcfbf3'
-down_revision = 'da5c9f4cce1c'
-branch_labels = None
-depends_on = None
+down_revision = None
+branch_labels = ("data",)
+depends_on = "da5c9f4cce1c"
 
 
 def upgrade() -> None:
diff --git a/gso/migrations/versions/2024-06-19_fvd7mfcfbs1q_update_modify_isis_workflow.py b/gso/migrations/versions/2024-06-19_fvd7mfcfbs1q_update_modify_isis_workflow.py
index f3a1ae003a77aba2735742588f2355eca100c93b..96a18957725701658d2f21aa09780001fa4ba1bc 100644
--- a/gso/migrations/versions/2024-06-19_fvd7mfcfbs1q_update_modify_isis_workflow.py
+++ b/gso/migrations/versions/2024-06-19_fvd7mfcfbs1q_update_modify_isis_workflow.py
@@ -1,4 +1,4 @@
-"""Add upstream migrations as a dependency.
+""" Modify ISIS metric workflow description
 
 Revision ID: fvd7mfcfbs1q
 Revises:
diff --git a/gso/migrations/versions/2024-06-27_ccc7ac05063b_add_importedopengear_product.py b/gso/migrations/versions/2024-06-27_ccc7ac05063b_add_importedopengear_product.py
new file mode 100644
index 0000000000000000000000000000000000000000..f6bee99fdfcd271f125504f50173db8c1fc7424d
--- /dev/null
+++ b/gso/migrations/versions/2024-06-27_ccc7ac05063b_add_importedopengear_product.py
@@ -0,0 +1,47 @@
+"""Add ImportedOpenGear product..
+
+Revision ID: ccc7ac05063b
+Revises: fvd7mfcfbs1q
+Create Date: 2024-06-27 11:07:11.122519
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = 'ccc7ac05063b'
+down_revision = 'fvd7mfcfbs1q'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+INSERT INTO products (name, description, product_type, tag, status) VALUES ('Imported Opengear', 'Imported Opengear Product', 'ImportedOpengear', 'IMPORTED_OPENGEAR', '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 Opengear')), (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('OpengearBlock')))
+    """))
+
+
+def downgrade() -> None:
+    conn = op.get_bind()
+    conn.execute(sa.text("""
+DELETE FROM product_product_blocks WHERE product_product_blocks.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported Opengear')) AND product_product_blocks.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('OpengearBlock'))
+    """))
+    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 Opengear'))))
+    """))
+    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 Opengear')))
+    """))
+    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 Opengear')))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM subscriptions WHERE subscriptions.product_id IN (SELECT products.product_id FROM products WHERE products.name IN ('Imported Opengear'))
+    """))
+    conn.execute(sa.text("""
+DELETE FROM products WHERE products.name IN ('Imported Opengear')
+    """))
diff --git a/gso/migrations/versions/2024-06-27_f6a38f9e9e18_add_import_opengear_workflows.py b/gso/migrations/versions/2024-06-27_f6a38f9e9e18_add_import_opengear_workflows.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff8a2ab3b1cb05131f352dd2cb480e39c4f2c9cf
--- /dev/null
+++ b/gso/migrations/versions/2024-06-27_f6a38f9e9e18_add_import_opengear_workflows.py
@@ -0,0 +1,45 @@
+"""Add import Opengear workflows..
+
+Revision ID: f6a38f9e9e18
+Revises: ccc7ac05063b
+Create Date: 2024-06-27 11:48:05.331149
+
+"""
+import sqlalchemy as sa
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = 'f6a38f9e9e18'
+down_revision = 'ccc7ac05063b'
+branch_labels = None
+depends_on = None
+
+
+from orchestrator.migrations.helpers import create_workflow, delete_workflow
+
+new_workflows = [
+    {
+        "name": "create_imported_opengear",
+        "target": "CREATE",
+        "description": "Import Opengear",
+        "product_type": "ImportedOpengear"
+    },
+    {
+        "name": "import_opengear",
+        "target": "MODIFY",
+        "description": "Import Opengear",
+        "product_type": "ImportedOpengear"
+    }
+]
+
+
+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/products/__init__.py b/gso/products/__init__.py
index e81b36b8bd9d1777edac64aea4b4da77cba49b4c..9278fbe752d1fc4614f89c3f60c72ef3021908b7 100644
--- a/gso/products/__init__.py
+++ b/gso/products/__init__.py
@@ -11,7 +11,7 @@ from pydantic_forms.types import strEnum
 from gso.products.product_types.iptrunk import ImportedIptrunk, Iptrunk
 from gso.products.product_types.lan_switch_interconnect import LanSwitchInterconnect
 from gso.products.product_types.office_router import ImportedOfficeRouter, OfficeRouter
-from gso.products.product_types.opengear import Opengear
+from gso.products.product_types.opengear import ImportedOpengear, Opengear
 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
@@ -36,6 +36,7 @@ class ProductName(strEnum):
     IMPORTED_SUPER_POP_SWITCH = "Imported super PoP switch"
     IMPORTED_OFFICE_ROUTER = "Imported office router"
     OPENGEAR = "Opengear"
+    IMPORTED_OPENGEAR = "Imported Opengear"
 
 
 class ProductType(strEnum):
@@ -55,6 +56,7 @@ class ProductType(strEnum):
     IMPORTED_SUPER_POP_SWITCH = ImportedSuperPopSwitch.__name__
     IMPORTED_OFFICE_ROUTER = ImportedOfficeRouter.__name__
     OPENGEAR = Opengear.__name__
+    IMPORTED_OPENGEAR = Opengear.__name__
 
 
 SUBSCRIPTION_MODEL_REGISTRY.update(
@@ -73,5 +75,6 @@ SUBSCRIPTION_MODEL_REGISTRY.update(
         ProductName.IMPORTED_SUPER_POP_SWITCH.value: ImportedSuperPopSwitch,
         ProductName.IMPORTED_OFFICE_ROUTER.value: ImportedOfficeRouter,
         ProductName.OPENGEAR.value: Opengear,
+        ProductName.IMPORTED_OPENGEAR.value: ImportedOpengear,
     },
 )
diff --git a/gso/products/product_types/opengear.py b/gso/products/product_types/opengear.py
index a752f07e958748584b4642f62776b8e88ab1fa54..816ff2cccdf8de64701601387a31d7d6399094a7 100644
--- a/gso/products/product_types/opengear.py
+++ b/gso/products/product_types/opengear.py
@@ -22,3 +22,17 @@ class Opengear(OpengearProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
     """An Opengear that is currently active."""
 
     opengear: OpengearBlock
+
+
+class ImportedOpengearInactive(SubscriptionModel, is_base=True):
+    """An imported, inactive Opengear."""
+
+    opengear: OpengearBlockInactive
+
+
+class ImportedOpengear(
+    ImportedOpengearInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING, SubscriptionLifecycle.ACTIVE]
+):
+    """An imported Opengear that is currently active."""
+
+    opengear: OpengearBlock
diff --git a/gso/workflows/__init__.py b/gso/workflows/__init__.py
index e10c8b7f415f22cfdc0348ea42b445ba198f3f35..cf2eca0f71b724ca482b15107c7cf1844f554918 100644
--- a/gso/workflows/__init__.py
+++ b/gso/workflows/__init__.py
@@ -59,3 +59,7 @@ LazyWorkflowInstance(
 #  Office router workflows
 LazyWorkflowInstance("gso.workflows.office_router.import_office_router", "import_office_router")
 LazyWorkflowInstance("gso.workflows.office_router.create_imported_office_router", "create_imported_office_router")
+
+#  Opengear workflows
+LazyWorkflowInstance("gso.workflows.opengear.create_imported_opengear", "create_imported_opengear")
+LazyWorkflowInstance("gso.workflows.opengear.import_opengear", "import_opengear")
diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index 440bb8e2ac0eef37df5af277864e126d61245214..30f2c46b172707fa905055339db060e57f81f440 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -494,11 +494,15 @@ def netbox_allocate_side_b_interfaces(subscription: IptrunkInactive) -> None:
 
 
 @step("Create a new SharePoint checklist item")
-def create_new_sharepoint_checklist(subscription: IptrunkProvisioning, tt_number: str) -> State:
+def create_new_sharepoint_checklist(subscription: IptrunkProvisioning, tt_number: str, process_id: UUIDstr) -> State:
     """Create a new checklist item in SharePoint for approving this IPtrunk."""
     new_list_item_url = SharePointClient().add_list_item(
-        "ip_trunk",
-        {"Title": f"{subscription.description} - {subscription.iptrunk.geant_s_sid}", "TT_NUMBER": tt_number},
+        list_name="ip_trunk",
+        fields={
+            "Title": f"{subscription.description} - {subscription.iptrunk.geant_s_sid}",
+            "TT_NUMBER": tt_number,
+            "GAP_PROCESS_URL": f"{load_oss_params().GENERAL.public_hostname}/workflows/{process_id}",
+        },
     )
 
     return {"checklist_url": new_list_item_url}
diff --git a/gso/workflows/iptrunk/migrate_iptrunk.py b/gso/workflows/iptrunk/migrate_iptrunk.py
index 11294d9e2c50fb29b55eb99370162fb6d12c39aa..a92294934f94ef949fbd912f32ce65ab598e57b6 100644
--- a/gso/workflows/iptrunk/migrate_iptrunk.py
+++ b/gso/workflows/iptrunk/migrate_iptrunk.py
@@ -25,7 +25,7 @@ from pydantic import AfterValidator, ConfigDict, field_validator
 from pydantic_forms.validators import ReadOnlyField, validate_unique_list
 from pynetbox.models.dcim import Interfaces
 
-from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock
+from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock, IptrunkType
 from gso.products.product_types.iptrunk import Iptrunk
 from gso.products.product_types.router import Router
 from gso.services import infoblox
@@ -266,6 +266,34 @@ def check_ip_trunk_optical_levels_post(
     return {"subscription": subscription}
 
 
+@step("Check LLDP on the trunk endpoints")
+def check_ip_trunk_lldp(
+    subscription: Iptrunk,
+    callback_route: str,
+    new_node: Router,
+    new_lag_member_interfaces: list[dict],
+    replace_index: int,
+) -> State:
+    """Check LLDP on the new trunk endpoints."""
+    extra_vars = {
+        "wfo_ip_trunk_json": json.loads(json_dumps(subscription)),
+        "new_node": json.loads(json_dumps(new_node)),
+        "new_lag_member_interfaces": new_lag_member_interfaces,
+        "replace_index": replace_index,
+        "check": "lldp",
+    }
+
+    execute_playbook(
+        playbook_name="iptrunks_checks.yaml",
+        callback_route=callback_route,
+        inventory=f"{subscription.iptrunk.iptrunk_sides[1 - replace_index].iptrunk_side_node.router_fqdn}\n"
+        f"{new_node.router.router_fqdn}\n",
+        extra_vars=extra_vars,
+    )
+
+    return {"subscription": subscription}
+
+
 @step("[DRY RUN] Disable configuration on old router")
 def disable_old_config_dry(
     subscription: Iptrunk,
@@ -416,6 +444,90 @@ def deploy_new_config_real(
     return {"subscription": subscription}
 
 
+@step("[DRY RUN] Update BFD on the remaining side")
+def update_remaining_side_bfd_dry(
+    subscription: Iptrunk,
+    callback_route: str,
+    new_node: Router,
+    replace_index: int,
+    process_id: UUIDstr,
+    tt_number: str,
+) -> State:
+    """Perform a dry run of updating configuration on the remaining router."""
+    extra_vars = {
+        "wfo_trunk_json": json.loads(json_dumps(subscription)),
+        "new_node": json.loads(json_dumps(new_node)),
+        "replace_index": replace_index,
+        "verb": "update",
+        "config_object": "bfd_update",
+        "dry_run": True,
+        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} " f"- Update BFD config.",
+    }
+
+    execute_playbook(
+        playbook_name="iptrunks_migration.yaml",
+        callback_route=callback_route,
+        inventory=subscription.iptrunk.iptrunk_sides[1 - replace_index].iptrunk_side_node.router_fqdn,
+        extra_vars=extra_vars,
+    )
+
+    return {"subscription": subscription}
+
+
+@step("[FOR REAL] Update BFD on the remaining side")
+def update_remaining_side_bfd_real(
+    subscription: Iptrunk,
+    callback_route: str,
+    new_node: Router,
+    replace_index: int,
+    process_id: UUIDstr,
+    tt_number: str,
+) -> State:
+    """Update configuration on the remaining router."""
+    extra_vars = {
+        "wfo_trunk_json": json.loads(json_dumps(subscription)),
+        "new_node": json.loads(json_dumps(new_node)),
+        "replace_index": replace_index,
+        "verb": "update",
+        "config_object": "bfd_update",
+        "dry_run": False,
+        "commit_comment": f"GSO_PROCESS_ID: {process_id} - TT_NUMBER: {tt_number} " f"- Update BFD config.",
+    }
+
+    execute_playbook(
+        playbook_name="iptrunks_migration.yaml",
+        callback_route=callback_route,
+        inventory=subscription.iptrunk.iptrunk_sides[1 - replace_index].iptrunk_side_node.router_fqdn,
+        extra_vars=extra_vars,
+    )
+
+    return {"subscription": subscription}
+
+
+@step("Check BFD session over trunk")
+def check_ip_trunk_bfd(
+    subscription: Iptrunk,
+    callback_route: str,
+    new_node: Router,
+    replace_index: int,
+) -> State:
+    """Check BFD session across the new trunk."""
+    extra_vars = {
+        "wfo_ip_trunk_json": json.loads(json_dumps(subscription)),
+        "new_node": json.loads(json_dumps(new_node)),
+        "check": "bfd",
+    }
+
+    execute_playbook(
+        playbook_name="iptrunks_checks.yaml",
+        callback_route=callback_route,
+        inventory=subscription.iptrunk.iptrunk_sides[1 - replace_index].iptrunk_side_node.router_fqdn,
+        extra_vars=extra_vars,
+    )
+
+    return {"subscription": subscription}
+
+
 @inputstep("Wait for confirmation", assignee=Assignee.SYSTEM)
 def confirm_continue_move_fiber() -> FormGenerator:
     """Wait for confirmation from an operator that the physical fiber has been moved."""
@@ -726,6 +838,9 @@ def migrate_iptrunk() -> StepList:
         == Vendor.NOKIA
     )
     should_restore_isis_metric = conditional(lambda state: state["restore_isis_metric"])
+    trunk_type_is_leased = conditional(
+        lambda state: state["subscription"]["iptrunk"]["iptrunk_type"] == IptrunkType.LEASED
+    )
 
     return (
         init
@@ -739,17 +854,21 @@ def migrate_iptrunk() -> StepList:
         >> lso_interaction(disable_old_config_real)
         >> lso_interaction(deploy_new_config_dry)
         >> lso_interaction(deploy_new_config_real)
+        >> trunk_type_is_leased(lso_interaction(update_remaining_side_bfd_dry))
+        >> trunk_type_is_leased(lso_interaction(update_remaining_side_bfd_real))
         >> confirm_continue_move_fiber
         >> lso_interaction(check_ip_trunk_optical_levels_post)
+        >> lso_interaction(check_ip_trunk_lldp)
+        >> trunk_type_is_leased(lso_interaction(check_ip_trunk_bfd))
         >> lso_interaction(check_ip_trunk_connectivity)
         >> lso_interaction(deploy_new_isis)
         >> lso_interaction(check_ip_trunk_isis)
-        >> should_restore_isis_metric(confirm_continue_restore_isis)
-        >> should_restore_isis_metric(lso_interaction(restore_isis_metric))
         >> lso_interaction(delete_old_config_dry)
         >> lso_interaction(delete_old_config_real)
         >> update_ipam
         >> update_subscription_model
+        >> should_restore_isis_metric(confirm_continue_restore_isis)
+        >> should_restore_isis_metric(lso_interaction(restore_isis_metric))
         >> old_side_is_nokia(netbox_remove_old_interfaces)
         >> new_side_is_nokia(netbox_allocate_new_interfaces)
         >> resync
diff --git a/gso/workflows/opengear/__init__.py b/gso/workflows/opengear/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..111b88820f4d9488cd8701f1a4bcd38a1f3f6705
--- /dev/null
+++ b/gso/workflows/opengear/__init__.py
@@ -0,0 +1 @@
+"""Workflows related to Opengear subscriptions."""
diff --git a/gso/workflows/opengear/create_imported_opengear.py b/gso/workflows/opengear/create_imported_opengear.py
new file mode 100644
index 0000000000000000000000000000000000000000..e88e329a44b505eaca4466078e9a68da6835e459
--- /dev/null
+++ b/gso/workflows/opengear/create_imported_opengear.py
@@ -0,0 +1,83 @@
+"""A creation workflow that adds an existing opengear to the service database."""
+
+from orchestrator import workflow
+from orchestrator.forms import FormPage
+from orchestrator.targets import Target
+from orchestrator.types import FormGenerator, State, SubscriptionLifecycle
+from orchestrator.workflow import StepList, done, init, step
+from orchestrator.workflows.steps import resync, set_status, store_process_subscription
+from pydantic import ConfigDict
+
+from gso.products import ProductName
+from gso.products.product_types.opengear import ImportedOpengearInactive
+from gso.services.partners import get_partner_by_name
+from gso.services.subscriptions import get_product_id_by_name, get_site_by_name
+from gso.utils.shared_enums import IPv4AddressType
+
+
+@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_OPENGEAR)
+    subscription = ImportedOpengearInactive.from_product_id(product_id, partner_id)
+
+    return {
+        "subscription": subscription,
+        "subscription_id": subscription.subscription_id,
+    }
+
+
+def initial_input_form_generator() -> FormGenerator:
+    """Generate a form that is filled in using information passed through the :term:`API` endpoint."""
+
+    class ImportOpengear(FormPage):
+        model_config = ConfigDict(title="Import Opengear")
+
+        partner: str
+        opengear_site: str
+        opengear_hostname: str
+        opengear_wan_address: IPv4AddressType
+        opengear_wan_netmask: IPv4AddressType
+        opengear_wan_gateway: IPv4AddressType
+
+    user_input = yield ImportOpengear
+
+    return user_input.dict()
+
+
+@step("Initialize subscription")
+def initialize_subscription(
+    subscription: ImportedOpengearInactive,
+    opengear_site: str,
+    opengear_hostname: str,
+    opengear_wan_address: IPv4AddressType | None,
+    opengear_wan_netmask: IPv4AddressType | None,
+    opengear_wan_gateway: IPv4AddressType | None,
+) -> State:
+    """Initialise the Imported Opengear subscription using input data."""
+    subscription.opengear.opengear_site = get_site_by_name(opengear_site).site
+    subscription.opengear.opengear_hostname = opengear_hostname
+    subscription.opengear.opengear_wan_address = opengear_wan_address
+    subscription.opengear.opengear_wan_netmask = opengear_wan_netmask
+    subscription.opengear.opengear_wan_gateway = opengear_wan_gateway
+
+    return {"subscription": subscription}
+
+
+@workflow(
+    "Import Opengear",
+    initial_input_form=initial_input_form_generator,
+    target=Target.CREATE,
+)
+def create_imported_opengear() -> StepList:
+    """Import an Opengear without provisioning it."""
+    return (
+        init
+        >> create_subscription
+        >> store_process_subscription(Target.CREATE)
+        >> initialize_subscription
+        >> set_status(SubscriptionLifecycle.ACTIVE)
+        >> resync
+        >> done
+    )
diff --git a/gso/workflows/opengear/import_opengear.py b/gso/workflows/opengear/import_opengear.py
new file mode 100644
index 0000000000000000000000000000000000000000..d9bb75306a39161dc03c78ca47cc70449cd56850
--- /dev/null
+++ b/gso/workflows/opengear/import_opengear.py
@@ -0,0 +1,27 @@
+"""A modification workflow for migrating an ImportedOpengear to an Opengear subscription."""
+
+from orchestrator.targets import Target
+from orchestrator.types import State, UUIDstr
+from orchestrator.workflow import StepList, done, init, 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 import ProductName
+from gso.products.product_types.opengear import ImportedOpengear, Opengear
+from gso.services.subscriptions import get_product_id_by_name
+
+
+@step("Create new Opengear subscription")
+def import_opengear_subscription(subscription_id: UUIDstr) -> State:
+    """Take an ImportedOpengear subscription, and turn it into an Opengear subscription."""
+    old_opengear = ImportedOpengear.from_subscription(subscription_id)
+    product_id = get_product_id_by_name(ProductName.OPENGEAR)
+    new_subscription = Opengear.from_other_product(old_opengear, product_id)  # type: ignore[arg-type]
+
+    return {"subscription": new_subscription}
+
+
+@workflow("Import Opengear", target=Target.MODIFY, initial_input_form=wrap_modify_initial_input_form(None))
+def import_opengear() -> StepList:
+    """Modify an ImportedOpengear subscription into an Opengear subscription to complete the import."""
+    return init >> store_process_subscription(Target.MODIFY) >> unsync >> import_opengear_subscription >> resync >> done
diff --git a/gso/workflows/router/create_router.py b/gso/workflows/router/create_router.py
index 233d982c0ea1a275b12b9540399c1bbd4d8b20dd..700f3f9c86112562d1a1ef127dad209da22b96be 100644
--- a/gso/workflows/router/create_router.py
+++ b/gso/workflows/router/create_router.py
@@ -21,6 +21,7 @@ from gso.services.lso_client import lso_interaction
 from gso.services.netbox_client import NetboxClient
 from gso.services.partners import get_partner_by_name
 from gso.services.sharepoint import SharePointClient
+from gso.settings import load_oss_params
 from gso.utils.helpers import generate_fqdn, iso_from_ipv4
 from gso.utils.shared_enums import PortNumber, Vendor
 from gso.utils.workflow_steps import (
@@ -224,10 +225,15 @@ def prompt_insert_in_radius(subscription: RouterInactive) -> FormGenerator:
 
 
 @step("Create a new SharePoint checklist")
-def create_new_sharepoint_checklist(subscription: RouterProvisioning, tt_number: str) -> State:
+def create_new_sharepoint_checklist(subscription: RouterProvisioning, 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(
-        "p_router", {"Title": subscription.router.router_fqdn, "TT_NUMBER": tt_number}
+        list_name="p_router",
+        fields={
+            "Title": subscription.router.router_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}
diff --git a/setup.py b/setup.py
index 646364102ed9634cc655a6882a8becf2cf3d02a7..64423cc3bf393a932ae4d2cd3b2c46c8e98e062f 100644
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@ from setuptools import find_packages, setup
 
 setup(
     name="geant-service-orchestrator",
-    version="2.4",
+    version="2.5",
     author="GÉANT Orchestration and Automation Team",
     author_email="goat@geant.org",
     description="GÉANT Service Orchestrator",
diff --git a/test/cli/conftest.py b/test/cli/conftest.py
index e002fa13c19973dfbe733aa47fba34981558f116..92d726fae5aaa0adf7a51eb4b4c4f0bc768b14c3 100644
--- a/test/cli/conftest.py
+++ b/test/cli/conftest.py
@@ -3,6 +3,7 @@ from test.fixtures import (  # noqa: F401
     iptrunk_subscription_factory,
     nokia_router_subscription_factory,
     office_router_subscription_factory,
+    opengear_subscription_factory,
     site_subscription_factory,
     super_pop_switch_subscription_factory,
 )
diff --git a/test/cli/test_imports.py b/test/cli/test_imports.py
index 3cd45db7d4715f046a0ab885b6b146f3b56f9db4..f25c64a98f6ea546394ac2b213ed668b4d8b24a1 100644
--- a/test/cli/test_imports.py
+++ b/test/cli/test_imports.py
@@ -7,6 +7,7 @@ import pytest
 from gso.cli.imports import (
     import_iptrunks,
     import_office_routers,
+    import_opengear,
     import_routers,
     import_sites,
     import_super_pop_switches,
@@ -175,6 +176,24 @@ def office_router_data(temp_file, faker, site_subscription_factory):
     return _office_router_data
 
 
+@pytest.fixture()
+def opengear_data(temp_file, faker, site_subscription_factory):
+    def _opengear_data(**kwargs):
+        opengear_data = {
+            "opengear_site": Site.from_subscription(site_subscription_factory()).site.site_name,
+            "opengear_hostname": faker.domain_name(levels=4),
+            "opengear_wan_address": str(faker.ipv4()),
+            "opengear_wan_netmask": str(faker.ipv4()),
+            "opengear_wan_gateway": str(faker.ipv4()),
+        }
+        opengear_data.update(**kwargs)
+
+        temp_file.write_text(json.dumps([opengear_data]))
+        return {"path": str(temp_file), "data": opengear_data}
+
+    return _opengear_data
+
+
 ###########
 #  TESTS  #
 ###########
@@ -339,3 +358,9 @@ def test_import_office_router_success(mock_start_process, office_router_data):
 def test_import_super_pop_switch_success(mock_start_process, super_pop_switch_data):
     import_super_pop_switches(super_pop_switch_data()["path"])
     assert mock_start_process.call_count == 1
+
+
+@patch("gso.cli.imports.start_process")
+def test_import_opengear_success(mock_start_process, opengear_data):
+    import_opengear(opengear_data()["path"])
+    assert mock_start_process.call_count == 1
diff --git a/test/conftest.py b/test/conftest.py
index 8fae41e74198cd47d0cc6543b60b3b459b6be273..d0391c02ab4c83b0c3d0cc98a418dabe11c9e5ad 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -42,6 +42,7 @@ from test.fixtures import (  # noqa: F401
     juniper_router_subscription_factory,
     nokia_router_subscription_factory,
     office_router_subscription_factory,
+    opengear_subscription_factory,
     site_subscription_factory,
     super_pop_switch_subscription_factory,
     test_workflow,
diff --git a/test/fixtures.py b/test/fixtures.py
index 316a43c338f20601fa4235f0cac11ceacc2317f4..4a996e7d63fa7f8f85af9235c5021aab7cdd44c7 100644
--- a/test/fixtures.py
+++ b/test/fixtures.py
@@ -25,6 +25,7 @@ from gso.products.product_blocks.router import RouterRole
 from gso.products.product_blocks.site import SiteTier
 from gso.products.product_types.iptrunk import ImportedIptrunkInactive, IptrunkInactive
 from gso.products.product_types.office_router import ImportedOfficeRouterInactive, OfficeRouterInactive
+from gso.products.product_types.opengear import ImportedOpengearInactive, OpengearInactive
 from gso.products.product_types.router import ImportedRouterInactive, Router, RouterInactive
 from gso.products.product_types.site import ImportedSiteInactive, Site, SiteInactive
 from gso.products.product_types.super_pop_switch import ImportedSuperPopSwitchInactive, SuperPopSwitchInactive
@@ -278,7 +279,7 @@ def iptrunk_subscription_factory(iptrunk_side_subscription_factory, faker, geant
         start_date="2023-05-24T00:00:00+00:00",
         geant_s_sid=None,
         iptrunk_description=None,
-        iptrunk_type=IptrunkType.DARK_FIBER,
+        iptrunk_type=IptrunkType.LEASED,
         iptrunk_speed=PhysicalPortCapacity.ONE_GIGABIT_PER_SECOND,
         iptrunk_isis_metric=None,
         iptrunk_ipv4_network=None,
@@ -463,6 +464,65 @@ def super_pop_switch_subscription_factory(site_subscription_factory, faker, gean
     return subscription_create
 
 
+@pytest.fixture()
+def opengear_subscription_factory(site_subscription_factory, faker, geant_partner):
+    def subscription_create(
+        description=None,
+        start_date="2023-05-24T00:00:00+00:00",
+        opengear_site=None,
+        opengear_hostname=None,
+        opengear_wan_address=None,
+        opengear_wan_netmask=None,
+        opengear_wan_gateway=None,
+        status: SubscriptionLifecycle | None = None,
+        partner: dict | None = None,
+        *,
+        is_imported: bool | None = True,
+    ) -> UUIDstr:
+        if partner is None:
+            partner = geant_partner
+
+        description = description or faker.text(max_nb_chars=30)
+        opengear_site = opengear_site or site_subscription_factory()
+        opengear_hostname = opengear_hostname or faker.domain_name(levels=4)
+        opengear_wan_address = opengear_wan_address or faker.ipv4()
+        opengear_wan_netmask = opengear_wan_netmask or faker.ipv4()
+        opengear_wan_gateway = opengear_wan_gateway or faker.ipv4()
+
+        if is_imported:
+            product_id = subscriptions.get_product_id_by_name(ProductName.OPENGEAR)
+            opengear_subscription = OpengearInactive.from_product_id(
+                product_id, customer_id=partner["partner_id"], insync=True
+            )
+        else:
+            product_id = subscriptions.get_product_id_by_name(ProductName.IMPORTED_OPENGEAR)
+            opengear_subscription = ImportedOpengearInactive.from_product_id(
+                product_id, customer_id=partner["partner_id"], insync=True
+            )
+
+        opengear_subscription.opengear.opengear_site = Site.from_subscription(opengear_site).site
+        opengear_subscription.opengear.opengear_hostname = opengear_hostname
+        opengear_subscription.opengear.opengear_wan_address = opengear_wan_address
+        opengear_subscription.opengear.opengear_wan_netmask = opengear_wan_netmask
+        opengear_subscription.opengear.opengear_wan_gateway = opengear_wan_gateway
+
+        opengear_subscription = SubscriptionModel.from_other_lifecycle(
+            opengear_subscription, SubscriptionLifecycle.ACTIVE
+        )
+        opengear_subscription.description = description
+        opengear_subscription.start_date = start_date
+
+        if status:
+            opengear_subscription.status = status
+
+        opengear_subscription.save()
+        db.session.commit()
+
+        return str(opengear_subscription.subscription_id)
+
+    return subscription_create
+
+
 @pytest.fixture()
 def test_workflow(generic_subscription_1: UUIDstr, generic_product_type_1) -> Generator:
     _, generic_product_one = generic_product_type_1
diff --git a/test/workflows/iptrunk/test_migrate_iptrunk.py b/test/workflows/iptrunk/test_migrate_iptrunk.py
index cd46d72100d3432cc868cdd8bb6cb710d0e74c44..5a8f49b3ad3e54bf106fafbb0d4392be8c696937 100644
--- a/test/workflows/iptrunk/test_migrate_iptrunk.py
+++ b/test/workflows/iptrunk/test_migrate_iptrunk.py
@@ -149,19 +149,19 @@ def test_migrate_iptrunk_success(
 
     result, process_stat, step_log = run_workflow("migrate_iptrunk", migrate_form_input)
 
-    for _ in range(6):
+    for _ in range(8):
         result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
 
     assert_suspended(result)
     result, step_log = resume_workflow(process_stat, step_log, input_data=USER_CONFIRM_EMPTY_FORM)
 
-    for _ in range(4):
+    for _ in range(8):
         result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
 
     assert_suspended(result)
     result, step_log = resume_workflow(process_stat, step_log, input_data=USER_CONFIRM_EMPTY_FORM)
 
-    for _ in range(3):
+    for _ in range(1):
         result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
 
     assert_complete(result)
@@ -171,7 +171,7 @@ def test_migrate_iptrunk_success(
     subscription = Iptrunk.from_subscription(subscription_id)
 
     assert subscription.status == "active"
-    assert mock_execute_playbook.call_count == 13
+    assert mock_execute_playbook.call_count == 17
     assert mock_create_host_by_ip.call_count == 1
     assert mock_delete_host_by_ip.call_count == 1
 
diff --git a/test/workflows/opengear/__init__.py b/test/workflows/opengear/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test/workflows/opengear/test_create_imported_opengear.py b/test/workflows/opengear/test_create_imported_opengear.py
new file mode 100644
index 0000000000000000000000000000000000000000..0f6d9bf171103c5b5152937b47114a9b666bad5c
--- /dev/null
+++ b/test/workflows/opengear/test_create_imported_opengear.py
@@ -0,0 +1,33 @@
+import pytest
+from orchestrator.types import SubscriptionLifecycle
+
+from gso.products import ImportedOpengear, ProductName
+from gso.products.product_types.site import Site
+from test.workflows import (
+    assert_complete,
+    extract_state,
+    run_workflow,
+)
+
+
+@pytest.fixture()
+def workflow_input_data(faker, site_subscription_factory):
+    return {
+        "partner": "GEANT",
+        "opengear_site": Site.from_subscription(site_subscription_factory()).site.site_name,
+        "opengear_hostname": faker.hostname(),
+        "opengear_wan_address": faker.ipv4(),
+        "opengear_wan_netmask": faker.ipv4(),
+        "opengear_wan_gateway": faker.ipv4(),
+    }
+
+
+@pytest.mark.workflow()
+def test_create_imported_opengear_success(workflow_input_data):
+    result, _, _ = run_workflow("create_imported_opengear", [workflow_input_data])
+    state = extract_state(result)
+    imported_opengear = ImportedOpengear.from_subscription(state["subscription_id"])
+
+    assert_complete(result)
+    assert imported_opengear.product.name == ProductName.IMPORTED_OPENGEAR
+    assert imported_opengear.status == SubscriptionLifecycle.ACTIVE
diff --git a/test/workflows/opengear/test_import_opengear.py b/test/workflows/opengear/test_import_opengear.py
new file mode 100644
index 0000000000000000000000000000000000000000..37c7d1718444341b8f645942b0c6baaf24f7e3a6
--- /dev/null
+++ b/test/workflows/opengear/test_import_opengear.py
@@ -0,0 +1,18 @@
+import pytest
+from orchestrator.types import SubscriptionLifecycle
+
+from gso.products import ProductName
+from gso.products.product_types.opengear import Opengear
+from test.workflows import assert_complete, run_workflow
+
+
+@pytest.mark.workflow()
+def test_import_office_router_success(opengear_subscription_factory):
+    imported_opengear = opengear_subscription_factory(is_imported=False)
+    result, _, _ = run_workflow("import_opengear", [{"subscription_id": imported_opengear}])
+    subscription = Opengear.from_subscription(imported_opengear)
+
+    assert_complete(result)
+    assert subscription.product.name == ProductName.OPENGEAR
+    assert subscription.status == SubscriptionLifecycle.ACTIVE
+    assert subscription.insync