blob: f75027d6acccb2a2cf40e26370d8ef74d7d498df [file] [log] [blame]
Yixiao Chen5ece00f2016-09-14 16:23:24 -04001/*
2 * Copyright 2016-present 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 */
16package org.onosproject.provider.te.topology;
17
Henry Yu4b4a7eb2016-11-09 20:07:53 -050018import com.google.common.base.Preconditions;
Yixiao Chen5ece00f2016-09-14 16:23:24 -040019import org.apache.commons.io.IOUtils;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.incubator.net.config.basics.ConfigException;
28import org.onosproject.net.DeviceId;
29import org.onosproject.net.config.ConfigFactory;
30import org.onosproject.net.config.NetworkConfigEvent;
31import org.onosproject.net.config.NetworkConfigListener;
32import org.onosproject.net.config.NetworkConfigRegistry;
33import org.onosproject.net.device.DeviceProviderRegistry;
34import org.onosproject.net.provider.AbstractProvider;
35import org.onosproject.net.provider.ProviderId;
36import org.onosproject.protocol.rest.RestSBDevice;
37import org.onosproject.protocol.restconf.RestConfSBController;
chengfan9d60b6e2016-12-01 11:06:39 +080038import org.onosproject.provider.te.utils.DefaultJsonCodec;
Henry Yu05dcc212017-01-05 16:05:26 -050039import org.onosproject.provider.te.utils.RestconfNotificationEventProcessor;
40import org.onosproject.provider.te.utils.TeTopologyRestconfEventListener;
chengfan9d60b6e2016-12-01 11:06:39 +080041import org.onosproject.provider.te.utils.YangCompositeEncodingImpl;
Yixiao Chen5ece00f2016-09-14 16:23:24 -040042import org.onosproject.tetopology.management.api.TeTopologyProvider;
43import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry;
44import org.onosproject.tetopology.management.api.TeTopologyProviderService;
Henry Yu4b4a7eb2016-11-09 20:07:53 -050045import org.onosproject.tetopology.management.api.TeTopologyService;
46import org.onosproject.tetopology.management.api.link.NetworkLink;
47import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
48import org.onosproject.tetopology.management.api.node.NetworkNode;
49import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
50import org.onosproject.teyang.utils.topology.LinkConverter;
Yixiao Chen5ece00f2016-09-14 16:23:24 -040051import org.onosproject.teyang.utils.topology.NetworkConverter;
Henry Yu4b4a7eb2016-11-09 20:07:53 -050052import org.onosproject.teyang.utils.topology.NodeConverter;
Yixiao Chen5ece00f2016-09-14 16:23:24 -040053import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208.IetfNetwork;
54import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208.ietfnetwork.networks.Network;
55import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev20151208.IetfNetworkTopology;
56import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708.IetfTeTopology;
Henry Yu8ac364b2016-12-15 18:24:20 -050057import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708.ietftetopology
58 .IetfTeTopologyEvent;
Henry Yu4b4a7eb2016-11-09 20:07:53 -050059import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708.ietftetopology.TeLinkEvent;
60import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708.ietftetopology.TeNodeEvent;
Yixiao Chen5ece00f2016-09-14 16:23:24 -040061import org.onosproject.yms.ych.YangCodecHandler;
62import org.onosproject.yms.ych.YangProtocolEncodingFormat;
63import org.onosproject.yms.ych.YangResourceIdentifierType;
64import org.onosproject.yms.ydt.YmsOperationType;
65import org.onosproject.yms.ymsm.YmsService;
66import org.slf4j.Logger;
67
Henry Yu4b4a7eb2016-11-09 20:07:53 -050068import java.io.IOException;
69import java.io.InputStream;
70import java.io.StringWriter;
71import java.nio.charset.StandardCharsets;
72import java.util.HashSet;
73import java.util.List;
74import java.util.Set;
75import java.util.concurrent.ExecutorService;
76import java.util.concurrent.Executors;
77
78import static org.onlab.util.Tools.groupedThreads;
79import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
80import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
81import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
Henry Yu05dcc212017-01-05 16:05:26 -050082import static org.onosproject.provider.te.utils.TeTopologyRestconfEventType.TE_TOPOLOGY_LINK_NOTIFICATION;
83import static org.onosproject.provider.te.utils.TeTopologyRestconfEventType.TE_TOPOLOGY_NODE_NOTIFICATION;
Henry Yu4b4a7eb2016-11-09 20:07:53 -050084import static org.slf4j.LoggerFactory.getLogger;
Yixiao Chen5ece00f2016-09-14 16:23:24 -040085
86/**
87 * Provider for IETF TE Topology that use RESTCONF as means of communication.
88 */
89@Component(immediate = true)
90public class TeTopologyRestconfProvider extends AbstractProvider
91 implements TeTopologyProvider {
Henry Yu8ac364b2016-12-15 18:24:20 -050092 private static final String APP_NAME = "org.onosproject.teprovider";
Yixiao Chen5ece00f2016-09-14 16:23:24 -040093 private static final String RESTCONF = "restconf";
Henry Yu4b4a7eb2016-11-09 20:07:53 -050094 private static final String PROVIDER =
95 "org.onosproject.teprovider.restconf.domain";
Yixiao Chen5ece00f2016-09-14 16:23:24 -040096 private static final String IETF_NETWORK_URI = "ietf-network:networks";
Henry Yu4b4a7eb2016-11-09 20:07:53 -050097 private static final String IETF_NETWORKS_PREFIX =
98 "{\"ietf-network:networks\":";
Henry Yu4b4a7eb2016-11-09 20:07:53 -050099 private static final String TE_LINK_EVENT_PREFIX =
100 "{\"ietf-te-topology:te-link-event\":";
101 private static final String TE_NODE_EVENT_PREFIX =
102 "{\"ietf-te-topology:te-node-event\":";
103 private static final String IETF_NOTIFICATION_URI = "netconf";
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400104 private static final String JSON = "json";
105 private static final String E_DEVICE_NULL = "Restconf device is null";
106
107 private final Logger log = getLogger(getClass());
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected DeviceProviderRegistry deviceProviderRegistry;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected TeTopologyProviderRegistry topologyProviderRegistry;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected RestConfSBController restconfClient;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected NetworkConfigRegistry cfgService;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected CoreService coreService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 protected YmsService ymsService;
126
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 protected TeTopologyService teTopologyService;
129
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400130 private YangCodecHandler codecHandler;
131
132 private TeTopologyProviderService topologyProviderService;
133
134 private final ExecutorService executor =
135 Executors.newFixedThreadPool(5, groupedThreads("onos/restconfsbprovider",
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500136 "device-installer-%d", log));
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400137
138 private final ConfigFactory<ApplicationId, RestconfServerConfig> factory =
139 new ConfigFactory<ApplicationId, RestconfServerConfig>(APP_SUBJECT_FACTORY,
140 RestconfServerConfig.class,
141 "restconfDevices",
142 true) {
143 @Override
144 public RestconfServerConfig createConfig() {
145 return new RestconfServerConfig();
146 }
147 };
148
149 private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener();
150 private ApplicationId appId;
151
152 private Set<DeviceId> addedDevices = new HashSet<>();
153
154 @Activate
155 public void activate() {
156 // Get the codec handler.
157 codecHandler = ymsService.getYangCodecHandler();
158 // Register all three IETF Topology YANG model schema with YMS.
159 codecHandler.addDeviceSchema(IetfNetwork.class);
160 codecHandler.addDeviceSchema(IetfNetworkTopology.class);
161 codecHandler.addDeviceSchema(IetfTeTopology.class);
162 // Register JSON CODEC functions
chengfan9d60b6e2016-12-01 11:06:39 +0800163 codecHandler.registerOverriddenCodec(new DefaultJsonCodec(ymsService),
Shankara-Huaweid5823ab2016-11-22 10:14:52 +0530164 YangProtocolEncodingFormat.JSON);
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400165
166 appId = coreService.registerApplication(APP_NAME);
167 topologyProviderService = topologyProviderRegistry.register(this);
168 cfgService.registerConfigFactory(factory);
169 cfgService.addListener(cfgLister);
170 executor.execute(TeTopologyRestconfProvider.this::connectDevices);
171 log.info("Started");
172 }
173
174 @Deactivate
175 public void deactivate() {
176 cfgService.removeListener(cfgLister);
177 restconfClient.getDevices().keySet().forEach(this::deviceRemoved);
178 topologyProviderRegistry.unregister(this);
179 cfgService.unregisterConfigFactory(factory);
180 log.info("Stopped");
181 }
182
183 /**
184 * Creates an instance of TeTopologyRestconf provider.
185 */
186 public TeTopologyRestconfProvider() {
187 super(new ProviderId(RESTCONF, PROVIDER));
188 }
189
190 private void deviceAdded(RestSBDevice nodeId) {
191 Preconditions.checkNotNull(nodeId, E_DEVICE_NULL);
192 nodeId.setActive(true);
193 addedDevices.add(nodeId.deviceId());
194 }
195
196 private void deviceRemoved(DeviceId deviceId) {
197 Preconditions.checkNotNull(deviceId, E_DEVICE_NULL);
198 restconfClient.removeDevice(deviceId);
199 }
200
201 private void connectDevices() {
202
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500203 RestconfServerConfig cfg = cfgService.getConfig(appId,
204 RestconfServerConfig.class);
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400205 try {
206 if (cfg != null && cfg.getDevicesAddresses() != null) {
207 //Precomputing the devices to be removed
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500208 Set<RestSBDevice> toBeRemoved = new HashSet<>(restconfClient.
209 getDevices().values());
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400210 toBeRemoved.removeAll(cfg.getDevicesAddresses());
211 //Adding new devices
212 for (RestSBDevice device : cfg.getDevicesAddresses()) {
213 device.setActive(false);
214 restconfClient.addDevice(device);
215 deviceAdded(device);
216 }
217
218 //Removing devices not wanted anymore
219 toBeRemoved.forEach(device -> deviceRemoved(device.deviceId()));
220 }
221 } catch (ConfigException e) {
222 log.error("Configuration error {}", e);
223 }
224
225 // Discover the topology from RESTCONF server
226 addedDevices.forEach(this::retrieveTopology);
227 addedDevices.clear();
228 }
229
230 private void retrieveTopology(DeviceId deviceId) {
231 // Retrieve IETF Network at top level.
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500232 InputStream jsonStream = restconfClient.get(deviceId,
233 IETF_NETWORK_URI,
234 JSON);
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400235 if (jsonStream == null) {
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500236 log.warn("Unable to retrieve network Topology from restconf " +
237 "server {}", deviceId);
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400238 return;
239 }
240
241 // Need to convert Input stream to String.
242 StringWriter writer = new StringWriter();
243 try {
244 IOUtils.copy(jsonStream, writer, StandardCharsets.UTF_8);
245 } catch (IOException e) {
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500246 log.warn("There is an exception {} for copy jsonStream to " +
247 "stringWriter for restconf {}",
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400248 e.getMessage(), deviceId);
249 return;
250 }
251 String jsonString = writer.toString();
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500252 String networkLevelJsonString = removePrefixTagFromJson(jsonString,
253 IETF_NETWORKS_PREFIX);
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400254
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500255 YangCompositeEncodingImpl yce =
256 new YangCompositeEncodingImpl(YangResourceIdentifierType.URI,
257 IETF_NETWORK_URI,
258 networkLevelJsonString);
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400259
260 Object yo = codecHandler.decode(yce,
Shankara-Huaweid5823ab2016-11-22 10:14:52 +0530261 YangProtocolEncodingFormat.JSON,
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400262 YmsOperationType.QUERY_REPLY);
263
264 if ((yo == null)) {
265 log.error("YMS decoder returns {} for restconf {}", yo, deviceId);
266 return;
267 }
268
269 // YMS returns an ArrayList in a single Object (i.e. yo in this case)
270 // this means yo is actually an ArrayList of size 1
271 IetfNetwork ietfNetwork = ((List<IetfNetwork>) yo).get(0);
272
273 if (ietfNetwork.networks() != null &&
274 ietfNetwork.networks().network() != null) {
275 //Convert the YO to TE Core data and update TE Core.
276 for (Network nw : ietfNetwork.networks().network()) {
277 topologyProviderService.networkUpdated(
Yixiao Chen265b3bb2017-01-13 10:17:03 -0500278 NetworkConverter.yang2TeSubsystemNetwork(nw, ietfNetwork.networks(), deviceId));
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400279 }
280 }
281
282 //TODO: Uncomment when YMS fixes the issue in NetworkState translation (network-ref)
283// org.onosproject.tetopology.management.api.Networks networks =
284// NetworkConverter.yang2TeSubsystemNetworks(ietfNetwork.networks(),
285// ietfNetwork.networksState());
286// if (networks == null || networks.networks() == null) {
287// log.error("Yang2Te returns null for restconf {}", deviceId);
288// return;
289// }
290// for (org.onosproject.tetopology.management.api.Network network : networks.networks()) {
291// topologyProviderService.networkUpdated(network);
292// }
293
Henry Yu05dcc212017-01-05 16:05:26 -0500294 subscribeRestconfNotification(deviceId);
295 }
296
297 private void subscribeRestconfNotification(DeviceId deviceId) {
298
299 TeTopologyRestconfEventListener listener =
300 new TeTopologyRestconfEventListener();
301
302 listener.addCallbackFunction(TE_TOPOLOGY_LINK_NOTIFICATION,
303 new InternalLinkEventProcessor());
304 listener.addCallbackFunction(TE_TOPOLOGY_NODE_NOTIFICATION,
305 new InternalNodeEventProcessor());
306
307 if (!restconfClient.isNotificationEnabled(deviceId)) {
308 restconfClient.enableNotifications(deviceId,
309 IETF_NOTIFICATION_URI,
310 "application/json",
311 listener);
312 } else {
313 restconfClient.addNotificationListener(deviceId, listener);
314 }
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400315 }
316
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500317 private String removePrefixTagFromJson(String jsonString, String prefixTag) {
318 if (jsonString.startsWith(prefixTag)) {
319 return jsonString.substring(prefixTag.length(), jsonString.length() - 1);
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400320 }
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400321 return jsonString;
322 }
323
Henry Yu05dcc212017-01-05 16:05:26 -0500324 private class InternalLinkEventProcessor implements
325 RestconfNotificationEventProcessor<String> {
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400326
327 @Override
Henry Yu05dcc212017-01-05 16:05:26 -0500328 public void processEventPayload(String payload) {
329 String linkString = removePrefixTagFromJson(payload,
330 TE_LINK_EVENT_PREFIX);
331 log.debug("link event={}", linkString);
332 handleRestconfLinkNotification(linkString);
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500333 }
334
335 private void handleRestconfLinkNotification(String linkString) {
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500336
Henry Yu8ac364b2016-12-15 18:24:20 -0500337 IetfTeTopologyEvent event = convertJson2IetfTeTopologyEvent(
338 "ietf-te-topology:te-link-event",
339 linkString);
340 if (event == null) {
341 log.error("ERROR: json to YO conversion failure");
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500342 return;
343 }
344
Henry Yu8ac364b2016-12-15 18:24:20 -0500345 if (event.type() != IetfTeTopologyEvent.Type.TE_LINK_EVENT) {
346 log.error("ERROR: wrong YO event type: {}", event.type());
347 return;
348 }
349
350 TeLinkEvent teLinkEvent = event.subject().teLinkEvent();
351
352 log.debug("TeLinkEvent: {}", teLinkEvent);
353
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500354 NetworkLinkKey linkKey = LinkConverter.yangLinkEvent2NetworkLinkKey(
Henry Yu8ac364b2016-12-15 18:24:20 -0500355 teLinkEvent);
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500356
357 NetworkLink networkLink = LinkConverter.yangLinkEvent2NetworkLink(
Henry Yu8ac364b2016-12-15 18:24:20 -0500358 teLinkEvent,
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500359 teTopologyService);
360
Henry Yu8ac364b2016-12-15 18:24:20 -0500361 if (networkLink == null) {
362 log.error("ERROR: yangLinkEvent2NetworkLink returns null");
363 return;
364 }
365
366 log.debug("networkLink: {}", networkLink);
367
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500368 topologyProviderService.linkUpdated(linkKey, networkLink);
369 }
Henry Yu05dcc212017-01-05 16:05:26 -0500370 }
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500371
Henry Yu05dcc212017-01-05 16:05:26 -0500372 private class InternalNodeEventProcessor implements
373 RestconfNotificationEventProcessor<String> {
Henry Yu8ac364b2016-12-15 18:24:20 -0500374
Henry Yu05dcc212017-01-05 16:05:26 -0500375 @Override
376 public void processEventPayload(String payload) {
377 String nodeString = removePrefixTagFromJson(payload, TE_NODE_EVENT_PREFIX);
378 log.debug("node event={}", nodeString);
379 handleRestconfNodeNotification(nodeString);
Henry Yu8ac364b2016-12-15 18:24:20 -0500380 }
381
382 private void handleRestconfNodeNotification(String nodeString) {
383
384 IetfTeTopologyEvent event = convertJson2IetfTeTopologyEvent(
385 "ietf-te-topology:te-node-event",
386 nodeString);
387
388 if (event == null) {
389 log.error("ERROR: json to YO conversion failure");
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500390 return;
391 }
392
Henry Yu8ac364b2016-12-15 18:24:20 -0500393 if (event.type() != IetfTeTopologyEvent.Type.TE_NODE_EVENT) {
394 log.error("ERROR: wrong YO event type: {}", event.type());
395 return;
396 }
397
398 TeNodeEvent teNodeEvent = event.subject().teNodeEvent();
399
400 log.debug("TeNodeEvent: {}", teNodeEvent);
401
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500402 NetworkNodeKey nodeKey = NodeConverter.yangNodeEvent2NetworkNodeKey(
Henry Yu8ac364b2016-12-15 18:24:20 -0500403 teNodeEvent);
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500404
405 NetworkNode networkNode = NodeConverter.yangNodeEvent2NetworkNode(
Henry Yu8ac364b2016-12-15 18:24:20 -0500406 teNodeEvent,
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500407 teTopologyService);
408
Henry Yu8ac364b2016-12-15 18:24:20 -0500409 if (networkNode == null) {
410 log.error("ERROR: yangNodeEvent2NetworkNode returns null");
411 return;
412 }
413
Henry Yu4b4a7eb2016-11-09 20:07:53 -0500414 topologyProviderService.nodeUpdated(nodeKey, networkNode);
415 }
416 }
Henry Yu05dcc212017-01-05 16:05:26 -0500417
418 private class InternalNetworkConfigListener implements NetworkConfigListener {
419
420 @Override
421 public void event(NetworkConfigEvent event) {
422 executor.execute(TeTopologyRestconfProvider.this::connectDevices);
423 }
424
425 @Override
426 public boolean isRelevant(NetworkConfigEvent event) {
427 return event.configClass().equals(RestconfServerConfig.class) &&
428 (event.type() == CONFIG_ADDED ||
429 event.type() == CONFIG_UPDATED);
430 }
431 }
432
433 private IetfTeTopologyEvent convertJson2IetfTeTopologyEvent(String uriString,
434 String jsonBody) {
435
436 YangCompositeEncodingImpl yce =
437 new YangCompositeEncodingImpl(YangResourceIdentifierType.URI,
438 uriString,
439 jsonBody);
440 Object yo = codecHandler.decode(yce,
441 YangProtocolEncodingFormat.JSON,
442 YmsOperationType.NOTIFICATION);
443
444 if (yo == null) {
445 log.error("YMS decoder error");
446 return null;
447 }
448
449 if (!(yo instanceof IetfTeTopologyEvent)) {
450 log.error("ERROR: YO is not IetfTeTopologyEvent");
451 return null;
452 }
453
454 return (IetfTeTopologyEvent) yo;
455 }
Yixiao Chen5ece00f2016-09-14 16:23:24 -0400456}