Updated ES Rapp version 36/14836/1
authorsaul.gill <saul.gill@est.tech>
Wed, 20 Aug 2025 12:44:03 +0000 (13:44 +0100)
committersaul.gill <saul.gill@est.tech>
Wed, 20 Aug 2025 12:44:09 +0000 (13:44 +0100)
Updated app and chart to 0.2.16
Added ncmp-sdnc query functionality
Added teiv query functionality
Updated README with smo install flafour info
Altered NRCellDU name parsing
Added retrieval of influx token from environment

Issue-ID: NONRTRIC-1083
Change-Id: I714ca70b6a11a497876ca45e4ff364930fb3dc1a
Signed-off-by: saul.gill <saul.gill@est.tech>
14 files changed:
sample-rapp-generator/es-demo-rapp/README.md
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/Chart.yaml
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/resources/config/config.json
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/templates/deployment.yaml
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-chart/values.yaml
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.16.tgz [new file with mode: 0644]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.5.tgz [deleted file]
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Definitions/asd.yaml
sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Files/Acm/instances/es-instance.json
sample-rapp-generator/es-demo-rapp/src/config.json
sample-rapp-generator/es-demo-rapp/src/data.py
sample-rapp-generator/es-demo-rapp/src/main.py
sample-rapp-generator/es-demo-rapp/src/ncmp_client.py
sample-rapp-generator/es-demo-rapp/src/teiv_client.py

