blob: c80c2e2a9233078ca177cfa3845e9f955d7df17c [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 Hunt732bb2e2015-05-13 18:32:16 -0700146 // we don't really care if the listener is not listed...
147 try {
148 listenerRegistry.removeListener(listener);
149 } catch (IllegalArgumentException e) {
150 log.debug("Oops, listener not registered: {}", listener);
151 }
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700152 }
153
154 @Override
155 public List<ObjectNode> getInitialState() {
156 List<ObjectNode> results = new ArrayList<>();
157 addInstances(results);
158 addDevices(results);
159 addLinks(results);
160 addHosts(results);
161 return results;
162 }
163
Simon Huntc54cd1b2015-05-11 13:43:44 -0700164 @Override
Simon Huntda580882015-05-12 20:58:18 -0700165 public synchronized void startSummaryMonitoring() {
166 // first, cancel previous task if not canceled already
167 stopSummaryMonitoring();
168
169 // create and start a summary task, to execute with no delay, and
170 // every SUMMARY_PERIOD milliseconds thereafter.
171 summaryTask = new TimerTask() {
172 @Override
173 public void run() {
174 if (summaryRunning) {
175 post(new TopoUiEvent(SUMMARY_UPDATE, null));
176 }
177 }
178 };
179
180 timer.schedule(summaryTask, 0, SUMMARY_PERIOD);
181 summaryRunning = true;
Simon Huntc54cd1b2015-05-11 13:43:44 -0700182 }
183
184 @Override
Simon Huntda580882015-05-12 20:58:18 -0700185 public synchronized void stopSummaryMonitoring() {
186 if (summaryTask != null) {
187 summaryTask.cancel();
188 summaryTask = null;
189 }
190 summaryRunning = false;
Simon Huntc54cd1b2015-05-11 13:43:44 -0700191 }
192
193 @Override
194 public SummaryData getSummaryData() {
195 return new SummaryDataImpl();
196 }
197
198 // =====================================================================
199
200 private final class SummaryDataImpl implements SummaryData {
201 private final Topology topology = topologyService.currentTopology();
202
203 @Override
204 public int deviceCount() {
205 return topology.deviceCount();
206 }
207
208 @Override
209 public int linkCount() {
210 return topology.linkCount();
211 }
212
213 @Override
214 public int hostCount() {
215 return hostService.getHostCount();
216 }
217
218 @Override
219 public int clusterCount() {
220 return topology.clusterCount();
221 }
222
223 @Override
224 public long intentCount() {
225 return intentService.getIntentCount();
226 }
227
228 @Override
229 public int flowRuleCount() {
230 return flowRuleService.getFlowRuleCount();
231 }
232 }
233
Simon Huntd7f7bcc2015-05-08 14:13:17 -0700234 // =====================================================================
235
236 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
237 (o1, o2) -> o1.id().toString().compareTo(o2.id().toString());
238
239 // =====================================================================
240
241 private void addInstances(List<ObjectNode> results) {
242 List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes());
243 Collections.sort(nodes, NODE_COMPARATOR);
244 for (ControllerNode node : nodes) {
245 ClusterEvent ev = new ClusterEvent(INSTANCE_ADDED, node);
246 results.add(messageFactory.instanceMessage(ev));
247 }
248 }
249
250 private void addDevices(List<ObjectNode> results) {
251 // Send optical first, others later -- for layered rendering
252 List<DeviceEvent> deferred = new ArrayList<>();
253
254 for (Device device : deviceService.getDevices()) {
255 DeviceEvent ev = new DeviceEvent(DEVICE_ADDED, device);
256 if (device.type() == Device.Type.ROADM) {
257 results.add(messageFactory.deviceMessage(ev));
258 } else {
259 deferred.add(ev);
260 }
261 }
262
263 for (DeviceEvent ev : deferred) {
264 results.add(messageFactory.deviceMessage(ev));
265 }
266 }
267
268 private void addLinks(List<ObjectNode> results) {
269 // Send optical first, others later -- for layered rendering
270 List<LinkEvent> deferred = new ArrayList<>();
271
272 for (Link link : linkService.getLinks()) {
273 LinkEvent ev = new LinkEvent(LINK_ADDED, link);
274 if (link.type() == Link.Type.OPTICAL) {
275 results.add(messageFactory.linkMessage(ev));
276 } else {
277 deferred.add(ev);
278 }
279 }
280
281 for (LinkEvent ev : deferred) {
282 results.add(messageFactory.linkMessage(ev));
283 }
284 }
285
286 private void addHosts(List<ObjectNode> results) {
287 for (Host host : hostService.getHosts()) {
288 HostEvent ev = new HostEvent(HOST_ADDED, host);
289 results.add(messageFactory.hostMessage(ev));
290 }
291 }
292
293 // =====================================================================
294
295 private void post(TopoUiEvent event) {
296 if (event != null) {
297 eventDispatcher.post(event);
298 }
299 }
300
301 // NOTE: session-independent state only
302 // private inner classes to listen to device/host/link events
303 // TODO..
304}