See the page in Wiki: `O-RU Fronthaul Recovery usecase <https://wiki.o-ran-sc.org/display/RICNR/O-RU+Fronthaul+Recovery+usecase>`_.
-O-DU Slicing use cases
-----------------------
-
-See the page in Wiki: `O-DU Slice Assurance usecase <https://wiki.o-ran-sc.org/display/RICNR/O-DU+Slice+Assurance+usecase>`_.
-
Helm Manager
------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A very simplified closed-loop rApp use case to re-prioritize a RAN slice's radio resource allocation priority if sufficient throughput cannot be maintained. Not intended to to be 'real-world'.
+* Repo: *nonrtric/rapp/ransliceassurance*
\ No newline at end of file
| | | | in usecase |
+------------+----------+------------------+--------------------+
-
-Version history usecase O-DU Slice Assurance
-============================================
-
-+------------+----------+------------------+-----------------+
-| **Date** | **Ver.** | **Author** | **Comment** |
-| | | | |
-+------------+----------+------------------+-----------------+
-| 2021-12-14 | 1.0.0 | Henrik Andersson | E Release |
-| | | | Initial version |
-+------------+----------+------------------+-----------------+
-| 2022-02-14 | 1.0.2 | Henrik Andersson | E Maintenance |
-| | | | Release |
-+------------+----------+------------------+-----------------+
-
-
Release Data
============
A very simplified closed-loop rApp use case to re-prioritize a RAN slice's radio resource allocation priority if sufficient throughput cannot be maintained. Not intended to to be 'real-world'.
The Go implementation of the solution can be found in
-this `link <https://gerrit.o-ran-sc.org/r/gitweb?p=nonrtric.git;a=tree;f=test/usecases/odusliceassurance/goversion>`_.
+this `link <https://gerrit.o-ran-sc.org/r/gitweb?p=nonrtric/rapp/ransliceassurance.git;a=tree;f=smoversion>`__.
+++ /dev/null
-{
- "event":{
- "commonEventHeader":{
- "domain":"measurement",
- "eventId":"_1634181300_PM15min",
- "eventName":"measurement_O_RAN_COMPONENT_PM15min",
- "eventType":"O_RAN_COMPONENT_PM15min",
- "internalHeaderFields":{
- "intervalEndTime":"Thu, 14 Oct 2021 03:15:00 +0000",
- "intervalStartTime":"Thu, 14 Oct 2021 03:00:00 +0000"
- },
- "lastEpochMicrosec":1634181300000000,
- "priority":"Low",
- "reportingEntityId":"",
- "reportingEntityName":"ORAN-DEV",
- "sequence":0,
- "sourceId":"",
- "sourceName":"",
- "startEpochMicrosec":1634180400000000,
- "version":"4.1",
- "vesEventListenerVersion":"7.2.1"
- },
- "measurementFields":{
- "additionalFields":{
-
- },
- "additionalMeasurements":[
- {
- "hashMap":{
- "cses":"0",
- "es":"0",
- "ses":"1",
- "unavailability":"0"
- },
- "name":"-1"
- },
- {
- "hashMap":{
- "cses":"0",
- "es":"0",
- "ses":"1",
- "unavailability":"0"
- },
- "name":"-2"
- }
- ],
- "additionalObjects":[
-
- ],
- "codecUsageArray":[
-
- ],
- "concurrentSessions":2,
- "configuredEntities":2,
- "cpuUsageArray":[
-
- ],
- "diskUsageArray":[
-
- ],
- "featureUsageArray":{
- "https://www.itu.int/rec/T-REC-G.841":"true"
- },
- "filesystemUsageArray":[
-
- ],
- "hugePagesArray":[
-
- ],
- "ipmi":{
-
- },
- "latencyDistribution":[
-
- ],
- "loadArray":[
-
- ],
- "machineCheckExceptionArray":[
-
- ],
- "meanRequestLatency":1000,
- "measurementFieldsVersion":"4.0",
- "measurementInterval":234,
- "memoryUsageArray":[
-
- ],
- "networkSliceArray":[
- {
- "DRB.UEThDl.SNSSAI":300,
- "DRB.UEThUl.SNSSAI":400,
- "networkSliceIdentifier":"SD0001"
- },
- {
- "DRB.UEThDl.SNSSAI":150,
- "DRB.UEThUl.SNSSAI":250,
- "networkSliceIdentifier":"SD0002"
- },
- {
- "DRB.UEThDl.SNSSAI":350,
- "DRB.UEThUl.SNSSAI":450,
- "networkSliceIdentifier":"SD0003"
- }
- ],
- "nfcScalingMetric":3,
- "nicPerformanceArray":[
-
- ],
- "numberOfMediaPortsInUse":234,
- "processStatsArray":[
-
- ],
- "requestRate":23
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-{
- "event":{
- "commonEventHeader":{
- "domain":"@domain@",
- "eventId":"@eventId@",
- "eventName":"@domain@_@eventType@",
- "eventType":"@eventType@",
- "sequence":0,
- "priority":"Low",
- "reportingEntityId":"",
- "reportingEntityName":"@controllerName@",
- "sourceId":"",
- "sourceName":"@controllerName@",
- "startEpochMicrosec":"@timestamp@",
- "lastEpochMicrosec":"@timestamp@",
- "nfNamingCode":"@type@",
- "nfVendorName":"@vendor@",
- "stndDefinedNamespace":"o-ran-sc-du-hello-world-pm-streaming-oas3",
- "timeZoneOffset":"+00:00",
- "version":"4.1",
- "vesEventListenerVersion":"7.2.1"
- },
- "stndDefinedFields":{
- "stndDefinedFieldsVersion":"1.0",
- "schemaReference":"https://gerrit.o-ran-sc.org/r/gitweb?p=scp/oam/modeling.git;a=blob_plain;f=data-model/oas3/experimental/o-ran-sc-du-hello-world-oas3.json;hb=refs/heads/master",
- "data":{
- "id":"string",
- "start-time":"@collectionStartTime@",
- "administrative-state":"locked",
- "operational-state":"disabled",
- "user-label":"string",
- "job-tag":"string",
- "granularity-period":0,
- "measurements":[
- {
- "measurement-type-instance-reference":"/network-function/distributed-unit-functions[id='%duId%']/cell[id='%cellId%']/supported-measurements/performance-measurement-type[.='user-equipment-average-throughput-downlink']/supported-snssai-subcounter-instances/slice-differentiator[.=%sd%]",
- "value":300,
- "unit":"kbit/s"
- },
- {
- "measurement-type-instance-reference":"/network-function/distributed-unit-functions[id='%duId%']/cell[id='%cellId%']/supported-measurements/performance-measurement-type[.='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances/slice-differentiator[.=%sd%]",
- "value":100,
- "unit":"kbit/s"
- }
- ]
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-{
- "type": "record",
- "name": "Osc_Defined_Input",
- "fields": [
- {
- "name": "event",
- "type": {
- "type": "record",
- "name": "Event_Type",
- "fields": [
- {
- "name": "commonEventHeader",
- "type": {
- "type": "record",
- "name": "Common_Event_Header_Type",
- "fields": [
- {
- "name": "domain",
- "type": "string"
- },
- {
- "name": "eventId",
- "type": "string"
- },
- {
- "name": "eventName",
- "type": "string"
- },
- {
- "name": "eventType",
- "type": "string"
- },
- {
- "name": "internalHeaderFields",
- "type": {
- "type": "record",
- "name": "Internal_Header_Fields_Type",
- "fields": [
- {
- "name": "intervalEndTime",
- "type": "string"
- },
- {
- "name": "intervalStartTime",
- "type": "string"
- }
- ]
- }
- },
- {
- "name": "lastEpochMicrosec",
- "type": "long"
- },
- {
- "name": "priority",
- "type": "string"
- },
- {
- "name": "reportingEntityId",
- "type": "string"
- },
- {
- "name": "reportingEntityName",
- "type": "string"
- },
- {
- "name": "sequence",
- "type": "int"
- },
- {
- "name": "sourceId",
- "type": "string"
- },
- {
- "name": "sourceName",
- "type": "string"
- },
- {
- "name": "startEpochMicrosec",
- "type": "long"
- },
- {
- "name": "version",
- "type": "string"
- },
- {
- "name": "vesEventListenerVersion",
- "type": "string"
- }
- ]
- }
- },
- {
- "name": "measurementFields",
- "type": {
- "type": "record",
- "name": "Measurement_Fields_Type",
- "fields": [
- {
- "name": "additionalFields",
- "type": {
- "type": "record",
- "name": "Additional_Fields_Type",
- "fields": []
- }
- },
- {
- "name": "additionalMeasurements",
- "type": {
- "type": "array",
- "items": {
- "name": "Additional_Measurements_Array",
- "type": "record",
- "fields": [
- {
- "name": "hashMap",
- "type": {
- "type": "record",
- "name": "Hash_Map_Type",
- "fields": [
- {
- "name": "cses",
- "type": "string"
- },
- {
- "name": "es",
- "type": "string"
- },
- {
- "name": "ses",
- "type": "string"
- },
- {
- "name": "unavailability",
- "type": "string"
- }
- ]
- }
- },
- {
- "name": "name",
- "type": "string"
- }
- ]
- }
- }
- },
- {
- "name": "additionalObjects",
- "type": {
- "type": "array",
- "items": {
- "name": "Additional_Objects_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "codecUsageArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Codec_Usage_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "concurrentSessions",
- "type": "int"
- },
- {
- "name": "configuredEntities",
- "type": "int"
- },
- {
- "name": "cpuUsageArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Cpu_Usage_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "diskUsageArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Disk_Usage_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "featureUsageArray",
- "type": {
- "type": "record",
- "name": "Feature_Usage_Array_Type",
- "fields": [
- {
- "name": "https_ColoN__SlasH__SlasH_www_DoT_itu_DoT_int_SlasH_rec_SlasH_T_DasH_REC_DasH_G_DoT_841",
- "type": "string"
- }
- ]
- }
- },
- {
- "name": "filesystemUsageArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Filesystem_Usage_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "hugePagesArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Huge_Pages_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "ipmi",
- "type": {
- "type": "record",
- "name": "ipmi_Type",
- "fields": []
- }
- },
- {
- "name": "latencyDistribution",
- "type": {
- "type": "array",
- "items": {
- "name": "Latency_Distribution_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "loadArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Load_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "machineCheckExceptionArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Machine_Check_Exception_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "meanRequestLatency",
- "type": "int"
- },
- {
- "name": "measurementFieldsVersion",
- "type": "string"
- },
- {
- "name": "measurementInterval",
- "type": "int"
- },
- {
- "name": "memoryUsageArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Memory_Usage_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "networkSliceArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Network_Slice_Array",
- "type": "record",
- "fields": [
- {
- "name": "DRB_DoT_UEThDl_DoT_SNSSAI",
- "type": "int"
- },
- {
- "name": "DRB_DoT_UEThUl_DoT_SNSSAI",
- "type": "int"
- },
- {
- "name": "networkSliceIdentifier",
- "type": "string"
- }
- ]
- }
- }
- },
- {
- "name": "nfcScalingMetric",
- "type": "int"
- },
- {
- "name": "nicPerformanceArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Nic_Performance_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "numberOfMediaPortsInUse",
- "type": "int"
- },
- {
- "name": "processStatsArray",
- "type": {
- "type": "array",
- "items": {
- "name": "Process_Stats_Array",
- "type": "record",
- "fields": []
- }
- }
- },
- {
- "name": "requestRate",
- "type": "int"
- }
- ]
- }
- }
- ]
- }
- }
- ]
-}
\ No newline at end of file
+++ /dev/null
-{
- "type": "record",
- "name": "Std_Defined_Input",
- "fields": [
- {
- "name": "event",
- "type": {
- "type": "record",
- "name": "Event_Type",
- "fields": [
- {
- "name": "commonEventHeader",
- "type": {
- "type": "record",
- "name": "Common_Event_Header_Type",
- "fields": [
- {
- "name": "domain",
- "type": "string"
- },
- {
- "name": "eventId",
- "type": "string"
- },
- {
- "name": "eventName",
- "type": "string"
- },
- {
- "name": "eventType",
- "type": "string"
- },
- {
- "name": "sequence",
- "type": "int"
- },
- {
- "name": "priority",
- "type": "string"
- },
- {
- "name": "reportingEntityId",
- "type": "string"
- },
- {
- "name": "reportingEntityName",
- "type": "string"
- },
- {
- "name": "sourceId",
- "type": "string"
- },
- {
- "name": "sourceName",
- "type": "string"
- },
- {
- "name": "startEpochMicrosec",
- "type": "string"
- },
- {
- "name": "lastEpochMicrosec",
- "type": "string"
- },
- {
- "name": "nfNamingCode",
- "type": "string"
- },
- {
- "name": "nfVendorName",
- "type": "string"
- },
- {
- "name": "stndDefinedNamespace",
- "type": "string"
- },
- {
- "name": "timeZoneOffset",
- "type": "string"
- },
- {
- "name": "version",
- "type": "string"
- },
- {
- "name": "vesEventListenerVersion",
- "type": "string"
- }
- ]
- }
- },
- {
- "name": "stndDefinedFields",
- "type": {
- "type": "record",
- "name": "Stnd_Defined_Fields_Type",
- "fields": [
- {
- "name": "stndDefinedFieldsVersion",
- "type": "string"
- },
- {
- "name": "schemaReference",
- "type": "string"
- },
- {
- "name": "data",
- "type": {
- "type": "record",
- "name": "Data_Type",
- "fields": [
- {
- "name": "id",
- "type": "string"
- },
- {
- "name": "start_DasH_time",
- "type": "string"
- },
- {
- "name": "administrative_DasH_state",
- "type": "string"
- },
- {
- "name": "operational_DasH_state",
- "type": "string"
- },
- {
- "name": "user_DasH_label",
- "type": "string"
- },
- {
- "name": "job_DasH_tag",
- "type": "string"
- },
- {
- "name": "granularity_DasH_period",
- "type": "int"
- },
- {
- "name": "measurements",
- "type": {
- "type": "array",
- "items": {
- "name": "Measurements_Array",
- "type": "record",
- "fields": [
- {
- "name": "measurement_DasH_type_DasH_instance_DasH_reference",
- "type": "string"
- },
- {
- "name": "value",
- "type": "int"
- },
- {
- "name": "unit",
- "type": "string"
- }
- ]
- }
- }
- }
- ]
- }
- }
- ]
- }
- }
- ]
- }
- }
- ]
-}
\ No newline at end of file
+++ /dev/null
-{
- "type": "record",
- "name": "Std_Defined_Output",
- "fields": [
- {
- "name": "radio_DasH_resource_DasH_management_DasH_policy_DasH_ratio",
- "type": {
- "type": "array",
- "items": {
- "name": "RRM_Policy_Ratio",
- "type": "record",
- "fields": [
- {
- "name": "id",
- "type": "string"
- },
- {
- "name": "administrative_DasH_state",
- "type": "string"
- },
- {
- "name": "user_DasH_label",
- "type": "string"
- },
- {
- "name": "radio_DasH_resource_DasH_management_DasH_policy_DasH_max_DasH_ratio",
- "type": "string"
- },
- {
- "name": "radio_DasH_resource_DasH_management_DasH_policy_DasH_min_DasH_ratio",
- "type": "string"
- },
- {
- "name": "radio_DasH_resource_DasH_management_DasH_policy_DasH_dedicated_DasH_ratio",
- "type": "string"
- },
- {
- "name": "resource_DasH_type",
- "type": "string"
- },
- {
- "name": "radio_DasH_resource_DasH_management_DasH_policy_DasH_members",
- "type": {
- "type": "array",
- "items": {
- "name": "RRM_Policy_Members",
- "type": "record",
- "fields": [
- {
- "name": "mobile_DasH_country_DasH_code",
- "type": "string"
- },
- {
- "name": "mobile_DasH_network_DasH_code",
- "type": "string"
- },
- {
- "name": "slice_DasH_differentiator",
- "type": "int"
- },
- {
- "name": "slice_DasH_service_DasH_type",
- "type": "int"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- ]
-}
+++ /dev/null
-#==================================================================================
-# Copyright (C) 2021: Nordix Foundation
-#
-# 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.
-#
-#==================================================================================
-##
-## Build
-##
-FROM nexus3.o-ran-sc.org:10001/golang:1.17-bullseye AS build
-
-WORKDIR /app
-
-COPY go.mod ./
-COPY go.sum ./
-RUN go mod download
-
-COPY . ./
-
-RUN go build -o /oduclosedloop-sliceassurance
-
-##
-## Deploy
-##
-FROM gcr.io/distroless/base-debian10
-
-WORKDIR /
-
-## Copy from "build" stage
-COPY --from=build /oduclosedloop-sliceassurance .
-
-USER nonroot:nonroot
-
-ENTRYPOINT ["/oduclosedloop-sliceassurance"]
\ No newline at end of file
+++ /dev/null
-# Copyright (C) 2022 Nordix Foundation. All rights reserved.
-# ========================================================================
-# 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.
-# ============LICENSE_END=================================================
-#
-
-##
-## Build
-##
-FROM golang:1.17.1-bullseye AS build
-
-WORKDIR /app
-
-COPY . ./
-
-RUN go build -o /sdnr-mr-sim ./stub/
-
-##
-## Deploy
-##
-FROM gcr.io/distroless/base-debian10
-
-WORKDIR /
-
-## Copy from "build" stage
-COPY --from=build /sdnr-mr-sim .
-COPY --from=build /app/stub/test-data.csv .
-
-USER nonroot:nonroot
-
-ENTRYPOINT ["/sdnr-mr-sim"]
+++ /dev/null
-# O-RAN-SC Non-RealTime RIC O-DU Closed Loop Usecase Slice Assurance
-
-## Configuration
-
-The consumer takes a number of environment variables, described below, as configuration.
-
->- MR_HOST **Required**. The host for Dmaap Message Router. Example: `http://mrproducer`
->- MR_PORT **Required**. The port for the Dmaap Message Router. Example: `8095`
->- SDNR_ADDR Optional. The address for SDNR. Defaults to `http://localhost:3904`.
->- SDNR_USER Optional. The user for the SDNR. Defaults to `admin`.
->- SDNR_PASSWORD Optional. The password for the SDNR user. Defaults to `Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U`.
->- LOG_LEVEL Optional. The log level, which can be `Error`, `Warn`, `Info` or `Debug`. Defaults to `Info`.
->- POLLTIME Optional. Waiting time between one pull request to Dmaap and another. Defaults to 10 sec
-
-## Functionality
-
-There is a status call provided in a REST API on port 40936.
->- /status OK
-
-## Development
-
-To make it easy to test during development of the consumer, there is a stub provided in the `stub` folder.
-
-This stub is used to simulate both received VES messages from Dmaap MR with information about performance measurements for the slices in a determinated DU and also SDNR, that sends information about Radio Resource Management Policy Ratio and allows to modify value for RRM Policy Dedicated Ratio from default to higher value.
-
-By default, SDNR stub listens to the port `3904`, but his can be overridden by passing a `--sdnr-port [PORT]` flag when starting the stub. For Dmaap MR stub default port is `3905` but it can be overriden by passing a `--dmaap-port [PORT]` flag when starting the stub.
-
-To build and start the stub, do the following:
-
->1. cd stub
->2. go build
->3. ./stub [--sdnr-port <portNo>] [--dmaap-port <portNo>]
-
-## License
-
-Copyright (C) 2021 Nordix Foundation.
-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.
-
-For more information about license please see the [LICENSE](LICENSE.txt) file for details.
\ No newline at end of file
+++ /dev/null
-# The Jenkins job requires a tag to build the Docker image.
-# By default this file is in the docker build directory,
-# but the location can configured in the JJB template.
----
-tag: 1.1.0
+++ /dev/null
-# Copyright (C) 2022 Nordix Foundation. All rights reserved.
-# ========================================================================
-# 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.
-# ============LICENSE_END=================================================
-#
-version: '3.5'
-
-networks:
- default:
- driver: bridge
- name: nonrtric-docker-net
-
-services:
- sdnr-mr-sim:
- build:
- context: .
- dockerfile: Dockerfile-simulator
- container_name: sdnr-mr-sim
- networks:
- default:
- aliases:
- - sdnr-mr-sim
- ports:
- - 3904:3904
- - 3905:3905
-
- odu-app:
- build:
- context: .
- dockerfile: Dockerfile
- container_name: odu-app
- networks:
- default:
- aliases:
- - odu-app
- ports:
- - 8086:8086
- - 40936:40936
- environment:
- - MR_HOST=http://sdnr-mr-sim
- - MR_PORT=3905
- - SDNR_ADDR=http://sdnr-mr-sim:3904
\ No newline at end of file
+++ /dev/null
-module oransc.org/usecase/oduclosedloop
-
-go 1.17
-
-require github.com/sirupsen/logrus v1.8.1
-
-require (
- github.com/gorilla/mux v1.8.0
- github.com/stretchr/testify v1.3.0
-)
-
-require (
- github.com/davecgh/go-spew v1.1.1 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
- golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
-)
+++ /dev/null
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
-golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+++ /dev/null
-# Patterns to ignore when building packages.
-# This supports shell glob matching, relative path matching, and
-# negation (prefixed with !). Only one pattern per line.
-.DS_Store
-# Common VCS dirs
-.git/
-.gitignore
-.bzr/
-.bzrignore
-.hg/
-.hgignore
-.svn/
-# Common backup files
-*.swp
-*.bak
-*.tmp
-*.orig
-*~
-# Various IDEs
-.project
-.idea/
-*.tmproj
-.vscode/
+++ /dev/null
-# Copyright (C) 2021 Nordix Foundation. All rights reserved.
-# ========================================================================
-# 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.
-# ============LICENSE_END=================================================
-
-apiVersion: v1
-name: odu-app
-description: A Helm chart for Kubernetes
-
-# A chart can be either an 'application' or a 'library' chart.
-#
-# Application charts are a collection of templates that can be packaged into versioned archives
-# to be deployed.
-#
-# Library charts provide useful utilities or functions for the chart developer. They're included as
-# a dependency of application charts to inject those utilities and functions into the rendering
-# pipeline. Library charts do not define any templates and therefore cannot be deployed.
-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.1.0
-
-# 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: "1.16.0"
+++ /dev/null
-{{/*
-# Copyright (C) 2021 Nordix Foundation. All rights reserved.
-# ========================================================================
-# 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.
-# ============LICENSE_END=================================================
-*/}}
-
-{{/*
-Expand the name of the chart.
-*/}}
-{{- define "odu-app.name" -}}
-{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
-{{- end }}
-
-{{/*
-Create a default fully qualified app name.
-We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
-If release name contains chart name it will be used as a full name.
-*/}}
-{{- define "odu-app.fullname" -}}
-{{- if .Values.fullnameOverride }}
-{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
-{{- else }}
-{{- $name := default .Chart.Name .Values.nameOverride }}
-{{- if contains $name .Release.Name }}
-{{- .Release.Name | trunc 63 | trimSuffix "-" }}
-{{- else }}
-{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
-{{- end }}
-{{- end }}
-{{- end }}
-
-{{/*
-Create chart name and version as used by the chart label.
-*/}}
-{{- define "odu-app.chart" -}}
-{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
-{{- end }}
-
-{{/*
-Common labels
-*/}}
-{{- define "odu-app.labels" -}}
-helm.sh/chart: {{ include "odu-app.chart" . }}
-{{ include "odu-app.selectorLabels" . }}
-{{- if .Chart.AppVersion }}
-app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
-{{- end }}
-app.kubernetes.io/managed-by: {{ .Release.Service }}
-{{- end }}
-
-{{/*
-Selector labels
-*/}}
-{{- define "odu-app.selectorLabels" -}}
-app.kubernetes.io/name: {{ include "odu-app.name" . }}
-app.kubernetes.io/instance: {{ .Release.Name }}
-{{- end }}
-
-{{/*
-Create the name of the service account to use
-*/}}
-{{- define "odu-app.serviceAccountName" -}}
-{{- if .Values.serviceAccount.create }}
-{{- default (include "odu-app.fullname" .) .Values.serviceAccount.name }}
-{{- else }}
-{{- default "default" .Values.serviceAccount.name }}
-{{- end }}
-{{- end }}
+++ /dev/null
-# Copyright (C) 2021 Nordix Foundation. All rights reserved.
-# ========================================================================
-# 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.
-# ============LICENSE_END=================================================
-
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: {{ include "odu-app.fullname" . }}
- labels:
- {{- include "odu-app.labels" . | nindent 4 }}
-spec:
- replicas: {{ .Values.replicaCount }}
- selector:
- matchLabels:
- {{- include "odu-app.selectorLabels" . | nindent 6 }}
- template:
- metadata:
- {{- with .Values.podAnnotations }}
- annotations:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- labels:
- {{- include "odu-app.selectorLabels" . | nindent 8 }}
- spec:
- {{- with .Values.imagePullSecrets }}
- imagePullSecrets:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- securityContext:
- {{- toYaml .Values.podSecurityContext | nindent 8 }}
- containers:
- - name: {{ .Chart.Name }}
- securityContext:
- {{- toYaml .Values.securityContext | nindent 12 }}
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
- imagePullPolicy: {{ .Values.image.pullPolicy }}
- env:
- - name: MR_HOST
- value: "{{ .Values.messagerouter.host }}"
- - name: MR_PORT
- value: "{{ .Values.messagerouter.port }}"
- - name: SDNR_ADDRESS
- value: "{{ .Values.sdnr.address }}"
- ports:
- - name: http
- containerPort: 80
- protocol: TCP
- resources:
- {{- toYaml .Values.resources | nindent 12 }}
- {{- with .Values.nodeSelector }}
- nodeSelector:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- {{- with .Values.affinity }}
- affinity:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- {{- with .Values.tolerations }}
- tolerations:
- {{- toYaml . | nindent 8 }}
- {{- end }}
+++ /dev/null
-# Copyright (C) 2021 Nordix Foundation. All rights reserved.
-# ========================================================================
-# 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.
-# ============LICENSE_END=================================================
-
-apiVersion: v1
-kind: Service
-metadata:
- name: {{ include "odu-app.fullname" . }}
- labels:
- {{- include "odu-app.labels" . | nindent 4 }}
-spec:
- type: {{ .Values.service.type }}
- ports:
- - port: {{ .Values.service.port }}
- targetPort: http
- protocol: TCP
- name: http
- selector:
- {{- include "odu-app.selectorLabels" . | nindent 4 }}
+++ /dev/null
-# Copyright (C) 2021 Nordix Foundation. All rights reserved.
-# ========================================================================
-# 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.
-# ============LICENSE_END=================================================
-
-# Default values for odu-app.
-# This is a YAML-formatted file.
-# Declare variables to be passed into your templates.
-
-replicaCount: 1
-
-image:
- repository: odu-app
- pullPolicy: IfNotPresent
- # Overrides the image tag whose default is the chart appVersion.
- tag: "latest"
-
-messagerouter:
- host: http://dmaap-mr
- port: 3904
-
-sdnr:
- address: http://sdnr-simulator:9990
-
-imagePullSecrets: []
-nameOverride: ""
-fullnameOverride: ""
-
-podAnnotations: {}
-
-podSecurityContext: {}
- # fsGroup: 2000
-
-securityContext: {}
- # capabilities:
- # drop:
- # - ALL
- # readOnlyRootFilesystem: true
- # runAsNonRoot: true
- # runAsUser: 1000
-
-service:
- type: ClusterIP
- port: 80
-
-resources: {}
- # We usually recommend not to specify default resources and to leave this as a conscious
- # choice for the user. This also increases chances charts run on environments with little
- # resources, such as Minikube. If you do want to specify resources, uncomment the following
- # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
- # limits:
- # cpu: 100m
- # memory: 128Mi
- # requests:
- # cpu: 100m
- # memory: 128Mi
-
-nodeSelector: {}
-
-tolerations: []
-
-affinity: {}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package config
-
-import (
- "fmt"
- "os"
- "strconv"
-
- log "github.com/sirupsen/logrus"
-)
-
-type Config struct {
- MRHost string
- MRPort string
- SDNRAddress string
- SDNRUser string
- SDNPassword string
- Polltime int
- LogLevel log.Level
-}
-
-func New() *Config {
- return &Config{
- MRHost: getEnv("MR_HOST", ""),
- MRPort: getEnv("MR_PORT", ""),
- SDNRAddress: getEnv("SDNR_ADDR", "http://localhost:3904"),
- SDNRUser: getEnv("SDNR_USER", "admin"),
- SDNPassword: getEnv("SDNR_PASSWORD", "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"),
- Polltime: getEnvAsInt("Polltime", 30),
- LogLevel: getLogLevel(),
- }
-}
-
-func (c Config) String() string {
- return fmt.Sprintf("[MRHost: %v, MRPort: %v, SDNRAddress: %v, SDNRUser: %v, SDNRPassword: %v, PollTime: %v, LogLevel: %v]", c.MRHost, c.MRPort, c.SDNRAddress, c.SDNRUser, c.SDNPassword, c.Polltime, c.LogLevel)
-}
-
-func getEnv(key string, defaultVal string) string {
- if value, exists := os.LookupEnv(key); exists {
- return value
- }
-
- return defaultVal
-}
-
-func getEnvAsInt(name string, defaultVal int) int {
- valueStr := getEnv(name, "")
- if value, err := strconv.Atoi(valueStr); err == nil {
- return value
- } else if valueStr != "" {
- log.Warnf("Invalid int value: %v for variable: %v. Default value: %v will be used", valueStr, name, defaultVal)
- }
-
- return defaultVal
-}
-
-func getLogLevel() log.Level {
- logLevelStr := getEnv("LOG_LEVEL", "Info")
- if loglevel, err := log.ParseLevel(logLevelStr); err == nil {
- return loglevel
- } else {
- log.Warnf("Invalid log level: %v. Log level will be Info!", logLevelStr)
- return log.InfoLevel
- }
-
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package config
-
-import (
- "bytes"
- "os"
- "testing"
-
- log "github.com/sirupsen/logrus"
- "github.com/stretchr/testify/require"
-)
-
-func TestNewEnvVarsSetConfigContainSetValues(t *testing.T) {
- assertions := require.New(t)
- os.Setenv("MR_HOST", "consumerHost")
- os.Setenv("MR_PORT", "8095")
- os.Setenv("SDNR_ADDR", "http://localhost:3904")
- os.Setenv("SDNR_USER", "admin")
- os.Setenv("SDNR_PASSWORD", "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U")
- os.Setenv("Polltime", "30")
- os.Setenv("LOG_LEVEL", "Debug")
- t.Cleanup(func() {
- os.Clearenv()
- })
- wantConfig := Config{
- MRHost: "consumerHost",
- MRPort: "8095",
- SDNRAddress: "http://localhost:3904",
- SDNRUser: "admin",
- SDNPassword: "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U",
- Polltime: 30,
- LogLevel: log.DebugLevel,
- }
-
- got := New()
- assertions.Equal(&wantConfig, got)
-}
-
-func TestNewFaultyIntValueSetConfigContainDefaultValueAndWarnInLog(t *testing.T) {
- assertions := require.New(t)
- var buf bytes.Buffer
- log.SetOutput(&buf)
-
- os.Setenv("Polltime", "wrong")
- t.Cleanup(func() {
- log.SetOutput(os.Stderr)
- os.Clearenv()
- })
- wantConfig := Config{
- MRHost: "",
- MRPort: "",
- SDNRAddress: "http://localhost:3904",
- SDNRUser: "admin",
- SDNPassword: "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U",
- Polltime: 30,
- LogLevel: log.InfoLevel,
- }
-
- got := New()
- assertions.Equal(&wantConfig, got)
-
- logString := buf.String()
- assertions.Contains(logString, "Invalid int value: wrong for variable: Polltime. Default value: 30 will be used")
-}
-
-func TestNewEnvFaultyLogLevelConfigContainDefaultValues(t *testing.T) {
- assertions := require.New(t)
- var buf bytes.Buffer
- log.SetOutput(&buf)
-
- os.Setenv("LOG_LEVEL", "wrong")
- t.Cleanup(func() {
- log.SetOutput(os.Stderr)
- os.Clearenv()
- })
- wantConfig := Config{
- MRHost: "",
- MRPort: "",
- SDNRAddress: "http://localhost:3904",
- SDNRUser: "admin",
- SDNPassword: "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U",
- Polltime: 30,
- LogLevel: log.InfoLevel,
- }
- got := New()
- assertions.Equal(&wantConfig, got)
- logString := buf.String()
- assertions.Contains(logString, "Invalid log level: wrong. Log level will be Info!")
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package restclient
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "net/http/httputil"
-
- log "github.com/sirupsen/logrus"
-)
-
-type RequestError struct {
- StatusCode int
- Body []byte
-}
-
-func (e RequestError) Error() string {
- return fmt.Sprintf("error response with status: %v and body: %v", e.StatusCode, string(e.Body))
-}
-
-type Client struct {
- httpClient *http.Client
- verbose bool
-}
-
-func New(httpClient *http.Client, verbose bool) *Client {
- return &Client{
- httpClient: httpClient,
- verbose: verbose,
- }
-}
-
-func (c *Client) Get(path string, v interface{}, userInfo ...string) error {
- var req *http.Request
- var err error
-
- if len(userInfo) > 1 {
- req, err = c.newRequest(http.MethodGet, path, nil, userInfo[0], userInfo[1])
- } else {
- req, err = c.newRequest(http.MethodGet, path, nil)
- }
-
- if err != nil {
- return fmt.Errorf("failed to create GET request: %w", err)
- }
-
- if err := c.doRequest(req, v); err != nil {
- return err
- }
-
- return nil
-}
-
-func (c *Client) Post(path string, payload interface{}, v interface{}, userInfo ...string) error {
- var req *http.Request
- var err error
-
- if len(userInfo) > 1 {
- req, err = c.newRequest(http.MethodPost, path, payload, userInfo[0], userInfo[1])
- } else {
- req, err = c.newRequest(http.MethodPost, path, payload)
- }
-
- if err != nil {
- return fmt.Errorf("failed to create POST request: %w", err)
- }
-
- if err := c.doRequest(req, v); err != nil {
- return err
- }
-
- return nil
-}
-
-func (c *Client) Put(path string, payload interface{}, v interface{}, userName string, password string) error {
- req, err := c.newRequest(http.MethodPut, path, payload, userName, password)
- if err != nil {
- return fmt.Errorf("failed to create PUT request: %w", err)
- }
-
- if err := c.doRequest(req, v); err != nil {
- return err
- }
-
- return nil
-}
-
-func (c *Client) newRequest(method, path string, payload interface{}, userInfo ...string) (*http.Request, error) {
- var reqBody io.Reader
-
- if payload != nil {
- bodyBytes, err := json.Marshal(payload)
- if err != nil {
- return nil, fmt.Errorf("failed to marshal request body: %w", err)
- }
- reqBody = bytes.NewReader(bodyBytes)
- }
-
- req, err := http.NewRequest(method, path, reqBody)
-
- if err != nil {
- return nil, fmt.Errorf("failed to create HTTP request: %w", err)
- }
-
- if len(userInfo) > 0 {
- req.SetBasicAuth(userInfo[0], userInfo[1])
- }
-
- if reqBody != nil {
- req.Header.Set("Content-Type", "application/json")
- }
-
- if c.verbose {
- if reqDump, error := httputil.DumpRequest(req, true); error != nil {
- fmt.Println(err)
- } else {
- fmt.Println(string(reqDump))
- }
- }
-
- return req, nil
-}
-
-func (c *Client) doRequest(r *http.Request, v interface{}) error {
- resp, err := c.do(r)
- if err != nil {
- return err
- }
-
- if resp == nil {
- return nil
- }
- defer resp.Body.Close()
-
- if v == nil {
- return nil
- }
-
- dec := json.NewDecoder(resp.Body)
- if err := dec.Decode(&v); err != nil {
- return fmt.Errorf("could not parse response body: %w [%s:%s]", err, r.Method, r.URL.String())
- }
- log.Debugf("Http Client Response: %v\n", v)
- return nil
-}
-
-func (c *Client) do(r *http.Request) (*http.Response, error) {
- resp, err := c.httpClient.Do(r)
- if err != nil {
- return nil, fmt.Errorf("failed to make request [%s:%s]: %w", r.Method, r.URL.String(), err)
- }
-
- if c.verbose {
- if responseDump, error := httputil.DumpResponse(resp, true); error != nil {
- fmt.Println(err)
- } else {
- fmt.Println(string(responseDump))
- }
- }
-
- if resp.StatusCode >= http.StatusOK && resp.StatusCode <= 299 {
- return resp, nil
- }
-
- defer resp.Body.Close()
- responseData, _ := io.ReadAll(resp.Body)
-
- putError := RequestError{
- StatusCode: resp.StatusCode,
- Body: responseData,
- }
-
- return resp, putError
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package restclient
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "net/http/httptest"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func TestNewRequest(t *testing.T) {
- assertions := require.New(t)
-
- bodyBytes, _ := json.Marshal("body")
- succesfullReq, _ := http.NewRequest(http.MethodGet, "url", bytes.NewReader(bodyBytes))
-
- type args struct {
- method string
- path string
- payload interface{}
- }
- tests := []struct {
- name string
- args args
- want *http.Request
- wantErr error
- }{
- {
- name: "succesfull newRequest",
- args: args{
- method: http.MethodGet,
- path: "url",
- payload: "body",
- },
- want: succesfullReq,
- wantErr: nil,
- },
- {
- name: "request failed json marshal",
- args: args{
- method: http.MethodGet,
- path: "url",
- payload: map[string]interface{}{
- "foo": make(chan int),
- },
- },
- want: nil,
- wantErr: fmt.Errorf("failed to marshal request body: json: unsupported type: chan int"),
- },
- {
- name: "request failed calling newRequest",
- args: args{
- method: "*?",
- path: "url",
- payload: "body",
- },
- want: nil,
- wantErr: fmt.Errorf("failed to create HTTP request: net/http: invalid method \"*?\""),
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- client := New(&http.Client{}, false)
-
- req, err := client.newRequest(tt.args.method, tt.args.path, tt.args.payload)
- if tt.wantErr != nil {
- assertions.Equal(tt.want, req)
- assertions.EqualError(tt.wantErr, err.Error())
- } else {
- assertions.Equal("url", req.URL.Path)
- assertions.Equal("application/json", req.Header.Get("Content-Type"))
- assertions.Empty(req.Header.Get("Authorization"))
- assertions.Nil(err)
- }
-
- })
- }
-}
-
-func TestGet(t *testing.T) {
- assertions := require.New(t)
- type args struct {
- header string
- respCode int
- resp interface{}
- }
- tests := []struct {
- name string
- args args
- wantErr string
- }{
- {
- name: "successful GET request",
- args: args{
- header: "application/json",
- respCode: http.StatusOK,
- resp: "Success!",
- },
- wantErr: "",
- },
- {
- name: "error GET request",
- args: args{
- header: "application/json",
- respCode: http.StatusBadRequest,
- resp: nil,
- },
- wantErr: "error response with status: 400 and body:",
- },
- }
-
- for _, tt := range tests {
-
- t.Run(tt.name, func(t *testing.T) {
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- assertions.Equal(http.MethodGet, r.Method)
- response, _ := json.Marshal(tt.args.resp)
- w.Header().Set("Content-Type", tt.args.header)
- w.WriteHeader(tt.args.respCode)
- w.Write(response)
- }))
- defer srv.Close()
-
- client := New(&http.Client{}, false)
- var res interface{}
- err := client.Get(srv.URL, &res)
-
- if err != nil {
- assertions.Contains(err.Error(), tt.wantErr)
- }
- assertions.Equal(tt.args.resp, res)
- })
- }
-}
-
-func TestPost(t *testing.T) {
- header := "application/json"
- respCode := http.StatusOK
- resp := "Success!"
-
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-
- assert.Equal(t, http.MethodPost, r.Method)
- assert.Contains(t, r.Header.Get("Content-Type"), "application/json")
-
- var reqBody string
- decoder := json.NewDecoder(r.Body)
- decoder.Decode(&reqBody)
- assert.Equal(t, reqBody, `json:"example"`)
-
- response, _ := json.Marshal(resp)
- w.Header().Set("Content-Type", header)
- w.WriteHeader(respCode)
- w.Write(response)
- }))
- defer srv.Close()
-
- client := New(&http.Client{}, false)
- payload := `json:"example"`
- err := client.Post(srv.URL, payload, nil, "admin", "pass")
-
- if err != nil {
- assert.Equal(t, "", err.Error())
- }
-}
-
-func TestPut(t *testing.T) {
- header := "application/json"
- respCode := http.StatusOK
- resp := "Success!"
-
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-
- assert.Equal(t, http.MethodPut, r.Method)
- assert.Contains(t, r.Header.Get("Content-Type"), "application/json")
-
- var reqBody string
- decoder := json.NewDecoder(r.Body)
- decoder.Decode(&reqBody)
- assert.Equal(t, reqBody, `json:"example"`)
-
- response, _ := json.Marshal(resp)
- w.Header().Set("Content-Type", header)
- w.WriteHeader(respCode)
- w.Write(response)
- }))
- defer srv.Close()
-
- client := New(&http.Client{}, false)
- payload := `json:"example"`
- err := client.Put(srv.URL, payload, nil, "admin", "pass")
-
- if err != nil {
- assert.Equal(t, "", err.Error())
- }
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package sliceassurance
-
-import (
- "encoding/json"
- "fmt"
- "net/http"
- "time"
-
- "oransc.org/usecase/oduclosedloop/internal/config"
- "oransc.org/usecase/oduclosedloop/internal/restclient"
- "oransc.org/usecase/oduclosedloop/internal/structures"
- "oransc.org/usecase/oduclosedloop/messages"
-
- log "github.com/sirupsen/logrus"
-)
-
-const (
- THRESHOLD_TPUT = 7000
- DEFAULT_DEDICATED_RATIO = 15
- NEW_DEDICATED_RATIO = 25
- NODE_ID = "O-DU-1122"
-)
-
-type App struct {
- client *restclient.Client
- metricsPolicies *structures.SliceAssuranceMeas
-}
-
-var dmaapMRUrl string
-var sDNRUrl string
-var sDNRUsername string
-var sDNRPassword string
-
-func (a *App) Initialize(config *config.Config) {
- dmaapMRUrl = config.MRHost + ":" + config.MRPort
- sDNRUrl = config.SDNRAddress
- sDNRUsername = config.SDNRUser
- sDNRPassword = config.SDNPassword
-
- a.client = restclient.New(&http.Client{}, false)
- a.metricsPolicies = structures.NewSliceAssuranceMeas()
-}
-
-func (a *App) Run(topic string, pollTime int) {
- for {
- a.getMessagesFromDmaap(dmaapMRUrl + topic)
-
- for key := range a.metricsPolicies.Metrics {
- a.getRRMInformation(key.Duid)
- }
- a.updateDedicatedRatio()
-
- time.Sleep(time.Second * time.Duration(pollTime))
- }
-}
-
-func (a *App) getMessagesFromDmaap(path string) {
- log.Infof("Polling new messages from DmaapMR %v", path)
-
- //Added to work with onap-Dmaap
- var messageStrings []string
- if error := a.client.Get(path, &messageStrings); error != nil {
- log.Warn("Send of Get messages from DmaapMR failed! ", error)
- }
-
- for _, msgString := range messageStrings {
- var message messages.StdDefinedMessage
- if err := json.Unmarshal([]byte(msgString), &message); err == nil {
- for _, meas := range message.GetMeasurements() {
- log.Infof("Create sliceMetric and check if metric exist and update existing one or create new one measurement: %+v\n", meas)
- //Create sliceMetric and check if metric exist and update existing one or create new one
- if _, err := a.metricsPolicies.AddOrUpdateMetric(meas); err != nil {
- log.Error("Metric could not be added ", err)
- }
- }
- } else {
- log.Warn(err)
- }
- }
-}
-
-func (a *App) getRRMInformation(duid string) {
- var duRRMPolicyRatio messages.ORanDuRestConf
-
- log.Infof("Get RRM Information from SDNR url: %v", sDNRUrl)
- if error := a.client.Get(getUrlForDistributedUnitFunctions(sDNRUrl, duid), &duRRMPolicyRatio, sDNRUsername, sDNRPassword); error == nil {
- prettyPrint(duRRMPolicyRatio.DistributedUnitFunction)
- } else {
- log.Warn("Send of Get RRM Information failed! ", error)
- }
-
- for _, odu := range duRRMPolicyRatio.DistributedUnitFunction {
- for _, policy := range odu.RRMPolicyRatio {
- log.Infof("Add or Update policy: %+v from DU id: %v", policy.Id, duid)
- a.metricsPolicies.AddNewPolicy(duid, policy)
- }
- }
-}
-
-func (a *App) updateDedicatedRatio() {
- for _, metric := range a.metricsPolicies.Metrics {
- policy, check := a.metricsPolicies.Policies[metric.RRMPolicyRatioId]
- //TODO What happened if dedicated ratio is already higher that default and threshold is exceed?
- if check && policy.PolicyDedicatedRatio <= DEFAULT_DEDICATED_RATIO {
- log.Infof("Send Request to update DedicatedRatio for DU id: %v Policy id: %v", metric.DUId, policy.PolicyRatioId)
- path := getUrlUpdatePolicyDedicatedRatio(sDNRUrl, metric.DUId, policy.PolicyRatioId)
- updatePolicyMessage := policy.GetUpdateDedicatedRatioMessage(metric.SliceDiff, metric.SliceServiceType, NEW_DEDICATED_RATIO)
- prettyPrint(updatePolicyMessage)
- if error := a.client.Put(path, updatePolicyMessage, nil, sDNRUsername, sDNRPassword); error == nil {
- log.Infof("Policy Dedicated Ratio for PolicyId: %v was updated to %v", policy.PolicyRatioId, NEW_DEDICATED_RATIO)
- } else {
- log.Warn("Send of Put Request to update DedicatedRatio failed! ", error)
- }
- }
- }
-}
-
-func getUrlForDistributedUnitFunctions(host string, duid string) string {
- return host + "/rests/data/network-topology:network-topology/topology=topology-netconf/node=" + NODE_ID + "/yang-ext:mount/o-ran-sc-du-hello-world:network-function/distributed-unit-functions=" + duid
-}
-
-func getUrlUpdatePolicyDedicatedRatio(host string, duid string, policyid string) string {
- return host + "/rests/data/network-topology:network-topology/topology=topology-netconf/node=" + NODE_ID + "/yang-ext:mount/o-ran-sc-du-hello-world:network-function/distributed-unit-functions=" + duid + "/radio-resource-management-policy-ratio=" + policyid
-}
-
-func prettyPrint(jsonStruct interface{}) {
- b, err := json.MarshalIndent(jsonStruct, "", " ")
- if err != nil {
- fmt.Println("error:", err)
- }
- fmt.Print(string(b))
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package structures
-
-import "oransc.org/usecase/oduclosedloop/messages"
-
-type SliceMetric struct {
- DUId string
- CellId string
- SliceDiff int
- SliceServiceType int
- RRMPolicyRatioId string
- PM map[string]int
-}
-
-func NewSliceMetric(duid string, cellid string, sd int, sst int) *SliceMetric {
- sm := SliceMetric{
- DUId: duid,
- CellId: cellid,
- SliceDiff: sd,
- SliceServiceType: sst,
- }
- sm.PM = make(map[string]int)
- return &sm
-}
-
-type PolicyRatio struct {
- PolicyRatioId string
- PolicyMaxRatio int
- PolicyMinRatio int
- PolicyDedicatedRatio int
-}
-
-func NewPolicyRatio(id string, max_ratio int, min_ratio int, ded_ratio int) *PolicyRatio {
- pr := PolicyRatio{
- PolicyRatioId: id,
- PolicyMaxRatio: max_ratio,
- PolicyMinRatio: min_ratio,
- PolicyDedicatedRatio: ded_ratio,
- }
- return &pr
-}
-
-func (pr *PolicyRatio) GetUpdateDedicatedRatioMessage(sd int, sst int, dedicatedRatio int) interface{} {
- message := messages.RRMPolicyRatio{
- Id: pr.PolicyRatioId,
- AdmState: "unlocked",
- UserLabel: pr.PolicyRatioId,
- RRMPolicyMaxRatio: pr.PolicyMaxRatio,
- RRMPolicyMinRatio: pr.PolicyMinRatio,
- RRMPolicyDedicatedRatio: dedicatedRatio,
- ResourceType: "prb",
- RRMPolicyMembers: []messages.RRMPolicyMember{
- {
- MobileCountryCode: "046",
- MobileNetworkCode: "651",
- SliceDifferentiator: sd,
- SliceServiceType: sst,
- },
- },
- }
- rrmPolicies := []messages.RRMPolicyRatio{message}
-
- return struct {
- RRMPolicies []messages.RRMPolicyRatio `json:"radio-resource-management-policy-ratio"`
- }{
- RRMPolicies: rrmPolicies,
- }
-
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package structures
-
-import (
- "fmt"
- "regexp"
- "strconv"
-
- log "github.com/sirupsen/logrus"
- "oransc.org/usecase/oduclosedloop/messages"
-)
-
-type MapKey struct {
- Duid string
- sd int
- sst int
-}
-
-type SliceAssuranceMeas struct {
- Metrics map[MapKey]*SliceMetric
- Policies map[string]*PolicyRatio
-}
-
-func NewSliceAssuranceMeas() *SliceAssuranceMeas {
- s := SliceAssuranceMeas{}
- s.Metrics = make(map[MapKey]*SliceMetric)
- s.Policies = make(map[string]*PolicyRatio)
- return &s
-}
-
-func (sa *SliceAssuranceMeas) AddNewPolicy(duid string, rrmPolicyRatio messages.RRMPolicyRatio) {
- for _, policyMember := range rrmPolicyRatio.RRMPolicyMembers {
- metric := sa.GetSliceMetric(duid, policyMember.SliceDifferentiator, policyMember.SliceServiceType)
- if metric != nil {
- pr := NewPolicyRatio(rrmPolicyRatio.Id, rrmPolicyRatio.RRMPolicyMaxRatio, rrmPolicyRatio.RRMPolicyMinRatio, rrmPolicyRatio.RRMPolicyDedicatedRatio)
- _, check := sa.Policies[pr.PolicyRatioId]
- if !check {
- log.Infof(" new policy has been added %+v", *pr)
- }
- sa.Policies[pr.PolicyRatioId] = pr
- metric.RRMPolicyRatioId = rrmPolicyRatio.Id
-
- }
- }
-}
-
-func (sa *SliceAssuranceMeas) GetSliceMetric(duid string, sd int, sst int) *SliceMetric {
- key := MapKey{duid, sd, sst}
- value, check := sa.Metrics[key]
-
- if check {
- return value
- }
-
- return nil
-}
-
-func (sa *SliceAssuranceMeas) AddOrUpdateMetric(meas messages.Measurement) (string, error) {
-
- var duid string
- var sd, sst int
-
- regex := *regexp.MustCompile(`\/(.*)network-function\/distributed-unit-functions\[id=\'(.*)\'\]\/cell\[id=\'(.*)\'\]\/supported-measurements\[performance-measurement-type=\'(.*)\'\]\/supported-snssai-subcounter-instances\[slice-differentiator=\'(\d+)\'\]\[slice-service-type=\'(\d+)\'\]`)
- res := regex.FindAllStringSubmatch(meas.MeasurementTypeInstanceReference, -1)
-
- if res != nil && len(res[0]) == 7 {
- duid = res[0][2]
- sd = toInt(res[0][5])
- sst = toInt(res[0][6])
-
- key := MapKey{duid, sd, sst}
- value, check := sa.Metrics[key]
-
- if check {
- sa.updateMetric(key, value, res[0][4], meas.Value)
- } else {
- // Only add new one if value exceeds threshold
- sa.addMetric(res, meas.Value)
- }
- } else {
- return duid, fmt.Errorf(" wrong format for MeasurementTypeInstanceReference")
- }
- return duid, nil
-}
-
-func (sa *SliceAssuranceMeas) addMetric(res [][]string, metricValue int) {
- if metricValue > 700 {
- metric := NewSliceMetric(res[0][2], res[0][3], toInt(res[0][5]), toInt(res[0][6]))
- metric.PM[res[0][3]] = metricValue
- key := MapKey{res[0][2], toInt(res[0][5]), toInt(res[0][6])}
- sa.Metrics[key] = metric
- log.Infof(" new metric has been added %+v", *metric)
- }
-}
-
-func (sa *SliceAssuranceMeas) updateMetric(key MapKey, value *SliceMetric, metricName string, metricValue int) {
- if metricValue < 700 {
- delete(sa.Metrics, key)
- log.Infof(" metric with key %+v has been deleted", key)
- } else {
- value.PM[metricName] = metricValue
- log.Infof(" metric value has been updated, new value: %v", metricValue)
- }
-}
-
-func toInt(num string) int {
- res, err := strconv.Atoi(num)
- if err != nil {
- return -1
- }
- return res
-}
-
-func (sa *SliceAssuranceMeas) PrintStructures() {
- fmt.Printf("SliceAssurance Metrics: \n")
- for key, metric := range sa.Metrics {
- fmt.Printf("Key: %+v\n", key)
- fmt.Printf("Metric: %+v\n", metric)
- }
- fmt.Printf("SliceAssurance Policies: \n")
- for key, metric := range sa.Policies {
- fmt.Printf("Key: %+v\n", key)
- fmt.Printf("Metric: %+v\n", metric)
- }
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package structures
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "oransc.org/usecase/oduclosedloop/messages"
-)
-
-func TestAddMetric(t *testing.T) {
- assertions := require.New(t)
- type args struct {
- meas messages.Measurement
- }
- tests := []struct {
- name string
- args args
- }{
- {
- name: "Test adding new metric",
- args: args{
- meas: messages.Measurement{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 51232,
- Unit: "kbit/s",
- },
- },
- },
- {
- name: "Test with invalid input",
- args: args{
- meas: messages.Measurement{
- MeasurementTypeInstanceReference: "/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 51232,
- Unit: "kbit/s",
- },
- },
- },
- }
-
- sliceAssuranceMeas := NewSliceAssuranceMeas()
- assertions.Equal(0, len(sliceAssuranceMeas.Metrics), "Metrics is not empty, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 0)
-
- for i, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
-
- if i == 0 {
- sliceAssuranceMeas.AddOrUpdateMetric(tt.args.meas)
- assertions.Equal(1, len(sliceAssuranceMeas.Metrics), "Metrics must have one new metric, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 1)
-
- testMapKey := MapKey{"O-DU-1211", 1, 1}
- assertions.Contains(sliceAssuranceMeas.Metrics, testMapKey, "Metric added with wrong values , got: %v.", sliceAssuranceMeas.Metrics[testMapKey])
- }
- if i == 1 {
- _, got := sliceAssuranceMeas.AddOrUpdateMetric(tt.args.meas)
- assertions.EqualError(got, " wrong format for MeasurementTypeInstanceReference")
- }
- })
- }
-}
-
-func TestUpdateExistingMetric(t *testing.T) {
- assertions := require.New(t)
- meas := messages.Measurement{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 51232,
- Unit: "kbit/s",
- }
-
- updateMeas := messages.Measurement{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 897,
- Unit: "kbit/s",
- }
-
- sliceAssuranceMeas := NewSliceAssuranceMeas()
- assertions.Equal(0, len(sliceAssuranceMeas.Metrics), "Metrics is not empty, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 0)
-
- sliceAssuranceMeas.AddOrUpdateMetric(meas)
- assertions.Equal(1, len(sliceAssuranceMeas.Metrics), "Metrics must have one new metric, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 1)
-
- sliceAssuranceMeas.AddOrUpdateMetric(updateMeas)
- assertions.Equal(1, len(sliceAssuranceMeas.Metrics), "Metrics must have one updated metric, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 1)
-
- testMapKey := MapKey{"O-DU-1211", 1, 1}
- metricName := "user-equipment-average-throughput-uplink"
- newMetricValue := 897
- if sliceAssuranceMeas.Metrics[testMapKey].PM[metricName] != newMetricValue {
- t.Errorf("Metric value was not update properly, got: %d, want: %d.", sliceAssuranceMeas.Metrics[testMapKey].PM[metricName], newMetricValue)
- }
-
-}
-
-func TestDeleteMetricWhenValueLessThanThreshold(t *testing.T) {
-
- meas := messages.Measurement{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 51232,
- Unit: "kbit/s",
- }
-
- newMeas := messages.Measurement{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 50,
- Unit: "kbit/s",
- }
-
- sliceAssuranceMeas := NewSliceAssuranceMeas()
- assert.Equal(t, 0, len(sliceAssuranceMeas.Metrics), "Metrics is not empty, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 0)
-
- sliceAssuranceMeas.AddOrUpdateMetric(meas)
- assert.Equal(t, 1, len(sliceAssuranceMeas.Metrics), "Metrics must have one new metric, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 1)
-
- sliceAssuranceMeas.AddOrUpdateMetric(newMeas)
- assert.Equal(t, 0, len(sliceAssuranceMeas.Metrics), "Metrics must have been deleted, got: %d, want: %d.", len(sliceAssuranceMeas.Metrics), 0)
-
-}
-
-func TestAddPolicy(t *testing.T) {
-
- meas := messages.Measurement{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 51232,
- Unit: "kbit/s",
- }
- sliceAssuranceMeas := NewSliceAssuranceMeas()
- sliceAssuranceMeas.AddOrUpdateMetric(meas)
-
- duid := "O-DU-1211"
- rrmPolicyRatio := messages.RRMPolicyRatio{
- Id: "id",
- AdmState: "locked",
- UserLabel: "user_label",
- RRMPolicyMaxRatio: 0,
- RRMPolicyMinRatio: 0,
- RRMPolicyDedicatedRatio: 0,
- ResourceType: "prb",
- RRMPolicyMembers: []messages.RRMPolicyMember{{
- MobileCountryCode: "046",
- MobileNetworkCode: "651",
- SliceDifferentiator: 1,
- SliceServiceType: 1,
- }},
- }
- assert.Equal(t, 0, len(sliceAssuranceMeas.Policies), "Policies is not empty, got: %d, want: %d.", len(sliceAssuranceMeas.Policies), 0)
-
- sliceAssuranceMeas.AddNewPolicy(duid, rrmPolicyRatio)
- assert.Equal(t, 1, len(sliceAssuranceMeas.Policies), "Policies must have one new policy, got: %d, want: %d.", len(sliceAssuranceMeas.Policies), 1)
-
- sliceAssuranceMeas.PrintStructures()
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package main
-
-import (
- "fmt"
- "net/http"
-
- log "github.com/sirupsen/logrus"
- "oransc.org/usecase/oduclosedloop/internal/config"
- "oransc.org/usecase/oduclosedloop/internal/sliceassurance"
-)
-
-const TOPIC string = "/events/unauthenticated.VES_O_RAN_SC_HELLO_WORLD_PM_STREAMING_OUTPUT/myG/C1"
-
-var configuration *config.Config
-
-func main() {
- configuration = config.New()
-
- log.SetLevel(configuration.LogLevel)
- log.SetFormatter(&log.JSONFormatter{})
-
- log.Debug("Using configuration: ", configuration)
-
- if err := validateConfiguration(configuration); err != nil {
- log.Fatalf("Unable to start consumer due to configuration error: %v", err)
- }
-
- a := sliceassurance.App{}
- a.Initialize(configuration)
- go a.Run(TOPIC, configuration.Polltime)
-
- http.HandleFunc("/status", statusHandler)
-
- log.Fatal(http.ListenAndServe(":40936", nil))
-}
-
-func validateConfiguration(configuration *config.Config) error {
- if configuration.MRHost == "" || configuration.MRPort == "" {
- return fmt.Errorf("message router host and port must be provided")
- }
- return nil
-}
-
-func statusHandler(w http.ResponseWriter, r *http.Request) {
- // Just respond OK to show the service is alive for now. Might be extended later.
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package messages
-
-type ORanDuRestConf struct {
- DistributedUnitFunction []DistributedUnitFunction `json:"o-ran-sc-du-hello-world:distributed-unit-functions"`
-}
-
-type DistributedUnitFunction struct {
- Id string `json:"id"`
- OperationalState string `json:"operational-state"`
- AdmState string `json:"administrative-state"`
- UserLabel string `json:"user-label"`
- RRMPolicyRatio []RRMPolicyRatio `json:"radio-resource-management-policy-ratio"`
- Cell []Cell `json:"cell"`
-}
-
-type RRMPolicyRatio struct {
- Id string `json:"id"`
- AdmState string `json:"administrative-state"`
- UserLabel string `json:"user-label"`
- RRMPolicyMaxRatio int `json:"radio-resource-management-policy-max-ratio"`
- RRMPolicyMinRatio int `json:"radio-resource-management-policy-min-ratio"`
- RRMPolicyDedicatedRatio int `json:"radio-resource-management-policy-dedicated-ratio"`
- ResourceType string `json:"resource-type"`
- RRMPolicyMembers []RRMPolicyMember `json:"radio-resource-management-policy-members"`
-}
-
-type RRMPolicyMember struct {
- MobileCountryCode string `json:"mobile-country-code"`
- MobileNetworkCode string `json:"mobile-network-code"`
- SliceDifferentiator int `json:"slice-differentiator"`
- SliceServiceType int `json:"slice-service-type"`
-}
-
-type Cell struct {
- Id string `json:"id"`
- LocalId int `json:"local-id"`
- PhysicalCellId int `json:"physical-cell-id"`
- BaseStationChannelBandwidth BaseStationChannelBandwidth `json:"base-station-channel-bandwidth"`
- OperationalState string `json:"operational-state"`
- TrackingAreaCode int `json:"tracking-area-code"`
- AdmState string `json:"administrative-state"`
- PublicLandMobileNetworks []PublicLandMobileNetworks `json:"public-land-mobile-networks"`
- SupportedMeasurements []SupportedMeasurements `json:"supported-measurements"`
- TrafficState string `json:"traffic-state"`
- AbsoluteRadioFrequencyChannelNumber AbsoluteRadioFrequencyChannelNumber `json:"absolute-radio-frequency-channel-number"`
- UserLabel string `json:"user-label"`
- SynchronizationSignalBlock SynchronizationSignalBlock `json:"synchronization-signal-block"`
-}
-
-type BaseStationChannelBandwidth struct {
- Uplink int `json:"uplink"`
- Downlink int `json:"downlink"`
- SupplementaryUplink int `json:"supplementary-uplink"`
-}
-
-type PublicLandMobileNetworks struct {
- SliceDifferentiator int `json:"slice-differentiator"`
- SliceServiceType int `json:"slice-service-type"`
- MobileCountryCode string `json:"mobile-country-code"`
- MobileNetworkCode string `json:"mobile-network-code"`
-}
-
-type SupportedMeasurements struct {
- PerformanceMeasurementType string `json:"performance-measurement-type"`
- SupportedSnssaiSubcounterInstances []SupportedSnssaiSubcounterInstances `json:"supported-snssai-subcounter-instances"`
-}
-
-type SupportedSnssaiSubcounterInstances struct {
- SliceDifferentiator int `json:"slice-differentiator"`
- SliceServiceType int `json:"slice-service-type"`
-}
-
-type AbsoluteRadioFrequencyChannelNumber struct {
- Uplink int `json:"uplink"`
- Downlink int `json:"downlink"`
- SupplementaryUplink int `json:"supplementary-uplink"`
-}
-
-type SynchronizationSignalBlock struct {
- Duration int `json:"duration"`
- FrequencyChannelNumber int `json:"frequency-channel-number"`
- Periodicity int `json:"periodicity"`
- SubcarrierSpacing int `json:"subcarrier-spacing"`
- Offset int `json:"offset"`
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package messages
-
-type StdDefinedMessage struct {
- Event Event `json:"event"`
-}
-
-type Event struct {
- CommonEventHeader CommonEventHeader `json:"commonEventHeader"`
- StndDefinedFields StndDefinedFields `json:"stndDefinedFields"`
-}
-
-type CommonEventHeader struct {
- Domain string `json:"domain"`
- EventId string `json:"eventId"`
- EventName string `json:"eventName"`
- EventType string `json:"eventType"`
- Sequence int `json:"sequence"`
- Priority string `json:"priority"`
- ReportingEntityId string `json:"reportingEntityId"`
- ReportingEntityName string `json:"reportingEntityName"`
- SourceId string `json:"sourceId"`
- SourceName string `json:"sourceName"`
- StartEpochMicrosec int64 `json:"startEpochMicrosec"`
- LastEpochMicrosec int64 `json:"lastEpochMicrosec"`
- NfNamingCode string `json:"nfNamingCode"`
- NfVendorName string `json:"nfVendorName"`
- StndDefinedNamespace string `json:"stndDefinedNamespace"`
- TimeZoneOffset string `json:"timeZoneOffset"`
- Version string `json:"version"`
- VesEventListenerVersion string `json:"vesEventListenerVersion"`
-}
-
-type StndDefinedFields struct {
- StndDefinedFieldsVersion string `json:"stndDefinedFieldsVersion"`
- SchemaReference string `json:"schemaReference"`
- Data Data `json:"data"`
-}
-
-type Data struct {
- DataId string `json:"id"`
- StartTime string `json:"start-time"`
- AdministrativeState string `json:"administrative-state"`
- OperationalState string `json:"operational-state"`
- UserLabel string `json:"user-label"`
- JobTag string `json:"job-tag"`
- GranularityPeriod int `json:"granularity-period"`
- Measurements []Measurement `json:"measurements"`
-}
-
-type Measurement struct {
- MeasurementTypeInstanceReference string `json:"measurement-type-instance-reference"`
- Value int `json:"value"`
- Unit string `json:"unit"`
-}
-
-func (message StdDefinedMessage) GetMeasurements() []Measurement {
- return message.Event.StndDefinedFields.Data.Measurements
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package messages
-
-import (
- "testing"
-
- "github.com/stretchr/testify/require"
-)
-
-func TestGetMeasurements(t *testing.T) {
- assertions := require.New(t)
- type fields struct {
- Event Event
- }
- tests := []struct {
- name string
- fields fields
- want []Measurement
- }{
- {
- name: "get measurements message",
- fields: fields{
- Event: Event{
- CommonEventHeader: CommonEventHeader{
- Domain: "stndDefined",
- StndDefinedNamespace: "o-ran-sc-du-hello-world-pm-streaming-oas3",
- },
- StndDefinedFields: StndDefinedFields{
- StndDefinedFieldsVersion: "1.0",
- SchemaReference: "https://gerrit.o-ran-sc.org/r/gitweb?p=scp/oam/modeling.git;a=blob_plain;f=data-model/oas3/experimental/o-ran-sc-du-hello-world-oas3.json;hb=refs/heads/master",
- Data: Data{
- DataId: "id",
- Measurements: []Measurement{{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 51232,
- Unit: "kbit/s",
- }},
- },
- },
- },
- },
- want: []Measurement{{
- MeasurementTypeInstanceReference: "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='O-DU-1211']/cell[id='cell-1']/supported-measurements[performance-measurement-type='user-equipment-average-throughput-uplink']/supported-snssai-subcounter-instances[slice-differentiator='1'][slice-service-type='1']",
- Value: 51232,
- Unit: "kbit/s",
- }},
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- message := StdDefinedMessage{
- Event: tt.fields.Event,
- }
- var got []Measurement
- if got = message.GetMeasurements(); len(got) != len(tt.want) {
- t.Errorf("Message.GetMeasurements() = %v, want %v", got, tt.want)
- }
-
- for _, meas := range got {
- assertions.Equal(51232, meas.Value)
- assertions.Contains(meas.MeasurementTypeInstanceReference, "user-equipment-average-throughput-uplink")
- }
-
- })
- }
-}
+++ /dev/null
-// -
-// ========================LICENSE_START=================================
-// O-RAN-SC
-// %%
-// Copyright (C) 2021: Nordix Foundation
-// %%
-// 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.
-// ========================LICENSE_END===================================
-//
-
-package main
-
-import (
- "encoding/csv"
- "encoding/json"
- "flag"
- "fmt"
- "math/rand"
- "net/http"
- "os"
- "strconv"
- "sync"
- "time"
-
- "github.com/gorilla/mux"
- "oransc.org/usecase/oduclosedloop/messages"
-
- log "github.com/sirupsen/logrus"
-)
-
-const THRESHOLD_TPUT int = 7000
-
-type SliceAssuranceInformation struct {
- duId string
- cellId string
- sd int
- sst int
- metricName string
- metricValue int
- policyRatioId string
- policyMaxRatio int
- policyMinRatio int
- policyDedicatedRatio int
-}
-
-var data []*SliceAssuranceInformation
-var messagesToSend []messages.Measurement
-
-func loadData() {
- lines, err := GetCsvFromFile("test-data.csv")
- if err != nil {
- panic(err)
- }
- for _, line := range lines {
- sai := SliceAssuranceInformation{
- duId: line[0],
- cellId: line[1],
- sd: toInt(line[2]),
- sst: toInt(line[3]),
- metricName: line[4],
- metricValue: toInt(line[5]),
- policyRatioId: line[6],
- policyMaxRatio: toInt(line[7]),
- policyMinRatio: toInt(line[8]),
- policyDedicatedRatio: toInt(line[9]),
- }
- data = append(data, &sai)
- }
-}
-
-func GetCsvFromFile(name string) ([][]string, error) {
- if csvFile, err := os.Open(name); err == nil {
- defer csvFile.Close()
- reader := csv.NewReader(csvFile)
- reader.FieldsPerRecord = -1
- if csvData, err := reader.ReadAll(); err == nil {
- return csvData, nil
- } else {
- return nil, err
- }
- } else {
- return nil, err
- }
-}
-
-func toInt(num string) int {
- res, err := strconv.Atoi(num)
- if err != nil {
- return -1
- }
- return res
-}
-
-func main() {
- rand.Seed(time.Now().UnixNano())
-
- portSdnr := flag.Int("sdnr-port", 3904, "The port this SDNR stub will listen on")
- portDmaapMR := flag.Int("dmaap-port", 3905, "The port this Dmaap message router will listen on")
- flag.Parse()
-
- loadData()
-
- wg := new(sync.WaitGroup)
- wg.Add(2)
-
- go func() {
-
- r := mux.NewRouter()
- r.HandleFunc("/rests/data/network-topology:network-topology/topology=topology-netconf/node={NODE-ID}/yang-ext:mount/o-ran-sc-du-hello-world:network-function/distributed-unit-functions={O-DU-ID}", getSdnrResponseMessage).Methods(http.MethodGet)
- r.HandleFunc("/rests/data/network-topology:network-topology/topology=topology-netconf/node={NODE-ID}/yang-ext:mount/o-ran-sc-du-hello-world:network-function/distributed-unit-functions={O-DU-ID}/radio-resource-management-policy-ratio={POLICY-ID}", updateRRMPolicyDedicatedRatio).Methods(http.MethodPut)
-
- fmt.Println("Starting SDNR stub on port: ", *portSdnr)
-
- log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", *portSdnr), r))
- wg.Done()
- }()
-
- go func() {
-
- r := mux.NewRouter()
- r.HandleFunc("/events/unauthenticated.VES_O_RAN_SC_HELLO_WORLD_PM_STREAMING_OUTPUT/myG/C1", sendDmaapMRMessages).Methods(http.MethodGet)
-
- fmt.Println("Starting DmaapMR stub on port: ", *portDmaapMR)
-
- log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", *portDmaapMR), r))
- wg.Done()
- }()
-
- wg.Wait()
-}
-
-func getSdnrResponseMessage(w http.ResponseWriter, r *http.Request) {
- vars := mux.Vars(r)
- log.Info("Get messages for RRM Policy Ratio information for O-Du ID ", vars["O-DU-ID"])
-
- distUnitFunctions := getDistributedUnitFunctionMessage(vars["O-DU-ID"])
-
- respondWithJSON(w, http.StatusOK, distUnitFunctions)
-}
-
-func getDistributedUnitFunctionMessage(oduId string) messages.ORanDuRestConf {
-
- var policies []messages.RRMPolicyRatio
- keys := make(map[string]bool)
- for _, entry := range data {
- if _, value := keys[entry.policyRatioId]; !value {
- keys[entry.policyRatioId] = true
- message := messages.RRMPolicyRatio{
-
- Id: entry.policyRatioId,
- AdmState: "locked",
- UserLabel: entry.policyRatioId,
- RRMPolicyMaxRatio: entry.policyMaxRatio,
- RRMPolicyMinRatio: entry.policyMinRatio,
- RRMPolicyDedicatedRatio: entry.policyDedicatedRatio,
- ResourceType: "prb",
- RRMPolicyMembers: []messages.RRMPolicyMember{
- {
- MobileCountryCode: "310",
- MobileNetworkCode: "150",
- SliceDifferentiator: entry.sd,
- SliceServiceType: entry.sst,
- },
- },
- }
- policies = append(policies, message)
- }
- }
-
- var publicLandMobileNetworks []messages.PublicLandMobileNetworks
- for _, entry := range data {
- publicLandMobileNetwork := messages.PublicLandMobileNetworks{
- MobileCountryCode: "310",
- MobileNetworkCode: "150",
- SliceDifferentiator: entry.sd,
- SliceServiceType: entry.sst,
- }
- publicLandMobileNetworks = append(publicLandMobileNetworks, publicLandMobileNetwork)
- }
-
- var supportedSnssaiSubcounterInstances []messages.SupportedSnssaiSubcounterInstances
- for _, entry := range data {
- supportedSnssaiSubcounterInstance := messages.SupportedSnssaiSubcounterInstances{
- SliceDifferentiator: entry.sd,
- SliceServiceType: entry.sst,
- }
- supportedSnssaiSubcounterInstances = append(supportedSnssaiSubcounterInstances, supportedSnssaiSubcounterInstance)
- }
-
- cell := messages.Cell{
- Id: "cell-1",
- LocalId: 1,
- PhysicalCellId: 1,
- BaseStationChannelBandwidth: messages.BaseStationChannelBandwidth{
- Uplink: 83000,
- Downlink: 80000,
- SupplementaryUplink: 84000,
- },
- OperationalState: "enabled",
- TrackingAreaCode: 10,
- AdmState: "unlocked",
- PublicLandMobileNetworks: publicLandMobileNetworks,
- SupportedMeasurements: []messages.SupportedMeasurements{
- {
- PerformanceMeasurementType: "o-ran-sc-du-hello-world:user-equipment-average-throughput-uplink",
- SupportedSnssaiSubcounterInstances: supportedSnssaiSubcounterInstances,
- },
- {
- PerformanceMeasurementType: "o-ran-sc-du-hello-world:user-equipment-average-throughput-downlink",
- SupportedSnssaiSubcounterInstances: supportedSnssaiSubcounterInstances,
- },
- },
- TrafficState: "active",
- AbsoluteRadioFrequencyChannelNumber: messages.AbsoluteRadioFrequencyChannelNumber{
- Uplink: 14000,
- Downlink: 15000,
- SupplementaryUplink: 14500,
- },
- UserLabel: "cell-1",
- SynchronizationSignalBlock: messages.SynchronizationSignalBlock{
- Duration: 2,
- FrequencyChannelNumber: 12,
- Periodicity: 10,
- SubcarrierSpacing: 30,
- Offset: 3,
- },
- }
-
- distUnitFunction := messages.DistributedUnitFunction{
- Id: oduId,
- OperationalState: "enabled",
- AdmState: "unlocked",
- UserLabel: oduId,
- Cell: []messages.Cell{
- cell,
- },
- RRMPolicyRatio: policies,
- }
-
- duRRMPolicyRatio := messages.ORanDuRestConf{
- DistributedUnitFunction: []messages.DistributedUnitFunction{
- distUnitFunction,
- },
- }
-
- return duRRMPolicyRatio
-}
-
-func updateRRMPolicyDedicatedRatio(w http.ResponseWriter, r *http.Request) {
- var policies struct {
- RRMPolicies []messages.RRMPolicyRatio `json:"radio-resource-management-policy-ratio"`
- }
- decoder := json.NewDecoder(r.Body)
-
- if err := decoder.Decode(&policies); err != nil {
- respondWithError(w, http.StatusBadRequest, "Invalid request payload")
- return
- }
- defer r.Body.Close()
-
- prMessages := policies.RRMPolicies
- log.Infof("Post request to update RRMPolicyDedicatedRatio %+v", prMessages)
- findAndUpdatePolicy(prMessages)
- respondWithJSON(w, http.StatusOK, map[string]string{"status": "200"})
-}
-
-func findAndUpdatePolicy(rRMPolicyRatio []messages.RRMPolicyRatio) {
- for _, policy := range rRMPolicyRatio {
- for _, entry := range data {
- if entry.policyRatioId == policy.Id {
- log.Infof("update Policy Dedicated Ratio: value for policy %+v\n Old value: %v New value: %v ", policy, entry.policyDedicatedRatio, policy.RRMPolicyDedicatedRatio)
- entry.policyDedicatedRatio = policy.RRMPolicyDedicatedRatio
- if entry.metricValue > THRESHOLD_TPUT {
- entry.metricValue = rand.Intn(THRESHOLD_TPUT)
- }
- messagesToSend = append(messagesToSend, generateMeasurementEntry(entry))
- }
- }
- }
-}
-
-func respondWithError(w http.ResponseWriter, code int, message string) {
- respondWithJSON(w, code, map[string]string{"error": message})
-}
-
-func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
- response, _ := json.Marshal(payload)
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(code)
- w.Write(response)
-}
-
-func sendDmaapMRMessages(w http.ResponseWriter, r *http.Request) {
- log.Info("Send Dmaap messages")
- entry := data[rand.Intn(5)]
-
- maxTput := THRESHOLD_TPUT + 100
- randomTput := rand.Intn(maxTput-THRESHOLD_TPUT+1) + THRESHOLD_TPUT
- if randomTput%3 == 0 {
- log.Info("Using tput value higher than THRESHOLD_TPUT ", randomTput)
- entry.metricValue = randomTput
- }
- randomEventId := rand.Intn(10000)
- messagesToSend = append(messagesToSend, generateMeasurementEntry(entry))
-
- message := messages.StdDefinedMessage{
- Event: messages.Event{
- CommonEventHeader: messages.CommonEventHeader{
- Domain: "stndDefined",
- EventId: "pm-1_16442" + strconv.Itoa(randomEventId),
- EventName: "stndDefined_performanceMeasurementStreaming",
- EventType: "performanceMeasurementStreaming",
- Sequence: 825,
- Priority: "Low",
- ReportingEntityId: "",
- ReportingEntityName: "O-DU-1122",
- SourceId: "",
- SourceName: "O-DU-1122",
- StartEpochMicrosec: 1644252450000000,
- LastEpochMicrosec: 1644252480000000,
- NfNamingCode: "SIM-O-DU",
- NfVendorName: "O-RAN-SC SIM Project",
- StndDefinedNamespace: "o-ran-sc-du-hello-world-pm-streaming-oas3",
- TimeZoneOffset: "+00:00",
- Version: "4.1",
- VesEventListenerVersion: "7.2.1",
- },
- StndDefinedFields: messages.StndDefinedFields{
- StndDefinedFieldsVersion: "1.0",
- SchemaReference: "https://gerrit.o-ran-sc.org/r/gitweb?p=scp/oam/modeling.git;a=blob_plain;f=data-model/oas3/experimental/o-ran-sc-du-hello-world-oas3.json;hb=refs/heads/master",
- Data: messages.Data{
- DataId: "pm-1_1644252450",
- StartTime: "2022-02-07T16:47:30.0Z",
- AdministrativeState: "unlocked",
- OperationalState: "enabled",
- UserLabel: "pm",
- JobTag: "my-job-tag",
- GranularityPeriod: 30,
- Measurements: messagesToSend,
- },
- },
- },
- }
-
- fmt.Printf("Sending Dmaap message:\n %+v\n", message)
-
- messageAsByteArray, _ := json.Marshal(message)
- response := [1]string{string(messageAsByteArray)}
-
- time.Sleep(time.Duration(rand.Intn(3)) * time.Second)
- respondWithJSON(w, http.StatusOK, response)
-
- messagesToSend = nil
-}
-
-func generateMeasurementEntry(entry *SliceAssuranceInformation) messages.Measurement {
-
- measurementTypeInstanceReference := "/o-ran-sc-du-hello-world:network-function/distributed-unit-functions[id='" + entry.duId + "']/cell[id='" + entry.cellId + "']/supported-measurements[performance-measurement-type='(urn:o-ran-sc:yang:o-ran-sc-du-hello-world?revision=2021-11-23)" + entry.metricName + "']/supported-snssai-subcounter-instances[slice-differentiator='" + strconv.Itoa(entry.sd) + "'][slice-service-type='" + strconv.Itoa(entry.sst) + "']"
- meas := messages.Measurement{
-
- MeasurementTypeInstanceReference: measurementTypeInstanceReference,
- Value: entry.metricValue,
- Unit: "kbit/s",
- }
- return meas
-}
+++ /dev/null
-O-DU-1122,cell-1,1,1,user-equipment-average-throughput-downlink,3761,rrm-pol-1,20,10,15
-O-DU-1122,cell-1,1,1,user-equipment-average-throughput-uplink,5861,rrm-pol-1,20,10,15
-O-DU-1122,cell-1,1,2,user-equipment-average-throughput-downlink,7791,rrm-pol-2,20,10,15
-O-DU-1122,cell-1,1,2,user-equipment-average-throughput-uplink,4539,rrm-pol-2,20,10,15
-O-DU-1122,cell-1,2,1,user-equipment-average-throughput-downlink,8987,rrm-pol-3,20,10,15
-O-DU-1122,cell-1,2,1,user-equipment-average-throughput-uplink,1134,rrm-pol-3,20,10,15
-O-DU-1122,cell-1,2,2,user-equipment-average-throughput-downlink,9123,rrm-pol-4,20,10,15
-O-DU-1122,cell-1,2,2,user-equipment-average-throughput-uplink,5368,rrm-pol-4,20,10,15
-O-DU-1122,cell-1,3,1,user-equipment-average-throughput-downlink,8764,rrm-pol-5,20,10,15
-O-DU-1122,cell-1,3,1,user-equipment-average-throughput-uplink,1367,rrm-pol-5,20,10,15
\ No newline at end of file