blob: 6500ae3ce5c248b675fd3a720b2e2d6831301ea2 [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;
Thomas Vachuska8c0b18a2017-04-14 16:27:33 -070070import org.onosproject.ui.model.topo.UiModelEvent;
Simon Huntd5b96732016-07-08 13:22:27 -070071import org.onosproject.ui.model.topo.UiRegion;
Simon Huntc13082f2016-08-03 21:20:23 -070072import org.onosproject.ui.model.topo.UiSynthLink;
Simon Hunted804d52016-03-30 09:51:40 -070073import org.slf4j.Logger;
74import org.slf4j.LoggerFactory;
75
Simon Huntd5b96732016-07-08 13:22:27 -070076import java.util.List;
Simon Hunt10973dd2016-08-01 15:50:35 -070077import java.util.Set;
Simon Huntd5b96732016-07-08 13:22:27 -070078import java.util.concurrent.ExecutorService;
Simon Hunt8eac4ae2017-01-20 12:56:45 -080079
80import static java.util.concurrent.Executors.newSingleThreadExecutor;
81import static org.onlab.util.Tools.groupedThreads;
Simon Huntd5b96732016-07-08 13:22:27 -070082
Simon Hunted804d52016-03-30 09:51:40 -070083/**
Simon Huntcda9c032016-04-11 10:32:54 -070084 * Service that creates and maintains the UI-model of the network topology.
Simon Hunted804d52016-03-30 09:51:40 -070085 */
Thomas Vachuska92b016b2016-05-20 11:37:57 -070086@Component(immediate = true, enabled = true)
Simon Huntcda9c032016-04-11 10:32:54 -070087@Service(value = UiSharedTopologyModel.class)
88public final class UiSharedTopologyModel
89 extends AbstractListenerManager<UiModelEvent, UiModelListener> {
Simon Hunted804d52016-03-30 09:51:40 -070090
91 private static final Logger log =
92 LoggerFactory.getLogger(UiSharedTopologyModel.class);
93
Simon Huntcda9c032016-04-11 10:32:54 -070094 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Simon Hunt4f4ffc32016-08-03 18:30:47 -070095 private UiTopoLayoutService layoutService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Simon Huntcda9c032016-04-11 10:32:54 -070098 private ClusterService clusterService;
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 private MastershipService mastershipService;
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 private RegionService regionService;
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 private DeviceService deviceService;
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 private LinkService linkService;
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 private HostService hostService;
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 private IntentService intentService;
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 private FlowRuleService flowService;
Simon Hunt7092cc42016-04-06 18:40:17 -0700113
Simon Huntcda9c032016-04-11 10:32:54 -0700114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 private StatisticService flowStatsService;
116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 private PortStatisticsService portStatsService;
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 private TopologyService topologyService;
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 private TunnelService tunnelService;
Simon Hunted804d52016-03-30 09:51:40 -0700122
Simon Huntcda9c032016-04-11 10:32:54 -0700123 private final ClusterEventListener clusterListener =
124 new InternalClusterListener();
125 private final MastershipListener mastershipListener =
126 new InternalMastershipListener();
127 private final RegionListener regionListener =
128 new InternalRegionListener();
129 private final DeviceListener deviceListener =
130 new InternalDeviceListener();
131 private final LinkListener linkListener =
132 new InternalLinkListener();
133 private final HostListener hostListener =
134 new InternalHostListener();
135 private final IntentListener intentListener =
136 new InternalIntentListener();
137 private final FlowRuleListener flowRuleListener =
138 new InternalFlowRuleListener();
Simon Hunt7092cc42016-04-06 18:40:17 -0700139
Madan Jampani492526a2016-06-06 17:24:04 -0700140 private ExecutorService eventHandler;
141
Simon Huntcda9c032016-04-11 10:32:54 -0700142
143 private ModelCache cache;
144
145
146 @Activate
147 protected void activate() {
Simon Hunt642bc452016-05-04 19:34:45 -0700148 cache = new ModelCache(new DefaultServiceBundle(), eventDispatcher);
Simon Hunt8eac4ae2017-01-20 12:56:45 -0800149 eventHandler = newSingleThreadExecutor(groupedThreads("onos/ui/topo", "event-handler", log));
Simon Huntcda9c032016-04-11 10:32:54 -0700150
151 eventDispatcher.addSink(UiModelEvent.class, listenerRegistry);
152
153 clusterService.addListener(clusterListener);
154 mastershipService.addListener(mastershipListener);
155 regionService.addListener(regionListener);
156 deviceService.addListener(deviceListener);
157 linkService.addListener(linkListener);
158 hostService.addListener(hostListener);
159 intentService.addListener(intentListener);
160 flowService.addListener(flowRuleListener);
161
162 cache.load();
163
164 log.info("Started");
Simon Hunted804d52016-03-30 09:51:40 -0700165 }
166
Simon Huntcda9c032016-04-11 10:32:54 -0700167 @Deactivate
168 protected void deactivate() {
169 eventDispatcher.removeSink(UiModelEvent.class);
170
171 clusterService.removeListener(clusterListener);
172 mastershipService.removeListener(mastershipListener);
173 regionService.removeListener(regionListener);
174 deviceService.removeListener(deviceListener);
175 linkService.removeListener(linkListener);
176 hostService.removeListener(hostListener);
177 intentService.removeListener(intentListener);
178 flowService.removeListener(flowRuleListener);
179
Madan Jampani492526a2016-06-06 17:24:04 -0700180 eventHandler.shutdown();
181
Simon Huntcda9c032016-04-11 10:32:54 -0700182 cache.clear();
183 cache = null;
184
185 log.info("Stopped");
186 }
187
Simon Hunt8eac4ae2017-01-20 12:56:45 -0800188 /**
189 * Injects an instance of the JSON-ifier (which has been bound to the
190 * services (link, host, device, ...)) to be passed on to the Model Cache,
191 * for use in forming UiModelEvent payloads.
192 *
193 * @param t2json JSONifier
194 */
195 public void injectJsonifier(Topo2Jsonifier t2json) {
196 cache.injectJsonifier(t2json);
197 }
198
Simon Huntcda9c032016-04-11 10:32:54 -0700199
Simon Huntf679c4e2016-04-01 17:02:24 -0700200 /**
201 * Registers a UI topology session with the topology model.
202 *
203 * @param session the session to register
204 */
205 public void register(UiTopoSession session) {
206 log.info("Registering topology session {}", session);
Simon Huntcda9c032016-04-11 10:32:54 -0700207 addListener(session);
Simon Hunted804d52016-03-30 09:51:40 -0700208 }
209
Simon Huntf679c4e2016-04-01 17:02:24 -0700210 /**
211 * Unregisters a UI topology session from the topology model.
212 *
213 * @param session the session to unregister
214 */
215 public void unregister(UiTopoSession session) {
216 log.info("Unregistering topology session {}", session);
Simon Huntcda9c032016-04-11 10:32:54 -0700217 removeListener(session);
Simon Huntf679c4e2016-04-01 17:02:24 -0700218 }
219
Simon Huntd5b96732016-07-08 13:22:27 -0700220
221 // =======================================================================
Simon Hunt10973dd2016-08-01 15:50:35 -0700222 // Methods for topo session (or CLI) to use to get information from us
Simon Huntd5b96732016-07-08 13:22:27 -0700223
224 /**
Simon Hunt4854f3d2016-08-02 18:13:15 -0700225 * Refreshes the cache's internal state.
226 */
227 public void refresh() {
228 cache.refresh();
229 }
230
231 /**
232 * Returns the list of cluster members stored in the model cache.
Simon Huntd5b96732016-07-08 13:22:27 -0700233 *
234 * @return list of cluster members
235 */
236 public List<UiClusterMember> getClusterMembers() {
237 return cache.getAllClusterMembers();
238 }
239
Simon Huntd5b96732016-07-08 13:22:27 -0700240 /**
Simon Hunt4854f3d2016-08-02 18:13:15 -0700241 * Returns the set of regions stored in the model cache.
Simon Hunt10973dd2016-08-01 15:50:35 -0700242 *
243 * @return set of regions
244 */
245 public Set<UiRegion> getRegions() {
246 return cache.getAllRegions();
247 }
248
249 /**
Simon Hunt977aa052016-07-20 17:08:29 -0700250 * Returns the region for the given identifier.
Simon Huntd5b96732016-07-08 13:22:27 -0700251 *
Simon Hunt977aa052016-07-20 17:08:29 -0700252 * @param id region identifier
253 * @return the region
Simon Huntd5b96732016-07-08 13:22:27 -0700254 */
Simon Hunt977aa052016-07-20 17:08:29 -0700255 public UiRegion getRegion(RegionId id) {
256 return cache.accessRegion(id);
Simon Huntd5b96732016-07-08 13:22:27 -0700257 }
258
Simon Huntb1ce2602016-07-23 14:04:31 -0700259 /**
260 * Returns the null region.
261 *
262 * @return the null region
263 */
264 public UiRegion getNullRegion() {
265 return cache.nullRegion();
266 }
267
268 /**
Simon Hunt4854f3d2016-08-02 18:13:15 -0700269 * Returns the set of devices stored in the model cache.
270 *
271 * @return set of devices
Simon Huntb1ce2602016-07-23 14:04:31 -0700272 */
Simon Hunt4854f3d2016-08-02 18:13:15 -0700273 public Set<UiDevice> getDevices() {
274 return cache.getAllDevices();
275 }
276
277 /**
278 * Returns the set of hosts stored in the model cache.
279 *
280 * @return set of hosts
281 */
282 public Set<UiHost> getHosts() {
283 return cache.getAllHosts();
284 }
285
286 /**
Simon Huntc13082f2016-08-03 21:20:23 -0700287 * Returns the set of device links stored in the model cache.
Simon Hunt4854f3d2016-08-02 18:13:15 -0700288 *
Simon Huntc13082f2016-08-03 21:20:23 -0700289 * @return set of device links
Simon Hunt4854f3d2016-08-02 18:13:15 -0700290 */
Simon Huntc13082f2016-08-03 21:20:23 -0700291 public Set<UiDeviceLink> getDeviceLinks() {
292 return cache.getAllDeviceLinks();
293 }
294
295 /**
296 * Returns the synthetic links associated with the specified region.
297 *
298 * @param regionId region ID
299 * @return synthetic links for that region
300 */
301 public List<UiSynthLink> getSynthLinks(RegionId regionId) {
302 return cache.getSynthLinks(regionId);
Simon Huntb1ce2602016-07-23 14:04:31 -0700303 }
304
Simon Huntd5b96732016-07-08 13:22:27 -0700305 // =====================================================================
306
307
Simon Hunt642bc452016-05-04 19:34:45 -0700308 /**
309 * Default implementation of service bundle to return references to our
310 * dynamically injected services.
311 */
312 private class DefaultServiceBundle implements ServiceBundle {
313 @Override
Simon Hunt4f4ffc32016-08-03 18:30:47 -0700314 public UiTopoLayoutService layout() {
315 return layoutService;
316 }
317
318 @Override
Simon Hunt642bc452016-05-04 19:34:45 -0700319 public ClusterService cluster() {
320 return clusterService;
321 }
322
323 @Override
324 public MastershipService mastership() {
325 return mastershipService;
326 }
327
328 @Override
329 public RegionService region() {
330 return regionService;
331 }
332
333 @Override
334 public DeviceService device() {
335 return deviceService;
336 }
337
338 @Override
339 public LinkService link() {
340 return linkService;
341 }
342
343 @Override
344 public HostService host() {
345 return hostService;
346 }
347
348 @Override
349 public IntentService intent() {
350 return intentService;
351 }
352
353 @Override
354 public FlowRuleService flow() {
355 return flowService;
356 }
357 }
358
Simon Hunt7092cc42016-04-06 18:40:17 -0700359
Simon Huntcda9c032016-04-11 10:32:54 -0700360 private class InternalClusterListener implements ClusterEventListener {
361 @Override
362 public void event(ClusterEvent event) {
Madan Jampani492526a2016-06-06 17:24:04 -0700363 eventHandler.execute(() -> handleEvent(event));
364 }
365
366 private void handleEvent(ClusterEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700367 ControllerNode cnode = event.subject();
368
369 switch (event.type()) {
370
371 case INSTANCE_ADDED:
372 case INSTANCE_ACTIVATED:
373 case INSTANCE_READY:
374 case INSTANCE_DEACTIVATED:
375 cache.addOrUpdateClusterMember(cnode);
376 break;
377
378 case INSTANCE_REMOVED:
379 cache.removeClusterMember(cnode);
380 break;
381
382 default:
383 break;
384 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700385 }
Simon Huntcda9c032016-04-11 10:32:54 -0700386 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700387
Simon Huntcda9c032016-04-11 10:32:54 -0700388 private class InternalMastershipListener implements MastershipListener {
389 @Override
390 public void event(MastershipEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700391 DeviceId deviceId = event.subject();
392 RoleInfo roleInfo = event.roleInfo();
393
394 switch (event.type()) {
395 case MASTER_CHANGED:
396 case BACKUPS_CHANGED:
397 cache.updateMasterships(deviceId, roleInfo);
398 break;
399
400 default:
401 break;
402 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700403 }
Simon Huntcda9c032016-04-11 10:32:54 -0700404 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700405
Simon Huntcda9c032016-04-11 10:32:54 -0700406 private class InternalRegionListener implements RegionListener {
407 @Override
408 public void event(RegionEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700409 Region region = event.subject();
410
411 switch (event.type()) {
412
413 case REGION_ADDED:
414 case REGION_UPDATED:
415 case REGION_MEMBERSHIP_CHANGED:
416 cache.addOrUpdateRegion(region);
417 break;
418
419 case REGION_REMOVED:
420 cache.removeRegion(region);
421 break;
422
423 default:
424 break;
425 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700426 }
Simon Huntcda9c032016-04-11 10:32:54 -0700427 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700428
Simon Huntcda9c032016-04-11 10:32:54 -0700429 private class InternalDeviceListener implements DeviceListener {
430 @Override
431 public void event(DeviceEvent event) {
Simon Huntcda9c032016-04-11 10:32:54 -0700432 Device device = event.subject();
Simon Hunt7092cc42016-04-06 18:40:17 -0700433
Simon Huntcda9c032016-04-11 10:32:54 -0700434 switch (event.type()) {
Simon Hunt7092cc42016-04-06 18:40:17 -0700435
Simon Huntcda9c032016-04-11 10:32:54 -0700436 case DEVICE_ADDED:
437 case DEVICE_UPDATED:
438 case DEVICE_AVAILABILITY_CHANGED:
439 case DEVICE_SUSPENDED:
440 cache.addOrUpdateDevice(device);
441 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700442
Simon Huntcda9c032016-04-11 10:32:54 -0700443 case DEVICE_REMOVED:
444 cache.removeDevice(device);
445 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700446
Simon Huntcda9c032016-04-11 10:32:54 -0700447 default:
448 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700449 }
450 }
451 }
452
Simon Huntcda9c032016-04-11 10:32:54 -0700453 private class InternalLinkListener implements LinkListener {
454 @Override
455 public void event(LinkEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700456 Link link = event.subject();
457
458 switch (event.type()) {
459
460 case LINK_ADDED:
461 case LINK_UPDATED:
Simon Huntc13082f2016-08-03 21:20:23 -0700462 cache.addOrUpdateDeviceLink(link);
Simon Hunt23fb1352016-04-11 12:15:19 -0700463 break;
464
465 case LINK_REMOVED:
Simon Huntc13082f2016-08-03 21:20:23 -0700466 cache.removeDeviceLink(link);
Simon Hunt23fb1352016-04-11 12:15:19 -0700467 break;
468
469 default:
470 break;
471 }
Simon Huntcda9c032016-04-11 10:32:54 -0700472 }
Simon Hunted804d52016-03-30 09:51:40 -0700473 }
474
Simon Huntcda9c032016-04-11 10:32:54 -0700475 private class InternalHostListener implements HostListener {
476 @Override
477 public void event(HostEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700478 Host host = event.subject();
479 Host prevHost = event.prevSubject();
480
481 switch (event.type()) {
482
483 case HOST_ADDED:
484 case HOST_UPDATED:
485 cache.addOrUpdateHost(host);
486 break;
487
488 case HOST_MOVED:
489 cache.moveHost(host, prevHost);
490 break;
491
492 case HOST_REMOVED:
493 cache.removeHost(host);
494 break;
495
496 default:
497 break;
498 }
Simon Huntcda9c032016-04-11 10:32:54 -0700499 }
Simon Hunted804d52016-03-30 09:51:40 -0700500 }
Simon Huntcda9c032016-04-11 10:32:54 -0700501
Simon Hunt23fb1352016-04-11 12:15:19 -0700502 // =======================================================================
503 // NOTE: Neither intents nor flows are modeled by the UiTopology.
504 // Rather, they are serviced directly from this class.
505 // Additionally, since we are only retrieving counts (in the current
506 // implementation), we'll fetch them on demand from the service.
507 // Thus, the following internal listeners are stubs only (for now).
508 // =======================================================================
509
Simon Huntcda9c032016-04-11 10:32:54 -0700510 private class InternalIntentListener implements IntentListener {
511 @Override
512 public void event(IntentEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700513 // do nothing (for now)
Simon Huntcda9c032016-04-11 10:32:54 -0700514 }
515 }
516
517 private class InternalFlowRuleListener implements FlowRuleListener {
518 @Override
519 public void event(FlowRuleEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700520 // do nothing (for now)
Simon Huntcda9c032016-04-11 10:32:54 -0700521 }
522 }
523
Simon Hunted804d52016-03-30 09:51:40 -0700524}