index 8b89ab5..0dee90d 100644 (file)
@@ -21,6 +21,30 @@ The instructions below describe how to:
 For a complete guide on the installation of the SMO rApp platform,
 please follow the instructions [here](https://gerrit.o-ran-sc.org/r/gitweb?p=it/dep.git;a=blob_plain;f=smo-install/README.md;hb=HEAD).
 
+As an additional note, a special flavour of the SMO installation is available for the Energy Saving rApp demo.
+This flavour is located in the `smo-install/helm-override/ranpm-pynts-es-rapp` directory. 
+There is some detail on flavours [here](https://github.com/o-ran-sc/it-dep/blob/master/smo-install/README.md).
+This flavour is designed to install the SMO components required for the Energy Saving rapp demo.
+After all the other steps in the SMO installation guide are completed, you can run the following command to 
+install the Energy Saving rApp flavour:
+
+```bash
+./dep/smo-install/scripts/layer-2/2-install-oran.sh ranpm-pynts-es-rapp dev
+```
+
+Once all the components are installed and ready, you can proceed with the install of the DU simulators.
+These will start a flow of sample data through the system, which will be used by the Energy Saving rApp demo.
+wait around 10 minutes after all the components are installed before proceeding with the next simulator install.
+
+```bash
+./dep/smo-install/scripts/layer-2/2-install-simulators.sh ranpm-pynts-es-rapp
+```
+
+```text
+NOTE: The installation is just pointed at with the above commands. For the full installation and details of flavours, go to the smo installation docs.
+```
+[SMO Install Guide](https://github.com/o-ran-sc/it-dep/blob/master/smo-install/README.md)
+
 ### Energy Saving rApp Deployment Preparation
 1. The rApp needs to know the address and port of your chart repository. We can do this by running the following command:
    ```bash
index 2fd7fe3..c3680e8 100644 (file)
@@ -32,10 +32,10 @@ type: application
 # This is the chart version. This version number should be incremented each time you make changes
 # to the chart and its templates, including the app version.
 # Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 0.2.5
+version: 0.2.16
 
 # This is the version number of the application being deployed. This version number should be
 # incremented each time you make changes to the application. Versions are not expected to
 # follow Semantic Versioning. They should reflect the version the application is using.
 # It is recommended to use it with quotes.
-appVersion: "0.2.5"
+appVersion: "0.2.16"
index e473291..6a25026 100644 (file)
@@ -7,6 +7,8 @@
     "ncmp_api_name": "{{ .Values.ncmp.apiName }}",
     "ncmp_resource_name": "{{ .Values.ncmp.resourceName }}",
     "resource_id": "{{ .Values.ncmp.resourceId}}",
+    "ncmp_managed_element_id": "{{ .Values.ncmp.managedElementId }}",
+    "ncmp_gnbdufunction_id": "{{ .Values.ncmp.gnbduFunctionId }}",
     "influxdb_invoker_id": "{{ .Values.environment.appId }}",
     "influxdb_api_name": "{{ .Values.influxdb.apiName }}",
     "influxdb_resource_name": "{{ .Values.influxdb.resourceName }}",
index 1ce26ac..d624ea6 100644 (file)
@@ -63,6 +63,11 @@ spec:
               value: {{ .Values.environment.appId | quote }}
             - name: SME_DISCOVERY_ENDPOINT
               value: {{ .Values.environment.smeDiscoveryEndpoint | quote }}
+            - name: INFLUX_TOKEN
+              valueFrom:
+                secretKeyRef:
+                  key: token
+                  name: {{ .Values.influxdb.tokenSecretName | quote }}
           volumeMounts:
             - mountPath: /app/config.json
               name: config
index 890579a..885b4dd 100644 (file)
@@ -25,7 +25,7 @@ image:
   repository: "nexus3.onap.org:10001/estdemoimages/es-rapp"
   pullPolicy: Always
   # Overrides the image tag whose default is the chart appVersion.
-  tag: "0.2.5"
+  tag: "0.2.16"
 
 imagePullSecrets: []
 nameOverride: "energy-saving-rapp"
@@ -103,13 +103,15 @@ environment:
 
 influxdb:
   token: "hIVMgY7vn3M772PSk3yrI2IjeWzybPw0"
+  # This token secret is part of the smo install. The rapp will expect that this secret is created in the same namespace as the rapp.
+  tokenSecretName: influxdb-api-token
   user: "admin"
   password: "mySuP3rS3cr3tT0keN"
   bucket: "pm-logg-bucket"
   org: "est"
   apiName: "influxdb2-http"
   resourceName: "root"
-  timeRange: "-6h"
+  timeRange: "-5m"
   measurements:
     - "ManagedElement=o-du-pynts-1122,ManagedElement=o-du-pynts-1122,GNBDUFunction=1,NRCellDU=1"
     - "ManagedElement=o-du-pynts-1123,ManagedElement=o-du-pynts-1123,GNBDUFunction=1,NRCellDU=1"
@@ -117,9 +119,11 @@ influxdb:
 
 
 ncmp:
-  apiName: "ncmp-dmi-plugin-http"
+  apiName: "cps-core-http"
   resourceName: "root"
   resourceId: "/_3gpp-common-managed-element:ManagedElement=ManagedElement-002/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction=GNBDUFunction-001/_3gpp-nr-nrm-nrcelldu:NRCellDU=NRCellDU-001/attributes"
+  managedElementId: "ManagedElement-002"
+  gnbduFunctionId: "GNBDUFunction-001"
 
 kserve:
   apiName: "es-predictor-http"
@@ -128,7 +132,7 @@ kserve:
 teiv:
   apiName: "topology-exposure-http"
   resourceName: "root"
-  oduFunctionId: "GNBDUFunction-001"
+  oduFunctionId: "urn:oran:smo:teiv:GNBDUFunction-001"
 
 appStartup:
   command: ["/bin/sh", "-c"]
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.16.tgz b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.16.tgz
new file mode 100644 (file)
index 0000000..1f80139
Binary files /dev/null and b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.16.tgz differ
diff --git a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.5.tgz b/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.5.tgz
deleted file mode 100644 (file)
index c4b3413..0000000
Binary files a/sample-rapp-generator/es-demo-rapp/rapp-energy-saving/Artifacts/Deployment/HELM/energy-saving-rapp-0.2.5.tgz and /dev/null differ
index 31ac972..3228768 100755 (executable)
@@ -22,7 +22,7 @@ topology_template:
       artifacts:\r
         energy-saving:\r
           type: tosca.artifacts.asd.deploymentItem\r
-          file: "Artifacts/Deployment/HELM/energy-saving-rapp-0.2.5.tgz"\r
+          file: "Artifacts/Deployment/HELM/energy-saving-rapp-0.2.16.tgz"\r
           properties:\r
             artifact_type: "helm_chart"\r
             target_server: "chartmuseum"\r
index 9184b9f..7651179 100644 (file)
@@ -15,9 +15,9 @@
         "chart": {
           "chartId": {
             "name": "energy-saving-rapp",
-            "version": "0.2.5"
+            "version": "0.2.16"
           },
-          "namespace": "nonrtric",
+          "namespace": "smo",
           "releaseName": "energy-saving-rapp",
           "podName": "energy-saving-rapp",
           "repository": {
index 33d2c4a..3189957 100644 (file)
@@ -4,9 +4,11 @@
     "host": "localhost",
     "port": 31575,
     "ncmp_invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
-    "ncmp_api_name": "ncmp-dmi-plugin-http",
+    "ncmp_api_name": "cps-core-http",
     "ncmp_resource_name": "root",
     "resource_id": "/_3gpp-common-managed-element:ManagedElement=ManagedElement-002/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction=GNBDUFunction-001/_3gpp-nr-nrm-nrcelldu:NRCellDU=NRCellDU-001/attributes",
+    "ncmp_managed_element_id": "ManagedElement-002",
+    "ncmp_gnbdufunction_id": "GNBDUFunction-001",
     "influxdb_invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
     "influxdb_api_name": "influxdb2-http",
     "influxdb_resource_name": "root",
@@ -16,7 +18,7 @@
     "teiv_invoker_id": "6a965002-ed7c-4f69-855c-ab9196f86e61",
     "teiv_api_name": "topology-exposure-http",
     "teiv_resource_name": "root",
-    "odufunction_id": "GNBDUFunction-001"
+    "odufunction_id": "urn:oran:smo:teiv:GNBDUFunction-001"
   },
   "DB": {
     "host": "10.101.3.89",
index 0b70154..4a11f91 100644 (file)
@@ -14,7 +14,7 @@
 #  limitations under the License.
 #  ============LICENSE_END=================================================
 #
-
+import os
 import time
 import logging
 from influxdb.exceptions import InfluxDBClientError, InfluxDBServerError
@@ -145,7 +145,7 @@ class DATABASE(object):
                 time.sleep(60)
 
     def mapping(self, data):
-        data[['S', 'B', 'C']] = data['CellID'].str.extract(r'S(\d+)/[BN](\d+)/C(\d+)')
+        data[['S', 'B', 'C']] = data['CellID'].str.extract(r'S(\d+)-[BN](\d+)-C(\d+)')
         data[['S', 'B', 'C']] = data[['S', 'B', 'C']].astype(int)
         data = data.sort_values(by=['B', 'S', 'C'])
         data['cellidnumber'] = data.groupby(['B', 'S', 'C']).ngroup().add(1)
@@ -165,7 +165,7 @@ class DATABASE(object):
 
             for field in fields:
                 value = (
-                    f"S{random.randint(1,9)}/B{random.randint(1,9)}/C{random.randint(1,9)}" if field == "CellID"
+                    f"S{random.randint(1,9)}-B{random.randint(1,9)}-C{random.randint(1,9)}" if field == "CellID"
                     else (900 if field == "GranularityPeriod"
                     else str(round(random.uniform(1, 100), 5)))
                 )
@@ -208,7 +208,13 @@ class DATABASE(object):
 
         # Initialize the InfluxDB client
         influx_config = config.get("DB", {})
-        self.token = influx_config.get("token")
+
+        if os.getenv('INFLUX_TOKEN'):
+            self.token = os.getenv('INFLUX_TOKEN')
+        else:
+            logger.info("INFLUX_TOKEN environment variable is not set.")
+            self.token = influx_config.get("token")
+
         self.org = influx_config.get("org")
         self.bucket = influx_config.get("bucket")
         self.address = influx_config.get("address")
index 89dd281..0c4a5d4 100644 (file)
@@ -131,40 +131,44 @@ class ESrapp():
             status_code, response_text = self.assist.send_request_to_server(json_data, randomize=self.random_predictions)
             if not self.check_and_perform_action(response_text):
                 cell_id_name = group_data['CellID'].iloc[0]
+                # Check if the cell is in TEIV
+                self.check_cell_in_teiv(cell_id_name)
                 du_name = self.extract_managed_element(group_data['_measurement'].iloc[0])
-                full_cell_id = cell_id_name + "-" + du_name
+                cell_with_node = cell_id_name + "_" + du_name
                 logger.info(f"Turn on the cell {group_name}")
                 # Wait for 3 seconds before performing the action
                 time.sleep(3)
 
-                if full_cell_id not in self.cell_power_status:
-                    logger.debug(f"Cell {full_cell_id} not in local cache. Adding it...")
-                    self.cell_power_status[full_cell_id] = "off"
+                if cell_with_node not in self.cell_power_status:
+                    logger.debug(f"Cell {cell_with_node} not in local cache. Adding it...")
+                    self.cell_power_status[cell_with_node] = "off"
                 # Check if the cell is already powered on
-                if self.cell_power_status[full_cell_id] == "on":
-                    logger.debug(f"Cell {full_cell_id} is already powered on.")
+                if self.cell_power_status[cell_with_node] == "on":
+                    logger.debug(f"Cell {cell_with_node} is already powered on.")
                     # continue
                 else:
-                    self.ncmp_client.power_on_cell(full_cell_id)
-                    self.cell_power_status[full_cell_id] = "on"
+                    self.ncmp_client.power_on_cell(cell_with_node)
+                    self.cell_power_status[cell_with_node] = "on"
             else:
                 du_name = self.extract_managed_element(group_data['_measurement'].iloc[0])
                 cell_id_name = group_data['CellID'].iloc[0]
-                full_cell_id = cell_id_name + "-" + du_name
+                # Check if the cell is in TEIV
+                self.check_cell_in_teiv(cell_id_name)
+                cell_with_node = cell_id_name + "_" + du_name
                 logger.info(f"Turn off the cell {group_name}")
                 # Wait for 3 seconds before performing the action
                 time.sleep(3)
 
-                if full_cell_id not in self.cell_power_status:
-                    logger.debug(f"Cell {full_cell_id} not in local cache. Adding it...")
-                    self.cell_power_status[full_cell_id] = "on"
+                if cell_with_node not in self.cell_power_status:
+                    logger.debug(f"Cell {cell_with_node} not in local cache. Adding it...")
+                    self.cell_power_status[cell_with_node] = "on"
 
-                if self.cell_power_status[full_cell_id] == "off":
-                    logger.debug(f"Cell {full_cell_id} is already powered off.")
+                if self.cell_power_status[cell_with_node] == "off":
+                    logger.debug(f"Cell {cell_with_node} is already powered off.")
                     # continue
                 else:
-                    self.ncmp_client.power_off_cell(full_cell_id)
-                    self.cell_power_status[full_cell_id] = "off"
+                    if self.ncmp_client.power_off_cell(cell_with_node):
+                        self.cell_power_status[cell_with_node] = "off"
 
     def extract_managed_element(self, measurement):
         if '=' not in measurement or ',' not in measurement:
@@ -201,7 +205,7 @@ class ESrapp():
     def mapping(self, data):
         data = pd.DataFrame(data)
         # TODO: This regex is not likely to match all cell IDs. Will need to be improved.
-        data[['S', 'B', 'C']] = data['CellID'].str.extract(r'S(\d+)/[BN](\d+)/C(\d+)')
+        data[['S', 'B', 'C']] = data['CellID'].str.extract(r'S(\d+)-[BN](\d+)-C(\d+)')
         data[['S', 'B', 'C']] = data[['S', 'B', 'C']].astype(int)
         data = data.sort_values(by=['B', 'S', 'C'])
         data['cellidnumber'] = data.groupby(['B', 'S', 'C']).ngroup().add(1)
@@ -220,20 +224,15 @@ class ESrapp():
                     return False
         return False
 
+    # Check if the cell is in TEIV cell inventory
+    def check_cell_in_teiv(self, cell_id):
+        # Check if the cell ID is in the TEIV cell inventory
+        self.teiv_cells = self.teiv_client.get_nrcelldus()
 
-
-    # def get_teiv_cells(self):
-    #     # Get the TEIV cells from the teiv
-    #     odufunction_id = self.teiv_client.odufunction_id
-    #     logger.info("ODU function ID: " + str(odufunction_id))
-    #     # Get the NRCellDUs from the TEIV
-    #     nrcelldus = self.teiv_client.get_nrcelldus(odufunction_id)
-    #     if nrcelldus is None:
-    #         logger.error("Failed to retrieve NRCellDUs.")
-    #         return None
-    #     # Extract the cell IDs from the NRCellDUs
-    #     self.teiv_cells = self.teiv_client.search_entity_data_for_ids(nrcelldus)
-    #     logger.info("NRCellDUs: " + str(self.nrcelldus))
+        if cell_id in self.teiv_cells:
+            logger.info(f"Cell {cell_id} is in the TEIV cell inventory.")
+        else:
+            logger.info(f"Cell {cell_id} is not in the TEIV cell inventory.")
 
 
 if __name__ == "__main__":
index 0093f88..fa97813 100644 (file)
@@ -17,6 +17,7 @@
 
 import json
 import logging
+import requests
 from sme_client import SMEClient
 
 logger = logging.getLogger(__name__)
@@ -32,6 +33,8 @@ class NCMP_CLIENT(object):
         self.ncmp_invoker_id = sme_config.get("ncmp_invoker_id")
         self.ncmp_api_name = sme_config.get("ncmp_api_name")
         self.ncmp_resource_name = sme_config.get("ncmp_resource_name")
+        self.ncmp_me = sme_config.get("ncmp_managed_element_id", "ManagedElement-002")
+        self.ncmp_gnb = sme_config.get("ncmp_gnbdufunction_id", "GNBDUFunction-001")
         self.resourse_identifier = sme_config.get("resource_id")
         self.ncmp_uri = None
 
@@ -45,61 +48,74 @@ class NCMP_CLIENT(object):
 
         print("Discovered NCMP URI: ", self.ncmp_uri)
 
-    def power_off_cell(self, endpoint):
+    def power_off_cell(self, cell_with_node):
 
+        passthrough_request = self.make_passthrough_request(cell_with_node)
         # This log is all it does in testing
-        logger.info("Powering-off cell " + str(endpoint) + " successful")
+        logger.info("Powering-off cell " + str(cell_with_node) + " in progress...")
 
         # It expects the SME ncmp endpoint to call power off
         # endpoint_with_query = f"{endpoint}?resourceIdentifier={self.resourse_identifier}"
         #
-        # headers = {
-        #     "Content-Type": "application/json"
-        # }
-        #
-        # body = {
-        #     "attributes": {
-        #         "administrativeState": "LOCKED"
-        #     }
-        # }
-        #
-        # response = requests.patch(endpoint_with_query, data=body, headers=headers)
-        #
-        # if response.status_code == 200:
-        #     logger.info("Power-off successful. " + response.text)
-        #     return response.json()
-        # else:
-        #     logger.error(f"Error in connection to NCMP for power off: {response.status_code}")
-        #     logger.error(response.text)
-        #     return None
+        headers = {
+            "Content-Type": "application/json"
+        }
+
+        body = {
+            "attributes": {
+                "administrativeState": "LOCKED"
+            }
+        }
+
+        response = requests.patch(passthrough_request, json=body, headers=headers)
 
-    def power_on_cell(self, endpoint):
+        if response.status_code == 200:
+            logger.info("Power-off successful. " + response.text)
+            return True
+        else:
+            logger.error(f"Error in connection to NCMP for power off: {response.status_code}")
+            logger.error(response.text)
+            return False
+
+    def power_on_cell(self, cell_with_node):
 
         # This log is all it does in testing
-        logger.info("Powering-on cell " + str(endpoint) + " successful")
+        passthrough_request = self.make_passthrough_request(cell_with_node)
+        logger.info("Powering-on cell " + str(cell_with_node) + " in progress...")
 
         # It expects the SME ncmp endpoint to call power on
         # endpoint_with_query = f"{endpoint}?resourceIdentifier={self.resourse_identifier}"
-        #
-        # headers = {
-        #     "Content-Type": "application/json"
-        # }
-        #
-        # body = {
-        #     "attributes": {
-        #         "administrativeState": "UNLOCKED"
-        #     }
-        # }
-        #
-        # response = requests.patch(endpoint_with_query, data=body, headers=headers)
-        #
-        # if response.status_code == 200:
-        #     logger.info("Power-on successful. " + response.text)
-        #     return response.json()
-        # else:
-        #     logger.error(f"Error in connection to NCMP for power on: {response.status_code}")
-        #     logger.error(response.text)
-        #     return None
+
+        headers = {
+            "Content-Type": "application/json"
+        }
+
+        body = {
+            "attributes": {
+                "administrativeState": "UNLOCKED"
+            }
+        }
+
+        response = requests.patch(passthrough_request, json=body, headers=headers)
+
+        if response.status_code == 200:
+            logger.info("Power-on successful. " + response.text)
+            return True
+        else:
+            logger.error(f"Error in connection to NCMP for power on: {response.status_code}")
+            logger.error(response.text)
+            return False
+
+    def make_passthrough_request(self, cell_with_node):
+        node_id = cell_with_node.split('_')[1]
+        cell_id = cell_with_node.split('_')[0]
+
+        endpoint = f"ncmp/v1/ch/{node_id}/data/ds/ncmp-datastore%3Apassthrough-running"
+        query_param = (f"?resourceIdentifier=/_3gpp-common-managed-element:ManagedElement={self.ncmp_me}"
+                       f"/_3gpp-nr-nrm-gnbdufunction:GNBDUFunction={self.ncmp_gnb}"
+                       f"/_3gpp-nr-nrm-nrcelldu:NRCellDU={cell_id}/attributes")
+
+        return f"{self.ncmp_uri}{endpoint}{query_param}"
 
 # if __name__ == "__main__":
 #     logging.basicConfig(level=logging.INFO)  # Set up logging for better visibility
index 3b4456b..a54f56a 100644 (file)
@@ -43,12 +43,12 @@ class TEIV_CLIENT(object):
             resource_name=self.teiv_resource_name
         )
 
-        self.teiv_uri = sme_client.discover_service()
+        self.teiv_uri = sme_client.discover_service() + "topology-inventory/v1alpha11/"
 
         print("Discovered TEIV URI: ", self.teiv_uri)
 
-    def get_nrcelldus(self, odufunction_id):
-
+    def get_nrcelldus(self):
+        odufunction_id = self.odufunction_id
         scope_filter = f"/provided-by-oduFunction[@id=\"{odufunction_id}\"]"
         encoded_scope_filter = urllib.parse.quote(scope_filter)
         endpoint = (
@@ -59,8 +59,9 @@ class TEIV_CLIENT(object):
         response = requests.get(endpoint)
         
         if response.status_code == 200:
-            logger.info("Retrieved NRCellDUs. " + response.text)
-            return response.json()
+            nrcelldu_ids = self.search_entity_data_for_ids(response.json())
+            logger.info(f"Retrieved NRCellDU IDs form TEIV: {nrcelldu_ids}")
+            return nrcelldu_ids
         else:
             logger.error(f"Error in connection to TEIV: {response.status_code}")
             logger.error(response.text)
@@ -71,7 +72,11 @@ class TEIV_CLIENT(object):
         ids = []
         for item in items:
             for key in item:
-                ids.extend(entity.get('id') for entity in item[key] if 'id' in entity)
+                ids.extend(
+                    entity.get('id').split(':')[-1]
+                    for entity in item[key]
+                    if 'id' in entity
+                )
         return ids
 
 # if __name__ == "__main__":
@@ -80,5 +85,4 @@ class TEIV_CLIENT(object):
 #     # Instantiate the TEIVClient
 #     teiv_client = TEIV_CLIENT()
 #
-#     nrcelldu_json = teiv_client.get_nrcelldus(teiv_client.odufunction_id)
-#     nrcelldu_ids = teiv_client.search_entity_data_for_ids(nrcelldu_json)
\ No newline at end of file
+#     nrcelldu_json = teiv_client.get_nrcelldus()