blob: 3c355abf92c1b306a89d71037761b153ff271269 [file] [log] [blame]
Simon Huntd7f7bcc2015-05-08 14:13:17 -07001/*
2 * Copyright 2015 Open Networking Laboratory
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 *
16 */
17
18package org.onosproject.ui.impl.topo;
19
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
27import org.onosproject.cluster.ClusterEvent;
28import org.onosproject.cluster.ClusterService;
29import org.onosproject.cluster.ControllerNode;
Simon Huntd7f7bcc2015-05-08 14:13:17 -070030import org.onosproject.event.EventDeliveryService;
31import org.onosproject.mastership.MastershipService;
32import org.onosproject.net.Device;
33import org.onosproject.net.Host;
34import org.onosproject.net.Link;
35import org.onosproject.net.device.DeviceEvent;
36import org.onosproject.net.device.DeviceService;
Simon Huntc54cd1b2015-05-11 13:43:44 -070037import org.onosproject.net.flow.FlowRuleService;
Simon Huntd7f7bcc2015-05-08 14:13:17 -070038import org.onosproject.net.host.HostEvent;
39import org.onosproject.net.host.HostService;
Simon Huntc54cd1b2015-05-11 13:43:44 -070040import org.onosproject.net.intent.IntentService;
Simon Huntd7f7bcc2015-05-08 14:13:17 -070041import org.onosproject.net.link.LinkEvent;
42import org.onosproject.net.link.LinkService;
Simon Huntc54cd1b2015-05-11 13:43:44 -070043import org.onosproject.net.topology.Topology;
44import org.onosproject.net.topology.TopologyService;
Simon Huntd7f7bcc2015-05-08 14:13:17 -070045import org.slf4j.Logger;
46import org.slf4j.LoggerFactory;
47
48import java.util.ArrayList;
49import java.util.Collections;
50import java.util.Comparator;
51import java.util.List;
Simon Huntda580882015-05-12 20:58:18 -070052import java.util.Timer;
53import java.util.TimerTask;
Simon Huntd7f7bcc2015-05-08 14:13:17 -070054
55import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
56import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
57import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
58import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
Simon Huntc54cd1b2015-05-11 13:43:44 -070059import static org.onosproject.ui.impl.topo.TopoUiEvent.Type.SUMMARY_UPDATE;
Simon Huntd7f7bcc2015-05-08 14:13:17 -070060
61
62/**
63 * Maintains a UI-centric model of the topology, as inferred from interactions
64 * with the different (device, host, link, ...) services. Will serve up this
65 * model to anyone who cares to {@link TopoUiListener listen}.
66 */
67@Component(immediate = true)
68@Service
69public class TopoUiModelManager implements TopoUiModelService {
70
Simon Huntda580882015-05-12 20:58:18 -070071 // TODO: put back to 30,000 ms for production
72 private static final long SUMMARY_PERIOD = 15_000;
73
Simon Huntd7f7bcc2015-05-08 14:13:17 -070074 private final Logger log = LoggerFactory.getLogger(getClass());
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected ClusterService clusterService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected DeviceService deviceService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected LinkService linkService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected HostService hostService;
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected MastershipService mastershipService;
90
Simon Huntc54cd1b2015-05-11 13:43:44 -070091 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected IntentService intentService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected FlowRuleService flowRuleService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected TopologyService topologyService;
Simon Huntd7f7bcc2015-05-08 14:13:17 -070099
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected EventDeliveryService eventDispatcher;
103
104
Simon Hunt732bb2e2015-05-13 18:32:16 -0700105 private final ModelListenerRegistry listenerRegistry =
106 new ModelListenerRegistry();
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700107
108 private final TopoMessageFactory messageFactory = new TopoMessageFactory();
109 private final MetaDb metaDb = new MetaDb();
110
Simon Huntda580882015-05-12 20:58:18 -0700111 private final Timer timer = new Timer("topology-view");
112
113 private TimerTask summaryTask = null;
114 private boolean summaryRunning = false;
115
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700116
117 @Activate
118 public void activate() {
119 eventDispatcher.addSink(TopoUiEvent.class, listenerRegistry);
120 messageFactory.injectServices(
121 metaDb,
122 clusterService,
123 deviceService,
124 linkService,
125 hostService,
126 mastershipService
Simon Huntc54cd1b2015-05-11 13:43:44 -0700127 // TODO: others??
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700128 );
129 log.info("Started");
130 }
131
132 @Deactivate
133 public void deactivate() {
134 eventDispatcher.removeSink(TopoUiEvent.class);
135 log.info("Stopped");
136 }
137
Simon Huntc54cd1b2015-05-11 13:43:44 -0700138
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700139 @Override
140 public void addListener(TopoUiListener listener) {
141 listenerRegistry.addListener(listener);
142 }
143
144 @Override
145 public void removeListener(TopoUiListener listener) {
Simon Huntff663742015-05-14 13:33:05 -0700146 listenerRegistry.removeListener(listener);
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700147 }
148
149 @Override
150 public List<ObjectNode> getInitialState() {
151 List<ObjectNode> results = new ArrayList<>();
152 addInstances(results);
153 addDevices(results);
154 addLinks(results);
155 addHosts(results);
156 return results;
157 }
158
Simon Huntc54cd1b2015-05-11 13:43:44 -0700159 @Override
Simon Huntda580882015-05-12 20:58:18 -0700160 public synchronized void startSummaryMonitoring() {
161 // first, cancel previous task if not canceled already
162 stopSummaryMonitoring();
163
164 // create and start a summary task, to execute with no delay, and
165 // every SUMMARY_PERIOD milliseconds thereafter.
166 summaryTask = new TimerTask() {
167 @Override
168 public void run() {
169 if (summaryRunning) {
170 post(new TopoUiEvent(SUMMARY_UPDATE, null));
171 }
172 }
173 };
174
175 timer.schedule(summaryTask, 0, SUMMARY_PERIOD);
176 summaryRunning = true;
Simon Huntc54cd1b2015-05-11 13:43:44 -0700177 }
178
179 @Override
Simon Huntda580882015-05-12 20:58:18 -0700180 public synchronized void stopSummaryMonitoring() {
181 if (summaryTask != null) {
182 summaryTask.cancel();
183 summaryTask = null;
184 }
185 summaryRunning = false;
Simon Huntc54cd1b2015-05-11 13:43:44 -0700186 }
187
188 @Override
189 public SummaryData getSummaryData() {
190 return new SummaryDataImpl();
191 }
192
193 // =====================================================================
194
195 private final class SummaryDataImpl implements SummaryData {
196 private final Topology topology = topologyService.currentTopology();
197
198 @Override
199 public int deviceCount() {
200 return topology.deviceCount();
201 }
202
203 @Override
204 public int linkCount() {
205 return topology.linkCount();
206 }
207
208 @Override
209 public int hostCount() {
210 return hostService.getHostCount();
211 }
212
213 @Override
214 public int clusterCount() {
215 return topology.clusterCount();
216 }
217
218 @Override
219 public long intentCount() {
220 return intentService.getIntentCount();
221 }
222
223 @Override
224 public int flowRuleCount() {
225 return flowRuleService.getFlowRuleCount();
226 }
227 }
228
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700229 // =====================================================================
230
231 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
232 (o1, o2) -> o1.id().toString().compareTo(o2.id().toString());
233
234 // =====================================================================
235
236 private void addInstances(List<ObjectNode> results) {
237 List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes());
238 Collections.sort(nodes, NODE_COMPARATOR);
239 for (ControllerNode node : nodes) {
240 ClusterEvent ev = new ClusterEvent(INSTANCE_ADDED, node);
241 results.add(messageFactory.instanceMessage(ev));
242 }
243 }
244
245 private void addDevices(List<ObjectNode> results) {
246 // Send optical first, others later -- for layered rendering
247 List<DeviceEvent> deferred = new ArrayList<>();
248
249 for (Device device : deviceService.getDevices()) {
250 DeviceEvent ev = new DeviceEvent(DEVICE_ADDED, device);
251 if (device.type() == Device.Type.ROADM) {
252 results.add(messageFactory.deviceMessage(ev));
253 } else {
254 deferred.add(ev);
255 }
256 }
257
258 for (DeviceEvent ev : deferred) {
259 results.add(messageFactory.deviceMessage(ev));
260 }
261 }
262
263 private void addLinks(List<ObjectNode> results) {
264 // Send optical first, others later -- for layered rendering
265 List<LinkEvent> deferred = new ArrayList<>();
266
267 for (Link link : linkService.getLinks()) {
268 LinkEvent ev = new LinkEvent(LINK_ADDED, link);
269 if (link.type() == Link.Type.OPTICAL) {
270 results.add(messageFactory.linkMessage(ev));
271 } else {
272 deferred.add(ev);
273 }
274 }
275
276 for (LinkEvent ev : deferred) {
277 results.add(messageFactory.linkMessage(ev));
278 }
279 }
280
281 private void addHosts(List<ObjectNode> results) {
282 for (Host host : hostService.getHosts()) {
283 HostEvent ev = new HostEvent(HOST_ADDED, host);
284 results.add(messageFactory.hostMessage(ev));
285 }
286 }
287
288 // =====================================================================
289
290 private void post(TopoUiEvent event) {
291 if (event != null) {
292 eventDispatcher.post(event);
293 }
294 }
295
296 // NOTE: session-independent state only
297 // private inner classes to listen to device/host/link events
298 // TODO..
299}