mirror of
https://github.com/Telecominfraproject/wlan-cloud-services.git
synced 2026-03-20 17:39:19 +00:00
Compare commits
17 Commits
WIFI-2670_
...
release/v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7f91a29f8 | ||
|
|
80cd0abd58 | ||
|
|
4555ff339b | ||
|
|
04a13877d1 | ||
|
|
e148bab291 | ||
|
|
9ad3cec4af | ||
|
|
dc0b838f83 | ||
|
|
7cac7fff3f | ||
|
|
b48340b709 | ||
|
|
44b3836758 | ||
|
|
4f0b032549 | ||
|
|
5ba0c4c242 | ||
|
|
304e80332a | ||
|
|
9fd3e73398 | ||
|
|
b9db744aee | ||
|
|
1eee65d284 | ||
|
|
d0a0ed59fe |
@@ -349,12 +349,6 @@
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>equipment-alarms-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>adoption-metrics-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
|
||||
@@ -250,12 +250,6 @@
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>equipment-alarms-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>adoption-metrics-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
|
||||
@@ -336,12 +336,6 @@
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>equipment-alarms-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>adoption-metrics-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package com.telecominfraproject.wlan.startuptasks;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
@@ -3162,6 +3162,14 @@ components:
|
||||
- wpa2OnlyPSK
|
||||
- wpa2OnlyRadius
|
||||
- wep
|
||||
- wpaEAP
|
||||
- wpa2EAP
|
||||
- wpa2OnlyEAP
|
||||
- wpa3OnlySAE
|
||||
- wpa3MixedSAE
|
||||
- wpa3OnlyEAP
|
||||
- wpa3MixedEAP
|
||||
- wpa3OnlyEAP192
|
||||
|
||||
RadioBasedSsidConfigurationMap:
|
||||
properties:
|
||||
@@ -4390,7 +4398,9 @@ components:
|
||||
- RADIO_CHANNEL
|
||||
channelNumberStatusDataMap:
|
||||
$ref: '#/components/schemas/IntegerPerRadioTypeMap'
|
||||
|
||||
txPowerDataMap:
|
||||
$ref: '#/components/schemas/IntegerPerRadioTypeMap'
|
||||
|
||||
#
|
||||
# Equipment configuration data models
|
||||
#
|
||||
|
||||
@@ -189,7 +189,6 @@
|
||||
|
||||
<module>../provisioning-sp</module>
|
||||
<module>../dashboard-sp</module>
|
||||
<module>../equipment-alarms-sp</module>
|
||||
<module>../adoption-metrics-sp</module>
|
||||
|
||||
<module>../single-process-streams</module>
|
||||
|
||||
1
equipment-alarms-sp/.gitignore
vendored
1
equipment-alarms-sp/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/target/
|
||||
@@ -1,111 +0,0 @@
|
||||
<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>
|
||||
<parent>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<artifactId>tip-wlan-cloud-root-pom</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<relativePath>../../wlan-cloud-root</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>equipment-alarms-sp</artifactId>
|
||||
<name>equipment-alarms-sp</name>
|
||||
<description>Stream Processors for raising/clearing equipment alarms based on reported metrics.</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<artifactId>base-stream-consumer</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>service-metric-models</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>system-event-models</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>alarm-service-interface</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>status-service-interface</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>equipment-service-interface</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- unit tests dependencies -->
|
||||
<dependency>
|
||||
<artifactId>single-process-streams</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>alarm-service-local</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>status-service-local</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>equipment-service-local</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>alarm-datastore-inmemory</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>status-datastore-inmemory</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>equipment-datastore-inmemory</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>cloud-event-dispatcher-empty</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
package com.telecominfraproject.wlan.streams.equipmentalarms;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.telecominfraproject.wlan.alarm.models.Alarm;
|
||||
import com.telecominfraproject.wlan.alarm.models.AlarmCode;
|
||||
import com.telecominfraproject.wlan.servicemetric.apnode.models.ApNodeMetrics;
|
||||
|
||||
/**
|
||||
* <br>This context keeps track of information needed for raising/clearing the alarms with the following codes:
|
||||
* <ul>
|
||||
* <li>AlarmCode.CPUTemperature
|
||||
* <li>AlarmCode.CPUUtilization
|
||||
* <li>AlarmCode.MemoryUtilization
|
||||
* <li>AlarmCode.NoMetricsReceived
|
||||
* </ul>
|
||||
*
|
||||
* @author dtop
|
||||
*/
|
||||
public class EquipmentAlarmsContext {
|
||||
|
||||
private final int customerId;
|
||||
private final long equipmentId;
|
||||
private final Map<AlarmCode, Alarm> existingAlarms = new ConcurrentHashMap<>();
|
||||
private final long timeBucketMs;
|
||||
private final int temperatureThresholdInC;
|
||||
private final int cpuUtilThresholdPct;
|
||||
private final int memoryUtilThresholdPct;
|
||||
|
||||
private final Map<Long, Integer> cpuTempSamples = new ConcurrentHashMap<>();
|
||||
private final Map<Long, Integer> cpuUtilSamples = new ConcurrentHashMap<>();
|
||||
private final Map<Long, Integer> memoryUtilSamples = new ConcurrentHashMap<>();
|
||||
private final Map<Long, Long> metricReceivedTimestamps = new ConcurrentHashMap<>();
|
||||
|
||||
private long totalAvailableMemoryKb;
|
||||
private final long contextCreationTimestampMs = System.currentTimeMillis();
|
||||
|
||||
public EquipmentAlarmsContext(int customerId, long equipmentId, List<Alarm> existingAlarmsList, long timeBucketMs, int temperatureThresholdInC, int cpuUtilThresholdPct, int memoryUtilThresholdPct) {
|
||||
this.customerId = customerId;
|
||||
this.equipmentId = equipmentId;
|
||||
existingAlarmsList.forEach(a -> this.existingAlarms.put(a.getAlarmCode(), a));
|
||||
this.timeBucketMs = timeBucketMs;
|
||||
this.temperatureThresholdInC = temperatureThresholdInC;
|
||||
this.cpuUtilThresholdPct = cpuUtilThresholdPct;
|
||||
this.memoryUtilThresholdPct = memoryUtilThresholdPct;
|
||||
}
|
||||
|
||||
public long getTotalAvailableMemoryKb() {
|
||||
return totalAvailableMemoryKb;
|
||||
}
|
||||
|
||||
public void setTotalAvailableMemoryKb(long totalAvailableMemoryKb) {
|
||||
this.totalAvailableMemoryKb = totalAvailableMemoryKb;
|
||||
}
|
||||
|
||||
public int getCustomerId() {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
public long getEquipmentId() {
|
||||
return equipmentId;
|
||||
}
|
||||
|
||||
public Map<AlarmCode, Alarm> getExistingAlarms() {
|
||||
return existingAlarms;
|
||||
}
|
||||
|
||||
|
||||
public void addDataSamples(long timestamp, ApNodeMetrics model) {
|
||||
// add new samples
|
||||
if(model.getApPerformance()!=null ) {
|
||||
if(model.getApPerformance().getCpuTemperature()!=null) {
|
||||
cpuTempSamples.put(timestamp, model.getApPerformance().getCpuTemperature());
|
||||
}
|
||||
|
||||
if(model.getApPerformance().getAvgCpuUtilized()!=null) {
|
||||
cpuUtilSamples.put(timestamp, model.getApPerformance().getAvgCpuUtilized().intValue());
|
||||
}
|
||||
|
||||
if(model.getApPerformance().getFreeMemory()!=null && totalAvailableMemoryKb>0) {
|
||||
memoryUtilSamples.put(timestamp, 100 - (int) (model.getApPerformance().getFreeMemory() * 100 / totalAvailableMemoryKb));
|
||||
}
|
||||
}
|
||||
|
||||
//we are using our own timestamp in here in case AP's time is out of sync - we do not want to raise connectivity alarm in that case
|
||||
Long currentTs = System.currentTimeMillis();
|
||||
metricReceivedTimestamps.put(currentTs, currentTs);
|
||||
|
||||
}
|
||||
|
||||
public void removeOldDataSamples() {
|
||||
// remove samples older than timeBucketMs
|
||||
long timeThresholdMs = System.currentTimeMillis() - timeBucketMs;
|
||||
cpuTempSamples.entrySet().removeIf( t -> t.getKey() < timeThresholdMs );
|
||||
cpuUtilSamples.entrySet().removeIf( t -> t.getKey() < timeThresholdMs );
|
||||
memoryUtilSamples.entrySet().removeIf( t -> t.getKey() < timeThresholdMs );
|
||||
metricReceivedTimestamps.entrySet().removeIf( t -> t.getKey() < timeThresholdMs );
|
||||
}
|
||||
|
||||
public boolean isAlarmNeedsToBeRaised(AlarmCode alarmCode) {
|
||||
|
||||
if(existingAlarms.containsKey(alarmCode) || System.currentTimeMillis() < contextCreationTimestampMs + timeBucketMs) {
|
||||
//no need to check for thresholds - alarm is either already present, or it is too early to tell because the first time bucket has not been filled yet
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean ret = false;
|
||||
AtomicInteger sum = new AtomicInteger();
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
|
||||
//check alarms against thresholds
|
||||
if(alarmCode.getId() == AlarmCode.NoMetricsReceived.getId()) {
|
||||
ret = metricReceivedTimestamps.isEmpty();
|
||||
} else if(alarmCode.getId() == AlarmCode.CPUTemperature.getId()) {
|
||||
cpuTempSamples.values().forEach(v -> { sum.addAndGet(v); count.incrementAndGet(); });
|
||||
if(count.get() > 0) {
|
||||
int avg = sum.get() / count.get();
|
||||
ret = avg >= temperatureThresholdInC ;
|
||||
}
|
||||
} else if(alarmCode.getId() == AlarmCode.CPUUtilization.getId()) {
|
||||
cpuUtilSamples.values().forEach(v -> { sum.addAndGet(v); count.incrementAndGet(); });
|
||||
if(count.get() > 0) {
|
||||
int avg = sum.get() / count.get();
|
||||
ret = avg >= cpuUtilThresholdPct ;
|
||||
}
|
||||
} else if(alarmCode.getId() == AlarmCode.MemoryUtilization.getId()) {
|
||||
memoryUtilSamples.values().forEach(v -> { sum.addAndGet(v); count.incrementAndGet(); });
|
||||
if(count.get() > 0) {
|
||||
int avg = sum.get() / count.get();
|
||||
ret = avg >= memoryUtilThresholdPct ;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean isAlarmNeedsToBeCleared(AlarmCode alarmCode) {
|
||||
|
||||
if(!existingAlarms.containsKey(alarmCode) || System.currentTimeMillis() < contextCreationTimestampMs + timeBucketMs) {
|
||||
//no need to check for thresholds - alarm is either not present, or it is too early to tell because the first time bucket has not been filled yet
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean ret = false;
|
||||
AtomicInteger sum = new AtomicInteger();
|
||||
AtomicInteger count = new AtomicInteger();
|
||||
|
||||
//check alarms against thresholds
|
||||
if(alarmCode.getId() == AlarmCode.NoMetricsReceived.getId()) {
|
||||
ret = !metricReceivedTimestamps.isEmpty();
|
||||
} else if(alarmCode.getId() == AlarmCode.CPUTemperature.getId()) {
|
||||
cpuTempSamples.values().forEach(v -> { sum.addAndGet(v); count.incrementAndGet(); });
|
||||
if(count.get() > 0) {
|
||||
int avg = sum.get() / count.get();
|
||||
ret = avg < temperatureThresholdInC ;
|
||||
} else {
|
||||
//no new data available, but the alarm exists -> clear the alarm
|
||||
ret = true;
|
||||
}
|
||||
} else if(alarmCode.getId() == AlarmCode.CPUUtilization.getId()) {
|
||||
cpuUtilSamples.values().forEach(v -> { sum.addAndGet(v); count.incrementAndGet(); });
|
||||
if(count.get() > 0) {
|
||||
int avg = sum.get() / count.get();
|
||||
ret = avg < cpuUtilThresholdPct ;
|
||||
} else {
|
||||
//no new data available, but the alarm exists -> clear the alarm
|
||||
ret = true;
|
||||
}
|
||||
} else if(alarmCode.getId() == AlarmCode.MemoryUtilization.getId()) {
|
||||
memoryUtilSamples.values().forEach(v -> { sum.addAndGet(v); count.incrementAndGet(); });
|
||||
if(count.get() > 0) {
|
||||
int avg = sum.get() / count.get();
|
||||
ret = avg < memoryUtilThresholdPct ;
|
||||
} else {
|
||||
//no new data available, but the alarm exists -> clear the alarm
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
package com.telecominfraproject.wlan.streams.equipmentalarms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.telecominfraproject.wlan.alarm.AlarmServiceInterface;
|
||||
import com.telecominfraproject.wlan.alarm.models.Alarm;
|
||||
import com.telecominfraproject.wlan.alarm.models.AlarmCode;
|
||||
import com.telecominfraproject.wlan.alarm.models.AlarmDetails;
|
||||
import com.telecominfraproject.wlan.alarm.models.AlarmScopeType;
|
||||
import com.telecominfraproject.wlan.alarm.models.OriginatorType;
|
||||
import com.telecominfraproject.wlan.core.model.json.BaseJsonModel;
|
||||
import com.telecominfraproject.wlan.core.model.streams.QueuedStreamMessage;
|
||||
import com.telecominfraproject.wlan.equipment.EquipmentServiceInterface;
|
||||
import com.telecominfraproject.wlan.equipment.models.Equipment;
|
||||
import com.telecominfraproject.wlan.servicemetric.apnode.models.ApNodeMetrics;
|
||||
import com.telecominfraproject.wlan.servicemetric.models.ServiceMetric;
|
||||
import com.telecominfraproject.wlan.servicemetric.models.ServiceMetricDetails;
|
||||
import com.telecominfraproject.wlan.status.StatusServiceInterface;
|
||||
import com.telecominfraproject.wlan.status.equipment.report.models.OperatingSystemPerformance;
|
||||
import com.telecominfraproject.wlan.status.models.Status;
|
||||
import com.telecominfraproject.wlan.status.models.StatusCode;
|
||||
import com.telecominfraproject.wlan.status.models.StatusDataType;
|
||||
import com.telecominfraproject.wlan.stream.StreamProcessor;
|
||||
|
||||
/**
|
||||
* @author dtop
|
||||
* <br> This stream processor is listening for APNodeMetrics, aggregating them in sliding windows of 5 minutes and raising/clearing alarms based on preconfigured thresholds.
|
||||
* <br> "No metrics received" alarm is raised when no APNodeMetrics have been received for the equipment in the last interval, cleared when APNodeMetrics appear again
|
||||
* <br> "Temperature too high" alarm is raised when average temperature over the last interval goes above the configured threshold of 80C, cleared when average temperature goes below the threshold
|
||||
* <br> "CPU utilization is too high" alarm is raised when average CPU utilization on AP over the last interval goes above the configured threshold of 80%, cleared when average CPU utilization goes below the threshold
|
||||
* <br> "Memory utilization is too high" alarm is raised when average RAM utilization on AP over the last interval goes above the configured threshold of 70%, cleared when average RAM utilization goes below the threshold
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class EquipmentAlarmsProcessor extends StreamProcessor {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(EquipmentAlarmsProcessor.class);
|
||||
|
||||
@Value("${tip.wlan.wlanServiceMetricsTopic:wlan_service_metrics}")
|
||||
private String wlanServiceMetricsTopic;
|
||||
|
||||
@Value("${tip.wlan.equipmentAlarmProcessor.timeBucketMs:300000}") //5 minutes aggregation buckets
|
||||
private long timeBucketMs;
|
||||
|
||||
@Value("${tip.wlan.equipmentAlarmProcessor.checkAlarmsIntervalMs:15000}") //check for raising/clearing alarms every 15 seconds
|
||||
private long checkAlarmsIntervalMs;
|
||||
|
||||
@Value("${tip.wlan.equipmentAlarmProcessor.temperatureThresholdInC:80}")
|
||||
private int temperatureThresholdInC;
|
||||
|
||||
@Value("${tip.wlan.equipmentAlarmProcessor.cpuUtilThresholdPct:80}")
|
||||
private int cpuUtilThresholdPct;
|
||||
|
||||
@Value("${tip.wlan.equipmentAlarmProcessor.memoryUtilThresholdPct:70}")
|
||||
private int memoryUtilThresholdPct;
|
||||
|
||||
|
||||
private final ConcurrentHashMap<Long, EquipmentAlarmsContext> contextPerEquipmentIdMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final Set<AlarmCode> alarmCodeSet = new HashSet<>();
|
||||
|
||||
@Autowired
|
||||
private AlarmServiceInterface alarmServiceInterface;
|
||||
|
||||
@Autowired
|
||||
private StatusServiceInterface statusServiceInterface;
|
||||
|
||||
@Autowired
|
||||
private EquipmentServiceInterface equipmentServiceInterface;
|
||||
|
||||
@Override
|
||||
protected boolean acceptMessage(QueuedStreamMessage message) {
|
||||
boolean ret = message.getTopic().equals(wlanServiceMetricsTopic);
|
||||
|
||||
if(ret && ( message.getModel() instanceof ServiceMetric) ) {
|
||||
|
||||
ServiceMetric sm = (ServiceMetric) message.getModel();
|
||||
ret = ret &&
|
||||
(
|
||||
sm.getDetails() instanceof ApNodeMetrics
|
||||
);
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
LOG.trace("acceptMessage {}", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processMessage(QueuedStreamMessage message) {
|
||||
|
||||
ServiceMetric mdl = (ServiceMetric) message.getModel();
|
||||
ServiceMetricDetails smd = mdl.getDetails();
|
||||
LOG.debug("Processing {}", mdl);
|
||||
|
||||
switch ( smd.getClass().getSimpleName() ) {
|
||||
case "ApNodeMetrics":
|
||||
process(mdl.getCustomerId(), mdl.getCreatedTimestamp(), mdl.getEquipmentId(), (ApNodeMetrics) smd);
|
||||
break;
|
||||
default:
|
||||
process(mdl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void process(int customerId, long timestamp, long equipmentId, ApNodeMetrics model) {
|
||||
LOG.debug("Processing ApNodeMetrics");
|
||||
//get context for the equipmentId
|
||||
EquipmentAlarmsContext context = contextPerEquipmentIdMap.get(equipmentId);
|
||||
if(context == null) {
|
||||
|
||||
//When creating EquipmentAlarmsContext - read currently raised alarms of the types we're interested, keep it in memory.
|
||||
//Only this SP is responsible for raising/clearing those alarms for this particular equipment
|
||||
List<Alarm> existingAlarms = alarmServiceInterface.get(customerId, Collections.singleton(equipmentId), alarmCodeSet);
|
||||
|
||||
//All alarms that are handled by this stream processor logically exist only once-per-alarmCode-per-equipment.
|
||||
//Ensure that there is only one alarm per alarmCode per equipment (the latest one), remove all others.
|
||||
//This is needed to recover from some corner-case scenarios that can happen with the distributed datastores (for example split-brain).
|
||||
existingAlarms = cleanUpDuplicateAlarms(existingAlarms);
|
||||
|
||||
context = new EquipmentAlarmsContext(customerId, equipmentId, existingAlarms, timeBucketMs, temperatureThresholdInC, cpuUtilThresholdPct, memoryUtilThresholdPct);
|
||||
context = contextPerEquipmentIdMap.putIfAbsent(equipmentId, context);
|
||||
if(context == null) {
|
||||
context = contextPerEquipmentIdMap.get(equipmentId);
|
||||
}
|
||||
}
|
||||
|
||||
//find out TotalAvailableMemory in kb, which is available as part of the OperatingSystemPerformance status object
|
||||
//we look for it separately because this status may not be populated when the first service_metrics_collection_config are coming in
|
||||
if(context.getTotalAvailableMemoryKb()==0L) {
|
||||
Status osPerformanceStatus = statusServiceInterface.getOrNull(customerId, equipmentId, StatusDataType.OS_PERFORMANCE);
|
||||
if(osPerformanceStatus!=null) {
|
||||
OperatingSystemPerformance osPerformance = (OperatingSystemPerformance) osPerformanceStatus.getDetails();
|
||||
if(osPerformance !=null && osPerformance.getTotalAvailableMemoryKb() > 0) {
|
||||
context.setTotalAvailableMemoryKb(osPerformance.getTotalAvailableMemoryKb());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update counters on the context
|
||||
context.addDataSamples(timestamp, model);
|
||||
|
||||
LOG.debug("Processed {}", model);
|
||||
}
|
||||
|
||||
private List<Alarm> cleanUpDuplicateAlarms(List<Alarm> existingAlarms) {
|
||||
|
||||
Map<AlarmCode, Alarm> alarmsToKeep= new HashMap<>();
|
||||
|
||||
//find out the latest existing alarms for each alarmCode
|
||||
existingAlarms.forEach(a -> {
|
||||
Alarm eA = alarmsToKeep.get(a.getAlarmCode());
|
||||
if(eA == null) {
|
||||
eA = a;
|
||||
alarmsToKeep.put(a.getAlarmCode(), a);
|
||||
}
|
||||
|
||||
if(eA.getCreatedTimestamp() < a.getCreatedTimestamp() ) {
|
||||
alarmsToKeep.put(a.getAlarmCode(), a);
|
||||
}
|
||||
});
|
||||
|
||||
List<Alarm> alarmsToRemove = new ArrayList<>(existingAlarms);
|
||||
alarmsToRemove.removeAll(alarmsToKeep.values());
|
||||
|
||||
alarmsToRemove.forEach(a -> {
|
||||
try {
|
||||
alarmServiceInterface.delete(a.getCustomerId(), a.getEquipmentId(), a.getAlarmCode(), a.getCreatedTimestamp());
|
||||
} catch(Exception e) {
|
||||
LOG.debug("Alarm was already deleted: {}", a);
|
||||
}
|
||||
});
|
||||
|
||||
return new ArrayList<>(alarmsToKeep.values());
|
||||
}
|
||||
|
||||
private void process(BaseJsonModel model) {
|
||||
LOG.warn("Unprocessed model: {}", model);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void postCreate() {
|
||||
|
||||
Thread equipmentAlarmsThread = new Thread( new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Starting equipmentAlarmsThread");
|
||||
while(true) {
|
||||
LOG.trace("Checking if alarms need to be raised");
|
||||
|
||||
//take a snapshot of existing contexts for this iteration of alarm checks
|
||||
List<EquipmentAlarmsContext> contexts = new ArrayList<>(contextPerEquipmentIdMap.values());
|
||||
|
||||
HashSet<Long> equipmentIdsFromContexts = new HashSet<>();
|
||||
contexts.forEach(ctx -> equipmentIdsFromContexts.add(ctx.getEquipmentId()));
|
||||
|
||||
//get a list of equipment records for the current contexts
|
||||
HashSet<Long> existingEquipmentIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
List<Equipment> existingEquipment = equipmentServiceInterface.get(equipmentIdsFromContexts);
|
||||
existingEquipment.forEach(e -> existingEquipmentIds.add(e.getId()));
|
||||
} catch(Exception e) {
|
||||
LOG.error("Error when retrieving existing equipment", e);
|
||||
sleep(checkAlarmsIntervalMs);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
for(EquipmentAlarmsContext context : contexts ) {
|
||||
|
||||
if(!existingEquipmentIds.contains(context.getEquipmentId())) {
|
||||
//equipment was removed, let's delete the context and remove all existing alarms for that equipmentId
|
||||
try {
|
||||
contextPerEquipmentIdMap.remove(context.getEquipmentId());
|
||||
alarmServiceInterface.delete(context.getCustomerId(), context.getEquipmentId());
|
||||
} catch(Exception e) {
|
||||
LOG.error("Error when removing stale alarms for deleted equipment", e);
|
||||
}
|
||||
//nothing else to do for this context
|
||||
continue;
|
||||
}
|
||||
|
||||
context.removeOldDataSamples();
|
||||
|
||||
alarmCodeSet.forEach(alarmCode -> {
|
||||
try {
|
||||
//check alarms against thresholds
|
||||
//if alarm needs to be raised - check if it is currently present, and if not - raise it, and add it to the context
|
||||
if(context.isAlarmNeedsToBeRaised(alarmCode)) {
|
||||
Alarm alarm = new Alarm();
|
||||
alarm.setCustomerId(context.getCustomerId());
|
||||
alarm.setEquipmentId(context.getEquipmentId());
|
||||
alarm.setAlarmCode(alarmCode);
|
||||
alarm.setOriginatorType(OriginatorType.AP);
|
||||
alarm.setSeverity(alarmCode.getSeverity());
|
||||
alarm.setScopeType(AlarmScopeType.EQUIPMENT);
|
||||
alarm.setScopeId("" + context.getEquipmentId());
|
||||
AlarmDetails alarmDetails = new AlarmDetails();
|
||||
alarmDetails.setMessage(alarmCode.getDescription());
|
||||
alarmDetails.setAffectedEquipmentIds(Collections.singletonList(context.getEquipmentId()));
|
||||
alarm.setDetails(alarmDetails);
|
||||
|
||||
alarm = alarmServiceInterface.create(alarm);
|
||||
context.getExistingAlarms().put(alarmCode, alarm);
|
||||
}
|
||||
|
||||
if(context.isAlarmNeedsToBeCleared(alarmCode)) {
|
||||
//if alarm needs to be cleared - check if it is currently present, and if it is - clear it, and remove it from the context
|
||||
Alarm alarm = context.getExistingAlarms().remove(alarmCode);
|
||||
if(alarm!=null) {
|
||||
//All alarms that are handled by this stream processor logically exist only once-per-alarmCode-per-equipment.
|
||||
//In order to self-heal from the corner cases with the datastore where more than one alarm with the same alarmCode
|
||||
// is raised per equipment (for example when the datastore experienced a split-brain scenario), we would remove
|
||||
// all alarms with the specified alarmCode for this equipment.
|
||||
//Most of the time the existingAlarms list below would contain only one alarm.
|
||||
//
|
||||
List<Alarm> existingAlarms = alarmServiceInterface.get(alarm.getCustomerId(), Collections.singleton(alarm.getEquipmentId()), Collections.singleton(alarmCode));
|
||||
existingAlarms.forEach(a -> {
|
||||
try {
|
||||
alarmServiceInterface.delete(a.getCustomerId(), a.getEquipmentId(), a.getAlarmCode(), a.getCreatedTimestamp());
|
||||
} catch(Exception e) {
|
||||
LOG.debug("Alarm was already deleted: {}", alarm);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
LOG.error("Error when processing context for customer {}", context.getCustomerId(), e);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
LOG.trace("Done alarms check");
|
||||
|
||||
sleep(checkAlarmsIntervalMs);
|
||||
|
||||
}
|
||||
}
|
||||
}, "equipmentAlarmsThread");
|
||||
|
||||
equipmentAlarmsThread.setDaemon(true);
|
||||
equipmentAlarmsThread.start();
|
||||
|
||||
//populate alarm codes this SP is responsible for
|
||||
alarmCodeSet.add(AlarmCode.NoMetricsReceived);
|
||||
alarmCodeSet.add(AlarmCode.CPUTemperature);
|
||||
alarmCodeSet.add(AlarmCode.CPUUtilization);
|
||||
alarmCodeSet.add(AlarmCode.MemoryUtilization);
|
||||
|
||||
}
|
||||
|
||||
private static void sleep(long ms) {
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,342 +0,0 @@
|
||||
package com.telecominfraproject.wlan.streams.equipmentalarms;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.telecominfraproject.wlan.alarm.AlarmServiceInterface;
|
||||
import com.telecominfraproject.wlan.alarm.AlarmServiceLocal;
|
||||
import com.telecominfraproject.wlan.alarm.controller.AlarmController;
|
||||
import com.telecominfraproject.wlan.alarm.datastore.inmemory.AlarmDatastoreInMemory;
|
||||
import com.telecominfraproject.wlan.alarm.models.Alarm;
|
||||
import com.telecominfraproject.wlan.alarm.models.AlarmCode;
|
||||
import com.telecominfraproject.wlan.cloudeventdispatcher.CloudEventDispatcherEmpty;
|
||||
import com.telecominfraproject.wlan.core.model.equipment.EquipmentType;
|
||||
import com.telecominfraproject.wlan.equipment.EquipmentServiceInterface;
|
||||
import com.telecominfraproject.wlan.equipment.EquipmentServiceLocal;
|
||||
import com.telecominfraproject.wlan.equipment.controller.EquipmentController;
|
||||
import com.telecominfraproject.wlan.equipment.datastore.inmemory.EquipmentDatastoreInMemory;
|
||||
import com.telecominfraproject.wlan.equipment.models.Equipment;
|
||||
import com.telecominfraproject.wlan.servicemetric.apnode.models.ApNodeMetrics;
|
||||
import com.telecominfraproject.wlan.servicemetric.apnode.models.ApPerformance;
|
||||
import com.telecominfraproject.wlan.servicemetric.models.ServiceMetric;
|
||||
import com.telecominfraproject.wlan.status.StatusServiceLocal;
|
||||
import com.telecominfraproject.wlan.status.controller.StatusController;
|
||||
import com.telecominfraproject.wlan.status.datastore.inmemory.StatusDatastoreInMemory;
|
||||
import com.telecominfraproject.wlan.stream.StreamInterface;
|
||||
import com.telecominfraproject.wlan.stream.StreamMessageDispatcher;
|
||||
import com.telecominfraproject.wlan.streams.simple.SimpleStreamsConfig;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.NONE, classes = EquipmentAlarmsProcessor.class)
|
||||
@Import(value = { EquipmentAlarmsProcessor.class, SimpleStreamsConfig.class, StreamMessageDispatcher.class,
|
||||
AlarmServiceLocal.class, AlarmController.class, AlarmDatastoreInMemory.class,
|
||||
StatusServiceLocal.class, StatusController.class, StatusDatastoreInMemory.class,
|
||||
EquipmentServiceLocal.class, EquipmentController.class, EquipmentDatastoreInMemory.class,
|
||||
CloudEventDispatcherEmpty.class,
|
||||
//EquipmentAlarmsProcessorTests.Config.class,
|
||||
})
|
||||
@Ignore("make these tests more robust, there are intermittent failures")
|
||||
/*
|
||||
expected: <0> but was: <1>
|
||||
org.opentest4j.AssertionFailedError: expected: <0> but was: <1>
|
||||
at com.telecominfraproject.wlan.streams.equipmentalarms.EquipmentAlarmsProcessorTests.testAccessPointIsUnreachableAlarm(EquipmentAlarmsProcessorTests.java:313)
|
||||
|
||||
*/
|
||||
public class EquipmentAlarmsProcessorTests {
|
||||
|
||||
private static final long testTimeBucketMs = 200;
|
||||
private static final long testCheckAlarmsIntervalMs = 50;
|
||||
|
||||
static {
|
||||
System.setProperty("tip.wlan.equipmentAlarmProcessor.checkAlarmsIntervalMs", "" + testCheckAlarmsIntervalMs);
|
||||
System.setProperty("tip.wlan.equipmentAlarmProcessor.timeBucketMs", "" + testTimeBucketMs);
|
||||
}
|
||||
|
||||
@Autowired @Qualifier("metricStreamInterface")
|
||||
StreamInterface<ServiceMetric> metricStreamInterface;
|
||||
|
||||
@Autowired
|
||||
EquipmentAlarmsProcessor equipmentAlarmsProcessor;
|
||||
|
||||
@Autowired
|
||||
AlarmServiceInterface alarmService;
|
||||
|
||||
@Autowired
|
||||
EquipmentServiceInterface equipmentService;
|
||||
|
||||
protected static final AtomicLong testSequence = new AtomicLong(1);
|
||||
|
||||
@Configuration
|
||||
public static class Config {
|
||||
|
||||
//Another way of configuring dependencies (instead of mentioning them in the pom.xml with the test scope) :
|
||||
// @Bean
|
||||
// AlarmServiceInterface getAlarmServiceInterface() {
|
||||
// return new AlarmServiceInterface() {
|
||||
// ...
|
||||
// };
|
||||
// }
|
||||
|
||||
// @Bean
|
||||
// StatusServiceInterface getStatusServiceInterface() {
|
||||
// return new StatusServiceInterface() {
|
||||
// ...
|
||||
// };
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCPUTemperatureAlarm() {
|
||||
int customerId = getNextCustomerId();
|
||||
|
||||
Equipment equipment = new Equipment();
|
||||
equipment.setCustomerId(customerId);
|
||||
equipment.setEquipmentType(EquipmentType.AP);
|
||||
equipment.setInventoryId("testCPUTemperatureAlarm");
|
||||
equipment.setName(equipment.getInventoryId());
|
||||
equipment = equipmentService.create(equipment);
|
||||
long equipmentId = equipment.getId();
|
||||
|
||||
ServiceMetric record = new ServiceMetric(customerId , equipmentId );
|
||||
//create metric a bit in the future so that it gets picked up by the processor and not simply discarded
|
||||
record.setCreatedTimestamp(System.currentTimeMillis() + 2 * testTimeBucketMs);
|
||||
|
||||
ApNodeMetrics apNodeMetrics = new ApNodeMetrics();
|
||||
record.setDetails(apNodeMetrics);
|
||||
|
||||
ApPerformance apPerformance = new ApPerformance();
|
||||
apNodeMetrics.setApPerformance(apPerformance);
|
||||
|
||||
//we will force the CPUTemperature alarm to be raised
|
||||
apPerformance.setCpuTemperature(85);
|
||||
|
||||
apPerformance.setCpuUtilized(new int[] { 70, 70 });
|
||||
|
||||
apPerformance.setFreeMemory(30000000);
|
||||
|
||||
//publish metric that should trigger alarm for the CPU Temperature
|
||||
metricStreamInterface.publish(record );
|
||||
|
||||
//wait for the metric to be processed
|
||||
sleep(2 * testTimeBucketMs);
|
||||
|
||||
//verify that alarm was raised
|
||||
List<Alarm> alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.CPUTemperature));
|
||||
assertEquals(1, alarms.size());
|
||||
|
||||
//Now create a metric that should clear the alarm
|
||||
ServiceMetric recordToClearAlarm = record.clone();
|
||||
recordToClearAlarm.setCreatedTimestamp(System.currentTimeMillis() + 2* testTimeBucketMs );
|
||||
((ApNodeMetrics)recordToClearAlarm.getDetails()).getApPerformance().setCpuTemperature(70);
|
||||
|
||||
//publish metric that should clear the alarm for the CPU Temperature
|
||||
metricStreamInterface.publish(recordToClearAlarm);
|
||||
|
||||
//wait for the metric to be processed
|
||||
sleep(2 * testTimeBucketMs);
|
||||
|
||||
//verify that alarm was cleared
|
||||
alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.CPUTemperature));
|
||||
assertEquals(0, alarms.size());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCPUTemperatureAlarm_NoEquipment() {
|
||||
int customerId = getNextCustomerId();
|
||||
long equipmentId = -5;
|
||||
|
||||
ServiceMetric record = new ServiceMetric(customerId , equipmentId );
|
||||
//create metric a bit in the future so that it gets picked up by the processor and not simply discarded
|
||||
record.setCreatedTimestamp(System.currentTimeMillis() + 2 * testTimeBucketMs);
|
||||
|
||||
ApNodeMetrics apNodeMetrics = new ApNodeMetrics();
|
||||
record.setDetails(apNodeMetrics);
|
||||
|
||||
ApPerformance apPerformance = new ApPerformance();
|
||||
apNodeMetrics.setApPerformance(apPerformance);
|
||||
|
||||
//we will force the CPUTemperature alarm to be raised
|
||||
apPerformance.setCpuTemperature(85);
|
||||
|
||||
apPerformance.setCpuUtilized(new int[] { 70, 70 });
|
||||
|
||||
apPerformance.setFreeMemory(30000000);
|
||||
|
||||
//publish metric that should trigger alarm for the CPU Temperature
|
||||
metricStreamInterface.publish(record );
|
||||
|
||||
//wait for the metric to be processed
|
||||
sleep(2 * testTimeBucketMs);
|
||||
|
||||
//verify that alarm was not raised - because equipment for that alarm does not exist
|
||||
List<Alarm> alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.CPUTemperature));
|
||||
assertEquals(0, alarms.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCPUUtilizationAlarm() {
|
||||
int customerId = getNextCustomerId();
|
||||
|
||||
Equipment equipment = new Equipment();
|
||||
equipment.setCustomerId(customerId);
|
||||
equipment.setEquipmentType(EquipmentType.AP);
|
||||
equipment.setInventoryId("testCPUUtilizationAlarm");
|
||||
equipment.setName(equipment.getInventoryId());
|
||||
equipment = equipmentService.create(equipment);
|
||||
long equipmentId = equipment.getId();
|
||||
|
||||
ServiceMetric record = new ServiceMetric(customerId , equipmentId );
|
||||
//create metric a bit in the future so that it gets picked up by the processor and not simply discarded
|
||||
record.setCreatedTimestamp(System.currentTimeMillis() + 2 * testTimeBucketMs);
|
||||
|
||||
ApNodeMetrics apNodeMetrics = new ApNodeMetrics();
|
||||
record.setDetails(apNodeMetrics);
|
||||
|
||||
ApPerformance apPerformance = new ApPerformance();
|
||||
apNodeMetrics.setApPerformance(apPerformance);
|
||||
|
||||
apPerformance.setCpuTemperature(55);
|
||||
|
||||
//we will force the CPUUtilization alarm to be raised
|
||||
apPerformance.setCpuUtilized(new int[] { 90, 90 });
|
||||
|
||||
apPerformance.setFreeMemory(30000000);
|
||||
|
||||
//publish metric that should trigger alarm for the CPU Utilization
|
||||
metricStreamInterface.publish(record );
|
||||
|
||||
//wait for the metric to be processed
|
||||
sleep(2 * testTimeBucketMs);
|
||||
|
||||
//verify that alarm was raised
|
||||
List<Alarm> alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.CPUUtilization));
|
||||
assertEquals(1, alarms.size());
|
||||
|
||||
//Now create a metric that should clear the alarm
|
||||
ServiceMetric recordToClearAlarm = record.clone();
|
||||
recordToClearAlarm.setCreatedTimestamp(System.currentTimeMillis() + 2* testTimeBucketMs );
|
||||
((ApNodeMetrics)recordToClearAlarm.getDetails()).getApPerformance().setCpuUtilized(new int[] { 50, 50 });
|
||||
|
||||
//publish metric that should clear the alarm for the CPU Utilization
|
||||
metricStreamInterface.publish(recordToClearAlarm);
|
||||
|
||||
//wait for the metric to be processed
|
||||
sleep(2 * testTimeBucketMs);
|
||||
|
||||
//verify that alarm was cleared
|
||||
alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.CPUUtilization));
|
||||
assertEquals(0, alarms.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessPointIsUnreachableAlarm() {
|
||||
int customerId = getNextCustomerId();
|
||||
|
||||
Equipment equipment = new Equipment();
|
||||
equipment.setCustomerId(customerId);
|
||||
equipment.setEquipmentType(EquipmentType.AP);
|
||||
equipment.setInventoryId("testAccessPointIsUnreachableAlarm");
|
||||
equipment.setName(equipment.getInventoryId());
|
||||
equipment = equipmentService.create(equipment);
|
||||
long equipmentId = equipment.getId();
|
||||
|
||||
ServiceMetric record = new ServiceMetric(customerId , equipmentId );
|
||||
//create metric a bit in the future so that it gets picked up by the processor and not simply discarded
|
||||
record.setCreatedTimestamp(System.currentTimeMillis() + testTimeBucketMs);
|
||||
|
||||
ApNodeMetrics apNodeMetrics = new ApNodeMetrics();
|
||||
record.setDetails(apNodeMetrics);
|
||||
|
||||
ApPerformance apPerformance = new ApPerformance();
|
||||
apNodeMetrics.setApPerformance(apPerformance);
|
||||
|
||||
apPerformance.setCpuTemperature(55);
|
||||
|
||||
//we will force the CPUUtilization alarm to be raised
|
||||
apPerformance.setCpuUtilized(new int[] { 50, 50 });
|
||||
|
||||
apPerformance.setFreeMemory(30000000);
|
||||
|
||||
//publish metric that should not trigger AccessPointIsUnreachable alarm
|
||||
metricStreamInterface.publish(record );
|
||||
|
||||
//wait for the metric to be processed
|
||||
sleep(testTimeBucketMs);
|
||||
|
||||
//verify that alarm was not raised
|
||||
List<Alarm> alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.AccessPointIsUnreachable));
|
||||
assertEquals(0, alarms.size());
|
||||
|
||||
//Now wait for the alarm to be raised because no service_metrics_collection_config were posted
|
||||
sleep(testTimeBucketMs);
|
||||
|
||||
//verify that alarm was raised
|
||||
for(int i = 0; i < 50; i++) {
|
||||
alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.AccessPointIsUnreachable));
|
||||
if(!alarms.isEmpty()) {
|
||||
break;
|
||||
}else {
|
||||
sleep(5);
|
||||
}
|
||||
}
|
||||
assertEquals(1, alarms.size());
|
||||
|
||||
//Now create a metric that should clear the alarm
|
||||
ServiceMetric recordToClearAlarm = record.clone();
|
||||
recordToClearAlarm.setCreatedTimestamp(System.currentTimeMillis() + testTimeBucketMs );
|
||||
|
||||
//publish metric that should clear the AccessPointIsUnreachable alarm
|
||||
metricStreamInterface.publish(recordToClearAlarm);
|
||||
|
||||
//wait for the metric to be processed
|
||||
sleep(testTimeBucketMs);
|
||||
|
||||
//verify that alarm was cleared
|
||||
for(int i = 0; i < 50; i++) {
|
||||
alarms = alarmService.get(customerId, Collections.singleton(equipmentId), Collections.singleton(AlarmCode.AccessPointIsUnreachable));
|
||||
if(alarms.isEmpty()) {
|
||||
break;
|
||||
}else {
|
||||
sleep(5);
|
||||
}
|
||||
}
|
||||
assertEquals(0, alarms.size());
|
||||
|
||||
}
|
||||
|
||||
public int getNextCustomerId() {
|
||||
return (int) testSequence.incrementAndGet();
|
||||
}
|
||||
|
||||
public long getNextEquipmentId() {
|
||||
return testSequence.incrementAndGet();
|
||||
}
|
||||
|
||||
public void sleep(long ms) {
|
||||
try {
|
||||
Thread.sleep( ms );
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<configuration>
|
||||
<conversionRule conversionWord="filteredStack"
|
||||
converterClass="com.telecominfraproject.wlan.server.exceptions.logback.ExceptionCompressingConverter" />
|
||||
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%filteredStack%nopex</pattern>
|
||||
<!-- See http://logback.qos.ch/manual/layouts.html for details -->
|
||||
<!-- %ex{5} - add at the end to display only 5 levels of the exception stack trace -->
|
||||
<!-- %nopex - add at the end to not display any of the exception stack traces -->
|
||||
<!-- %ex{full} - add at the end to display all the levels of the exception stack trace -->
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
details: http://logback.qos.ch/manual/configuration.html#auto_configuration
|
||||
|
||||
runtime configuration, if need to override the defaults:
|
||||
-Dlogging.config=file:///home/ec2-user/opensync/logback.xml
|
||||
|
||||
for log configuration debugging - use
|
||||
-Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener
|
||||
|
||||
log levels:
|
||||
OFF ERROR WARN INFO DEBUG TRACE
|
||||
-->
|
||||
<logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
|
||||
<logger name="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" level="INFO"/>
|
||||
<logger name="org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer" level="INFO"/>
|
||||
<logger name="org.springframework.security.web.authentication.preauth" level="OFF"/>
|
||||
<logger name="com.netflix.servo.tag.aws.AwsInjectableTag" level="OFF"/>
|
||||
|
||||
<logger name="com.telecominfraproject" level="WARN"/>
|
||||
|
||||
<!--
|
||||
<logger name="com.telecominfraproject.wlan.streams.simple" level="TRACE"/>
|
||||
<logger name="com.telecominfraproject.wlan.streams.equipmentalarms" level="TRACE"/>
|
||||
-->
|
||||
|
||||
<root level="WARN">
|
||||
<appender-ref ref="stdout"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -118,6 +118,51 @@
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test dependencies -->
|
||||
<dependency>
|
||||
<artifactId>equipment-service-local</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>equipment-service</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>equipment-datastore-inmemory</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>cloud-event-dispatcher-empty</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>profile-service-local</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>profile-service</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>profile-datastore-inmemory</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
|
||||
@@ -158,55 +158,66 @@ public class ProfilePortalController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "/profile/equipmentCounts", method = RequestMethod.GET)
|
||||
public ListOfPairLongLong getCountsOfEquipmentThatUseProfiles(@RequestParam Set<Long> profileIdSet) {
|
||||
LOG.debug("getCountsOfEquipmentThatUseProfiles({})", profileIdSet);
|
||||
|
||||
//first get top-level profiles for the supplied set - only top-level profiles are linked to equipment
|
||||
List<PairLongLong> topLevelProfiles = this.profileServiceInterface.getTopLevelProfiles(profileIdSet);
|
||||
Map<Long, AtomicInteger> profileIdToCountMap = new HashMap<Long, AtomicInteger>();
|
||||
profileIdSet.forEach(profileId -> profileIdToCountMap.put(profileId, new AtomicInteger(0)));
|
||||
|
||||
//Maps child at all top level profiles that reference it. A top level profile references itself int this map
|
||||
Map<Long, List<Long>> childProfileToTopProfileMap = new HashMap<Long, List<Long>>();
|
||||
|
||||
List<PairLongLong> topLevelProfileList = profileServiceInterface.getTopLevelProfiles(profileIdSet);
|
||||
Set<Long> topProfileIdSet= new HashSet<Long>();
|
||||
|
||||
topLevelProfileList.forEach(pair ->
|
||||
{
|
||||
if (childProfileToTopProfileMap.putIfAbsent(
|
||||
pair.getValue1(),
|
||||
new ArrayList<Long>() {{ add(pair.getValue2());}}
|
||||
) != null)
|
||||
{
|
||||
childProfileToTopProfileMap.compute(pair.getValue1(), (k,v) ->
|
||||
new ArrayList<Long>() {{
|
||||
addAll(v);
|
||||
add(pair.getValue2());}});
|
||||
}
|
||||
topProfileIdSet.add(pair.getValue2());
|
||||
});
|
||||
|
||||
Map<Long, AtomicInteger> topProfileToEquipmentCountMap = new HashMap<>();
|
||||
topProfileIdSet.forEach(p -> topProfileToEquipmentCountMap.put(p, new AtomicInteger()));
|
||||
|
||||
PaginationContext<PairLongLong> context = new PaginationContext<>(500);
|
||||
equipmentServiceInterface.getEquipmentIdsByProfileIds(topProfileIdSet, context);
|
||||
|
||||
while(!context.isLastPage()) {
|
||||
PaginationResponse<PairLongLong> page = equipmentServiceInterface.getEquipmentIdsByProfileIds(topProfileIdSet, context );
|
||||
context = page.getContext();
|
||||
|
||||
page.getItems().forEach(p -> {
|
||||
AtomicInteger cnt = topProfileToEquipmentCountMap.get(p.getValue1());
|
||||
if(cnt!=null) {
|
||||
cnt.incrementAndGet();
|
||||
}
|
||||
});
|
||||
|
||||
LOG.debug("Page {} - counted {} equipmentids", context.getLastReturnedPageNumber(), context.getTotalItemsReturned());
|
||||
}
|
||||
|
||||
// assemble profile count for return, using child to top level profile id map
|
||||
childProfileToTopProfileMap.forEach((childKey,TopLevelIdList) ->
|
||||
{
|
||||
for (Long topProfileId : TopLevelIdList)
|
||||
{
|
||||
profileIdToCountMap.get(childKey).addAndGet(topProfileToEquipmentCountMap.get(topProfileId).get());
|
||||
}
|
||||
});
|
||||
//package results to get equipment counts for the original profile ids
|
||||
ListOfPairLongLong ret = new ListOfPairLongLong();
|
||||
profileIdToCountMap.forEach((id, count) -> ret.add(new PairLongLong(id, count.get())));
|
||||
|
||||
//map each supplied profile to its top-level parent
|
||||
Map<Long, Long> profileIdToTopProfileIdMap = new HashMap<>();
|
||||
topLevelProfiles.forEach(pair -> profileIdToTopProfileIdMap.put(pair.getValue1(), pair.getValue2()));
|
||||
|
||||
//gather top-level profile ids
|
||||
Set<Long> topProfileIds = new HashSet<>();
|
||||
topLevelProfiles.forEach(pair -> topProfileIds.add(pair.getValue2()));
|
||||
|
||||
|
||||
//TODO: this may be more efficiently done by a specialized count method on equipment datastore
|
||||
|
||||
//now get pages of equipmentIds that refer to the top-level profiles and count the equipmentIds
|
||||
PaginationContext<PairLongLong> context = new PaginationContext<>(500);
|
||||
this.equipmentServiceInterface.getEquipmentIdsByProfileIds(topProfileIds, context );
|
||||
|
||||
//prepare map of top-level profileId to the count of equipmentIds
|
||||
Map<Long, AtomicInteger> topProfileIdToEquipmentCountsMap = new HashMap<>();
|
||||
topProfileIds.forEach(p -> topProfileIdToEquipmentCountsMap.put(p, new AtomicInteger()));
|
||||
|
||||
while(!context.isLastPage()) {
|
||||
PaginationResponse<PairLongLong> page = equipmentServiceInterface.getEquipmentIdsByProfileIds(topProfileIds, context );
|
||||
context = page.getContext();
|
||||
|
||||
page.getItems().forEach(p -> {
|
||||
AtomicInteger cnt = topProfileIdToEquipmentCountsMap.get(p.getValue1());
|
||||
if(cnt!=null) {
|
||||
cnt.incrementAndGet();
|
||||
}
|
||||
});
|
||||
|
||||
LOG.debug("Page {} - counted {} equipmentids", context.getLastReturnedPageNumber(), context.getTotalItemsReturned());
|
||||
}
|
||||
|
||||
|
||||
//package results to get equipment counts for the original profile ids
|
||||
profileIdToTopProfileIdMap.forEach((p, tp) -> ret.add(new PairLongLong(p, topProfileIdToEquipmentCountsMap.get(tp).intValue())));
|
||||
|
||||
LOG.debug("getCountsOfEquipmentThatUseProfiles({}) return {}", profileIdSet, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2266,7 +2266,8 @@ components:
|
||||
- wpa3OnlySAE
|
||||
- wpa3MixedSAE
|
||||
- wpa3OnlyEAP
|
||||
- wpa3MixedEAP
|
||||
- wpa3MixedEAP
|
||||
- wpa3OnlyEAP192
|
||||
|
||||
RadioBasedSsidConfigurationMap:
|
||||
properties:
|
||||
@@ -4308,6 +4309,8 @@ components:
|
||||
- RADIO_CHANNEL
|
||||
channelNumberStatusDataMap:
|
||||
$ref: '#/components/schemas/IntegerPerRadioTypeMap'
|
||||
txPowerDataMap:
|
||||
$ref: '#/components/schemas/IntegerPerRadioTypeMap'
|
||||
|
||||
#
|
||||
# Objects related to Client sessions
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
package com.telecominfraproject.wlan.portal.controller.profile;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.telecominfraproject.wlan.cloudeventdispatcher.CloudEventDispatcherEmpty;
|
||||
import com.telecominfraproject.wlan.core.model.equipment.EquipmentType;
|
||||
import com.telecominfraproject.wlan.core.model.pair.PairLongLong;
|
||||
import com.telecominfraproject.wlan.equipment.EquipmentServiceLocal;
|
||||
import com.telecominfraproject.wlan.equipment.controller.EquipmentController;
|
||||
import com.telecominfraproject.wlan.equipment.datastore.EquipmentDatastore;
|
||||
import com.telecominfraproject.wlan.equipment.datastore.inmemory.EquipmentDatastoreInMemory;
|
||||
import com.telecominfraproject.wlan.equipment.models.Equipment;
|
||||
import com.telecominfraproject.wlan.portal.controller.profile.ProfilePortalController.ListOfPairLongLong;
|
||||
import com.telecominfraproject.wlan.profile.ProfileServiceLocal;
|
||||
import com.telecominfraproject.wlan.profile.controller.ProfileController;
|
||||
import com.telecominfraproject.wlan.profile.datastore.ProfileDatastore;
|
||||
import com.telecominfraproject.wlan.profile.datastore.inmemory.ProfileDatastoreInMemory;
|
||||
import com.telecominfraproject.wlan.profile.models.Profile;
|
||||
import com.telecominfraproject.wlan.profile.models.ProfileByCustomerRequestFactory;
|
||||
import com.telecominfraproject.wlan.profile.models.ProfileType;
|
||||
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@ActiveProfiles(profiles = {
|
||||
"integration_test",
|
||||
}) //NOTE: these profiles will be ADDED to the list of active profiles
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.NONE, classes = ProfilePortalControllerTest.class)
|
||||
@Import(value = {
|
||||
EquipmentServiceLocal.class,
|
||||
EquipmentController.class,
|
||||
EquipmentDatastoreInMemory.class,
|
||||
ProfileServiceLocal.class,
|
||||
ProfileController.class,
|
||||
ProfileDatastoreInMemory.class,
|
||||
ProfileByCustomerRequestFactory.class,
|
||||
CloudEventDispatcherEmpty.class,
|
||||
ProfilePortalController.class
|
||||
})
|
||||
public class ProfilePortalControllerTest {
|
||||
private static AtomicLong profileIncrementer = new AtomicLong(1);
|
||||
private static AtomicLong equipmentIncrementer = new AtomicLong(1);
|
||||
private static Set<Long> profileIds = new HashSet<Long>();
|
||||
private static Set<Long> equipmentIds = new HashSet<Long>();
|
||||
|
||||
@Autowired private ProfilePortalController profilePortalController;
|
||||
@Autowired private EquipmentDatastore equipmentDatastore;
|
||||
@Autowired private ProfileDatastore profileDatastore;
|
||||
|
||||
@BeforeEach
|
||||
public void setup()
|
||||
{
|
||||
profileIds.clear();
|
||||
equipmentIds.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCountsOfEquipmentThatUseProfilesTest()
|
||||
{
|
||||
|
||||
Profile parentProfile_1 = createProfile(); // 3 equipment
|
||||
Profile parentProfile_2 = createProfile(); // 2 equipment
|
||||
Profile parentProfile_3 = createProfile(); // 1 equipment
|
||||
|
||||
Profile ssidProfile_1 = createSsidProfile(); // linked to parent ids: 1 = 3 expected count
|
||||
Profile ssidProfile_2 = createSsidProfile(); // linked to parent ids: 1,2 = 5 expected count
|
||||
Profile ssidProfile_3 = createSsidProfile(); // linked to parent ids: 3 = 1 expected count
|
||||
|
||||
Profile captivePortalProfile_1 = createCaptivePortalProfile(); // linked to 4 -> 1 = 3 expected count
|
||||
Profile captivePortalProfile_2 = createCaptivePortalProfile(); // linked to 5 and 6 -> 5 + 1 = 6 expected count
|
||||
|
||||
Profile radiusProfile_1 = createRadiusProfile(); // 7, 8 -> 4, 5, 6 -> 1 , 2 , 3 -> 6 expected
|
||||
Profile radiusProfile_2 = createRadiusProfile(); // 0 expected
|
||||
|
||||
// link ssid to AP profiles
|
||||
linkChildToParent(ssidProfile_1.getId(), parentProfile_1.getId());
|
||||
linkChildToParent(ssidProfile_2.getId(), parentProfile_1.getId());
|
||||
linkChildToParent(ssidProfile_2.getId(), parentProfile_2.getId());
|
||||
linkChildToParent(ssidProfile_3.getId(), parentProfile_3.getId());
|
||||
|
||||
//link captive portal profiles to ssid profiles
|
||||
linkChildToParent(captivePortalProfile_1.getId(), ssidProfile_1.getId());
|
||||
linkChildToParent(captivePortalProfile_2.getId(), ssidProfile_2.getId());
|
||||
linkChildToParent(captivePortalProfile_2.getId(), ssidProfile_3.getId());
|
||||
|
||||
//link radius profiles to captive portal profiles
|
||||
linkChildToParent(radiusProfile_1.getId(), captivePortalProfile_1.getId());
|
||||
linkChildToParent(radiusProfile_1.getId(), captivePortalProfile_2.getId());
|
||||
|
||||
createEquipment(parentProfile_1.getId());
|
||||
createEquipment(parentProfile_1.getId());
|
||||
createEquipment(parentProfile_1.getId());
|
||||
createEquipment(parentProfile_2.getId());
|
||||
createEquipment(parentProfile_2.getId());
|
||||
createEquipment(parentProfile_3.getId());
|
||||
|
||||
ListOfPairLongLong ret = profilePortalController.getCountsOfEquipmentThatUseProfiles(profileIds);
|
||||
|
||||
List<PairLongLong> expectedReturn = new ArrayList<PairLongLong>() {{
|
||||
add(new PairLongLong(parentProfile_1.getId(), 3));
|
||||
add(new PairLongLong(parentProfile_2.getId(), 2));
|
||||
add(new PairLongLong(parentProfile_3.getId(), 1));
|
||||
add(new PairLongLong(ssidProfile_1.getId(), 3));
|
||||
add(new PairLongLong(ssidProfile_2.getId(), 5));
|
||||
add(new PairLongLong(ssidProfile_3.getId(), 1));
|
||||
add(new PairLongLong(captivePortalProfile_1.getId(), 3));
|
||||
add(new PairLongLong(captivePortalProfile_2.getId(), 6));
|
||||
add(new PairLongLong(radiusProfile_1.getId(), 6));
|
||||
add(new PairLongLong(radiusProfile_2.getId(), 0));
|
||||
}};
|
||||
|
||||
expectedReturn.forEach(pair -> assertTrue(ret.contains(pair)));
|
||||
equipmentIds.forEach(id -> equipmentDatastore.delete(id));
|
||||
profileIds.forEach(id -> profileDatastore.delete(id));
|
||||
}
|
||||
|
||||
private Profile createProfile()
|
||||
{
|
||||
Profile profile = new Profile();
|
||||
profile.setName("test" + profileIncrementer.getAndIncrement());
|
||||
profile.setProfileType(ProfileType.equipment_ap);
|
||||
profile.setCustomerId(2);
|
||||
|
||||
Profile created = profileDatastore.create(profile);
|
||||
profileIds.add(created.getId());
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
private Profile createSsidProfile()
|
||||
{
|
||||
Profile profile = new Profile();
|
||||
profile.setName("test" + profileIncrementer.getAndIncrement());
|
||||
profile.setProfileType(ProfileType.ssid);
|
||||
profile.setCustomerId(2);
|
||||
|
||||
Profile created = profileDatastore.create(profile);
|
||||
profileIds.add(created.getId());
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
private Profile createCaptivePortalProfile()
|
||||
{
|
||||
Profile profile = new Profile();
|
||||
profile.setName("test" + profileIncrementer.getAndIncrement());
|
||||
profile.setProfileType(ProfileType.captive_portal);
|
||||
profile.setCustomerId(2);
|
||||
|
||||
Profile created = profileDatastore.create(profile);
|
||||
profileIds.add(created.getId());
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
private Profile createRadiusProfile()
|
||||
{
|
||||
Profile profile = new Profile();
|
||||
profile.setName("test" + profileIncrementer.getAndIncrement());
|
||||
profile.setProfileType(ProfileType.radius);
|
||||
profile.setCustomerId(2);
|
||||
|
||||
Profile created = profileDatastore.create(profile);
|
||||
profileIds.add(created.getId());
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
private void linkChildToParent(long childId, long parentId)
|
||||
{
|
||||
Profile parentProfile = profileDatastore.get(parentId);
|
||||
parentProfile.getChildProfileIds().add(childId);
|
||||
|
||||
profileDatastore.update(parentProfile);
|
||||
}
|
||||
|
||||
private Equipment createEquipment(long profileId)
|
||||
{
|
||||
Equipment equipment = new Equipment();
|
||||
equipment.setCustomerId(2);
|
||||
equipment.setEquipmentType(EquipmentType.AP);
|
||||
equipment.setName("test" + equipmentIncrementer.getAndIncrement());
|
||||
equipment.setProfileId(profileId);
|
||||
return equipmentDatastore.create(equipment);
|
||||
}
|
||||
}
|
||||
@@ -69,15 +69,15 @@ public class PortalUserDAO extends BaseJdbcDao {
|
||||
private static final Set<String> columnsToSkipForInsert = new HashSet<>(Arrays.asList(COL_ID));
|
||||
private static final Set<String> columnsToSkipForUpdate = new HashSet<>(Arrays.asList(COL_ID, "createdTimestamp"));
|
||||
|
||||
private static final String TABLE_NAME = "portal_user";
|
||||
private static final String TABLE_PREFIX = "s.";
|
||||
private static final String ALL_COLUMNS;
|
||||
public static final String TABLE_NAME = "portal_user";
|
||||
public static final String TABLE_PREFIX = "s.";
|
||||
public static final String ALL_COLUMNS;
|
||||
|
||||
private static final Set<String> ALL_COLUMNS_LOWERCASE = new HashSet<>();
|
||||
public static final Set<String> ALL_COLUMNS_LOWERCASE = new HashSet<>();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
//use this for queries where multiple tables are involved
|
||||
private static final String ALL_COLUMNS_WITH_PREFIX;
|
||||
public static final String ALL_COLUMNS_WITH_PREFIX;
|
||||
|
||||
private static final String ALL_COLUMNS_FOR_INSERT;
|
||||
private static final String BIND_VARS_FOR_INSERT;
|
||||
@@ -162,8 +162,8 @@ public class PortalUserDAO extends BaseJdbcDao {
|
||||
|
||||
private static final String SQL_GET_ALL_IN_SET = "select " + ALL_COLUMNS + " from "+TABLE_NAME + " where "+ COL_ID +" in ";
|
||||
|
||||
private static final String SQL_PAGING_SUFFIX = " LIMIT ? OFFSET ? ";
|
||||
private static final String SORT_SUFFIX = "";
|
||||
public static final String SQL_PAGING_SUFFIX = " LIMIT ? OFFSET ? ";
|
||||
public static final String SORT_SUFFIX = "";
|
||||
|
||||
|
||||
private static final RowMapper<PortalUser> portalUserRowMapper = new PortalUserRowMapper();
|
||||
|
||||
@@ -370,11 +370,9 @@ public class SsidConfiguration extends ProfileDetails implements PushableConfigu
|
||||
|
||||
public static enum SecureMode {
|
||||
|
||||
open(0L), wpaPSK(1L), wpa2PSK(2L), wpaRadius(3L), wpa2Radius(4L), wpa2OnlyPSK(5L), wpa2OnlyRadius(6L), wep(
|
||||
7L), wpaEAP(8L), wpa2EAP(
|
||||
9L), wpa2OnlyEAP(10L), wpa3OnlySAE(11L), wpa3MixedSAE(12L), wpa3OnlyEAP(13L), wpa3MixedEAP(14L),
|
||||
|
||||
UNSUPPORTED(-1L);
|
||||
open(0L), wpaPSK(1L), wpa2PSK(2L), wpaRadius(3L), wpa2Radius(4L), wpa2OnlyPSK(5L), wpa2OnlyRadius(6L), wep(7L),
|
||||
wpaEAP(8L), wpa2EAP(9L), wpa2OnlyEAP(10L), wpa3OnlySAE(11L), wpa3MixedSAE(12L), wpa3OnlyEAP(13L), wpa3MixedEAP(14L),
|
||||
wpa3OnlyEAP192(15L), UNSUPPORTED(-1L);
|
||||
|
||||
private final long id;
|
||||
private static final Map<Long, SecureMode> ELEMENTS = new HashMap<>();
|
||||
@@ -415,7 +413,7 @@ public class SsidConfiguration extends ProfileDetails implements PushableConfigu
|
||||
}
|
||||
|
||||
public static boolean isWPA3_Enterprise_or_Personal(SecureMode mode) {
|
||||
return mode == wpa3OnlySAE || mode == wpa3OnlyEAP;
|
||||
return mode == wpa3OnlySAE || mode == wpa3OnlyEAP || mode == wpa3OnlyEAP192;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1024,6 +1024,7 @@ components:
|
||||
- wpa3MixedSAE
|
||||
- wpa3OnlyEAP
|
||||
- wpa3MixedEAP
|
||||
- wpa3OnlyEAP192
|
||||
|
||||
RadioBasedSsidConfigurationMap:
|
||||
properties:
|
||||
|
||||
@@ -53,12 +53,6 @@
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>equipment-alarms-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>adoption-metrics-sp</artifactId>
|
||||
<groupId>com.telecominfraproject.wlan</groupId>
|
||||
|
||||
@@ -12,6 +12,7 @@ public class EquipmentChannelStatusData extends StatusDetails {
|
||||
private static final long serialVersionUID = 470569467119609438L;
|
||||
|
||||
private Map<RadioType, Integer> channelNumberStatusDataMap = new EnumMap<>(RadioType.class);
|
||||
private Map<RadioType, Integer> txPowerDataMap = new EnumMap<>(RadioType.class);
|
||||
|
||||
|
||||
public EquipmentChannelStatusData()
|
||||
@@ -34,10 +35,18 @@ public class EquipmentChannelStatusData extends StatusDetails {
|
||||
public Map<RadioType, Integer> getChannelNumberStatusDataMap() {
|
||||
return channelNumberStatusDataMap;
|
||||
}
|
||||
|
||||
public Map<RadioType, Integer> getTxPowerDataMap() {
|
||||
return txPowerDataMap;
|
||||
}
|
||||
|
||||
public void setChannelNumberStatusDataMap(Map<RadioType, Integer> channelNumberStatusDataMap) {
|
||||
this.channelNumberStatusDataMap = channelNumberStatusDataMap;
|
||||
}
|
||||
|
||||
public void setTxPowerDataMap(Map<RadioType, Integer> txPowerDataMap) {
|
||||
this.txPowerDataMap = txPowerDataMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EquipmentChannelStatusData clone() {
|
||||
@@ -49,19 +58,33 @@ public class EquipmentChannelStatusData extends StatusDetails {
|
||||
result.channelNumberStatusDataMap.put(k, v);
|
||||
});
|
||||
}
|
||||
|
||||
if (getTxPowerDataMap() != null) {
|
||||
result.setTxPowerDataMap(new EnumMap<>(RadioType.class));
|
||||
|
||||
this.txPowerDataMap.forEach((k, v) -> {
|
||||
result.txPowerDataMap.put(k, v);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
EquipmentChannelStatusData other = (EquipmentChannelStatusData) obj;
|
||||
return Objects.equals(channelNumberStatusDataMap, other.channelNumberStatusDataMap);
|
||||
public int hashCode() {
|
||||
return Objects.hash(channelNumberStatusDataMap, txPowerDataMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(channelNumberStatusDataMap);
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
EquipmentChannelStatusData other = (EquipmentChannelStatusData) obj;
|
||||
return Objects.equals(channelNumberStatusDataMap, other.channelNumberStatusDataMap)
|
||||
&& Objects.equals(txPowerDataMap, other.txPowerDataMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3172,6 +3172,14 @@ components:
|
||||
- wpa2OnlyPSK
|
||||
- wpa2OnlyRadius
|
||||
- wep
|
||||
- wpaEAP
|
||||
- wpa2EAP
|
||||
- wpa2OnlyEAP
|
||||
- wpa3OnlySAE
|
||||
- wpa3MixedSAE
|
||||
- wpa3OnlyEAP
|
||||
- wpa3MixedEAP
|
||||
- wpa3OnlyEAP192
|
||||
|
||||
RadioBasedSsidConfigurationMap:
|
||||
properties:
|
||||
@@ -4401,6 +4409,8 @@ components:
|
||||
- RADIO_CHANNEL
|
||||
channelNumberStatusDataMap:
|
||||
$ref: '#/components/schemas/IntegerPerRadioTypeMap'
|
||||
txPowerDataMap:
|
||||
$ref: '#/components/schemas/IntegerPerRadioTypeMap'
|
||||
|
||||
#
|
||||
# Equipment configuration data models
|
||||
|
||||
Reference in New Issue
Block a user