Jian Li
Committed by Gerrit Code Review

Resolve some NPEs during collecting system metrics

Change-Id: Id018026676948d732f342d634dff6fba630c1414
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.cpman.impl; 16 package org.onosproject.cpman.impl;
17 17
18 +import com.google.common.collect.ImmutableMap;
18 import com.google.common.collect.ImmutableSet; 19 import com.google.common.collect.ImmutableSet;
19 import com.google.common.collect.Maps; 20 import com.google.common.collect.Maps;
20 import com.google.common.collect.Sets; 21 import com.google.common.collect.Sets;
...@@ -340,6 +341,9 @@ public class ControlPlaneMonitor implements ControlPlaneMonitorService { ...@@ -340,6 +341,9 @@ public class ControlPlaneMonitor implements ControlPlaneMonitorService {
340 } 341 }
341 342
342 private Map convertMap(Map<ControlMetricType, Double> map) { 343 private Map convertMap(Map<ControlMetricType, Double> map) {
344 + if (map == null) {
345 + return ImmutableMap.of();
346 + }
343 Map newMap = Maps.newConcurrentMap(); 347 Map newMap = Maps.newConcurrentMap();
344 map.forEach((k, v) -> newMap.putIfAbsent(k.toString(), v)); 348 map.forEach((k, v) -> newMap.putIfAbsent(k.toString(), v));
345 return newMap; 349 return newMap;
......
...@@ -18,14 +18,18 @@ package org.onosproject.cpman.rest; ...@@ -18,14 +18,18 @@ package org.onosproject.cpman.rest;
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 19 import com.fasterxml.jackson.databind.node.ArrayNode;
20 import com.fasterxml.jackson.databind.node.ObjectNode; 20 import com.fasterxml.jackson.databind.node.ObjectNode;
21 +import org.apache.commons.lang3.StringUtils;
21 import org.onosproject.cpman.ControlMetric; 22 import org.onosproject.cpman.ControlMetric;
22 import org.onosproject.cpman.ControlMetricType; 23 import org.onosproject.cpman.ControlMetricType;
23 import org.onosproject.cpman.ControlPlaneMonitorService; 24 import org.onosproject.cpman.ControlPlaneMonitorService;
25 +import org.onosproject.cpman.ControlResource;
24 import org.onosproject.cpman.MetricValue; 26 import org.onosproject.cpman.MetricValue;
25 import org.onosproject.cpman.SystemInfo; 27 import org.onosproject.cpman.SystemInfo;
26 import org.onosproject.cpman.impl.DefaultSystemInfo; 28 import org.onosproject.cpman.impl.DefaultSystemInfo;
27 import org.onosproject.cpman.impl.SystemInfoFactory; 29 import org.onosproject.cpman.impl.SystemInfoFactory;
28 import org.onosproject.rest.AbstractWebResource; 30 import org.onosproject.rest.AbstractWebResource;
31 +import org.slf4j.Logger;
32 +import org.slf4j.LoggerFactory;
29 33
30 import javax.ws.rs.Consumes; 34 import javax.ws.rs.Consumes;
31 import javax.ws.rs.POST; 35 import javax.ws.rs.POST;
...@@ -35,7 +39,10 @@ import javax.ws.rs.core.MediaType; ...@@ -35,7 +39,10 @@ import javax.ws.rs.core.MediaType;
35 import javax.ws.rs.core.Response; 39 import javax.ws.rs.core.Response;
36 import java.io.IOException; 40 import java.io.IOException;
37 import java.io.InputStream; 41 import java.io.InputStream;
42 +import java.util.Iterator;
38 import java.util.Optional; 43 import java.util.Optional;
44 +import java.util.Set;
45 +import java.util.stream.Collectors;
39 46
40 import static org.onlab.util.Tools.nullIsIllegal; 47 import static org.onlab.util.Tools.nullIsIllegal;
41 48
...@@ -45,11 +52,21 @@ import static org.onlab.util.Tools.nullIsIllegal; ...@@ -45,11 +52,21 @@ import static org.onlab.util.Tools.nullIsIllegal;
45 @Path("collector") 52 @Path("collector")
46 public class SystemMetricsCollectorWebResource extends AbstractWebResource { 53 public class SystemMetricsCollectorWebResource extends AbstractWebResource {
47 54
55 + private final Logger log = LoggerFactory.getLogger(getClass());
48 private final ControlPlaneMonitorService service = get(ControlPlaneMonitorService.class); 56 private final ControlPlaneMonitorService service = get(ControlPlaneMonitorService.class);
49 private static final int UPDATE_INTERVAL_IN_MINUTE = 1; 57 private static final int UPDATE_INTERVAL_IN_MINUTE = 1;
50 private static final String INVALID_SYSTEM_SPECS = "Invalid system specifications"; 58 private static final String INVALID_SYSTEM_SPECS = "Invalid system specifications";
51 private static final String INVALID_RESOURCE_NAME = "Invalid resource name"; 59 private static final String INVALID_RESOURCE_NAME = "Invalid resource name";
52 private static final String INVALID_REQUEST = "Invalid request"; 60 private static final String INVALID_REQUEST = "Invalid request";
61 + private static final int PERCENT_CONSTANT = 100;
62 +
63 + private static final Set<String> MEMORY_FIELD_SET = ControlResource.MEMORY_METRICS
64 + .stream().map(type -> toCamelCase(type.toString(), true))
65 + .collect(Collectors.toSet());
66 +
67 + private static final Set<String> CPU_FIELD_SET = ControlResource.CPU_METRICS
68 + .stream().map(type -> toCamelCase(type.toString(), true))
69 + .collect(Collectors.toSet());
53 70
54 /** 71 /**
55 * Collects CPU metrics. 72 * Collects CPU metrics.
...@@ -67,7 +84,13 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -67,7 +84,13 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
67 ControlMetric cm; 84 ControlMetric cm;
68 try { 85 try {
69 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); 86 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
70 - long cpuLoad = nullIsIllegal(jsonTree.get("cpuLoad").asLong(), INVALID_REQUEST); 87 +
88 + if (jsonTree == null || !checkFields(jsonTree, CPU_FIELD_SET)) {
89 + ok(root).build();
90 + }
91 +
92 + long cpuLoad = nullIsIllegal((long) (jsonTree.get("cpuLoad").asDouble()
93 + * PERCENT_CONSTANT), INVALID_REQUEST);
71 long totalCpuTime = nullIsIllegal(jsonTree.get("totalCpuTime").asLong(), INVALID_REQUEST); 94 long totalCpuTime = nullIsIllegal(jsonTree.get("totalCpuTime").asLong(), INVALID_REQUEST);
72 long sysCpuTime = nullIsIllegal(jsonTree.get("sysCpuTime").asLong(), INVALID_REQUEST); 95 long sysCpuTime = nullIsIllegal(jsonTree.get("sysCpuTime").asLong(), INVALID_REQUEST);
73 long userCpuTime = nullIsIllegal(jsonTree.get("userCpuTime").asLong(), INVALID_REQUEST); 96 long userCpuTime = nullIsIllegal(jsonTree.get("userCpuTime").asLong(), INVALID_REQUEST);
...@@ -95,6 +118,8 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -95,6 +118,8 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
95 118
96 } catch (IOException e) { 119 } catch (IOException e) {
97 throw new IllegalArgumentException(e.getMessage()); 120 throw new IllegalArgumentException(e.getMessage());
121 + } catch (IllegalArgumentException iae) {
122 + log.error("[CPU] Illegal arguments in JSON input, msg: {}", iae.getMessage());
98 } 123 }
99 return ok(root).build(); 124 return ok(root).build();
100 } 125 }
...@@ -115,10 +140,16 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -115,10 +140,16 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
115 ControlMetric cm; 140 ControlMetric cm;
116 try { 141 try {
117 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); 142 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
118 - long memUsedRatio = nullIsIllegal(jsonTree.get("memoryUsedRatio").asLong(), INVALID_REQUEST); 143 +
119 - long memFreeRatio = nullIsIllegal(jsonTree.get("memoryFreeRatio").asLong(), INVALID_REQUEST); 144 + if (jsonTree == null || !checkFields(jsonTree, MEMORY_FIELD_SET)) {
145 + ok(root).build();
146 + }
147 +
120 long memUsed = nullIsIllegal(jsonTree.get("memoryUsed").asLong(), INVALID_REQUEST); 148 long memUsed = nullIsIllegal(jsonTree.get("memoryUsed").asLong(), INVALID_REQUEST);
121 long memFree = nullIsIllegal(jsonTree.get("memoryFree").asLong(), INVALID_REQUEST); 149 long memFree = nullIsIllegal(jsonTree.get("memoryFree").asLong(), INVALID_REQUEST);
150 + long memTotal = memUsed + memFree;
151 + long memUsedRatio = memTotal == 0L ? 0L : (memUsed * PERCENT_CONSTANT) / memTotal;
152 + long memFreeRatio = memTotal == 0L ? 0L : (memFree * PERCENT_CONSTANT) / memTotal;
122 153
123 cm = new ControlMetric(ControlMetricType.MEMORY_USED_RATIO, 154 cm = new ControlMetric(ControlMetricType.MEMORY_USED_RATIO,
124 new MetricValue.Builder().load(memUsedRatio).add()); 155 new MetricValue.Builder().load(memUsedRatio).add());
...@@ -138,6 +169,8 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -138,6 +169,8 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
138 169
139 } catch (IOException e) { 170 } catch (IOException e) {
140 throw new IllegalArgumentException(e.getMessage()); 171 throw new IllegalArgumentException(e.getMessage());
172 + } catch (IllegalArgumentException iae) {
173 + log.error("[RAM] Illegal arguments in JSON input, msg: {}", iae.getMessage());
141 } 174 }
142 return ok(root).build(); 175 return ok(root).build();
143 } 176 }
...@@ -158,7 +191,9 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -158,7 +191,9 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
158 ControlMetric cm; 191 ControlMetric cm;
159 try { 192 try {
160 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); 193 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
161 - ArrayNode diskRes = (ArrayNode) jsonTree.get("disks"); 194 + ArrayNode diskRes =
195 + jsonTree.get("disks") == null ? mapper().createArrayNode() : (ArrayNode) jsonTree.get("disks");
196 +
162 for (JsonNode node : diskRes) { 197 for (JsonNode node : diskRes) {
163 JsonNode resourceName = node.get("resourceName"); 198 JsonNode resourceName = node.get("resourceName");
164 nullIsIllegal(resourceName, INVALID_RESOURCE_NAME); 199 nullIsIllegal(resourceName, INVALID_RESOURCE_NAME);
...@@ -176,6 +211,8 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -176,6 +211,8 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
176 } 211 }
177 } catch (IOException e) { 212 } catch (IOException e) {
178 throw new IllegalArgumentException(e.getMessage()); 213 throw new IllegalArgumentException(e.getMessage());
214 + } catch (IllegalArgumentException iae) {
215 + log.error("[DISK] Illegal arguments in JSON input, msg: {}", iae.getMessage());
179 } 216 }
180 return ok(root).build(); 217 return ok(root).build();
181 } 218 }
...@@ -196,7 +233,10 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -196,7 +233,10 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
196 ControlMetric cm; 233 ControlMetric cm;
197 try { 234 try {
198 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); 235 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
199 - ArrayNode networkRes = (ArrayNode) jsonTree.get("networks"); 236 +
237 + ArrayNode networkRes = jsonTree.get("networks") == null
238 + ? mapper().createArrayNode() : (ArrayNode) jsonTree.get("networks");
239 +
200 for (JsonNode node : networkRes) { 240 for (JsonNode node : networkRes) {
201 JsonNode resourceName = node.get("resourceName"); 241 JsonNode resourceName = node.get("resourceName");
202 nullIsIllegal(resourceName, INVALID_RESOURCE_NAME); 242 nullIsIllegal(resourceName, INVALID_RESOURCE_NAME);
...@@ -271,4 +311,24 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource { ...@@ -271,4 +311,24 @@ public class SystemMetricsCollectorWebResource extends AbstractWebResource {
271 } 311 }
272 return ok(root).build(); 312 return ok(root).build();
273 } 313 }
314 +
315 + private boolean checkFields(ObjectNode node, Set<String> original) {
316 + Iterator<String> fieldNames = node.fieldNames();
317 + while (fieldNames.hasNext()) {
318 + String fieldName = fieldNames.next();
319 + if (!original.contains(fieldName) || node.get(fieldName) == null) {
320 + log.warn("Illegal field name: {}", fieldName);
321 + return false;
322 + }
323 + }
324 + return true;
325 + }
326 +
327 + private static String toCamelCase(String value, boolean startWithLowerCase) {
328 + String[] strings = StringUtils.split(value.toLowerCase(), "_");
329 + for (int i = startWithLowerCase ? 1 : 0; i < strings.length; i++) {
330 + strings[i] = StringUtils.capitalize(strings[i]);
331 + }
332 + return StringUtils.join(strings);
333 + }
274 } 334 }
......