blob: 80d134a14746b4e6bfc0d405384fc5029a481e86 [file] [log] [blame]
Simon Hunted804d52016-03-30 09:51:40 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Simon Hunted804d52016-03-30 09:51:40 -07003 *
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
17package org.onosproject.ui.impl.topo.model;
18
Simon Huntcda9c032016-04-11 10:32:54 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
Simon Hunt7092cc42016-04-06 18:40:17 -070025import org.onosproject.cluster.ClusterEvent;
26import org.onosproject.cluster.ClusterEventListener;
27import org.onosproject.cluster.ClusterService;
Simon Hunt23fb1352016-04-11 12:15:19 -070028import org.onosproject.cluster.ControllerNode;
29import org.onosproject.cluster.RoleInfo;
Simon Huntcda9c032016-04-11 10:32:54 -070030import org.onosproject.event.AbstractListenerManager;
Simon Hunt7092cc42016-04-06 18:40:17 -070031import org.onosproject.incubator.net.PortStatisticsService;
32import org.onosproject.incubator.net.tunnel.TunnelService;
33import org.onosproject.mastership.MastershipEvent;
34import org.onosproject.mastership.MastershipListener;
35import org.onosproject.mastership.MastershipService;
Simon Huntcda9c032016-04-11 10:32:54 -070036import org.onosproject.net.Device;
Simon Hunt23fb1352016-04-11 12:15:19 -070037import org.onosproject.net.DeviceId;
38import org.onosproject.net.Host;
39import org.onosproject.net.Link;
Simon Hunt7092cc42016-04-06 18:40:17 -070040import org.onosproject.net.device.DeviceEvent;
41import org.onosproject.net.device.DeviceListener;
42import org.onosproject.net.device.DeviceService;
43import org.onosproject.net.flow.FlowRuleEvent;
44import org.onosproject.net.flow.FlowRuleListener;
45import org.onosproject.net.flow.FlowRuleService;
46import org.onosproject.net.host.HostEvent;
47import org.onosproject.net.host.HostListener;
48import org.onosproject.net.host.HostService;
49import org.onosproject.net.intent.IntentEvent;
50import org.onosproject.net.intent.IntentListener;
51import org.onosproject.net.intent.IntentService;
52import org.onosproject.net.link.LinkEvent;
53import org.onosproject.net.link.LinkListener;
54import org.onosproject.net.link.LinkService;
Simon Hunt23fb1352016-04-11 12:15:19 -070055import org.onosproject.net.region.Region;
Simon Hunt7092cc42016-04-06 18:40:17 -070056import org.onosproject.net.region.RegionEvent;
Simon Hunt977aa052016-07-20 17:08:29 -070057import org.onosproject.net.region.RegionId;
Simon Hunt7092cc42016-04-06 18:40:17 -070058import org.onosproject.net.region.RegionListener;
59import org.onosproject.net.region.RegionService;
60import org.onosproject.net.statistic.StatisticService;
61import org.onosproject.net.topology.TopologyService;
Simon Hunt4f4ffc32016-08-03 18:30:47 -070062import org.onosproject.ui.UiTopoLayoutService;
Simon Hunt8eac4ae2017-01-20 12:56:45 -080063import org.onosproject.ui.impl.topo.Topo2Jsonifier;
Simon Huntf679c4e2016-04-01 17:02:24 -070064import org.onosproject.ui.impl.topo.UiTopoSession;
Simon Hunt642bc452016-05-04 19:34:45 -070065import org.onosproject.ui.model.ServiceBundle;
Simon Huntd5b96732016-07-08 13:22:27 -070066import org.onosproject.ui.model.topo.UiClusterMember;
Simon Hunt4854f3d2016-08-02 18:13:15 -070067import org.onosproject.ui.model.topo.UiDevice;
Simon Huntc13082f2016-08-03 21:20:23 -070068import org.onosproject.ui.model.topo.UiDeviceLink;
Simon Hunt4854f3d2016-08-02 18:13:15 -070069import org.onosproject.ui.model.topo.UiHost;
Simon Huntd5b96732016-07-08 13:22:27 -070070import org.onosproject.ui.model.topo.UiRegion;
Simon Huntc13082f2016-08-03 21:20:23 -070071import org.onosproject.ui.model.topo.UiSynthLink;
Simon Hunted804d52016-03-30 09:51:40 -070072import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74
Simon Huntd5b96732016-07-08 13:22:27 -070075import java.util.List;
Simon Hunt10973dd2016-08-01 15:50:35 -070076import java.util.Set;
Simon Huntd5b96732016-07-08 13:22:27 -070077import java.util.concurrent.ExecutorService;
Simon Hunt8eac4ae2017-01-20 12:56:45 -080078
79import static java.util.concurrent.Executors.newSingleThreadExecutor;
80import static org.onlab.util.Tools.groupedThreads;
Simon Huntd5b96732016-07-08 13:22:27 -070081
Simon Hunted804d52016-03-30 09:51:40 -070082/**
Simon Huntcda9c032016-04-11 10:32:54 -070083 * Service that creates and maintains the UI-model of the network topology.
Simon Hunted804d52016-03-30 09:51:40 -070084 */
Thomas Vachuska92b016b2016-05-20 11:37:57 -070085@Component(immediate = true, enabled = true)
Simon Huntcda9c032016-04-11 10:32:54 -070086@Service(value = UiSharedTopologyModel.class)
87public final class UiSharedTopologyModel
88 extends AbstractListenerManager<UiModelEvent, UiModelListener> {
Simon Hunted804d52016-03-30 09:51:40 -070089
90 private static final Logger log =
91 LoggerFactory.getLogger(UiSharedTopologyModel.class);
92
Simon Huntcda9c032016-04-11 10:32:54 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Simon Hunt4f4ffc32016-08-03 18:30:47 -070094 private UiTopoLayoutService layoutService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Simon Huntcda9c032016-04-11 10:32:54 -070097 private ClusterService clusterService;
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 private MastershipService mastershipService;
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 private RegionService regionService;
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 private DeviceService deviceService;
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 private LinkService linkService;
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 private HostService hostService;
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 private IntentService intentService;
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 private FlowRuleService flowService;
Simon Hunt7092cc42016-04-06 18:40:17 -0700112
Simon Huntcda9c032016-04-11 10:32:54 -0700113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 private StatisticService flowStatsService;
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 private PortStatisticsService portStatsService;
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 private TopologyService topologyService;
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 private TunnelService tunnelService;
Simon Hunted804d52016-03-30 09:51:40 -0700121
Simon Huntcda9c032016-04-11 10:32:54 -0700122 private final ClusterEventListener clusterListener =
123 new InternalClusterListener();
124 private final MastershipListener mastershipListener =
125 new InternalMastershipListener();
126 private final RegionListener regionListener =
127 new InternalRegionListener();
128 private final DeviceListener deviceListener =
129 new InternalDeviceListener();
130 private final LinkListener linkListener =
131 new InternalLinkListener();
132 private final HostListener hostListener =
133 new InternalHostListener();
134 private final IntentListener intentListener =
135 new InternalIntentListener();
136 private final FlowRuleListener flowRuleListener =
137 new InternalFlowRuleListener();
Simon Hunt7092cc42016-04-06 18:40:17 -0700138
Madan Jampani492526a2016-06-06 17:24:04 -0700139 private ExecutorService eventHandler;
140
Simon Huntcda9c032016-04-11 10:32:54 -0700141
142 private ModelCache cache;
143
144
145 @Activate
146 protected void activate() {
Simon Hunt642bc452016-05-04 19:34:45 -0700147 cache = new ModelCache(new DefaultServiceBundle(), eventDispatcher);
Simon Hunt8eac4ae2017-01-20 12:56:45 -0800148 eventHandler = newSingleThreadExecutor(groupedThreads("onos/ui/topo", "event-handler", log));
Simon Huntcda9c032016-04-11 10:32:54 -0700149
150 eventDispatcher.addSink(UiModelEvent.class, listenerRegistry);
151
152 clusterService.addListener(clusterListener);
153 mastershipService.addListener(mastershipListener);
154 regionService.addListener(regionListener);
155 deviceService.addListener(deviceListener);
156 linkService.addListener(linkListener);
157 hostService.addListener(hostListener);
158 intentService.addListener(intentListener);
159 flowService.addListener(flowRuleListener);
160
161 cache.load();
162
163 log.info("Started");
Simon Hunted804d52016-03-30 09:51:40 -0700164 }
165
Simon Huntcda9c032016-04-11 10:32:54 -0700166 @Deactivate
167 protected void deactivate() {
168 eventDispatcher.removeSink(UiModelEvent.class);
169
170 clusterService.removeListener(clusterListener);
171 mastershipService.removeListener(mastershipListener);
172 regionService.removeListener(regionListener);
173 deviceService.removeListener(deviceListener);
174 linkService.removeListener(linkListener);
175 hostService.removeListener(hostListener);
176 intentService.removeListener(intentListener);
177 flowService.removeListener(flowRuleListener);
178
Madan Jampani492526a2016-06-06 17:24:04 -0700179 eventHandler.shutdown();
180
Simon Huntcda9c032016-04-11 10:32:54 -0700181 cache.clear();
182 cache = null;
183
184 log.info("Stopped");
185 }
186
Simon Hunt8eac4ae2017-01-20 12:56:45 -0800187 /**
188 * Injects an instance of the JSON-ifier (which has been bound to the
189 * services (link, host, device, ...)) to be passed on to the Model Cache,
190 * for use in forming UiModelEvent payloads.
191 *
192 * @param t2json JSONifier
193 */
194 public void injectJsonifier(Topo2Jsonifier t2json) {
195 cache.injectJsonifier(t2json);
196 }
197
Simon Huntcda9c032016-04-11 10:32:54 -0700198
Simon Huntf679c4e2016-04-01 17:02:24 -0700199 /**
200 * Registers a UI topology session with the topology model.
201 *
202 * @param session the session to register
203 */
204 public void register(UiTopoSession session) {
205 log.info("Registering topology session {}", session);
Simon Huntcda9c032016-04-11 10:32:54 -0700206 addListener(session);
Simon Hunted804d52016-03-30 09:51:40 -0700207 }
208
Simon Huntf679c4e2016-04-01 17:02:24 -0700209 /**
210 * Unregisters a UI topology session from the topology model.
211 *
212 * @param session the session to unregister
213 */
214 public void unregister(UiTopoSession session) {
215 log.info("Unregistering topology session {}", session);
Simon Huntcda9c032016-04-11 10:32:54 -0700216 removeListener(session);
Simon Huntf679c4e2016-04-01 17:02:24 -0700217 }
218
Simon Huntd5b96732016-07-08 13:22:27 -0700219
220 // =======================================================================
Simon Hunt10973dd2016-08-01 15:50:35 -0700221 // Methods for topo session (or CLI) to use to get information from us
Simon Huntd5b96732016-07-08 13:22:27 -0700222
223 /**
Simon Hunt4854f3d2016-08-02 18:13:15 -0700224 * Refreshes the cache's internal state.
225 */
226 public void refresh() {
227 cache.refresh();
228 }
229
230 /**
231 * Returns the list of cluster members stored in the model cache.
Simon Huntd5b96732016-07-08 13:22:27 -0700232 *
233 * @return list of cluster members
234 */
235 public List<UiClusterMember> getClusterMembers() {
236 return cache.getAllClusterMembers();
237 }
238
Simon Huntd5b96732016-07-08 13:22:27 -0700239 /**
Simon Hunt4854f3d2016-08-02 18:13:15 -0700240 * Returns the set of regions stored in the model cache.
Simon Hunt10973dd2016-08-01 15:50:35 -0700241 *
242 * @return set of regions
243 */
244 public Set<UiRegion> getRegions() {
245 return cache.getAllRegions();
246 }
247
248 /**
Simon Hunt977aa052016-07-20 17:08:29 -0700249 * Returns the region for the given identifier.
Simon Huntd5b96732016-07-08 13:22:27 -0700250 *
Simon Hunt977aa052016-07-20 17:08:29 -0700251 * @param id region identifier
252 * @return the region
Simon Huntd5b96732016-07-08 13:22:27 -0700253 */
Simon Hunt977aa052016-07-20 17:08:29 -0700254 public UiRegion getRegion(RegionId id) {
255 return cache.accessRegion(id);
Simon Huntd5b96732016-07-08 13:22:27 -0700256 }
257
Simon Huntb1ce2602016-07-23 14:04:31 -0700258 /**
259 * Returns the null region.
260 *
261 * @return the null region
262 */
263 public UiRegion getNullRegion() {
264 return cache.nullRegion();
265 }
266
267 /**
Simon Hunt4854f3d2016-08-02 18:13:15 -0700268 * Returns the set of devices stored in the model cache.
269 *
270 * @return set of devices
Simon Huntb1ce2602016-07-23 14:04:31 -0700271 */
Simon Hunt4854f3d2016-08-02 18:13:15 -0700272 public Set<UiDevice> getDevices() {
273 return cache.getAllDevices();
274 }
275
276 /**
277 * Returns the set of hosts stored in the model cache.
278 *
279 * @return set of hosts
280 */
281 public Set<UiHost> getHosts() {
282 return cache.getAllHosts();
283 }
284
285 /**
Simon Huntc13082f2016-08-03 21:20:23 -0700286 * Returns the set of device links stored in the model cache.
Simon Hunt4854f3d2016-08-02 18:13:15 -0700287 *
Simon Huntc13082f2016-08-03 21:20:23 -0700288 * @return set of device links
Simon Hunt4854f3d2016-08-02 18:13:15 -0700289 */
Simon Huntc13082f2016-08-03 21:20:23 -0700290 public Set<UiDeviceLink> getDeviceLinks() {
291 return cache.getAllDeviceLinks();
292 }
293
294 /**
295 * Returns the synthetic links associated with the specified region.
296 *
297 * @param regionId region ID
298 * @return synthetic links for that region
299 */
300 public List<UiSynthLink> getSynthLinks(RegionId regionId) {
301 return cache.getSynthLinks(regionId);
Simon Huntb1ce2602016-07-23 14:04:31 -0700302 }
303
Simon Huntd5b96732016-07-08 13:22:27 -0700304 // =====================================================================
305
306
Simon Hunt642bc452016-05-04 19:34:45 -0700307 /**
308 * Default implementation of service bundle to return references to our
309 * dynamically injected services.
310 */
311 private class DefaultServiceBundle implements ServiceBundle {
312 @Override
Simon Hunt4f4ffc32016-08-03 18:30:47 -0700313 public UiTopoLayoutService layout() {
314 return layoutService;
315 }
316
317 @Override
Simon Hunt642bc452016-05-04 19:34:45 -0700318 public ClusterService cluster() {
319 return clusterService;
320 }
321
322 @Override
323 public MastershipService mastership() {
324 return mastershipService;
325 }
326
327 @Override
328 public RegionService region() {
329 return regionService;
330 }
331
332 @Override
333 public DeviceService device() {
334 return deviceService;
335 }
336
337 @Override
338 public LinkService link() {
339 return linkService;
340 }
341
342 @Override
343 public HostService host() {
344 return hostService;
345 }
346
347 @Override
348 public IntentService intent() {
349 return intentService;
350 }
351
352 @Override
353 public FlowRuleService flow() {
354 return flowService;
355 }
356 }
357
Simon Hunt7092cc42016-04-06 18:40:17 -0700358
Simon Huntcda9c032016-04-11 10:32:54 -0700359 private class InternalClusterListener implements ClusterEventListener {
360 @Override
361 public void event(ClusterEvent event) {
Madan Jampani492526a2016-06-06 17:24:04 -0700362 eventHandler.execute(() -> handleEvent(event));
363 }
364
365 private void handleEvent(ClusterEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700366 ControllerNode cnode = event.subject();
367
368 switch (event.type()) {
369
370 case INSTANCE_ADDED:
371 case INSTANCE_ACTIVATED:
372 case INSTANCE_READY:
373 case INSTANCE_DEACTIVATED:
374 cache.addOrUpdateClusterMember(cnode);
375 break;
376
377 case INSTANCE_REMOVED:
378 cache.removeClusterMember(cnode);
379 break;
380
381 default:
382 break;
383 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700384 }
Simon Huntcda9c032016-04-11 10:32:54 -0700385 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700386
Simon Huntcda9c032016-04-11 10:32:54 -0700387 private class InternalMastershipListener implements MastershipListener {
388 @Override
389 public void event(MastershipEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700390 DeviceId deviceId = event.subject();
391 RoleInfo roleInfo = event.roleInfo();
392
393 switch (event.type()) {
394 case MASTER_CHANGED:
395 case BACKUPS_CHANGED:
396 cache.updateMasterships(deviceId, roleInfo);
397 break;
398
399 default:
400 break;
401 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700402 }
Simon Huntcda9c032016-04-11 10:32:54 -0700403 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700404
Simon Huntcda9c032016-04-11 10:32:54 -0700405 private class InternalRegionListener implements RegionListener {
406 @Override
407 public void event(RegionEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700408 Region region = event.subject();
409
410 switch (event.type()) {
411
412 case REGION_ADDED:
413 case REGION_UPDATED:
414 case REGION_MEMBERSHIP_CHANGED:
415 cache.addOrUpdateRegion(region);
416 break;
417
418 case REGION_REMOVED:
419 cache.removeRegion(region);
420 break;
421
422 default:
423 break;
424 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700425 }
Simon Huntcda9c032016-04-11 10:32:54 -0700426 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700427
Simon Huntcda9c032016-04-11 10:32:54 -0700428 private class InternalDeviceListener implements DeviceListener {
429 @Override
430 public void event(DeviceEvent event) {
Simon Huntcda9c032016-04-11 10:32:54 -0700431 Device device = event.subject();
Simon Hunt7092cc42016-04-06 18:40:17 -0700432
Simon Huntcda9c032016-04-11 10:32:54 -0700433 switch (event.type()) {
Simon Hunt7092cc42016-04-06 18:40:17 -0700434
Simon Huntcda9c032016-04-11 10:32:54 -0700435 case DEVICE_ADDED:
436 case DEVICE_UPDATED:
437 case DEVICE_AVAILABILITY_CHANGED:
438 case DEVICE_SUSPENDED:
439 cache.addOrUpdateDevice(device);
440 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700441
Simon Huntcda9c032016-04-11 10:32:54 -0700442 case DEVICE_REMOVED:
443 cache.removeDevice(device);
444 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700445
Simon Huntcda9c032016-04-11 10:32:54 -0700446 default:
447 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700448 }
449 }
450 }
451
Simon Huntcda9c032016-04-11 10:32:54 -0700452 private class InternalLinkListener implements LinkListener {
453 @Override
454 public void event(LinkEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700455 Link link = event.subject();
456
457 switch (event.type()) {
458
459 case LINK_ADDED:
460 case LINK_UPDATED:
Simon Huntc13082f2016-08-03 21:20:23 -0700461 cache.addOrUpdateDeviceLink(link);
Simon Hunt23fb1352016-04-11 12:15:19 -0700462 break;
463
464 case LINK_REMOVED:
Simon Huntc13082f2016-08-03 21:20:23 -0700465 cache.removeDeviceLink(link);
Simon Hunt23fb1352016-04-11 12:15:19 -0700466 break;
467
468 default:
469 break;
470 }
Simon Huntcda9c032016-04-11 10:32:54 -0700471 }
Simon Hunted804d52016-03-30 09:51:40 -0700472 }
473
Simon Huntcda9c032016-04-11 10:32:54 -0700474 private class InternalHostListener implements HostListener {
475 @Override
476 public void event(HostEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700477 Host host = event.subject();
478 Host prevHost = event.prevSubject();
479
480 switch (event.type()) {
481
482 case HOST_ADDED:
483 case HOST_UPDATED:
484 cache.addOrUpdateHost(host);
485 break;
486
487 case HOST_MOVED:
488 cache.moveHost(host, prevHost);
489 break;
490
491 case HOST_REMOVED:
492 cache.removeHost(host);
493 break;
494
495 default:
496 break;
497 }
Simon Huntcda9c032016-04-11 10:32:54 -0700498 }
Simon Hunted804d52016-03-30 09:51:40 -0700499 }
Simon Huntcda9c032016-04-11 10:32:54 -0700500
Simon Hunt23fb1352016-04-11 12:15:19 -0700501 // =======================================================================
502 // NOTE: Neither intents nor flows are modeled by the UiTopology.
503 // Rather, they are serviced directly from this class.
504 // Additionally, since we are only retrieving counts (in the current
505 // implementation), we'll fetch them on demand from the service.
506 // Thus, the following internal listeners are stubs only (for now).
507 // =======================================================================
508
Simon Huntcda9c032016-04-11 10:32:54 -0700509 private class InternalIntentListener implements IntentListener {
510 @Override
511 public void event(IntentEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700512 // do nothing (for now)
Simon Huntcda9c032016-04-11 10:32:54 -0700513 }
514 }
515
516 private class InternalFlowRuleListener implements FlowRuleListener {
517 @Override
518 public void event(FlowRuleEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700519 // do nothing (for now)
Simon Huntcda9c032016-04-11 10:32:54 -0700520 }
521 }
522
Simon Hunted804d52016-03-30 09:51:40 -0700523}