blob: 77e8e89166e0c3d5156bddf3dc10ee8bcdee2ae9 [file] [log] [blame]
Jian Li60804322015-12-02 14:46:31 -08001/*
Jian Lie044d1a2016-01-25 09:01:20 -08002 * Copyright 2015-2016 Open Networking Laboratory
Jian Li60804322015-12-02 14:46:31 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jian Li6b86a762016-01-29 09:30:40 -080016package org.onosproject.cpman.impl;
Jian Li60804322015-12-02 14:46:31 -080017
Jian Li7d180c52016-02-01 21:53:08 -080018import com.google.common.collect.ImmutableSet;
Jian Li85060ac2016-02-04 09:58:56 -080019import com.google.common.collect.Maps;
20import com.google.common.collect.Sets;
Jian Li60804322015-12-02 14:46:31 -080021import org.apache.felix.scr.annotations.Activate;
Jian Lic132c112016-01-28 20:27:34 -080022import org.apache.felix.scr.annotations.Component;
Jian Li60804322015-12-02 14:46:31 -080023import org.apache.felix.scr.annotations.Deactivate;
Jian Li7d180c52016-02-01 21:53:08 -080024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Jian Li60804322015-12-02 14:46:31 -080026import org.apache.felix.scr.annotations.Service;
Jian Li7d180c52016-02-01 21:53:08 -080027import org.onosproject.cluster.ClusterService;
28import org.onosproject.cluster.ControllerNode;
Jian Li60804322015-12-02 14:46:31 -080029import org.onosproject.cluster.NodeId;
Jian Li6b86a762016-01-29 09:30:40 -080030import org.onosproject.cpman.ControlLoad;
31import org.onosproject.cpman.ControlMetric;
32import org.onosproject.cpman.ControlMetricType;
33import org.onosproject.cpman.ControlPlaneMonitorService;
Jian Li7d180c52016-02-01 21:53:08 -080034import org.onosproject.cpman.MetricsDatabase;
Jian Li60804322015-12-02 14:46:31 -080035import org.onosproject.net.DeviceId;
Jian Li60804322015-12-02 14:46:31 -080036import org.slf4j.Logger;
Jian Li7d180c52016-02-01 21:53:08 -080037import org.slf4j.LoggerFactory;
Jian Li60804322015-12-02 14:46:31 -080038
Jian Li7d180c52016-02-01 21:53:08 -080039import java.util.Map;
Jian Li60804322015-12-02 14:46:31 -080040import java.util.Optional;
Jian Lic5cb4a12016-02-03 23:24:42 -080041import java.util.Set;
Jian Li85060ac2016-02-04 09:58:56 -080042import java.util.stream.Collectors;
Jian Li60804322015-12-02 14:46:31 -080043
Jian Li85060ac2016-02-04 09:58:56 -080044import static org.onosproject.cpman.ControlResource.*;
Jian Li60804322015-12-02 14:46:31 -080045
46/**
47 * Control plane monitoring service class.
48 */
49@Component(immediate = true)
50@Service
51public class ControlPlaneMonitor implements ControlPlaneMonitorService {
52
Jian Li7d180c52016-02-01 21:53:08 -080053 private final Logger log = LoggerFactory.getLogger(getClass());
54 private MetricsDatabase cpuMetrics;
55 private MetricsDatabase memoryMetrics;
56 private Map<DeviceId, MetricsDatabase> controlMessageMap;
57 private Map<String, MetricsDatabase> diskMetricsMap;
58 private Map<String, MetricsDatabase> networkMetricsMap;
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected ClusterService clusterService;
62
Jian Li85060ac2016-02-04 09:58:56 -080063 private static final Set RESOURCE_TYPE_SET =
64 ImmutableSet.of(Type.CONTROL_MESSAGE, Type.DISK, Type.NETWORK);
Jian Li7d180c52016-02-01 21:53:08 -080065
Jian Li7d180c52016-02-01 21:53:08 -080066 private Map<ControlMetricType, Double> cpuBuf;
67 private Map<ControlMetricType, Double> memoryBuf;
68 private Map<String, Map<ControlMetricType, Double>> diskBuf;
69 private Map<String, Map<ControlMetricType, Double>> networkBuf;
70 private Map<DeviceId, Map<ControlMetricType, Double>> ctrlMsgBuf;
Jian Li60804322015-12-02 14:46:31 -080071
Jian Li85060ac2016-02-04 09:58:56 -080072 private Map<Type, Set<String>> availableResourceMap;
73 private Set<DeviceId> availableDeviceIdSet;
74
Jian Li60804322015-12-02 14:46:31 -080075 @Activate
76 public void activate() {
Jian Li85060ac2016-02-04 09:58:56 -080077 cpuMetrics = genMDbBuilder(Type.CPU, CPU_METRICS);
78 memoryMetrics = genMDbBuilder(Type.MEMORY, MEMORY_METRICS);
79 controlMessageMap = Maps.newConcurrentMap();
80 diskMetricsMap = Maps.newConcurrentMap();
81 networkMetricsMap = Maps.newConcurrentMap();
Jian Li7d180c52016-02-01 21:53:08 -080082
Jian Li85060ac2016-02-04 09:58:56 -080083 cpuBuf = Maps.newConcurrentMap();
84 memoryBuf = Maps.newConcurrentMap();
85 diskBuf = Maps.newConcurrentMap();
86 networkBuf = Maps.newConcurrentMap();
87 ctrlMsgBuf = Maps.newConcurrentMap();
88
89 availableResourceMap = Maps.newConcurrentMap();
90 availableDeviceIdSet = Sets.newConcurrentHashSet();
Jian Li7d180c52016-02-01 21:53:08 -080091
92 log.info("Started");
Jian Li60804322015-12-02 14:46:31 -080093 }
94
95 @Deactivate
96 public void deactivate() {
Jian Li7d180c52016-02-01 21:53:08 -080097
98 // TODO: need to handle the mdb close.
99 cpuBuf.clear();
100 memoryBuf.clear();
101 diskBuf.clear();
102 networkBuf.clear();
103 ctrlMsgBuf.clear();
104
105 log.info("Stopped");
Jian Li60804322015-12-02 14:46:31 -0800106 }
107
Jian Li60804322015-12-02 14:46:31 -0800108 @Override
Jian Lic5cb4a12016-02-03 23:24:42 -0800109 public void updateMetric(ControlMetric cm, int updateIntervalInMinutes,
Jian Li60804322015-12-02 14:46:31 -0800110 Optional<DeviceId> deviceId) {
Jian Li7d180c52016-02-01 21:53:08 -0800111 if (deviceId.isPresent()) {
Jian Li46148902016-01-29 13:33:50 -0800112
Jian Li7d180c52016-02-01 21:53:08 -0800113 // insert a new device entry if we cannot find any
Jian Li85060ac2016-02-04 09:58:56 -0800114 ctrlMsgBuf.putIfAbsent(deviceId.get(), Maps.newConcurrentMap());
Jian Li7d180c52016-02-01 21:53:08 -0800115
116 // update control message metrics
Jian Li85060ac2016-02-04 09:58:56 -0800117 if (CONTROL_MESSAGE_METRICS.contains(cm.metricType())) {
118
119 if (!availableDeviceIdSet.contains(deviceId.get())) {
120 availableDeviceIdSet.add(deviceId.get());
121 }
Jian Li7d180c52016-02-01 21:53:08 -0800122
123 // we will accumulate the metric value into buffer first
124 ctrlMsgBuf.get(deviceId.get()).putIfAbsent(cm.metricType(),
125 (double) cm.metricValue().getLoad());
126
127 // if buffer contains all control message metrics,
128 // we simply set and update the values into MetricsDatabase.
Jian Li85060ac2016-02-04 09:58:56 -0800129 if (ctrlMsgBuf.get(deviceId.get()).keySet()
130 .containsAll(CONTROL_MESSAGE_METRICS)) {
Jian Li7d180c52016-02-01 21:53:08 -0800131 updateControlMessages(ctrlMsgBuf.get(deviceId.get()), deviceId.get());
132 ctrlMsgBuf.get(deviceId.get()).clear();
133 }
134 }
135 } else {
136
137 // update cpu metrics
138 if (CPU_METRICS.contains(cm.metricType())) {
139 cpuBuf.putIfAbsent(cm.metricType(),
140 (double) cm.metricValue().getLoad());
141 if (cpuBuf.keySet().containsAll(CPU_METRICS)) {
142 cpuMetrics.updateMetrics(convertMap(cpuBuf));
143 cpuBuf.clear();
144 }
145 }
146
147 // update memory metrics
148 if (MEMORY_METRICS.contains(cm.metricType())) {
149 memoryBuf.putIfAbsent(cm.metricType(),
150 (double) cm.metricValue().getLoad());
151 if (memoryBuf.keySet().containsAll(MEMORY_METRICS)) {
152 memoryMetrics.updateMetrics(convertMap(memoryBuf));
153 memoryBuf.clear();
154 }
155 }
156 }
Jian Li60804322015-12-02 14:46:31 -0800157 }
158
159 @Override
Jian Lic5cb4a12016-02-03 23:24:42 -0800160 public void updateMetric(ControlMetric cm, int updateIntervalInMinutes,
Jian Lie044d1a2016-01-25 09:01:20 -0800161 String resourceName) {
Jian Li7d180c52016-02-01 21:53:08 -0800162 // update disk metrics
163 if (DISK_METRICS.contains(cm.metricType())) {
Jian Li85060ac2016-02-04 09:58:56 -0800164 diskBuf.putIfAbsent(resourceName, Maps.newConcurrentMap());
165
166 availableResourceMap.putIfAbsent(Type.DISK, Sets.newHashSet());
167 availableResourceMap.computeIfPresent(Type.DISK, (k, v) -> {
168 v.add(resourceName);
169 return v;
170 });
171
Jian Li7d180c52016-02-01 21:53:08 -0800172 diskBuf.get(resourceName).putIfAbsent(cm.metricType(),
173 (double) cm.metricValue().getLoad());
174 if (diskBuf.get(resourceName).keySet().containsAll(DISK_METRICS)) {
175 updateDiskMetrics(diskBuf.get(resourceName), resourceName);
176 diskBuf.clear();
177 }
178 }
Jian Lie044d1a2016-01-25 09:01:20 -0800179
Jian Li7d180c52016-02-01 21:53:08 -0800180 // update network metrics
181 if (NETWORK_METRICS.contains(cm.metricType())) {
Jian Li85060ac2016-02-04 09:58:56 -0800182 networkBuf.putIfAbsent(resourceName, Maps.newConcurrentMap());
183
184 availableResourceMap.putIfAbsent(Type.NETWORK, Sets.newHashSet());
185 availableResourceMap.computeIfPresent(Type.NETWORK, (k, v) -> {
186 v.add(resourceName);
187 return v;
188 });
189
Jian Li7d180c52016-02-01 21:53:08 -0800190 networkBuf.get(resourceName).putIfAbsent(cm.metricType(),
191 (double) cm.metricValue().getLoad());
192 if (networkBuf.get(resourceName).keySet().containsAll(NETWORK_METRICS)) {
193 updateNetworkMetrics(networkBuf.get(resourceName), resourceName);
194 networkBuf.clear();
195 }
196 }
Jian Lie044d1a2016-01-25 09:01:20 -0800197 }
198
199 @Override
Jian Li60804322015-12-02 14:46:31 -0800200 public ControlLoad getLoad(NodeId nodeId, ControlMetricType type,
201 Optional<DeviceId> deviceId) {
Jian Li7d180c52016-02-01 21:53:08 -0800202 ControllerNode node = clusterService.getNode(nodeId);
203 if (clusterService.getLocalNode().equals(node)) {
204
205 if (deviceId.isPresent()) {
Jian Li85060ac2016-02-04 09:58:56 -0800206 if (CONTROL_MESSAGE_METRICS.contains(type) &&
207 availableDeviceIdSet.contains(deviceId.get())) {
Jian Li7d180c52016-02-01 21:53:08 -0800208 return new DefaultControlLoad(controlMessageMap.get(deviceId.get()), type);
209 }
210 } else {
211 // returns controlLoad of CPU metrics
212 if (CPU_METRICS.contains(type)) {
213 return new DefaultControlLoad(cpuMetrics, type);
214 }
215
216 // returns memoryLoad of memory metrics
217 if (MEMORY_METRICS.contains(type)) {
218 return new DefaultControlLoad(memoryMetrics, type);
219 }
220 }
221 } else {
222 // TODO: currently only query the metrics of local node
223 return null;
224 }
Jian Li60804322015-12-02 14:46:31 -0800225 return null;
226 }
227
228 @Override
229 public ControlLoad getLoad(NodeId nodeId, ControlMetricType type,
Jian Li7d180c52016-02-01 21:53:08 -0800230 String resourceName) {
231 if (clusterService.getLocalNode().id().equals(nodeId)) {
Jian Li85060ac2016-02-04 09:58:56 -0800232 if (DISK_METRICS.contains(type) &&
233 availableResources(Type.DISK).contains(resourceName)) {
Jian Li7d180c52016-02-01 21:53:08 -0800234 return new DefaultControlLoad(diskMetricsMap.get(resourceName), type);
235 }
236
Jian Li85060ac2016-02-04 09:58:56 -0800237 if (NETWORK_METRICS.contains(type) &&
238 availableResources(Type.NETWORK).contains(resourceName)) {
Jian Li7d180c52016-02-01 21:53:08 -0800239 return new DefaultControlLoad(networkMetricsMap.get(resourceName), type);
240 }
241 } else {
242 // TODO: currently only query the metrics of local node
243 return null;
244 }
Jian Li60804322015-12-02 14:46:31 -0800245 return null;
246 }
Jian Li7d180c52016-02-01 21:53:08 -0800247
Jian Li85060ac2016-02-04 09:58:56 -0800248 @Override
249 public Set<String> availableResources(Type resourceType) {
250 if (RESOURCE_TYPE_SET.contains(resourceType)) {
251 if (Type.CONTROL_MESSAGE.equals(resourceType)) {
252 return availableDeviceIdSet.stream().map(id ->
253 id.toString()).collect(Collectors.toSet());
254 } else {
255 return availableResourceMap.get(resourceType);
256 }
257 }
258 return null;
259 }
260
261 private MetricsDatabase genMDbBuilder(Type resourceType,
Jian Lic5cb4a12016-02-03 23:24:42 -0800262 Set<ControlMetricType> metricTypes) {
Jian Li7d180c52016-02-01 21:53:08 -0800263 MetricsDatabase.Builder builder = new DefaultMetricsDatabase.Builder();
Jian Li85060ac2016-02-04 09:58:56 -0800264 builder.withMetricName(resourceType.toString());
Jian Li7d180c52016-02-01 21:53:08 -0800265 metricTypes.forEach(type -> builder.addMetricType(type.toString()));
266 return builder.build();
267 }
268
269 private void updateNetworkMetrics(Map<ControlMetricType, Double> metricMap,
270 String resName) {
Jian Li85060ac2016-02-04 09:58:56 -0800271 networkMetricsMap.putIfAbsent(resName,
272 genMDbBuilder(Type.NETWORK, NETWORK_METRICS));
Jian Li7d180c52016-02-01 21:53:08 -0800273 networkMetricsMap.get(resName).updateMetrics(convertMap(metricMap));
274 }
275
276 private void updateDiskMetrics(Map<ControlMetricType, Double> metricMap,
277 String resName) {
Jian Li85060ac2016-02-04 09:58:56 -0800278 diskMetricsMap.putIfAbsent(resName, genMDbBuilder(Type.DISK, DISK_METRICS));
Jian Li7d180c52016-02-01 21:53:08 -0800279 diskMetricsMap.get(resName).updateMetrics(convertMap(metricMap));
280 }
281
282 private void updateControlMessages(Map<ControlMetricType, Double> metricMap,
283 DeviceId devId) {
Jian Li85060ac2016-02-04 09:58:56 -0800284 controlMessageMap.putIfAbsent(devId,
285 genMDbBuilder(Type.CONTROL_MESSAGE, CONTROL_MESSAGE_METRICS));
Jian Li7d180c52016-02-01 21:53:08 -0800286 controlMessageMap.get(devId).updateMetrics(convertMap(metricMap));
287 }
288
289 private Map convertMap(Map<ControlMetricType, Double> map) {
Jian Li85060ac2016-02-04 09:58:56 -0800290 Map newMap = Maps.newConcurrentMap();
Jian Li7d180c52016-02-01 21:53:08 -0800291 map.forEach((k, v) -> newMap.putIfAbsent(k.toString(), v));
292 return newMap;
293 }
Jian Li60804322015-12-02 14:46:31 -0800294}