diff --git a/src/tests/eucnc24/.gitlab-ci.yml b/src/tests/eucnc24/.gitlab-ci.yml
index 4ed3574a88e5900a209e96933b3906d873cd4e0e..6a9acaffd8a56f897972f7ab17058a98d027232e 100644
--- a/src/tests/eucnc24/.gitlab-ci.yml
+++ b/src/tests/eucnc24/.gitlab-ci.yml
@@ -112,12 +112,61 @@ end2end_test eucnc24:
     #  done
     - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server
 
-    # Run end-to-end tests
+    # Run end-to-end test: onboard scenario
     - >
       docker run -t --name ${TEST_NAME} --network=host 
       --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
       --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
-      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_onboarding.sh
+
+    # Run end-to-end test: configure service TFS
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_tfs_service_create.sh
+
+    # Run end-to-end test: test connectivity with ping
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.10'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.1'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.1'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.10'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.3.10'
+
+    # Run end-to-end test: deconfigure service TFS
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_tfs_service_remove.sh
+
+    # Run end-to-end test: configure service IETF
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_ietf_service_create.sh
+
+    # Run end-to-end test: test connectivity with ping
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.10'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.1.1'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.1'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.2.10'
+    - sudo containerlab exec --name eucnc24 --label clab-node-name=dc1 --cmd 'ping -n -c3 192.168.3.10'
+
+    # Run end-to-end test: deconfigure service IETF
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_ietf_service_remove.sh
+
+    # Run end-to-end test: cleanup scenario
+    - >
+      docker run -t --name ${TEST_NAME} --network=host 
+      --volume "$PWD/tfs_runtime_env_vars.sh:/var/teraflow/tfs_runtime_env_vars.sh"
+      --volume "$PWD/src/tests/${TEST_NAME}:/opt/results"
+      $CI_REGISTRY_IMAGE/${TEST_NAME}:latest ./run_cleanup.sh
 
   after_script:
     # Dump TeraFlowSDN component logs
