blob: c91f9d8bfe2dcd809df53c8ab271e6e1cdf7edc9 [file] [log] [blame]
kdarapu97843dc2018-05-10 12:46:32 +05301/*
2 * Copyright 2017-present Open Networking Foundation
3 *
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 */
16package org.onosproject.nodemetrics.impl;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
24import org.hyperic.sigar.CpuPerc;
25import org.hyperic.sigar.FileSystemUsage;
26import org.hyperic.sigar.Mem;
27import org.hyperic.sigar.Sigar;
28import org.hyperic.sigar.SigarException;
29import org.onlab.util.KryoNamespace;
30import org.onlab.util.Tools;
31import org.onosproject.cluster.ClusterService;
32import org.onosproject.cluster.NodeId;
33import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.nodemetrics.NodeCpu;
36import org.onosproject.nodemetrics.NodeDiskUsage;
37import org.onosproject.nodemetrics.NodeMemory;
38import org.onosproject.nodemetrics.NodeMetricsService;
39import org.onosproject.nodemetrics.Units;
40import org.onosproject.store.serializers.KryoNamespaces;
41import org.onosproject.store.service.EventuallyConsistentMap;
42import org.onosproject.store.service.LogicalClockService;
43import org.onosproject.store.service.StorageService;
44import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
47import java.util.Map;
48import java.util.concurrent.Executors;
49import java.util.concurrent.ScheduledExecutorService;
50import java.util.concurrent.ScheduledFuture;
51import java.util.concurrent.TimeUnit;
52import java.util.stream.Collectors;
53
54@Service
55@Component(immediate = true)
56public class NodeMetricsManager implements NodeMetricsService {
57 private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 15;
58 private static final String SLASH = "/";
59 private static final Double PERCENTAGE_MULTIPLIER = 100.0;
60 private final Logger log = LoggerFactory
61 .getLogger(this.getClass());
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected CoreService coreService;
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected StorageService storageService;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected ClusterService clusterService;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected LogicalClockService clockService;
74
75 private ScheduledExecutorService metricsExecutor;
76 private ScheduledFuture<?> scheduledTask;
77
78 private ApplicationId appId;
79 private NodeId localNodeId;
80
81 private EventuallyConsistentMap<NodeId, NodeMemory> memoryStore;
82 private EventuallyConsistentMap<NodeId, NodeDiskUsage> diskStore;
83 private EventuallyConsistentMap<NodeId, NodeCpu> cpuStore;
84
85 private Sigar sigar;
86
87 @Activate
88 public void activate() {
89 appId = coreService
90 .registerApplication("org.onosproject.nodemetrics");
91 metricsExecutor = Executors.newSingleThreadScheduledExecutor(
92 Tools.groupedThreads("nodemetrics/pollingStatics",
93 "statistics-executor-%d", log));
94
95 localNodeId = clusterService.getLocalNode().id();
96 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
97 .register(KryoNamespaces.API)
98 .register(NodeMemory.class)
99 .register(NodeDiskUsage.class)
100 .register(NodeCpu.class)
101 .register(Units.class);
102 memoryStore = storageService.<NodeId, NodeMemory>eventuallyConsistentMapBuilder()
103 .withSerializer(serializer)
104 .withTimestampProvider((nodeId, memory) -> clockService.getTimestamp())
105 .withName("nodemetrics-memory")
106 .build();
107
108 diskStore = storageService.<NodeId, NodeDiskUsage>eventuallyConsistentMapBuilder()
109 .withSerializer(serializer)
110 .withTimestampProvider((nodeId, disk) -> clockService.getTimestamp())
111 .withName("nodemetrics-disk")
112 .build();
113
114 cpuStore = storageService.<NodeId, NodeCpu>eventuallyConsistentMapBuilder()
115 .withSerializer(serializer)
116 .withTimestampProvider((nodeId, cpu) -> clockService.getTimestamp())
117 .withName("nodemetrics-cpu")
118 .build();
119
120 scheduledTask = schedulePolling();
121 sigar = new Sigar();
122 pollMetrics();
123 }
124
125 @Deactivate
126 public void deactivate() {
127 scheduledTask.cancel(true);
128 metricsExecutor.shutdown();
129 sigar.close();
130 }
131
132 @Override
133 public Map<NodeId, NodeMemory> memory() {
134 return this.ecToMap(memoryStore);
135 }
136
137 @Override
138 public Map<NodeId, NodeDiskUsage> disk() {
139 return this.ecToMap(diskStore);
140 }
141
142 @Override
143 public Map<NodeId, NodeCpu> cpu() {
144 return this.ecToMap(cpuStore);
145 }
146
147 @Override
148 public NodeMemory memory(NodeId nodeid) {
149 return memoryStore.get(nodeid);
150 }
151
152 @Override
153 public NodeDiskUsage disk(NodeId nodeid) {
154 return diskStore.get(nodeid);
155 }
156
157 @Override
158 public NodeCpu cpu(NodeId nodeid) {
159 return cpuStore.get(nodeid);
160 }
161
162 private ScheduledFuture schedulePolling() {
163 return metricsExecutor.scheduleAtFixedRate(this::pollMetrics,
164 DEFAULT_POLL_FREQUENCY_SECONDS / 4,
165 DEFAULT_POLL_FREQUENCY_SECONDS, TimeUnit.SECONDS);
166 }
167
168 private <K, V> Map<K, V> ecToMap(EventuallyConsistentMap<K, V> ecMap) {
169 return ecMap.entrySet()
170 .stream()
171 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
172 }
173 private void pollMetrics() {
174 try {
175 CpuPerc cpu = sigar.getCpuPerc();
176 Mem mem = sigar.getMem();
177 FileSystemUsage disk = sigar.getFileSystemUsage(SLASH);
178
179 NodeMemory memoryNode = new NodeMemory.Builder().free(mem.getFree())
180 .used(mem.getUsed()).total(mem.getTotal()).withUnit(Units.BYTES)
181 .withNode(localNodeId).build();
182 NodeCpu cpuNode = new NodeCpu.Builder().withNode(localNodeId)
183 .usage(cpu.getCombined() * PERCENTAGE_MULTIPLIER).build();
184 NodeDiskUsage diskNode = new NodeDiskUsage.Builder().withNode(localNodeId)
185 .free(disk.getFree()).used(disk.getUsed()).withUnit(Units.KBYTES)
186 .total(disk.getTotal()).build();
187 diskStore.put(localNodeId, diskNode);
188 memoryStore.put(localNodeId, memoryNode);
189 cpuStore.put(localNodeId, cpuNode);
190
191 } catch (SigarException e) {
192 log.error("Exception occurred ", e);
193 }
194
195 }
196}