blob: 54c92f6f365b866abf55e879ba286db81217ff7d [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;
Madan Jampani492526a2016-06-06 17:24:04 -070025import org.onlab.util.Tools;
Simon Hunt7092cc42016-04-06 18:40:17 -070026import org.onosproject.cluster.ClusterEvent;
27import org.onosproject.cluster.ClusterEventListener;
28import org.onosproject.cluster.ClusterService;
Simon Hunt23fb1352016-04-11 12:15:19 -070029import org.onosproject.cluster.ControllerNode;
30import org.onosproject.cluster.RoleInfo;
Simon Huntcda9c032016-04-11 10:32:54 -070031import org.onosproject.event.AbstractListenerManager;
Simon Hunt7092cc42016-04-06 18:40:17 -070032import org.onosproject.incubator.net.PortStatisticsService;
33import org.onosproject.incubator.net.tunnel.TunnelService;
34import org.onosproject.mastership.MastershipEvent;
35import org.onosproject.mastership.MastershipListener;
36import org.onosproject.mastership.MastershipService;
Simon Huntcda9c032016-04-11 10:32:54 -070037import org.onosproject.net.Device;
Simon Hunt23fb1352016-04-11 12:15:19 -070038import org.onosproject.net.DeviceId;
39import org.onosproject.net.Host;
40import org.onosproject.net.Link;
Simon Hunt7092cc42016-04-06 18:40:17 -070041import org.onosproject.net.device.DeviceEvent;
42import org.onosproject.net.device.DeviceListener;
43import org.onosproject.net.device.DeviceService;
44import org.onosproject.net.flow.FlowRuleEvent;
45import org.onosproject.net.flow.FlowRuleListener;
46import org.onosproject.net.flow.FlowRuleService;
47import org.onosproject.net.host.HostEvent;
48import org.onosproject.net.host.HostListener;
49import org.onosproject.net.host.HostService;
50import org.onosproject.net.intent.IntentEvent;
51import org.onosproject.net.intent.IntentListener;
52import org.onosproject.net.intent.IntentService;
53import org.onosproject.net.link.LinkEvent;
54import org.onosproject.net.link.LinkListener;
55import org.onosproject.net.link.LinkService;
Simon Hunt23fb1352016-04-11 12:15:19 -070056import org.onosproject.net.region.Region;
Simon Hunt7092cc42016-04-06 18:40:17 -070057import org.onosproject.net.region.RegionEvent;
58import org.onosproject.net.region.RegionListener;
59import org.onosproject.net.region.RegionService;
60import org.onosproject.net.statistic.StatisticService;
61import org.onosproject.net.topology.TopologyService;
Simon Huntf679c4e2016-04-01 17:02:24 -070062import org.onosproject.ui.impl.topo.UiTopoSession;
Simon Hunt642bc452016-05-04 19:34:45 -070063import org.onosproject.ui.model.ServiceBundle;
Simon Huntd5b96732016-07-08 13:22:27 -070064import org.onosproject.ui.model.topo.UiClusterMember;
65import org.onosproject.ui.model.topo.UiElement;
66import org.onosproject.ui.model.topo.UiRegion;
67import org.onosproject.ui.model.topo.UiTopoLayout;
Simon Hunted804d52016-03-30 09:51:40 -070068import org.slf4j.Logger;
69import org.slf4j.LoggerFactory;
70
Simon Huntd5b96732016-07-08 13:22:27 -070071import java.util.HashSet;
72import java.util.List;
73import java.util.Set;
74import java.util.concurrent.ExecutorService;
75import java.util.concurrent.Executors;
76
Simon Hunted804d52016-03-30 09:51:40 -070077/**
Simon Huntcda9c032016-04-11 10:32:54 -070078 * Service that creates and maintains the UI-model of the network topology.
Simon Hunted804d52016-03-30 09:51:40 -070079 */
Thomas Vachuska92b016b2016-05-20 11:37:57 -070080@Component(immediate = true, enabled = true)
Simon Huntcda9c032016-04-11 10:32:54 -070081@Service(value = UiSharedTopologyModel.class)
82public final class UiSharedTopologyModel
83 extends AbstractListenerManager<UiModelEvent, UiModelListener> {
Simon Hunted804d52016-03-30 09:51:40 -070084
85 private static final Logger log =
86 LoggerFactory.getLogger(UiSharedTopologyModel.class);
87
Simon Huntcda9c032016-04-11 10:32:54 -070088 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 private ClusterService clusterService;
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 private MastershipService mastershipService;
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 private RegionService regionService;
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 private DeviceService deviceService;
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 private LinkService linkService;
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 private HostService hostService;
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 private IntentService intentService;
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 private FlowRuleService flowService;
Simon Hunt7092cc42016-04-06 18:40:17 -0700104
Simon Huntcda9c032016-04-11 10:32:54 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 private StatisticService flowStatsService;
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 private PortStatisticsService portStatsService;
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 private TopologyService topologyService;
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 private TunnelService tunnelService;
Simon Hunted804d52016-03-30 09:51:40 -0700113
Simon Huntcda9c032016-04-11 10:32:54 -0700114 private final ClusterEventListener clusterListener =
115 new InternalClusterListener();
116 private final MastershipListener mastershipListener =
117 new InternalMastershipListener();
118 private final RegionListener regionListener =
119 new InternalRegionListener();
120 private final DeviceListener deviceListener =
121 new InternalDeviceListener();
122 private final LinkListener linkListener =
123 new InternalLinkListener();
124 private final HostListener hostListener =
125 new InternalHostListener();
126 private final IntentListener intentListener =
127 new InternalIntentListener();
128 private final FlowRuleListener flowRuleListener =
129 new InternalFlowRuleListener();
Simon Hunt7092cc42016-04-06 18:40:17 -0700130
Madan Jampani492526a2016-06-06 17:24:04 -0700131 private ExecutorService eventHandler;
132
Simon Huntcda9c032016-04-11 10:32:54 -0700133
134 private ModelCache cache;
135
136
137 @Activate
138 protected void activate() {
Simon Hunt642bc452016-05-04 19:34:45 -0700139 cache = new ModelCache(new DefaultServiceBundle(), eventDispatcher);
Madan Jampani492526a2016-06-06 17:24:04 -0700140 eventHandler = Executors.newSingleThreadExecutor(Tools.groupedThreads("onos/ui/topo", "event-handler"));
Simon Huntcda9c032016-04-11 10:32:54 -0700141
142 eventDispatcher.addSink(UiModelEvent.class, listenerRegistry);
143
144 clusterService.addListener(clusterListener);
145 mastershipService.addListener(mastershipListener);
146 regionService.addListener(regionListener);
147 deviceService.addListener(deviceListener);
148 linkService.addListener(linkListener);
149 hostService.addListener(hostListener);
150 intentService.addListener(intentListener);
151 flowService.addListener(flowRuleListener);
152
153 cache.load();
154
155 log.info("Started");
Simon Hunted804d52016-03-30 09:51:40 -0700156 }
157
Simon Huntcda9c032016-04-11 10:32:54 -0700158 @Deactivate
159 protected void deactivate() {
160 eventDispatcher.removeSink(UiModelEvent.class);
161
162 clusterService.removeListener(clusterListener);
163 mastershipService.removeListener(mastershipListener);
164 regionService.removeListener(regionListener);
165 deviceService.removeListener(deviceListener);
166 linkService.removeListener(linkListener);
167 hostService.removeListener(hostListener);
168 intentService.removeListener(intentListener);
169 flowService.removeListener(flowRuleListener);
170
Madan Jampani492526a2016-06-06 17:24:04 -0700171 eventHandler.shutdown();
172
Simon Huntcda9c032016-04-11 10:32:54 -0700173 cache.clear();
174 cache = null;
175
176 log.info("Stopped");
177 }
178
179
Simon Huntf679c4e2016-04-01 17:02:24 -0700180 /**
181 * Registers a UI topology session with the topology model.
182 *
183 * @param session the session to register
184 */
185 public void register(UiTopoSession session) {
186 log.info("Registering topology session {}", session);
Simon Huntcda9c032016-04-11 10:32:54 -0700187 addListener(session);
Simon Hunted804d52016-03-30 09:51:40 -0700188 }
189
Simon Huntf679c4e2016-04-01 17:02:24 -0700190 /**
191 * Unregisters a UI topology session from the topology model.
192 *
193 * @param session the session to unregister
194 */
195 public void unregister(UiTopoSession session) {
196 log.info("Unregistering topology session {}", session);
Simon Huntcda9c032016-04-11 10:32:54 -0700197 removeListener(session);
Simon Huntf679c4e2016-04-01 17:02:24 -0700198 }
199
Simon Huntd5b96732016-07-08 13:22:27 -0700200
201 // =======================================================================
202 // methods that the topo session will use to extract information from us
203
204 /**
205 * Returns the list of cluster members stored in our model cache.
206 *
207 * @return list of cluster members
208 */
209 public List<UiClusterMember> getClusterMembers() {
210 return cache.getAllClusterMembers();
211 }
212
213 public Set<UiElement> getElements(UiTopoLayout layout) {
214 Set<UiElement> results = new HashSet<>();
215
216 // TODO: figure out how to extract the appropriate nodes
217 // from the cache, for the given layout.
218
219 return results;
220 }
221
222 /**
223 * Returns the region for the given layout.
224 *
225 * @param layout layout filter
226 * @return the region the layout is based upon
227 */
228 public UiRegion getRegion(UiTopoLayout layout) {
229 return cache.accessRegion(layout.regionId());
230 }
231
232 // =====================================================================
233
234
Simon Hunt642bc452016-05-04 19:34:45 -0700235 /**
236 * Default implementation of service bundle to return references to our
237 * dynamically injected services.
238 */
239 private class DefaultServiceBundle implements ServiceBundle {
240 @Override
241 public ClusterService cluster() {
242 return clusterService;
243 }
244
245 @Override
246 public MastershipService mastership() {
247 return mastershipService;
248 }
249
250 @Override
251 public RegionService region() {
252 return regionService;
253 }
254
255 @Override
256 public DeviceService device() {
257 return deviceService;
258 }
259
260 @Override
261 public LinkService link() {
262 return linkService;
263 }
264
265 @Override
266 public HostService host() {
267 return hostService;
268 }
269
270 @Override
271 public IntentService intent() {
272 return intentService;
273 }
274
275 @Override
276 public FlowRuleService flow() {
277 return flowService;
278 }
279 }
280
Simon Hunt7092cc42016-04-06 18:40:17 -0700281
Simon Huntcda9c032016-04-11 10:32:54 -0700282 private class InternalClusterListener implements ClusterEventListener {
283 @Override
284 public void event(ClusterEvent event) {
Madan Jampani492526a2016-06-06 17:24:04 -0700285 eventHandler.execute(() -> handleEvent(event));
286 }
287
288 private void handleEvent(ClusterEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700289 ControllerNode cnode = event.subject();
290
291 switch (event.type()) {
292
293 case INSTANCE_ADDED:
294 case INSTANCE_ACTIVATED:
295 case INSTANCE_READY:
296 case INSTANCE_DEACTIVATED:
297 cache.addOrUpdateClusterMember(cnode);
298 break;
299
300 case INSTANCE_REMOVED:
301 cache.removeClusterMember(cnode);
302 break;
303
304 default:
305 break;
306 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700307 }
Simon Huntcda9c032016-04-11 10:32:54 -0700308 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700309
Simon Huntcda9c032016-04-11 10:32:54 -0700310 private class InternalMastershipListener implements MastershipListener {
311 @Override
312 public void event(MastershipEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700313 DeviceId deviceId = event.subject();
314 RoleInfo roleInfo = event.roleInfo();
315
316 switch (event.type()) {
317 case MASTER_CHANGED:
318 case BACKUPS_CHANGED:
319 cache.updateMasterships(deviceId, roleInfo);
320 break;
321
322 default:
323 break;
324 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700325 }
Simon Huntcda9c032016-04-11 10:32:54 -0700326 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700327
Simon Huntcda9c032016-04-11 10:32:54 -0700328 private class InternalRegionListener implements RegionListener {
329 @Override
330 public void event(RegionEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700331 Region region = event.subject();
332
333 switch (event.type()) {
334
335 case REGION_ADDED:
336 case REGION_UPDATED:
337 case REGION_MEMBERSHIP_CHANGED:
338 cache.addOrUpdateRegion(region);
339 break;
340
341 case REGION_REMOVED:
342 cache.removeRegion(region);
343 break;
344
345 default:
346 break;
347 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700348 }
Simon Huntcda9c032016-04-11 10:32:54 -0700349 }
Simon Hunt7092cc42016-04-06 18:40:17 -0700350
Simon Huntcda9c032016-04-11 10:32:54 -0700351 private class InternalDeviceListener implements DeviceListener {
352 @Override
353 public void event(DeviceEvent event) {
Simon Huntcda9c032016-04-11 10:32:54 -0700354 Device device = event.subject();
Simon Hunt7092cc42016-04-06 18:40:17 -0700355
Simon Huntcda9c032016-04-11 10:32:54 -0700356 switch (event.type()) {
Simon Hunt7092cc42016-04-06 18:40:17 -0700357
Simon Huntcda9c032016-04-11 10:32:54 -0700358 case DEVICE_ADDED:
359 case DEVICE_UPDATED:
360 case DEVICE_AVAILABILITY_CHANGED:
361 case DEVICE_SUSPENDED:
362 cache.addOrUpdateDevice(device);
363 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700364
Simon Huntcda9c032016-04-11 10:32:54 -0700365 case DEVICE_REMOVED:
366 cache.removeDevice(device);
367 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700368
Simon Huntcda9c032016-04-11 10:32:54 -0700369 default:
370 break;
Simon Hunt7092cc42016-04-06 18:40:17 -0700371 }
372 }
373 }
374
Simon Huntcda9c032016-04-11 10:32:54 -0700375 private class InternalLinkListener implements LinkListener {
376 @Override
377 public void event(LinkEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700378 Link link = event.subject();
379
380 switch (event.type()) {
381
382 case LINK_ADDED:
383 case LINK_UPDATED:
384 cache.addOrUpdateLink(link);
385 break;
386
387 case LINK_REMOVED:
388 cache.removeLink(link);
389 break;
390
391 default:
392 break;
393 }
Simon Huntcda9c032016-04-11 10:32:54 -0700394 }
Simon Hunted804d52016-03-30 09:51:40 -0700395 }
396
Simon Huntcda9c032016-04-11 10:32:54 -0700397 private class InternalHostListener implements HostListener {
398 @Override
399 public void event(HostEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700400 Host host = event.subject();
401 Host prevHost = event.prevSubject();
402
403 switch (event.type()) {
404
405 case HOST_ADDED:
406 case HOST_UPDATED:
407 cache.addOrUpdateHost(host);
408 break;
409
410 case HOST_MOVED:
411 cache.moveHost(host, prevHost);
412 break;
413
414 case HOST_REMOVED:
415 cache.removeHost(host);
416 break;
417
418 default:
419 break;
420 }
Simon Huntcda9c032016-04-11 10:32:54 -0700421 }
Simon Hunted804d52016-03-30 09:51:40 -0700422 }
Simon Huntcda9c032016-04-11 10:32:54 -0700423
Simon Hunt23fb1352016-04-11 12:15:19 -0700424 // =======================================================================
425 // NOTE: Neither intents nor flows are modeled by the UiTopology.
426 // Rather, they are serviced directly from this class.
427 // Additionally, since we are only retrieving counts (in the current
428 // implementation), we'll fetch them on demand from the service.
429 // Thus, the following internal listeners are stubs only (for now).
430 // =======================================================================
431
Simon Huntcda9c032016-04-11 10:32:54 -0700432 private class InternalIntentListener implements IntentListener {
433 @Override
434 public void event(IntentEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700435 // do nothing (for now)
Simon Huntcda9c032016-04-11 10:32:54 -0700436 }
437 }
438
439 private class InternalFlowRuleListener implements FlowRuleListener {
440 @Override
441 public void event(FlowRuleEvent event) {
Simon Hunt23fb1352016-04-11 12:15:19 -0700442 // do nothing (for now)
Simon Huntcda9c032016-04-11 10:32:54 -0700443 }
444 }
445
Simon Hunted804d52016-03-30 09:51:40 -0700446}