diff --git a/src/tests/eucnc24/Dockerfile b/src/tests/eucnc24/Dockerfile
index c46100fff94ad0c08ea6da44f4efcddc997ba832..06c463ac6d2ade010c371921fe1bdc4bf172c0fc 100644
--- a/src/tests/eucnc24/Dockerfile
+++ b/src/tests/eucnc24/Dockerfile
@@ -75,17 +75,4 @@ COPY src/tests/*.py ./tests/
 COPY src/tests/eucnc24/__init__.py ./tests/eucnc24/__init__.py
 COPY src/tests/eucnc24/data/. ./tests/eucnc24/data/
 COPY src/tests/eucnc24/tests/. ./tests/eucnc24/tests/
-
-RUN tee ./run_tests.sh <<EOF
-#!/bin/bash
-source /var/teraflow/tfs_runtime_env_vars.sh
-export PYTHONPATH=/var/teraflow
-pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_bootstrap.py    --junitxml=/opt/results/report_bootstrap.xml
-pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_service_tfs.py  --junitxml=/opt/results/report_service_tfs.xml
-pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_service_ietf.py --junitxml=/opt/results/report_service_ietf.xml
-pytest --verbose --log-level=INFO /var/teraflow/tests/eucnc24/tests/test_functional_cleanup.py      --junitxml=/opt/results/report_cleanup.xml
-EOF
-RUN chmod ug+x ./run_tests.sh
-
-# Run the tests
-ENTRYPOINT ["./run_tests.sh"]
+COPY src/tests/eucnc24/scripts/. ./
diff --git a/src/tests/eucnc24/scripts/clab-cli-dc1.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-dc1.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-cli-dc1.sh
rename to src/tests/eucnc24/deploy-scripts/clab-cli-dc1.sh
diff --git a/src/tests/eucnc24/scripts/clab-cli-dc2.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-dc2.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-cli-dc2.sh
rename to src/tests/eucnc24/deploy-scripts/clab-cli-dc2.sh
diff --git a/src/tests/eucnc24/scripts/clab-cli-r1.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-r1.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-cli-r1.sh
rename to src/tests/eucnc24/deploy-scripts/clab-cli-r1.sh
diff --git a/src/tests/eucnc24/scripts/clab-cli-r2.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-r2.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-cli-r2.sh
rename to src/tests/eucnc24/deploy-scripts/clab-cli-r2.sh
diff --git a/src/tests/eucnc24/scripts/clab-cli-r3.sh b/src/tests/eucnc24/deploy-scripts/clab-cli-r3.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-cli-r3.sh
rename to src/tests/eucnc24/deploy-scripts/clab-cli-r3.sh
diff --git a/src/tests/eucnc24/scripts/clab-deploy.sh b/src/tests/eucnc24/deploy-scripts/clab-deploy.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-deploy.sh
rename to src/tests/eucnc24/deploy-scripts/clab-deploy.sh
diff --git a/src/tests/eucnc24/scripts/clab-destroy.sh b/src/tests/eucnc24/deploy-scripts/clab-destroy.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-destroy.sh
rename to src/tests/eucnc24/deploy-scripts/clab-destroy.sh
diff --git a/src/tests/eucnc24/scripts/clab-inspect.sh b/src/tests/eucnc24/deploy-scripts/clab-inspect.sh
similarity index 100%
rename from src/tests/eucnc24/scripts/clab-inspect.sh
rename to src/tests/eucnc24/deploy-scripts/clab-inspect.sh
diff --git a/src/tests/eucnc24/scripts/run-cleanup.sh b/src/tests/eucnc24/scripts/run-cleanup.sh
new file mode 100644
index 0000000000000000000000000000000000000000..c4b5867b37e472ed1828598fc980c6467283cb73
--- /dev/null
+++ b/src/tests/eucnc24/scripts/run-cleanup.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO \
+    --junitxml=/opt/results/report_cleanup.xml \
+    /var/teraflow/tests/eucnc24/tests/test_functional_cleanup.py
diff --git a/src/tests/eucnc24/scripts/run-onboarding.sh b/src/tests/eucnc24/scripts/run-onboarding.sh
new file mode 100644
index 0000000000000000000000000000000000000000..b94ab6f79f3f60f1ce3567d3a0188c014f94d213
--- /dev/null
+++ b/src/tests/eucnc24/scripts/run-onboarding.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO \
+    --junitxml=/opt/results/report_onboarding.xml \
+    /var/teraflow/tests/eucnc24/tests/test_functional_onboarding.py
diff --git a/src/tests/eucnc24/scripts/run-service-ietf-create.sh b/src/tests/eucnc24/scripts/run-service-ietf-create.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d2ec9eef51a1dbe311ddbc052d305ef0d8c92085
--- /dev/null
+++ b/src/tests/eucnc24/scripts/run-service-ietf-create.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO \
+    --junitxml=/opt/results/report_service_ietf_create.xml \
+    /var/teraflow/tests/eucnc24/tests/test_service_ietf_create.py
diff --git a/src/tests/eucnc24/scripts/run-service-ietf-remove.sh b/src/tests/eucnc24/scripts/run-service-ietf-remove.sh
new file mode 100644
index 0000000000000000000000000000000000000000..8c52636001fb8163b3a94fa0b229c7ab1264ab13
--- /dev/null
+++ b/src/tests/eucnc24/scripts/run-service-ietf-remove.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO \
+    --junitxml=/opt/results/report_service_ietf_remove.xml \
+    /var/teraflow/tests/eucnc24/tests/test_service_ietf_remove.py
diff --git a/src/tests/eucnc24/scripts/run-service-tfs-create.sh b/src/tests/eucnc24/scripts/run-service-tfs-create.sh
new file mode 100644
index 0000000000000000000000000000000000000000..5395f38b3ab82a11361a066f2d80b750e636b010
--- /dev/null
+++ b/src/tests/eucnc24/scripts/run-service-tfs-create.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO \
+    --junitxml=/opt/results/report_service_tfs_create.xml \
+    /var/teraflow/tests/eucnc24/tests/test_service_tfs_create.py
diff --git a/src/tests/eucnc24/scripts/run-service-tfs-remove.sh b/src/tests/eucnc24/scripts/run-service-tfs-remove.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d82d6d7738c24039fc4b8e878f48bb3c0c90f3fe
--- /dev/null
+++ b/src/tests/eucnc24/scripts/run-service-tfs-remove.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source /var/teraflow/tfs_runtime_env_vars.sh
+export PYTHONPATH=/var/teraflow
+pytest --verbose --log-level=INFO \
+    --junitxml=/opt/results/report_service_tfs_remove.xml \
+    /var/teraflow/tests/eucnc24/tests/test_service_tfs_remove.py
diff --git a/src/tests/eucnc24/tests/Fixtures.py b/src/tests/eucnc24/tests/Fixtures.py
index a9d2ceb24488dbd5b3775c958358df419dec4172..9eae2e2acda193157d0b5ed2fc8cde71cbcb2102 100644
--- a/src/tests/eucnc24/tests/Fixtures.py
+++ b/src/tests/eucnc24/tests/Fixtures.py
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 import pytest
+from typing import Dict
 from context.client.ContextClient import ContextClient
 from device.client.DeviceClient import DeviceClient
 from monitoring.client.MonitoringClient import MonitoringClient
@@ -41,3 +42,7 @@ def service_client():
     _client = ServiceClient()
     yield _client
     _client.close()
+
+@pytest.fixture(scope='session')
+def storage() -> Dict:
+    yield dict()
diff --git a/src/tests/eucnc24/tests/test_functional_cleanup.py b/src/tests/eucnc24/tests/test_cleanup.py
similarity index 100%
rename from src/tests/eucnc24/tests/test_functional_cleanup.py
rename to src/tests/eucnc24/tests/test_cleanup.py
diff --git a/src/tests/eucnc24/tests/test_functional_service_ietf.py b/src/tests/eucnc24/tests/test_functional_service_ietf.py
deleted file mode 100644
index 1abdb466b3c7cbb1da7b8bb676bdca0dee839652..0000000000000000000000000000000000000000
--- a/src/tests/eucnc24/tests/test_functional_service_ietf.py
+++ /dev/null
@@ -1,147 +0,0 @@
-# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import json, logging, os, pytest
-from typing import Dict
-from common.Constants import DEFAULT_CONTEXT_NAME
-from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum
-from common.tools.grpc.Tools import grpc_message_to_json_string
-from common.tools.object_factory.Context import json_context_id
-from context.client.ContextClient import ContextClient
-from .Fixtures import context_client   # pylint: disable=unused-import
-from .Tools import do_rest_delete_request, do_rest_get_request, do_rest_post_request
-
-
-LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
-
-REQUEST_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'ietf-l3vpn-service.json')
-ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
-
-@pytest.fixture(scope='session')
-def storage() -> Dict:
-    yield dict()
-
-# pylint: disable=redefined-outer-name, unused-argument
-def test_service_ietf_creation(
-    context_client : ContextClient,
-    storage : Dict
-):
-    # Issue service creation request
-    with open(REQUEST_FILE, 'r', encoding='UTF-8') as f:
-        svc1_data = json.load(f)
-    URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services'
-    do_rest_post_request(URL, body=svc1_data, logger=LOGGER, expected_status_codes={201})
-    vpn_id = svc1_data['ietf-l3vpn-svc:l3vpn-svc']['vpn-services']['vpn-service'][0]['vpn-id']
-
-    URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(vpn_id)
-    service_data = do_rest_get_request(URL, logger=LOGGER, expected_status_codes={200})
-    service_uuid = service_data['service-id']
-    storage['svc-uuid'] = service_uuid
-
-    # Verify service was created
-    response = context_client.GetContext(ADMIN_CONTEXT_ID)
-    assert len(response.service_ids) == 1
-    assert len(response.slice_ids) == 0
-
-    # Check there is 1 service
-    response = context_client.ListServices(ADMIN_CONTEXT_ID)
-    LOGGER.warning('Services[{:d}] = {:s}'.format(
-        len(response.services), grpc_message_to_json_string(response)
-    ))
-    assert len(response.services) == 1
-
-    for service in response.services:
-        service_id = service.service_id
-        assert service_id.service_uuid.uuid == service_uuid
-        assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
-        assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM
-
-        response = context_client.ListConnections(service_id)
-        LOGGER.warning('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
-            grpc_message_to_json_string(service_id), len(response.connections),
-            grpc_message_to_json_string(response)
-        ))
-        assert len(response.connections) == 1
-
-
-# pylint: disable=redefined-outer-name, unused-argument
-def test_service_ietf_retrieval(
-    context_client : ContextClient, # pylint: disable=redefined-outer-name
-    storage : Dict
-):
-    # Verify the scenario has 1 service and 0 slices
-    response = context_client.GetContext(ADMIN_CONTEXT_ID)
-    assert len(response.service_ids) == 1
-    assert len(response.slice_ids) == 0
-
-    # Check there are no slices
-    response = context_client.ListSlices(ADMIN_CONTEXT_ID)
-    LOGGER.warning('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
-    assert len(response.slices) == 0
-
-    # Check there is 1 service
-    response = context_client.ListServices(ADMIN_CONTEXT_ID)
-    LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 1
-
-    assert 'svc-uuid' in storage
-    service_uuid = storage['svc-uuid']
-    URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(service_uuid)
-    do_rest_get_request(URL, logger=LOGGER, expected_status_codes={200})
-
-
-# pylint: disable=redefined-outer-name, unused-argument
-def test_service_ietf_removal(
-    context_client : ContextClient, # pylint: disable=redefined-outer-name
-    storage : Dict
-):
-    # Verify the scenario has 1 service and 0 slices
-    response = context_client.GetContext(ADMIN_CONTEXT_ID)
-    assert len(response.service_ids) == 1
-    assert len(response.slice_ids) == 0
-
-    # Check there are no slices
-    response = context_client.ListSlices(ADMIN_CONTEXT_ID)
-    LOGGER.warning('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
-    assert len(response.slices) == 0
-
-    # Check there is 1 service
-    response = context_client.ListServices(ADMIN_CONTEXT_ID)
-    LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 1
-
-    assert 'svc-uuid' in storage
-    service_uuid = storage['svc-uuid']
-
-    for service in response.services:
-        service_id = service.service_id
-        assert service_id.service_uuid.uuid == service_uuid
-        assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
-        assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM
-
-        response = context_client.ListConnections(service_id)
-        LOGGER.warning('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
-            grpc_message_to_json_string(service_id), len(response.connections),
-            grpc_message_to_json_string(response)
-        ))
-        assert len(response.connections) == 1
-
-    URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(service_uuid)
-    do_rest_delete_request(URL, logger=LOGGER, expected_status_codes={204})
-
-    # Verify the scenario has no services/slices
-    response = context_client.GetContext(ADMIN_CONTEXT_ID)
-    assert len(response.service_ids) == 0
-    assert len(response.slice_ids) == 0
diff --git a/src/tests/eucnc24/tests/test_functional_bootstrap.py b/src/tests/eucnc24/tests/test_onboarding.py
similarity index 99%
rename from src/tests/eucnc24/tests/test_functional_bootstrap.py
rename to src/tests/eucnc24/tests/test_onboarding.py
index 5222a4c871997410c874b884ff70a215d090c1a9..93f040877a4d0c40e2a9d832872e78c75688cffb 100644
--- a/src/tests/eucnc24/tests/test_functional_bootstrap.py
+++ b/src/tests/eucnc24/tests/test_onboarding.py
@@ -27,7 +27,7 @@ LOGGER.setLevel(logging.DEBUG)
 DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'tfs-topology.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
-def test_scenario_bootstrap(
+def test_scenario_onboarding(
     context_client : ContextClient, # pylint: disable=redefined-outer-name
     device_client : DeviceClient,   # pylint: disable=redefined-outer-name
 ) -> None:
diff --git a/src/tests/eucnc24/tests/test_service_ietf_create.py b/src/tests/eucnc24/tests/test_service_ietf_create.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f713d45be7e24e3fcaf9e5c3f6f338a4db73950
--- /dev/null
+++ b/src/tests/eucnc24/tests/test_service_ietf_create.py
@@ -0,0 +1,73 @@
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import json, logging, os
+from typing import Dict
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from .Fixtures import context_client, storage   # pylint: disable=unused-import
+from .Tools import do_rest_get_request, do_rest_post_request
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+REQUEST_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'ietf-l3vpn-service.json')
+ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
+
+
+# pylint: disable=redefined-outer-name, unused-argument
+def test_service_ietf_creation(
+    context_client : ContextClient,
+    storage : Dict
+):
+    # Issue service creation request
+    with open(REQUEST_FILE, 'r', encoding='UTF-8') as f:
+        svc1_data = json.load(f)
+    URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services'
+    do_rest_post_request(URL, body=svc1_data, logger=LOGGER, expected_status_codes={201})
+    vpn_id = svc1_data['ietf-l3vpn-svc:l3vpn-svc']['vpn-services']['vpn-service'][0]['vpn-id']
+
+    URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(vpn_id)
+    service_data = do_rest_get_request(URL, logger=LOGGER, expected_status_codes={200})
+    service_uuid = service_data['service-id']
+    storage['svc-uuid'] = service_uuid
+
+    # Verify service was created
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 1
+    assert len(response.slice_ids) == 0
+
+    # Check there is 1 service
+    response = context_client.ListServices(ADMIN_CONTEXT_ID)
+    LOGGER.warning('Services[{:d}] = {:s}'.format(
+        len(response.services), grpc_message_to_json_string(response)
+    ))
+    assert len(response.services) == 1
+
+    for service in response.services:
+        service_id = service.service_id
+        assert service_id.service_uuid.uuid == service_uuid
+        assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
+        assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM
+
+        response = context_client.ListConnections(service_id)
+        LOGGER.warning('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections),
+            grpc_message_to_json_string(response)
+        ))
+        assert len(response.connections) == 1
diff --git a/src/tests/eucnc24/tests/test_service_ietf_remove.py b/src/tests/eucnc24/tests/test_service_ietf_remove.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe4210a57b264805184f130e7dab8e0c6d9c5c07
--- /dev/null
+++ b/src/tests/eucnc24/tests/test_service_ietf_remove.py
@@ -0,0 +1,75 @@
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging, os
+from typing import Dict
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from .Fixtures import context_client, storage   # pylint: disable=unused-import
+from .Tools import do_rest_delete_request
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+REQUEST_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'ietf-l3vpn-service.json')
+ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
+
+
+# pylint: disable=redefined-outer-name, unused-argument
+def test_service_ietf_removal(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    storage : Dict
+):
+    # Verify the scenario has 1 service and 0 slices
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 1
+    assert len(response.slice_ids) == 0
+
+    # Check there are no slices
+    response = context_client.ListSlices(ADMIN_CONTEXT_ID)
+    LOGGER.warning('Slices[{:d}] = {:s}'.format(len(response.slices), grpc_message_to_json_string(response)))
+    assert len(response.slices) == 0
+
+    # Check there is 1 service
+    response = context_client.ListServices(ADMIN_CONTEXT_ID)
+    LOGGER.warning('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 1
+
+    assert 'svc-uuid' in storage
+    service_uuid = storage['svc-uuid']
+
+    for service in response.services:
+        service_id = service.service_id
+        assert service_id.service_uuid.uuid == service_uuid
+        assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
+        assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM
+
+        response = context_client.ListConnections(service_id)
+        LOGGER.warning('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections),
+            grpc_message_to_json_string(response)
+        ))
+        assert len(response.connections) == 1
+
+    URL = '/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={:s}/'.format(service_uuid)
+    do_rest_delete_request(URL, logger=LOGGER, expected_status_codes={204})
+
+    # Verify the scenario has no services/slices
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 0
+    assert len(response.slice_ids) == 0
diff --git a/src/tests/eucnc24/tests/test_service_tfs_create.py b/src/tests/eucnc24/tests/test_service_tfs_create.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e0492f86f21b02c7f047d84c2db49d342710ac7
--- /dev/null
+++ b/src/tests/eucnc24/tests/test_service_tfs_create.py
@@ -0,0 +1,76 @@
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging, os
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import ContextId, ServiceStatusEnum, ServiceTypeEnum
+from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from service.client.ServiceClient import ServiceClient
+from .Fixtures import context_client, device_client, service_client        # pylint: disable=unused-import
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'tfs-service.json')
+ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
+
+
+def test_service_tfs_creation(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    device_client  : DeviceClient,  # pylint: disable=redefined-outer-name
+    service_client : ServiceClient, # pylint: disable=redefined-outer-name
+):
+    # Load descriptors and validate the base scenario
+    descriptor_loader = DescriptorLoader(
+        descriptors_file=DESCRIPTOR_FILE, context_client=context_client,
+        device_client=device_client, service_client=service_client
+    )
+    results = descriptor_loader.process()
+    check_descriptor_load_results(results, descriptor_loader)
+
+    # Verify the scenario has 1 service and 0 slices
+    response = context_client.GetContext(ADMIN_CONTEXT_ID)
+    assert len(response.service_ids) == 1
+    assert len(response.slice_ids) == 0
+
+    # Check there are no slices
+    response = context_client.ListSlices(ADMIN_CONTEXT_ID)
+    LOGGER.warning('Slices[{:d}] = {:s}'.format(
+        len(response.slices), grpc_message_to_json_string(response)
+    ))
+    assert len(response.slices) == 0
+
+    # Check there is 1 service
+    response = context_client.ListServices(ADMIN_CONTEXT_ID)
+    LOGGER.warning('Services[{:d}] = {:s}'.format(
+        len(response.services), grpc_message_to_json_string(response)
+    ))
+    assert len(response.services) == 1
+
+    for service in response.services:
+        service_id = service.service_id
+        assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
+        assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM
+
+        response = context_client.ListConnections(service_id)
+        LOGGER.warning('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections),
+            grpc_message_to_json_string(response)
+        ))
+        assert len(response.connections) == 1
diff --git a/src/tests/eucnc24/tests/test_functional_service_tfs.py b/src/tests/eucnc24/tests/test_service_tfs_remove.py
similarity index 62%
rename from src/tests/eucnc24/tests/test_functional_service_tfs.py
rename to src/tests/eucnc24/tests/test_service_tfs_remove.py
index 84385843b5a982219ac3b6d5d473e7371153db2a..76fdf0fc7407ce86bbd87806932eb1a4a45c40d1 100644
--- a/src/tests/eucnc24/tests/test_functional_service_tfs.py
+++ b/src/tests/eucnc24/tests/test_service_tfs_remove.py
@@ -16,14 +16,13 @@ import logging, os
 from typing import Set, Tuple
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import ContextId, ServiceId, ServiceStatusEnum, ServiceTypeEnum
-from common.tools.descriptor.Loader import DescriptorLoader, check_descriptor_load_results
 from common.tools.grpc.Tools import grpc_message_to_json_string
 from common.tools.object_factory.Context import json_context_id
 from common.tools.object_factory.Service import json_service_id
 from context.client.ContextClient import ContextClient
-from device.client.DeviceClient import DeviceClient
 from service.client.ServiceClient import ServiceClient
-from .Fixtures import context_client, device_client, service_client        # pylint: disable=unused-import
+from .Fixtures import context_client, service_client        # pylint: disable=unused-import
+
 
 LOGGER = logging.getLogger(__name__)
 LOGGER.setLevel(logging.DEBUG)
@@ -31,49 +30,6 @@ LOGGER.setLevel(logging.DEBUG)
 DESCRIPTOR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'tfs-service.json')
 ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
 
-def test_service_tfs_creation(
-    context_client : ContextClient, # pylint: disable=redefined-outer-name
-    device_client  : DeviceClient,  # pylint: disable=redefined-outer-name
-    service_client : ServiceClient, # pylint: disable=redefined-outer-name
-):
-    # Load descriptors and validate the base scenario
-    descriptor_loader = DescriptorLoader(
-        descriptors_file=DESCRIPTOR_FILE, context_client=context_client,
-        device_client=device_client, service_client=service_client
-    )
-    results = descriptor_loader.process()
-    check_descriptor_load_results(results, descriptor_loader)
-
-    # Verify the scenario has 1 service and 0 slices
-    response = context_client.GetContext(ADMIN_CONTEXT_ID)
-    assert len(response.service_ids) == 1
-    assert len(response.slice_ids) == 0
-
-    # Check there are no slices
-    response = context_client.ListSlices(ADMIN_CONTEXT_ID)
-    LOGGER.warning('Slices[{:d}] = {:s}'.format(
-        len(response.slices), grpc_message_to_json_string(response)
-    ))
-    assert len(response.slices) == 0
-
-    # Check there is 1 service
-    response = context_client.ListServices(ADMIN_CONTEXT_ID)
-    LOGGER.warning('Services[{:d}] = {:s}'.format(
-        len(response.services), grpc_message_to_json_string(response)
-    ))
-    assert len(response.services) == 1
-
-    for service in response.services:
-        service_id = service.service_id
-        assert service.service_status.service_status == ServiceStatusEnum.SERVICESTATUS_ACTIVE
-        assert service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM
-
-        response = context_client.ListConnections(service_id)
-        LOGGER.warning('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
-            grpc_message_to_json_string(service_id), len(response.connections),
-            grpc_message_to_json_string(response)
-        ))
-        assert len(response.connections) == 1
 
 def test_service_tfs_removal(
     context_client : ContextClient, # pylint: disable=redefined-outer-name