diff options
50 files changed, 2826 insertions, 0 deletions
@@ -22,6 +22,7 @@ <name>rapp</name> <description>rapp applications</description> <modules> + <module>sleepingcelldetector</module> <module>datacollector</module> </modules> diff --git a/sleepingcelldetector/README.md b/sleepingcelldetector/README.md new file mode 100644 index 0000000..1a7b432 --- /dev/null +++ b/sleepingcelldetector/README.md @@ -0,0 +1,200 @@ +# SleepingCellDetector R-APP + +SleepingCellDetector R-APP is a Java SpringBoot application for reading Aggregated PM Metrics from DataCollector R-APP +and make sleeping cell prediction based on PM data + +## Use of SleepingCellDetector R-APP + +SleepingCellDetector R-APP needs several parameters to be defined before start. + +TCA Algorithm configuration situated in `resources/tca.json` file, example: + +```json +[ + { + "name": "latency", + "condition": "MORE_OR_EQUAL", + "averageThresholdValue": 400, + "latestThresholdValue": 150, + "latestSize": 2 + }, + { + "name": "throughput", + "condition": "LESS_OR_EQUAL", + "averageThresholdValue": 10, + "latestThresholdValue": 10, + "latestSize": 2 + } +] +``` + +File contains information about names of performance measurement parameters, conditions and values of thresholds for +them. +`"averageThresholdValue"`- is a threshold of performance signal average +`"latestThresholdValue"` - is a threshold of last slots of performance signal (number defined in " +latestThresholdValue"). Needed to detect correction of performance signal. Conditions available: "LESS", "LESS_OR_EQUAL" +, "EQUAL", "MORE_OR_EQUAL", "MORE"' + +Actually DataCollector R-APP returns Aggregated Metrics of "latency" and "throughput" parameters, example: + +```json +{ + "pm": [ + { + "cellId": "Cell1", + "performance": [ + { + "latency": 50, + "throughput": 80 + }, + { + "latency": 50, + "throughput": 80 + }, + { + "latency": 50, + "throughput": 80 + } + ] + } + ], + "itemsLength": 1 +} +``` + +Set parameters of environment variables: + +A1PolicyManagementService URL can be set using environment variables: + +- A1\_HOST +- A1\_PORT + +To customize DataCollector R-APP connectivity you need to set the following: + +- DC_HOST +- DC_PORT +- DC_VERSION + +SleepingCellDetector R-APP configuration fields: + +- SCD_PREFIX +- SCD_SLOT +- SCD_COUNT + +Prefix of high priority user equipment (policy instances will be created only for user equipments with this prefix), +example: +`emergency_` - policy instances will be created only for UEs with "emergency\_" prefix Slot of time in seconds, +number of slots for DataCollector R-APP Aggregated Metrics endpoint call. Slot: aggregation period (in seconds) for +which an average performance metrics are calculated Count: number of aggregated performance metrics that should be +returned by the method, one aggregated performance metric per each slot. The first performance metrics is average +metrics for (startTime, startTime +slot). StartTime for DataCollector R-APP Aggregated Metrics endpoint call is +generated based on slot and count parameters as "time.now - slot\*count" + +Example configuration in environment variables in application.yml: + +``` +server: + port: 8382 +a1: + host: "policy-agent" + port: 8081 +dc: + host: "localhost" + port: 8087 + version: "v1" +scd: + prefix: "emergency" + slot: 10 + count: 12 +logging: + level: + org: + springframework: DEBUG + logging.file.name: logs/rapp-sleepingcelldetector.log + pattern: + console: "%d %-5level %logger : %msg%n" + file: "%d %-5level [%thread] %logger : %msg%n" +``` + +During start-up, SleepingCellDetector R-APP registers itself as a service in A1PolicyManagmentService(PMS). After that +SleepingCellDetector R-APP sends periodic keepalive requests to PMS. PMS exposes the Ric Configuration for SleepingCellDetector R-APP. +Ric Configuration contains information about Policy Type and Ric name, example: + +```json +[ + { + "ricName": "ric1", + "managedElementIds": [ + ], + "policyTypes": [ + "1000" + ], + "state": "AVAILABLE" + } +] +``` + +SleepingCellDetector R-APP uses this information with created UUID are used for Policy Instances creation request to +A1PolicyManagementService, example: + +`{a1policymanagementservicehost}/policy?id=123e4567-e89b-12d3-a456-426614174000&ric=ric1&service=rapp-sleepingcelldetector&type=1000` + +```json +{ + "scope": { + "ueId": "emergency_samsung_s10_01" + }, + "resources": [ + { + "cellIdList": [ + "Cell3" + ], + "preference": "AVOID" + } + ] +} +``` + +SleepingCellDetector R-APP creates the policy resources, which are used to traffic steering, +selecting cell for a connection, or scheduling traffic on available cells, +in a different way than what would be done through default behaviour. + +Like was presented on the example above, created policy instances provided information +which cells (mention in the array "cellIdList") the User Equipment (define in the section "scope", key "ueId"") +should avoid (section "resources", key "preference"). + +After start-up SleepingCellDetector R-APP begins to make predictions periodically in intervals defined by CSD_SLOT +period based on new PM metrics measurement data received in each interval. +When sleeping cell is detected, creation of A1 Policy instance is enforced by SleepingCellDetector R-APP. +If cell becomes active again, A1Policy instance deletion request is sent. + +# Developer Guide + +## Build SleepingCellDetector R-APP + +Following mvn command (in the current directory) will build SleepingCellDetector R-APP: + +```bash +mvn clean install +``` + +To build docker image add `-P docker:build` flag. + +## Run SleepingCellDetector R-APP + +Following command will run SleepingCellDetector R-APP: + +```bash +java -jar sleepingcelldetector-0.0.1-SNAPSHOT.jar org.onap.rapp.sleepingcelldetector.SleepingCellDetectorApplication +``` + +## Logging + +The log file will be created in the /log path. Parameters of logging are in application.yml file. +After SleepingCellDetector R-APP starts successfully, log/rapp-sleepingcelldetector.log should start to contain the logs: + +``` +. +└──log + └── rapp-sleepingcelldetector.log +``` diff --git a/sleepingcelldetector/pom.xml b/sleepingcelldetector/pom.xml new file mode 100644 index 0000000..80b790d --- /dev/null +++ b/sleepingcelldetector/pom.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (C) 2021 Samsung Electronics + ~ 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 + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>sleepingcelldetector</artifactId> + <groupId>org.onap.rapp.sleepingcelldetector</groupId> + <version>0.0.1-SNAPSHOT</version> + <packaging>jar</packaging> + + <parent> + <groupId>org.onap.rapp</groupId> + <artifactId>rapp</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + <properties> + <docker-image.name.prefix>org.onap.rapp.sleepingcelldetector</docker-image.name.prefix> + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20190722</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>28.2-android</version> + </dependency> + </dependencies> +</project> diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/SleepingCellDetectorApplication.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/SleepingCellDetectorApplication.java new file mode 100644 index 0000000..ebb825c --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/SleepingCellDetectorApplication.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector; + +import org.onap.rapp.sleepingcelldetector.configuration.A1Properties; +import org.onap.rapp.sleepingcelldetector.configuration.DataCollectorProperties; +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorProperties; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +@ComponentScan(basePackages = {"org.onap.rapp.sleepingcelldetector"}) +@EnableConfigurationProperties({A1Properties.class, DataCollectorProperties.class, + SleepingCellDetectorProperties.class}) +@EnableAutoConfiguration +public class SleepingCellDetectorApplication { + public static void main(String[] args) { + SpringApplication.run(SleepingCellDetectorApplication.class, args); + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/A1Properties.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/A1Properties.java new file mode 100644 index 0000000..24981e4 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/A1Properties.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.configuration; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@Setter +@ConfigurationProperties(prefix = "a1") +public class A1Properties { + private String host; + private int port; + + public String getA1PolicyUrl() { + return String.format("http://%s:%d", host, port); + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/DataCollectorProperties.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/DataCollectorProperties.java new file mode 100644 index 0000000..6e6b289 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/DataCollectorProperties.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.configuration; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@Setter +@ConfigurationProperties(prefix = "dc") +public class DataCollectorProperties { + private String host; + private int port; + private String version; + + public String getDataCollectorUrl() { + return String.format("http://%s:%d/%s", host, port, version); + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorConfiguration.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorConfiguration.java new file mode 100644 index 0000000..e7c1d25 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorConfiguration.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.configuration; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class SleepingCellDetectorConfiguration { + + private final A1Properties a1Properties; + private final DataCollectorProperties dataCollectorProperties; + private final SleepingCellDetectorProperties scdProperties; + + @Autowired + public SleepingCellDetectorConfiguration(A1Properties a1Properties, DataCollectorProperties dataCollectorProperties, + SleepingCellDetectorProperties scdProperties) { + this.a1Properties = a1Properties; + this.dataCollectorProperties = dataCollectorProperties; + this.scdProperties = scdProperties; + } + + public String getA1PolicyBaseUrl() { + return a1Properties.getA1PolicyUrl(); + } + + public String getDataCollectorBaseUrl() { + return dataCollectorProperties.getDataCollectorUrl(); + } + + public String getUeFilteringPrefix(){ + return scdProperties.getPrefix(); + } + + public int getPredictionTimeSlot(){ + return scdProperties.getSlot(); + } + + public int getPredictionSlotNumber(){ + return scdProperties.getCount(); + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } + +} + + diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorProperties.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorProperties.java new file mode 100644 index 0000000..4e3145f --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorProperties.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.configuration; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@Setter +@ConfigurationProperties(prefix = "scd") +public class SleepingCellDetectorProperties { + private String prefix; + private int slot; + private int count; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/MeasurementConfiguration.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/MeasurementConfiguration.java new file mode 100644 index 0000000..984eb1a --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/MeasurementConfiguration.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.onap.rapp.sleepingcelldetector.service.scd.condition.ConditionEnum; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class MeasurementConfiguration { + private String name; + private ConditionEnum condition; + private int averageThresholdValue; + private int latestThresholdValue; + private int latestSize; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/RicConfiguration.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/RicConfiguration.java new file mode 100644 index 0000000..db09f8a --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/RicConfiguration.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class RicConfiguration { + private String ricName; + private List<String> managedElementIds; + private List<String> policyTypes; + private String state; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/ServiceRegistrationPayload.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/ServiceRegistrationPayload.java new file mode 100644 index 0000000..3cb2777 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/ServiceRegistrationPayload.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ServiceRegistrationPayload { + private String callBackUrl; + private String keepAliveIntervalSeconds; + private String serviceName; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/pm/PMData.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/pm/PMData.java new file mode 100644 index 0000000..5d26c5f --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/pm/PMData.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.pm; + +import java.util.List; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class PMData { + String cellId; + List<Map<String, Integer>> performance; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/pm/PMEntity.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/pm/PMEntity.java new file mode 100644 index 0000000..805569b --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/pm/PMEntity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.pm; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class PMEntity { + List<PMData> pm; + int totalCell; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/A1PolicyEvent.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/A1PolicyEvent.java new file mode 100644 index 0000000..7b70c0a --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/A1PolicyEvent.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.policy; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Getter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class A1PolicyEvent { + private Scope scope; + private List<Resources> resources; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/PolicyInstance.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/PolicyInstance.java new file mode 100644 index 0000000..55d7531 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/PolicyInstance.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.policy; + +import java.util.Date; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class PolicyInstance { + private String id; + private String type; + private String ric; + private String service; + private Date lastModified; + private A1PolicyEvent json; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Preference.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Preference.java new file mode 100644 index 0000000..72a3569 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Preference.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.policy; + +public enum Preference { + SHALL("SHALL"), PREFER("PREFER"), AVOID("AVOID"), FORBID("FORBID"); + public final String value; + + Preference(String stateName) { + this.value = stateName; + } +}
\ No newline at end of file diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Resources.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Resources.java new file mode 100644 index 0000000..6214726 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Resources.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.policy; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonTypeName; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Getter +@JsonTypeName("resources") +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Resources { + private List<String> cellIdList; + private Preference preference; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Scope.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Scope.java new file mode 100644 index 0000000..37e72bd --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/policy/Scope.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.policy; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonTypeName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Getter +@JsonTypeName("scope") +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Scope { + private String ueId; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/ue/UEInfo.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/ue/UEInfo.java new file mode 100644 index 0000000..7f5f997 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/entity/ue/UEInfo.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.entity.ue; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class UEInfo { + private List<String> ues; +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CallbackController.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CallbackController.java new file mode 100644 index 0000000..47b6e3e --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CallbackController.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping({"/"}) +public class CallbackController { + + private static final Logger logger = LoggerFactory.getLogger(CallbackController.class); + + @GetMapping() + public ResponseEntity<String> checkHealth() { + logger.info("Health check performed"); + return ResponseEntity.ok("Service up and running"); + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceHandler.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceHandler.java new file mode 100644 index 0000000..72bc8d6 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceHandler.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.service.scd.SleepingCellDetectorService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class CellPerformanceHandler { + + private static final Logger logger = LoggerFactory.getLogger(CellPerformanceHandler.class); + + private final SleepingCellDetectorService sleepingCellDetectorService; + private final RicConfigurationHolder ricConfigHolder; + private final PolicyInstanceManager policyInstancesManager; + private final SleepingCellDetectorConfiguration config; + private final DataCollectorClient dataCollectorClient; + + public CellPerformanceHandler(SleepingCellDetectorService sleepingCellDetectorService, RicConfigurationHolder ricConfigHolder, + PolicyInstanceManager policyInstanceManager, SleepingCellDetectorConfiguration config, + DataCollectorClient dataCollectorClient) { + this.sleepingCellDetectorService = sleepingCellDetectorService; + this.ricConfigHolder = ricConfigHolder; + this.policyInstancesManager = policyInstanceManager; + this.config = config; + this.dataCollectorClient = dataCollectorClient; + } + + public void handleCellPerformance(String cell, List<Map<String, Integer>> pmData) { + logger.info("Handle cell: {} started", cell); + try { + if (pmData.isEmpty()) { + logger.warn("pm data is empty for cell: {}", cell); + return; + } + + Boolean isFailing = sleepingCellDetectorService.isFailing(pmData); + handleCell(cell, isFailing); + } catch (Exception e) { + logger.error("Error during sleeping cell detecting: {}", e.getMessage()); + } + } + + private void handleCell(String cell, boolean isFailing) { + if (isFailing) { + handleFailingCell(cell); + } else { + handleActiveCell(cell); + } + } + + private void handleFailingCell(String cell) { + logger.info("Cell {} is in failed status, policy instance will be created", cell); + + Optional<RicConfiguration> ricConfig = ricConfigHolder.getRicConfig(); + if (ricConfig.isEmpty()) { + logger.warn("Can't find ric configuration for cell: {}", cell); + return; + } + + Set<String> userEquipmentsIds = getHighPriorityUEs(); + if (userEquipmentsIds.isEmpty()) { + logger.warn("No high priority user equipment for cell: {}", cell); + return; + } + + createPolicyInstance(ricConfig.get(), userEquipmentsIds, cell); + } + + private Set<String> getHighPriorityUEs() { + return dataCollectorClient.getUserEquipment().getUes().stream() + .filter(ue -> ue.startsWith(config.getUeFilteringPrefix())) + .collect(Collectors.toSet()); + } + + private void createPolicyInstance(RicConfiguration ricConfig, Set<String> userEquipmentsIds, String cell) { + userEquipmentsIds.stream() + .filter(ue -> !policyInstancesManager.cellContainsPolicyForUe(cell, ue)) + .forEach(ue -> policyInstancesManager.createPolicyInstance(cell, ue, ricConfig)); + } + + private void handleActiveCell(String cell) { + if (policyInstancesManager.cellContainsPolicy(cell)) { + policyInstancesManager.removePolicyInstancesForCell(cell); + } + logger.info("Cell {} is not in failed status", cell); + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceVerifierScheduler.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceVerifierScheduler.java new file mode 100644 index 0000000..bc2aaaf --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceVerifierScheduler.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.onap.rapp.sleepingcelldetector.entity.pm.PMEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Service +public class CellPerformanceVerifierScheduler { + + private static final Logger logger = LoggerFactory.getLogger(CellPerformanceVerifierScheduler.class); + + private final DataCollectorClient dataCollectorClient; + private final CellPerformanceHandler cellPerformanceHandler; + + public CellPerformanceVerifierScheduler(DataCollectorClient dataCollectorClient, CellPerformanceHandler cellPerformanceHandler) { + this.dataCollectorClient = dataCollectorClient; + this.cellPerformanceHandler = cellPerformanceHandler; + } + + @Scheduled(fixedRateString = "${scd.slot}000") + public void handleMeasurements() { + logger.debug("Perform measurements check"); + performVesEventsMeasurementVerification(); + } + + private void performVesEventsMeasurementVerification() { + try { + PMEntity performanceData = dataCollectorClient.getPMData(); + Map<String, List<Map<String, Integer>>> eventsByCell = groupByCell(performanceData); + eventsByCell.forEach(cellPerformanceHandler::handleCellPerformance); + } catch (Exception e) { + logger.error("Error occurred during events verification, message: {}", e.getMessage()); + } + } + + private Map<String, List<Map<String, Integer>>> groupByCell(PMEntity pmEntity) { + Map<String, List<Map<String, Integer>>> cellPerformanceMap = new HashMap<>(); + pmEntity.getPm().forEach(pmData -> cellPerformanceMap.put(pmData.getCellId(), pmData.getPerformance())); + return cellPerformanceMap; + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/DataCollectorClient.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/DataCollectorClient.java new file mode 100644 index 0000000..85a5e06 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/DataCollectorClient.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.pm.PMEntity; +import org.onap.rapp.sleepingcelldetector.entity.ue.UEInfo; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class DataCollectorClient { + + public static final String AGGREGATED_METRICS_URL = "/pm/events/aggregatedmetrics"; + public static final String UES_URL = "/pm/ues"; + private final SleepingCellDetectorConfiguration config; + private final RestTemplate restTemplate; + + public DataCollectorClient(SleepingCellDetectorConfiguration config, RestTemplate restTemplate) { + this.config = config; + this.restTemplate = restTemplate; + } + + public PMEntity getPMData() throws UnsupportedEncodingException { + String dataCollectorUrl = config.getDataCollectorBaseUrl() + AGGREGATED_METRICS_URL + getQueryParams(); + URI uri = URI.create(dataCollectorUrl); + ResponseEntity<PMEntity> pmEntityResponse = restTemplate.getForEntity(uri, PMEntity.class); + return pmEntityResponse.getBody(); + } + + private String getQueryParams() throws UnsupportedEncodingException { + long slot = config.getPredictionTimeSlot(); + long count = config.getPredictionSlotNumber(); + String time = URLEncoder.encode(OffsetDateTime.now().minusSeconds(slot * count).toString(), + StandardCharsets.UTF_8.toString()); + return "?slot=" + slot + "&count=" + count + "&startTime=" + time; + } + + public UEInfo getUserEquipment() { + String dataCollectorUrl = config.getDataCollectorBaseUrl() + UES_URL; + ResponseEntity<UEInfo> userEquipmentResponse = restTemplate.getForEntity(dataCollectorUrl, UEInfo.class); + return userEquipmentResponse.getBody(); + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/JsonHelper.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/JsonHelper.java new file mode 100644 index 0000000..cc48ea5 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/JsonHelper.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.stereotype.Service; + +@Service +public class JsonHelper { + + private ObjectMapper mapper; + + public JsonHelper() { + this.mapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + public <T> T deserialize(String object, Class<T> clazz) { + try { + return mapper.readValue(object, clazz); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public String objectToJsonString(Object object) { + try { + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyAgentClient.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyAgentClient.java new file mode 100644 index 0000000..e6d3566 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyAgentClient.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.ServiceRegistrationPayload; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class PolicyAgentClient { + + private static final Logger logger = LoggerFactory.getLogger(PolicyAgentClient.class); + + public static final String SERVICE_KEEPALIVE_URL = "/services/keepalive?name="; + public static final String SERVICE_URL = "/service"; + public static final String POLICY_TYPES_URL = "/policy_types"; + public static final String POLICY_URL = "/policy"; + public static final String POLICIES_URL = "/policies"; + public static final String SCD_SERVICE_NAME = "rapp-sleepingcelldetector"; + public static final String RICS_POLICY_TYPE_URL = "/rics?policyType="; + public static final String POLICY_ACTOR_CALLBACK_URL = "http://rapp-sleepingcelldetector:8382/"; + + private final SleepingCellDetectorConfiguration config; + private final RestTemplate restTemplate; + private final JsonHelper jsonHelper; + + public PolicyAgentClient(SleepingCellDetectorConfiguration config, RestTemplate restTemplate, JsonHelper jsonHelper) { + this.config = config; + this.restTemplate = restTemplate; + this.jsonHelper = jsonHelper; + } + + public void sendPolicyEvent(PolicyInstance policy, RicConfiguration ricConfig) { + ricConfig.getPolicyTypes().forEach(policyType -> { + String policyServiceUrl = getUpdatePolicyUrl(ricConfig, policyType, policy.getId()); + String policyRequest = jsonHelper.objectToJsonString(policy.getJson()); + sendUpdatePolicyRequest(policyServiceUrl, policyRequest); + }); + } + + private String getUpdatePolicyUrl(RicConfiguration ricConfig, String policyTypeId, String policyId) { + String queryParams = POLICY_URL + "?id=" + policyId + "&ric=" + ricConfig.getRicName() + + "&service=" + SCD_SERVICE_NAME + "&type=" + policyTypeId; + return getA1PolicyBaseUrl() + queryParams; + } + + private void sendUpdatePolicyRequest(String policyServiceUrl, String policyRequest) { + logger.info("Sending policy event; URL: {},\n Policy: {}", policyServiceUrl, policyRequest); + restTemplate.put(policyServiceUrl, createPolicyUpdateRequestEntity(policyRequest)); + } + + private HttpEntity<String> createPolicyUpdateRequestEntity(String policy) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + return new HttpEntity<>(policy, headers); + } + + public void deletePolicyInstance(String id){ + try { + logger.info("Policy instance {} remove request will be send", id); + String deletePolicyUrl = getA1PolicyBaseUrl() + POLICY_URL + "?id=" + id; + restTemplate.delete(deletePolicyUrl); + } catch (Exception e){ + logger.warn("Exception during policy deletion: {} \nPolicy {} was already removed", e.getMessage(), id); + } + + } + + public List<String> getPoliciesIds() { + String policyIdsUrl = getA1PolicyBaseUrl() + POLICY_TYPES_URL; + ResponseEntity<String[]> policyIds = restTemplate.getForEntity(policyIdsUrl, String[].class); + return Arrays.asList(Objects.requireNonNull(policyIds.getBody())); + } + + public List<PolicyInstance> getPoliciesInstances(){ + String policiesUrl = getA1PolicyBaseUrl() + POLICIES_URL; + ResponseEntity<PolicyInstance[]> policiesResponse = restTemplate.getForEntity(policiesUrl, PolicyInstance[].class); + + if (policiesResponse.hasBody()){ + return Arrays.asList(policiesResponse.getBody()); + } else { + return Collections.emptyList(); + } + } + + public List<RicConfiguration> getRicConfigurationsByPolicyId(String policyId) { + String ricConfigUrl = getA1PolicyBaseUrl() + RICS_POLICY_TYPE_URL + policyId; + ResponseEntity<RicConfiguration[]> ricConfigResponse = restTemplate.getForEntity(ricConfigUrl, RicConfiguration[].class); + + if (ricConfigResponse.hasBody()){ + return Arrays.asList(ricConfigResponse.getBody()); + } else { + return Collections.emptyList(); + } + } + + public boolean createService() { + String createServiceUrl = getA1PolicyBaseUrl() + SERVICE_URL; + ServiceRegistrationPayload payload = buildPayload(); + HttpEntity<String> entity = prepareRequest(payload); + ResponseEntity<String> response = restTemplate.exchange(createServiceUrl, HttpMethod.PUT, entity, String.class); + + if (response.getStatusCode().is2xxSuccessful()) { + logger.info("Service created"); + return true; + } else { + logger.warn("Problem with service registration request, response: {}", response.getStatusCode()); + return false; + } + } + + private HttpEntity<String> prepareRequest(ServiceRegistrationPayload payload) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + return new HttpEntity<>(jsonHelper.objectToJsonString(payload), headers); + } + + private ServiceRegistrationPayload buildPayload() { + return ServiceRegistrationPayload.builder() + .callBackUrl(POLICY_ACTOR_CALLBACK_URL) + .keepAliveIntervalSeconds("20") + .serviceName(SCD_SERVICE_NAME) + .build(); + } + + public void sendKeepAliveRequest() { + String createServiceUrl = getA1PolicyBaseUrl() + SERVICE_KEEPALIVE_URL + SCD_SERVICE_NAME; + restTemplate.put(createServiceUrl, Void.class); + logger.info("Keep alive request performed"); + } + + private String getA1PolicyBaseUrl() { + return config.getA1PolicyBaseUrl(); + } + + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceBuilder.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceBuilder.java new file mode 100644 index 0000000..c2dcd5e --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceBuilder.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import com.google.common.collect.Lists; +import java.util.UUID; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.policy.A1PolicyEvent; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.onap.rapp.sleepingcelldetector.entity.policy.Preference; +import org.onap.rapp.sleepingcelldetector.entity.policy.Resources; +import org.onap.rapp.sleepingcelldetector.entity.policy.Scope; +import org.springframework.stereotype.Service; + +@Service +public class PolicyInstanceBuilder { + + public static final String SCD_SERVICE_NAME = "sleepingcelldetector"; + + public PolicyInstance buildPolicyInstance(String cell, String userEquipment, RicConfiguration ric) { + Scope scope = new Scope(userEquipment); + Resources resources = new Resources(Lists.newArrayList(cell), Preference.AVOID); + String id = UUID.randomUUID().toString(); + return PolicyInstance.builder() + .id(id) + .ric(ric.getRicName()) + .service(SCD_SERVICE_NAME) + .json(new A1PolicyEvent(scope, Lists.newArrayList(resources))) + .build(); + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceManager.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceManager.java new file mode 100644 index 0000000..bce6675 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceManager.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class PolicyInstanceManager { + + private static final Logger logger = LoggerFactory.getLogger(PolicyInstanceManager.class); + private Multimap<String, PolicyInstance> cellPolicyInstancesMap = ArrayListMultimap.create(); + + private final PolicyAgentClient policyAgentClient; + private final PolicyInstanceBuilder payloadBuilder; + + public PolicyInstanceManager(PolicyAgentClient policyAgentClient, PolicyInstanceBuilder payloadBuilder) { + this.policyAgentClient = policyAgentClient; + this.payloadBuilder = payloadBuilder; + } + + public boolean cellContainsPolicy(String cell) { + return cellPolicyInstancesMap.containsKey(cell); + } + + public boolean cellContainsPolicyForUe(String cell, String ue) { + if (cellContainsPolicy(cell)) { + List<PolicyInstance> policyInstances = new ArrayList<>(cellPolicyInstancesMap.get(cell)); + return policyInstances.stream().anyMatch(pi -> pi.getJson().getScope().getUeId().equals(ue)); + } + return false; + } + + public void createPolicyInstance(String cell, String ue, RicConfiguration ric) { + try { + PolicyInstance policy = payloadBuilder.buildPolicyInstance(cell, ue, ric); + cellPolicyInstancesMap.put(cell, policy); + policyAgentClient.sendPolicyEvent(policy, ric); + logger.info("Policy Instance for ue {}, cell {} created with id {}", ue, cell, policy.getId()); + } catch (Exception e) { + logger.error("Error during request to Policy Management Service: {}", e.getMessage()); + removePolicyInstancesForCell(cell); + } + } + + public void addPolicyInstance(PolicyInstance policyInstance) { + List<String> cells = policyInstance.getJson().getResources() + .stream().flatMap(resources -> resources.getCellIdList().stream()).collect(Collectors.toList()); + cells.forEach(cell -> cellPolicyInstancesMap.put(cell, policyInstance)); + } + + public void removePolicyInstancesForCell(String cell) { + Collection<PolicyInstance> policyInstancesByCell = cellPolicyInstancesMap.get(cell); + policyInstancesByCell.forEach(pi -> policyAgentClient.deletePolicyInstance(pi.getId())); + cellPolicyInstancesMap.removeAll(cell); + logger.info("Policy Instances for cell {} removed", cell); + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/RicConfigurationHolder.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/RicConfigurationHolder.java new file mode 100644 index 0000000..da89fe8 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/RicConfigurationHolder.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import java.util.Optional; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class RicConfigurationHolder { + + private static final Logger logger = LoggerFactory.getLogger(RicConfigurationHolder.class); + + private RicConfiguration ricConfiguration; + + public void addRic(RicConfiguration ricConfig, String policyTypeId) { + logger.info("Adding ric configuration for Policy Type {}, config: {}", policyTypeId, ricConfig); + ricConfiguration = ricConfig; + } + + public Optional<RicConfiguration> getRicConfig() { + return Optional.of(ricConfiguration); + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/RicConfigurationManager.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/RicConfigurationManager.java new file mode 100644 index 0000000..9253865 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/RicConfigurationManager.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import javax.annotation.PostConstruct; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class RicConfigurationManager { + + private static final Logger logger = LoggerFactory.getLogger(RicConfigurationManager.class); + + private final RicConfigurationHolder ricConfigurationHolder; + private final PolicyInstanceManager policyInstanceManager; + private final PolicyAgentClient policyAgentClient; + + public RicConfigurationManager(RicConfigurationHolder ricConfigurationHolder, PolicyAgentClient policyAgentClient, + PolicyInstanceManager policyInstanceManager + ) { + this.ricConfigurationHolder = ricConfigurationHolder; + this.policyAgentClient = policyAgentClient; + this.policyInstanceManager = policyInstanceManager; + } + + @PostConstruct + private void getRicConfigurations() throws InterruptedException { + logger.info("Policy fetching process started"); + boolean ricConfigUploadStatus = false; + while (!ricConfigUploadStatus) { + ricConfigUploadStatus = getRicConfigs(); + TimeUnit.SECONDS.sleep(10); + } + } + + private boolean getRicConfigs() { + try { + List<String> policyIds = policyAgentClient.getPoliciesIds(); + + if (policyIds.isEmpty()) { + logger.warn("Problems with ric configuration fetching; Next try in 10 sec"); + return false; + } + + saveRicConfiguration(policyIds); + policyIds.forEach(this::verifyExistingPolicyInstances); + logger.info("Policy fetching process ended successfully"); + return true; + } catch (Exception e) { + logger.error("Problems with ric configuration fetching; Next try in 10 sec: " + e.getMessage()); + return false; + } + } + + private void saveRicConfiguration(List<String> policyIds) { + policyIds.forEach(policyId -> { + logger.info("Saving ric configurations for policyId {}", policyId); + List<RicConfiguration> ricConfigs = policyAgentClient.getRicConfigurationsByPolicyId(policyId); + ricConfigs.forEach(rc -> ricConfigurationHolder.addRic(rc, policyId)); + }); + } + + private void verifyExistingPolicyInstances(String policyTypeId) { + List<PolicyInstance> policyInstances = policyAgentClient.getPoliciesInstances(); + if (policyInstances.isEmpty()) { + logger.info("No policy instances of type {}", policyTypeId); + } else { + policyInstances.stream() + .filter(pi -> pi.getType().equals(policyTypeId)) + .forEach(this::addPolicyInstance); + } + } + + private void addPolicyInstance(PolicyInstance pi) { + policyInstanceManager.addPolicyInstance(pi); + logger.info("Policy Instance of type {} and id {} added on startup", pi.getType(), pi.getId()); + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/ServiceLifeCycleManager.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/ServiceLifeCycleManager.java new file mode 100644 index 0000000..70407e8 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/ServiceLifeCycleManager.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import java.util.concurrent.TimeUnit; +import javax.annotation.PostConstruct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +@Service +public class ServiceLifeCycleManager { + + private static final Logger logger = LoggerFactory.getLogger(ServiceLifeCycleManager.class); + private final PolicyAgentClient policyAPIClient; + + public ServiceLifeCycleManager(PolicyAgentClient policyAPIClient) { + this.policyAPIClient = policyAPIClient; + } + + @PostConstruct + private void createService() { + logger.info("Registering policy actor service"); + + boolean serviceCreated = false; + while (!serviceCreated) { + try { + serviceCreated = policyAPIClient.createService(); + TimeUnit.SECONDS.sleep(10); + } catch (Exception e) { + logger.error("Error during service registration {}", e.getMessage()); + } + } + } + + @Scheduled(fixedRate = 20000) + private void keepAlive() { + try { + logger.info("Send keep alive request"); + policyAPIClient.sendKeepAliveRequest(); + } catch (Exception e) { + logger.warn("Error during keep alive request {}", e.getMessage()); + createService(); + } + + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/CalculationUtil.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/CalculationUtil.java new file mode 100644 index 0000000..95aecae --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/CalculationUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.List; +import java.util.Objects; +import java.util.OptionalDouble; +import java.util.stream.Collectors; + +public class CalculationUtil { + + private static final Logger logger = LoggerFactory.getLogger(CalculationUtil .class); + public static final int MIN_PERCENTAGE_OF_DATA_FILLING = 30; + + private CalculationUtil(){ + } + + public static Integer calculateAverage(List<Integer> values){ + OptionalDouble average = values.stream().mapToDouble(l -> l).average(); + + if (average.isPresent()) { + return (int) average.getAsDouble(); + } else { + throw new ArithmeticException("Can't calculate average"); + } + } + + public static List<Integer> fillGaps(List<Integer> values){ + verifyDataFilling(values); + Integer average = calculateAverage(values.stream().filter(Objects::nonNull).collect(Collectors.toList())); + + for (int i=0; i<values.size(); i++){ + if(values.get(i) == null){ + values.set(i, average); + } + } + return values; + } + + public static void verifyDataFilling(List<Integer> values) { + double measurementsNumber = values.stream().filter(Objects::nonNull).count(); + double listSize = values.size(); + double dataFillingPercentage = measurementsNumber/listSize * 100; + if (dataFillingPercentage < MIN_PERCENTAGE_OF_DATA_FILLING){ + logger.warn("Not enough data to make prediction, must be at least 30%; Data filling: {}%", dataFillingPercentage); + throw new ArithmeticException("Not enough performance data for prediction, data filling: " + dataFillingPercentage + "%"); + } + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/SleepingCellDetectorService.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/SleepingCellDetectorService.java new file mode 100644 index 0000000..f942162 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/SleepingCellDetectorService.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.MeasurementConfiguration; +import org.onap.rapp.sleepingcelldetector.service.JsonHelper; +import org.onap.rapp.sleepingcelldetector.service.scd.condition.Condition; +import org.onap.rapp.sleepingcelldetector.service.scd.condition.ConditionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SleepingCellDetectorService { + + private static final Logger logger = LoggerFactory.getLogger(SleepingCellDetectorService.class); + + private final JsonHelper jsonHelper; + private final SleepingCellDetectorConfiguration configuration; + + protected Map<String, MeasurementConfiguration> measurementMap = new HashMap<>(); + + @Autowired + public SleepingCellDetectorService(JsonHelper jsonHelper, SleepingCellDetectorConfiguration configuration) { + this.jsonHelper = jsonHelper; + this.configuration = configuration; + } + + @PostConstruct + public void loadConditionMap() throws Exception { + logger.info("TCA config fetching process started"); + boolean tcaConfigUploadStatus = false; + while (!tcaConfigUploadStatus) { + tcaConfigUploadStatus = getTCAConfig(); + TimeUnit.SECONDS.sleep(10); + } + } + + private boolean getTCAConfig() { + try { + InputStream in = this.getClass().getResourceAsStream("/tca.json"); + BufferedReader inr = new BufferedReader(new InputStreamReader(in)); + String tcaConfig = inr.lines().collect(Collectors.joining(" ")); + + MeasurementConfiguration[] measurementConfigurations = jsonHelper.deserialize(tcaConfig, MeasurementConfiguration[].class); + Arrays.stream(measurementConfigurations).forEach(mf -> measurementMap.put(mf.getName(), mf)); + return true; + } catch (Exception e) { + logger.error("Error during loading Measurement Configuration for TCA: {}", e.getMessage()); + return false; + } + } + + public Boolean isFailing(List<Map<String, Integer>> performanceData) { + Map<String, List<Integer>> measurementValuesMap = groupMeasurementValues(performanceData); + + measurementValuesMap.forEach((fieldName, values) -> { + if (containsEmptyValues(values)) { + CalculationUtil.fillGaps(values); + } + }); + + List<Boolean> predictions = new ArrayList<>(); + measurementValuesMap.forEach((fieldName, values) -> predictions.add(isFailing(values, measurementMap.get(fieldName)))); + + return predictions.contains(true); + } + + private Map<String, List<Integer>> groupMeasurementValues(List<Map<String, Integer>> performanceData) { + Map<String, List<Integer>> measurementValuesMap = prepareMeasurementMap(); + + performanceData.forEach(pm -> measurementMap.forEach((fieldName, configuration) -> { + Integer measurement = pm.get(fieldName); + List<Integer> measurements = measurementValuesMap.get(fieldName); + measurements.add(measurement); + })); + + return measurementValuesMap; + } + + private Map<String, List<Integer>> prepareMeasurementMap() { + Map<String, List<Integer>> measurementValuesMap = new HashMap<>(); + measurementMap.forEach((fieldName, values) -> measurementValuesMap.put(fieldName, new ArrayList<>())); + return measurementValuesMap; + } + + private boolean containsEmptyValues(List<Integer> performanceData) { + for (Integer value : performanceData) { + if (value == null) { + return true; + } + } + return false; + } + + private Boolean isFailing(List<Integer> values, MeasurementConfiguration measurementConfiguration) { + Condition condition = ConditionFactory.getCondition(measurementConfiguration.getCondition()); + Integer totalAverage = CalculationUtil.calculateAverage(values); + Integer latestAverage = CalculationUtil.calculateAverage(values.stream() + .skip(configuration.getPredictionSlotNumber() - measurementConfiguration.getLatestSize()) + .collect(Collectors.toList())); + + return condition.compare(totalAverage, measurementConfiguration.getAverageThresholdValue()) + && condition.compare(latestAverage, measurementConfiguration.getLatestThresholdValue()); + } + +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Condition.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Condition.java new file mode 100644 index 0000000..d6b6153 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Condition.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public interface Condition { + boolean compare(int value, int toCompare); +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/ConditionEnum.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/ConditionEnum.java new file mode 100644 index 0000000..e4279ec --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/ConditionEnum.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public enum ConditionEnum { + MORE(), + MORE_OR_EQUAL(), + LESS(), + LESS_OR_EQUAL(), + EQUAL(); + + private ConditionEnum(){ + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/ConditionFactory.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/ConditionFactory.java new file mode 100644 index 0000000..a2f07c1 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/ConditionFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public class ConditionFactory { + + private static final Condition less = new Less(); + private static final Condition more = new More(); + private static final Condition equal = new Equal(); + private static final Condition lessOrEqual = new LessOrEqual(); + private static final Condition moreOrEqual= new MoreOrEqual(); + + + public static Condition getCondition(ConditionEnum condition) { + switch (condition) { + case LESS: + return less; + case MORE: + return more; + case EQUAL: + return equal; + case LESS_OR_EQUAL: + return lessOrEqual; + case MORE_OR_EQUAL: + return moreOrEqual; + default: + throw new RuntimeException("Can't find operation for condition \" " + condition + "\""); + } + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Equal.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Equal.java new file mode 100644 index 0000000..c4d9940 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Equal.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public class Equal implements Condition { + + @Override + public boolean compare(int value, int toCompare) { + return value == toCompare; + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Less.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Less.java new file mode 100644 index 0000000..7d6db87 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/Less.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public class Less implements Condition { + + @Override + public boolean compare(int value, int toCompare) { + return value < toCompare; + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/LessOrEqual.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/LessOrEqual.java new file mode 100644 index 0000000..2abd5a3 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/LessOrEqual.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public class LessOrEqual implements Condition { + + @Override + public boolean compare(int value, int toCompare) { + return value <= toCompare; + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/More.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/More.java new file mode 100644 index 0000000..b257e30 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/More.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public class More implements Condition { + + @Override + public boolean compare(int value, int toCompare) { + return value > toCompare; + } +} diff --git a/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/MoreOrEqual.java b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/MoreOrEqual.java new file mode 100644 index 0000000..37e9496 --- /dev/null +++ b/sleepingcelldetector/src/main/java/org/onap/rapp/sleepingcelldetector/service/scd/condition/MoreOrEqual.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd.condition; + +public class MoreOrEqual implements Condition { + + @Override + public boolean compare(int value, int toCompare) { + return value >= toCompare; + } +} diff --git a/sleepingcelldetector/src/main/resources/application.yml b/sleepingcelldetector/src/main/resources/application.yml new file mode 100644 index 0000000..bfa3982 --- /dev/null +++ b/sleepingcelldetector/src/main/resources/application.yml @@ -0,0 +1,21 @@ +server: + port: 8382 +a1: + host: "policy-agent" + port: 8081 +dc: + host: "localhost" + port: 8087 + version: "v1" +scd: + prefix: "emergency" + slot: 10 + count: 12 +logging: + level: + org: + springframework: DEBUG + logging.file.name: logs/rapp-sleepingcelldetector.log + pattern: + console: "%d %-5level %logger : %msg%n" + file: "%d %-5level [%thread] %logger : %msg%n" diff --git a/sleepingcelldetector/src/main/resources/tca.json b/sleepingcelldetector/src/main/resources/tca.json new file mode 100644 index 0000000..3d7baaa --- /dev/null +++ b/sleepingcelldetector/src/main/resources/tca.json @@ -0,0 +1,16 @@ +[ + { + "name": "latency", + "condition": "MORE_OR_EQUAL", + "averageThresholdValue": 400, + "latestThresholdValue": 150, + "latestSize": 2 + }, + { + "name": "throughput", + "condition": "LESS_OR_EQUAL", + "averageThresholdValue": 10, + "latestThresholdValue": 10, + "latestSize": 2 + } +] diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorConfigurationTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorConfigurationTest.java new file mode 100644 index 0000000..dbf59d4 --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/configuration/SleepingCellDetectorConfigurationTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.configuration; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@ComponentScan("org.onap.rapp.sleepingcelldetector.configuration") +@EnableConfigurationProperties({A1Properties.class, DataCollectorProperties.class, + SleepingCellDetectorProperties.class}) +@ContextConfiguration(classes = {SleepingCellDetectorConfiguration.class}) +@TestPropertySource(properties = {"a1.host=policy-agent", "a1.port=8081", + "dc.host=rapp-datacollector", + "dc.port=8087", + "dc.version=v1", + "scd.prefix=emergency", + "scd.slot=10", + "scd.count=12" +}) +public class SleepingCellDetectorConfigurationTest { + + @Autowired() + private SleepingCellDetectorConfiguration config; + + @Test + public void verifyPolicyAgentUrlConstructionTest() { + final String actual = config.getA1PolicyBaseUrl(); + final String expected = "http://policy-agent:8081"; + + Assert.assertEquals(expected, actual); + } + + @Test + public void verifyDataCollectorUrlConstructionTest() { + final String actual = config.getDataCollectorBaseUrl(); + final String expected = "http://rapp-datacollector:8087/v1"; + + Assert.assertEquals(expected, actual); + } + + @Test + public void verifyA1PAPropertiesTest() { + Assert.assertEquals(config.getPredictionTimeSlot(), 10); + Assert.assertEquals(config.getPredictionSlotNumber(), 12); + Assert.assertEquals(config.getUeFilteringPrefix(), "emergency"); + } +} diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceHandlerTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceHandlerTest.java new file mode 100644 index 0000000..7a72c61 --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/CellPerformanceHandlerTest.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.ue.UEInfo; +import org.onap.rapp.sleepingcelldetector.service.scd.SleepingCellDetectorService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@RunWith(MockitoJUnitRunner.class) +public class CellPerformanceHandlerTest { + + @Mock + private SleepingCellDetectorService scdClient; + + @Mock + private RicConfigurationHolder ricConfigHolder; + + @Mock + private PolicyInstanceManager policyInstancesManager; + + @Mock + private SleepingCellDetectorConfiguration config; + + @Mock + private DataCollectorClient dcClient; + + private CellPerformanceHandler cellPerformanceHandler; + + @Before + public void init() { + cellPerformanceHandler = new CellPerformanceHandler(scdClient, ricConfigHolder, policyInstancesManager, config, dcClient); + } + + @Test + public void handleActiveCellTest() { + List<Map<String, Integer>> performanceData = getPMDataList(20, 80); + Mockito.when(scdClient.isFailing(performanceData)).thenReturn(false); + Mockito.when(policyInstancesManager.cellContainsPolicy("Cell1")).thenReturn(false); + + cellPerformanceHandler.handleCellPerformance("Cell1", performanceData); + + Mockito.verify(scdClient, Mockito.times(1)).isFailing(performanceData); + Mockito.verify(policyInstancesManager, Mockito.times(1)).cellContainsPolicy("Cell1"); + Mockito.verify(policyInstancesManager, Mockito.times(0)).removePolicyInstancesForCell("Cell1"); + } + + @Test + public void handleActiveCellWithPolicyTest() { + List<Map<String, Integer>> performanceData = getPMDataList(20, 80); + Mockito.when(scdClient.isFailing( performanceData)).thenReturn(false); + Mockito.when(policyInstancesManager.cellContainsPolicy("Cell1")).thenReturn(true); + + cellPerformanceHandler.handleCellPerformance("Cell1", performanceData); + + Mockito.verify(scdClient, Mockito.times(1)).isFailing( performanceData); + Mockito.verify(policyInstancesManager, Mockito.times(1)).cellContainsPolicy("Cell1"); + Mockito.verify(policyInstancesManager, Mockito.times(1)).removePolicyInstancesForCell("Cell1"); + } + + @Test + public void handleFailingCellTest() { + List<Map<String, Integer>> performanceData = getPMDataList(300, 2); + Optional<RicConfiguration> ricConfiguration = getRicConfig(); + Mockito.when(scdClient.isFailing(performanceData)).thenReturn(true); + Mockito.when(policyInstancesManager.cellContainsPolicyForUe("Cell1", "emergency_samsung_s10_01")).thenReturn(false); + Mockito.when(policyInstancesManager.cellContainsPolicyForUe("Cell1", "emergency_police_01")).thenReturn(false); + Mockito.when(ricConfigHolder.getRicConfig()).thenReturn(ricConfiguration); + Mockito.when(dcClient.getUserEquipment()).thenReturn(getUEInfo()); + Mockito.when(config.getUeFilteringPrefix()).thenReturn("emergency"); + + cellPerformanceHandler.handleCellPerformance("Cell1", performanceData); + + Mockito.verify(scdClient, Mockito.times(1)).isFailing( performanceData); + Mockito.verify(policyInstancesManager, Mockito.times(1)).cellContainsPolicyForUe("Cell1", "emergency_samsung_s10_01"); + Mockito.verify(policyInstancesManager, Mockito.times(1)).cellContainsPolicyForUe("Cell1", "emergency_police_01"); + Mockito.verify(policyInstancesManager, Mockito.times(1)).createPolicyInstance("Cell1", "emergency_samsung_s10_01", ricConfiguration.get()); + Mockito.verify(policyInstancesManager, Mockito.times(1)).createPolicyInstance("Cell1", "emergency_police_01", ricConfiguration.get()); + } + + @Test + public void handleFailingCellForUeWithPolicyTest() { + List<Map<String, Integer>> performanceData = getPMDataList(300, 2); + Optional<RicConfiguration> ricConfiguration = getRicConfig(); + Mockito.when(scdClient.isFailing( performanceData)).thenReturn(true); + Mockito.when(policyInstancesManager.cellContainsPolicyForUe("Cell1", "emergency_samsung_s10_01")).thenReturn(false); + Mockito.when(policyInstancesManager.cellContainsPolicyForUe("Cell1", "emergency_police_01")).thenReturn(true); + Mockito.when(ricConfigHolder.getRicConfig()).thenReturn(ricConfiguration); + Mockito.when(dcClient.getUserEquipment()).thenReturn(getUEInfo()); + Mockito.when(config.getUeFilteringPrefix()).thenReturn("emergency"); + + cellPerformanceHandler.handleCellPerformance("Cell1", performanceData); + + Mockito.verify(scdClient, Mockito.times(1)).isFailing(performanceData); + Mockito.verify(policyInstancesManager, Mockito.times(1)).cellContainsPolicyForUe("Cell1", "emergency_samsung_s10_01"); + Mockito.verify(policyInstancesManager, Mockito.times(1)).cellContainsPolicyForUe("Cell1", "emergency_police_01"); + Mockito.verify(policyInstancesManager, Mockito.times(1)).createPolicyInstance("Cell1", "emergency_samsung_s10_01", ricConfiguration.get()); + Mockito.verify(policyInstancesManager, Mockito.times(0)).createPolicyInstance("Cell1", "emergency_police_01", ricConfiguration.get()); + } + + @Test + public void handleFailingCellForEmptyRicConfigTest() { + List<Map<String, Integer>> performanceData = getPMDataList(300, 2); + Optional<RicConfiguration> ricConfiguration = getRicConfig(); + Mockito.when(scdClient.isFailing( performanceData)).thenReturn(true); + Mockito.when(ricConfigHolder.getRicConfig()).thenReturn(Optional.empty()); + + cellPerformanceHandler.handleCellPerformance("Cell1", performanceData); + + Mockito.verify(scdClient, Mockito.times(1)).isFailing(performanceData); + Mockito.verify(policyInstancesManager, Mockito.times(0)).cellContainsPolicyForUe("Cell1", "emergency_samsung_s10_01"); + Mockito.verify(policyInstancesManager, Mockito.times(0)).cellContainsPolicyForUe("Cell1", "emergency_police_01"); + Mockito.verify(policyInstancesManager, Mockito.times(0)).createPolicyInstance("Cell1", "emergency_samsung_s10_01", ricConfiguration.get()); + Mockito.verify(policyInstancesManager, Mockito.times(0)).createPolicyInstance("Cell1", "emergency_police_01", ricConfiguration.get()); + } + + @Test + public void handleFailingCellForEmptyUeListTest() { + List<Map<String, Integer>> performanceData = getPMDataList(300, 2); + Optional<RicConfiguration> ricConfiguration = getRicConfig(); + Mockito.when(scdClient.isFailing( performanceData)).thenReturn(true); + Mockito.when(ricConfigHolder.getRicConfig()).thenReturn(ricConfiguration); + Mockito.when(dcClient.getUserEquipment()).thenReturn(new UEInfo(Collections.emptyList())); + + cellPerformanceHandler.handleCellPerformance("Cell1", performanceData); + + Mockito.verify(scdClient, Mockito.times(1)).isFailing(performanceData); + Mockito.verify(policyInstancesManager, Mockito.times(0)).cellContainsPolicyForUe("Cell1", "emergency_samsung_s10_01"); + Mockito.verify(policyInstancesManager, Mockito.times(0)).cellContainsPolicyForUe("Cell1", "emergency_police_01"); + Mockito.verify(policyInstancesManager, Mockito.times(0)).createPolicyInstance("Cell1", "emergency_samsung_s10_01", ricConfiguration.get()); + Mockito.verify(policyInstancesManager, Mockito.times(0)).createPolicyInstance("Cell1", "emergency_police_01", ricConfiguration.get()); + } + + public static List<Map<String, Integer>> getPMDataList(int latency, int throughput) { + List<Map<String, Integer>> performanceData = new ArrayList<>(); + for (int i = 0; i < 12; i++) { + Map<String, Integer> measurement = new HashMap<>(); + measurement.put("latency", latency); + measurement.put("throughput", throughput); + performanceData.add(measurement); + } + return performanceData; + } + + private Optional<RicConfiguration> getRicConfig() { + return Optional.of(new RicConfiguration("ric1", Collections.emptyList(), List.of("1000"), "AVAILABLE")); + } + + private UEInfo getUEInfo() { + return new UEInfo(List.of("emergency_samsung_s10_01", "mobile_samsung_s20_02", "emergency_police_01")); + } + +} diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/JsonHelperTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/JsonHelperTest.java new file mode 100644 index 0000000..e6768e4 --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/JsonHelperTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import com.google.common.collect.Lists; +import org.onap.rapp.sleepingcelldetector.entity.MeasurementConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.policy.A1PolicyEvent; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.onap.rapp.sleepingcelldetector.entity.policy.Preference; +import org.onap.rapp.sleepingcelldetector.entity.policy.Resources; +import org.onap.rapp.sleepingcelldetector.entity.policy.Scope; +import org.onap.rapp.sleepingcelldetector.service.scd.condition.ConditionEnum; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JsonHelperTest { + + private static final String policy = "{\r\n" + + " \"id\" : \"1\",\r\n" + + " \"type\" : \"1000\",\r\n" + + " \"ric\" : \"ric1\",\r\n" + + " \"service\" : \"sleepingcelldetector\",\r\n" + + " \"lastModified\" : null,\r\n" + + " \"json\" : {\r\n" + + " \"scope\" : {\r\n" + + " \"ueId\" : \"ue_1\"\r\n" + + " },\r\n" + + " \"resources\" : [ {\r\n" + + " \"cellIdList\" : [ \"Cell1\" ],\r\n" + + " \"preference\" : \"AVOID\"\r\n" + + " } ]\r\n" + + " }\r\n" + + "}"; + + private static final String tcaConfig = "[\n" + + " {\n" + + " \"name\": \"latency\",\n" + + " \"condition\": \"MORE_OR_EQUAL\",\n" + + " \"averageThresholdValue\": 400,\n" + + " \"latestThresholdValue\": 150,\n" + + " \"latestSize\" : 2\n" + + " },\n" + + " {\n" + + " \"name\": \"throughput\",\n" + + " \"condition\": \"LESS_OR_EQUAL\",\n" + + " \"averageThresholdValue\": 10,\n" + + " \"latestThresholdValue\": 10,\n" + + " \"latestSize\" : 2\n" + + " }\n" + + "]"; + + JsonHelper jsonHelper; + + @Before() + public void initialSetUp() { + jsonHelper = new JsonHelper(); + } + + @Test + public void policyToJsonStringTest() { + PolicyInstance instance = getPolicyToCompare(); + assertThat(policy).isEqualToNormalizingNewlines(jsonHelper.objectToJsonString(instance)); + } + + @Test + public void tcaConfigDeserializeTest() { + MeasurementConfiguration[] configurations = jsonHelper.deserialize(tcaConfig, MeasurementConfiguration[].class); + assertThat(configurations).isEqualTo(prepareTcaConfig()); + } + + private PolicyInstance getPolicyToCompare() { + Scope scope = new Scope("ue_1"); + Resources resources = new Resources(Lists.newArrayList("Cell1"), Preference.AVOID); + return PolicyInstance.builder() + .json(new A1PolicyEvent(scope, Lists.newArrayList(resources))) + .service("sleepingcelldetector") + .ric("ric1") + .id("1") + .type("1000") + .build(); + } + + private MeasurementConfiguration[] prepareTcaConfig() { + MeasurementConfiguration latencyConfig = new MeasurementConfiguration("latency", ConditionEnum.MORE_OR_EQUAL, 400, 150, 2); + MeasurementConfiguration throughputConfig = new MeasurementConfiguration("throughput", ConditionEnum.LESS_OR_EQUAL, 10, 10, 2); + return new MeasurementConfiguration[]{latencyConfig, throughputConfig}; + } + +} diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyAgentClientTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyAgentClientTest.java new file mode 100644 index 0000000..8eb2a31 --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyAgentClientTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import com.google.common.collect.Lists; +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.policy.A1PolicyEvent; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.onap.rapp.sleepingcelldetector.entity.policy.Preference; +import org.onap.rapp.sleepingcelldetector.entity.policy.Resources; +import org.onap.rapp.sleepingcelldetector.entity.policy.Scope; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.web.client.RestTemplate; +import java.util.Collections; +import java.util.List; + +@RunWith(MockitoJUnitRunner.class) +public class PolicyAgentClientTest { + + @Mock + SleepingCellDetectorConfiguration config; + + @Mock + RestTemplate restTemplate; + + @Mock + JsonHelper jsonHelper; + + private static final String policy = "{\r\n" + + " \"scope\" : {\r\n" + + " \"ueId\" : \"ue_1\"\r\n" + + " },\r\n" + + " \"resources\" : [ {\r\n" + + " \"cellIdList\" : [ \"Cell1\" ],\r\n" + + " \"preference\" : \"AVOID\"\r\n" + + " } ]\r\n" + + "}"; + + PolicyAgentClient policyAgentClient; + + @Before + public void init() throws Exception { + policyAgentClient = new PolicyAgentClient(config, restTemplate, jsonHelper); + } + + @Test + public void sendPolicyTest(){ + PolicyInstance instance = getPolicyInstance(); + RicConfiguration ricConfiguration = getRicConfig(); + Mockito.when(config.getA1PolicyBaseUrl()).thenReturn("http://rapp-datacollector:8087"); + Mockito.when(jsonHelper.objectToJsonString(instance.getJson())).thenReturn(policy); + + policyAgentClient.sendPolicyEvent(instance, ricConfiguration); + + Mockito.verify(config, Mockito.times(1)).getA1PolicyBaseUrl(); + Mockito.verify(restTemplate, Mockito.times(1)).put("http://rapp-datacollector:8087/policy?id=1&ric=ric1&service=rapp-sleepingcelldetector&type=1000", getHttpEntity(policy)); + } + + @Test + public void removePolicyTest(){ + Mockito.when(config.getA1PolicyBaseUrl()).thenReturn("http://rapp-datacollector:8087"); + + policyAgentClient.deletePolicyInstance("1"); + + Mockito.verify(config, Mockito.times(1)).getA1PolicyBaseUrl(); + Mockito.verify(restTemplate, Mockito.times(1)).delete("http://rapp-datacollector:8087/policy?id=1"); + } + + private PolicyInstance getPolicyInstance() { + Scope scope = new Scope("ue_1"); + Resources resources = new Resources(Lists.newArrayList("Cell1"), Preference.AVOID); + return PolicyInstance.builder() + .json(new A1PolicyEvent(scope, Lists.newArrayList(resources))) + .service("sleepingcelldetector") + .ric("ric1") + .id("1") + .type("1000") + .build(); + } + + private RicConfiguration getRicConfig() { + return new RicConfiguration("ric1", Collections.emptyList(), List.of("1000"), "AVAILABLE"); + } + + private HttpEntity<String> getHttpEntity(String policy) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + return new HttpEntity<>(policy, headers); + } +} diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceBuilderTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceBuilderTest.java new file mode 100644 index 0000000..5c6b459 --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceBuilderTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import com.google.common.collect.Lists; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.policy.A1PolicyEvent; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.onap.rapp.sleepingcelldetector.entity.policy.Preference; +import org.onap.rapp.sleepingcelldetector.entity.policy.Resources; +import org.onap.rapp.sleepingcelldetector.entity.policy.Scope; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +import java.util.List; + +public class PolicyInstanceBuilderTest { + + private PolicyInstanceBuilder policyInstanceBuilder; + + @Test + public void buildPolicyInstanceTest(){ + policyInstanceBuilder = new PolicyInstanceBuilder(); + PolicyInstance policyToCompare = getPolicyToCompare(); + RicConfiguration ricConfiguration = getRicConfig(); + + PolicyInstance policy = policyInstanceBuilder.buildPolicyInstance("Cell1", "ue_1", ricConfiguration); + + Assert.assertEquals(policy.getJson(), policyToCompare.getJson()); + Assert.assertEquals(policy.getLastModified(), policyToCompare.getLastModified()); + Assert.assertEquals(policy.getService(), policyToCompare.getService()); + Assert.assertEquals(policy.getRic(), policyToCompare.getRic()); + } + + private PolicyInstance getPolicyToCompare() { + Scope scope = new Scope("ue_1"); + Resources resources = new Resources(Lists.newArrayList("Cell1"), Preference.AVOID); + return PolicyInstance.builder() + .json(new A1PolicyEvent(scope, Lists.newArrayList(resources))) + .service("sleepingcelldetector") + .ric("ric1") + .build(); + } + + private RicConfiguration getRicConfig() { + return new RicConfiguration("ric1", Collections.emptyList(), List.of("1000"), "AVAILABLE"); + } + +} diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceManagerTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceManagerTest.java new file mode 100644 index 0000000..64277de --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/PolicyInstanceManagerTest.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service; + +import com.google.common.collect.Lists; +import org.onap.rapp.sleepingcelldetector.entity.RicConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.policy.A1PolicyEvent; +import org.onap.rapp.sleepingcelldetector.entity.policy.PolicyInstance; +import org.onap.rapp.sleepingcelldetector.entity.policy.Preference; +import org.onap.rapp.sleepingcelldetector.entity.policy.Resources; +import org.onap.rapp.sleepingcelldetector.entity.policy.Scope; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Collections; +import java.util.List; + +@RunWith(MockitoJUnitRunner.class) +public class PolicyInstanceManagerTest { + + @Mock + PolicyAgentClient policyAgentClient; + + @Mock + PolicyInstanceBuilder policyInstanceBuilder; + + PolicyInstanceManager policyInstanceManager; + + @Test + public void createInstanceTest() { + initPolicyInstanceManager(); + RicConfiguration ricConfiguration = getRicConfig(); + PolicyInstance policyInstance = getPolicy(ricConfiguration); + Mockito.when(policyInstanceBuilder.buildPolicyInstance("Cell1", "ue_1", ricConfiguration)) + .thenReturn(policyInstance); + + Mockito.doNothing().when(policyAgentClient).sendPolicyEvent(policyInstance, ricConfiguration); + + policyInstanceManager.createPolicyInstance("Cell1", "ue_1", ricConfiguration); + + Mockito.verify(policyAgentClient, Mockito.times(1)).sendPolicyEvent(policyInstance, ricConfiguration); + containsPolicyTest(policyInstanceManager); + } + + @Test + public void addInstanceTest(){ + initPolicyInstanceManager(); + RicConfiguration ricConfiguration = getRicConfig(); + PolicyInstance policyInstance = getPolicy(ricConfiguration); + + policyInstanceManager.addPolicyInstance(policyInstance); + containsPolicyTest(policyInstanceManager); + } + + @Test + public void removeInstanceTest(){ + initPolicyInstanceManager(); + RicConfiguration ricConfiguration = getRicConfig(); + PolicyInstance policyInstance = getPolicy(ricConfiguration); + + policyInstanceManager.addPolicyInstance(policyInstance); + policyInstanceManager.removePolicyInstancesForCell("Cell1"); + Assert.assertFalse(policyInstanceManager.cellContainsPolicy("Cell1")); + Assert.assertFalse(policyInstanceManager.cellContainsPolicyForUe("Cell1", "ue_1")); + } + + + private void containsPolicyTest(PolicyInstanceManager policyInstanceManager){ + Assert.assertTrue(policyInstanceManager.cellContainsPolicy("Cell1")); + Assert.assertTrue(policyInstanceManager.cellContainsPolicyForUe("Cell1", "ue_1")); + Assert.assertFalse(policyInstanceManager.cellContainsPolicy("Cell2")); + Assert.assertFalse(policyInstanceManager.cellContainsPolicyForUe("Cell2", "ue_1")); + Assert.assertFalse(policyInstanceManager.cellContainsPolicyForUe("Cell1", "ue_2")); + Assert.assertFalse(policyInstanceManager.cellContainsPolicyForUe("Cell2", "ue_2")); + } + + private void initPolicyInstanceManager(){ + policyInstanceManager = new PolicyInstanceManager(policyAgentClient, policyInstanceBuilder); + } + + + private RicConfiguration getRicConfig() { + return new RicConfiguration("ric1", Collections.emptyList(), List.of("1000"), "AVAILABLE"); + } + + private PolicyInstance getPolicy(RicConfiguration configuration) { + Scope scope = new Scope("ue_1"); + Resources resources = new Resources(Lists.newArrayList("Cell1"), Preference.AVOID); + return PolicyInstance.builder() + .json(new A1PolicyEvent(scope, Lists.newArrayList(resources))) + .service("sleepingcelldetector") + .ric(configuration.getRicName()) + .build(); + } +} diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/scd/CalculationUtilTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/scd/CalculationUtilTest.java new file mode 100644 index 0000000..f402fe9 --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/scd/CalculationUtilTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd; + +import org.assertj.core.util.Lists; +import org.junit.Assert; +import org.junit.Test; +import java.util.List; + +public class CalculationUtilTest { + + @Test + public void calculateAverageTest(){ + List<Integer> integers = Lists.list(1,2,3,4,5,6,7,8,9); + Assert.assertEquals(CalculationUtil.calculateAverage(integers), Integer.valueOf(5)); + } + + @Test + public void calculateAverageWithSameValuesTest(){ + List<Integer> integers = Lists.list(1,1,1,1,1,1,1,1,1); + Assert.assertEquals(CalculationUtil.calculateAverage(integers), Integer.valueOf(1)); + } + + @Test + public void fillGapsInBeginningTest(){ + List<Integer> integers = Lists.list(null,null,null,1,2,3,4,5,6,7,8,9); + List<Integer> integersToCompare = List.of(5,5,5,1,2,3,4,5,6,7,8,9); + Assert.assertEquals(CalculationUtil.fillGaps(integers), integersToCompare); + } + + @Test + public void fillGapsInMiddleTest(){ + List<Integer> integers = Lists.list(1,2,3,4,null,null,null,5,6,7,8,9); + List<Integer> integersToCompare = List.of(1,2,3,4,5,5,5,5,6,7,8,9); + Assert.assertEquals(CalculationUtil.fillGaps(integers), integersToCompare); + } + + @Test + public void fillGapsInEndTest(){ + List<Integer> integers = Lists.list(1,2,3,4,5,6,7,8,9,null,null,null); + List<Integer> integersToCompare = List.of(1,2,3,4,5,6,7,8,9,5,5,5); + Assert.assertEquals(CalculationUtil.fillGaps(integers), integersToCompare); + } + + @Test + public void fillGapsWithNotEnoughDataTest(){ + List<Integer> integers = Lists.list(1,2,3,null,null,null,null,null,null,null,null,null); + Exception exception = Assert.assertThrows(ArithmeticException.class, () -> CalculationUtil.fillGaps(integers)); + + String expectedMessage = "Not enough performance data for prediction, data filling: 25.0%"; + String actualMessage = exception.getMessage(); + + Assert.assertEquals(actualMessage, expectedMessage); + } + + +} diff --git a/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/scd/SleepingCellDetectorServiceTest.java b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/scd/SleepingCellDetectorServiceTest.java new file mode 100644 index 0000000..4caa5f1 --- /dev/null +++ b/sleepingcelldetector/src/test/java/org/onap/rapp/sleepingcelldetector/service/scd/SleepingCellDetectorServiceTest.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2021 Samsung Electronics + * 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 + */ + +package org.onap.rapp.sleepingcelldetector.service.scd; + +import org.onap.rapp.sleepingcelldetector.configuration.SleepingCellDetectorConfiguration; +import org.onap.rapp.sleepingcelldetector.entity.MeasurementConfiguration; +import org.onap.rapp.sleepingcelldetector.service.CellPerformanceHandlerTest; +import org.onap.rapp.sleepingcelldetector.service.JsonHelper; +import org.onap.rapp.sleepingcelldetector.service.scd.condition.ConditionEnum; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RunWith(MockitoJUnitRunner.class) +public class SleepingCellDetectorServiceTest { + + private SleepingCellDetectorService sleepingCellDetectorService; + + @Mock + SleepingCellDetectorConfiguration configuration; + + @Before + public void init() { + sleepingCellDetectorService = new SleepingCellDetectorService(new JsonHelper(), configuration); + sleepingCellDetectorService.measurementMap = prepareMeasurementConfig(); + } + + @Test + public void predictingActiveCellTestWithFullDataTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(CellPerformanceHandlerTest.getPMDataList(20, 80)); + Assert.assertFalse(prediction); + } + + @Test + public void predictingActiveCellTWithEmptyDataOnBeginningTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(preparePerformanceDataWithEmptyDataOnBeginning(20, 80)); + Assert.assertFalse(prediction); + } + + @Test + public void predictingActiveCellTWithEmptyDataInMiddleTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(preparePerformanceDataWithEmptyDataInMiddle(20, 80)); + Assert.assertFalse(prediction); + } + + @Test + public void predictingActiveCellTWithEmptyDataInEndTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(preparePerformanceDataWithEmptyDataInEnd(20, 80)); + Assert.assertFalse(prediction); + } + + @Test + public void predictingFailingCellTestWithFullDataTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(CellPerformanceHandlerTest.getPMDataList(500, 5)); + Assert.assertTrue(prediction); + } + + @Test + public void predictingFailingCellTWithEmptyDataOnBeginningTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(preparePerformanceDataWithEmptyDataOnBeginning(500, 5)); + Assert.assertTrue(prediction); + } + + @Test + public void predictingFailingCellTWithEmptyDataInMiddleTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(preparePerformanceDataWithEmptyDataInMiddle(500, 5)); + Assert.assertTrue(prediction); + } + + @Test + public void predictingFailingCellTWithEmptyDataInEndTest() { + Mockito.when(configuration.getPredictionSlotNumber()).thenReturn(12); + boolean prediction = sleepingCellDetectorService.isFailing(preparePerformanceDataWithEmptyDataInEnd(500, 5)); + Assert.assertTrue(prediction); + } + + private List<Map<String, Integer>> preparePerformanceDataWithEmptyDataOnBeginning(int latency, int throughput){ + List<Map<String, Integer>> pmList = CellPerformanceHandlerTest.getPMDataList(latency, throughput); + pmList.set(0, getEmptyMeasurementsData()); + pmList.set(1, getEmptyMeasurementsData()); + pmList.set(2, getEmptyMeasurementsData()); + return pmList; + } + + private List<Map<String, Integer>> preparePerformanceDataWithEmptyDataInMiddle(int latency, int throughput){ + List<Map<String, Integer>> pmList = CellPerformanceHandlerTest.getPMDataList(latency, throughput); + pmList.set(6, getEmptyMeasurementsData()); + pmList.set(7, getEmptyMeasurementsData()); + pmList.set(8, getEmptyMeasurementsData()); + return pmList; + } + + private List<Map<String, Integer>> preparePerformanceDataWithEmptyDataInEnd(int latency, int throughput){ + List<Map<String, Integer>> pmList = CellPerformanceHandlerTest.getPMDataList(latency, throughput); + pmList.set(9, getEmptyMeasurementsData()); + pmList.set(10, getEmptyMeasurementsData()); + pmList.set(11, getEmptyMeasurementsData()); + return pmList; + } + + private Map<String, Integer> getEmptyMeasurementsData() { + Map<String, Integer> emptyDataMap = new HashMap<>(); + emptyDataMap.put("latency", null); + emptyDataMap.put("throughput", null); + return emptyDataMap; + } + + private Map<String, MeasurementConfiguration> prepareMeasurementConfig() { + MeasurementConfiguration latencyConfig = new MeasurementConfiguration("latency", ConditionEnum.MORE_OR_EQUAL, 400, 150, 2); + MeasurementConfiguration throughputConfig = new MeasurementConfiguration("throughput", ConditionEnum.LESS_OR_EQUAL, 10, 10, 2); + + Map<String, MeasurementConfiguration> configMap = new HashMap<>(); + configMap.put("latency", latencyConfig); + configMap.put("throughput", throughputConfig); + + return configMap; + } +} |