blob: eec8b299765ffb2749d835d39fedc76a4d96cdf8 [file] [log] [blame]
Sanjay Se8dcfee2015-04-23 10:07:08 +05301/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Sanjay Se8dcfee2015-04-23 10:07:08 +05303 *
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 */
andreaeb70a942015-10-16 21:34:46 -070016
Sanjay Se8dcfee2015-04-23 10:07:08 +053017package org.onosproject.provider.netconf.device.impl;
18
andreaeb70a942015-10-16 21:34:46 -070019import com.google.common.base.Preconditions;
Sanjay Se8dcfee2015-04-23 10:07:08 +053020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
Sanjay Se8dcfee2015-04-23 10:07:08 +053023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onlab.packet.ChassisId;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070026import org.onosproject.cluster.ClusterService;
27import org.onosproject.cluster.NodeId;
andreaeb70a942015-10-16 21:34:46 -070028import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.incubator.net.config.basics.ConfigException;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070031import org.onosproject.mastership.MastershipService;
Marc De Leenheerb0d131c2016-03-01 20:34:59 -080032import org.onosproject.net.AnnotationKeys;
andreaeb70a942015-10-16 21:34:46 -070033import org.onosproject.net.DefaultAnnotations;
Sanjay Se8dcfee2015-04-23 10:07:08 +053034import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.MastershipRole;
Saurav Dasa2d37502016-03-25 17:50:40 -070037import org.onosproject.net.PortNumber;
andreaeb70a942015-10-16 21:34:46 -070038import org.onosproject.net.SparseAnnotations;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080039import org.onosproject.net.behaviour.PortDiscovery;
andreaeb70a942015-10-16 21:34:46 -070040import org.onosproject.net.config.ConfigFactory;
41import org.onosproject.net.config.NetworkConfigEvent;
42import org.onosproject.net.config.NetworkConfigListener;
43import org.onosproject.net.config.NetworkConfigRegistry;
Sanjay Se8dcfee2015-04-23 10:07:08 +053044import org.onosproject.net.device.DefaultDeviceDescription;
45import org.onosproject.net.device.DeviceDescription;
Andrea Campanella6c71a052016-04-22 11:56:31 -070046import org.onosproject.net.device.DeviceDescriptionDiscovery;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070047import org.onosproject.net.device.DeviceEvent;
48import org.onosproject.net.device.DeviceListener;
Sanjay Se8dcfee2015-04-23 10:07:08 +053049import org.onosproject.net.device.DeviceProvider;
50import org.onosproject.net.device.DeviceProviderRegistry;
51import org.onosproject.net.device.DeviceProviderService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080052import org.onosproject.net.device.DeviceService;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070053import org.onosproject.net.key.DeviceKey;
54import org.onosproject.net.key.DeviceKeyAdminService;
55import org.onosproject.net.key.DeviceKeyId;
Sanjay Se8dcfee2015-04-23 10:07:08 +053056import org.onosproject.net.provider.AbstractProvider;
57import org.onosproject.net.provider.ProviderId;
andreaeb70a942015-10-16 21:34:46 -070058import org.onosproject.netconf.NetconfController;
andreaeb70a942015-10-16 21:34:46 -070059import org.onosproject.netconf.NetconfDeviceListener;
Andrea Campanella8b1cb672016-01-25 13:58:58 -080060import org.onosproject.netconf.NetconfException;
Sanjay Se8dcfee2015-04-23 10:07:08 +053061import org.slf4j.Logger;
62
Andrea Campanella087ceb92015-12-07 09:58:34 -080063import java.io.IOException;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070064import java.net.Socket;
65import java.net.URI;
66import java.net.URISyntaxException;
67import java.util.Arrays;
Andrea Campanella5c999e22016-03-01 15:12:53 -080068import java.util.concurrent.ExecutorService;
69import java.util.concurrent.Executors;
helenyrwufd296b62016-06-22 17:43:02 -070070import java.util.concurrent.ScheduledExecutorService;
71import java.util.concurrent.ScheduledFuture;
72import java.util.concurrent.TimeUnit;
andreaeb70a942015-10-16 21:34:46 -070073
Andrea Campanella5c999e22016-03-01 15:12:53 -080074import static org.onlab.util.Tools.groupedThreads;
andreaeb70a942015-10-16 21:34:46 -070075import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
76import static org.slf4j.LoggerFactory.getLogger;
77
Sanjay Se8dcfee2015-04-23 10:07:08 +053078/**
andreaeb70a942015-10-16 21:34:46 -070079 * Provider which uses an NETCONF controller to detect device.
Sanjay Se8dcfee2015-04-23 10:07:08 +053080 */
81@Component(immediate = true)
82public class NetconfDeviceProvider extends AbstractProvider
83 implements DeviceProvider {
Andrea Campanella7e6200a2016-03-21 09:48:40 -070084
85 public static final String ACTIVE = "active";
andreaeb70a942015-10-16 21:34:46 -070086 private final Logger log = getLogger(getClass());
Sanjay Se8dcfee2015-04-23 10:07:08 +053087
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected DeviceProviderRegistry providerRegistry;
90
andreaeb70a942015-10-16 21:34:46 -070091 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella101417d2015-12-11 17:58:07 -080092 protected NetconfController controller;
Sanjay Se8dcfee2015-04-23 10:07:08 +053093
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -070095 protected NetworkConfigRegistry cfgService;
Sanjay Se8dcfee2015-04-23 10:07:08 +053096
Thomas Vachuskad6811712015-04-29 21:37:04 -070097 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -070098 protected CoreService coreService;
Thomas Vachuskad6811712015-04-29 21:37:04 -070099
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700101 protected DeviceService deviceService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700104 protected DeviceKeyAdminService deviceKeyAdminService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected MastershipService mastershipService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected ClusterService clusterService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800111
Andrea Campanella101417d2015-12-11 17:58:07 -0800112 private static final String APP_NAME = "org.onosproject.netconf";
113 private static final String SCHEME_NAME = "netconf";
114 private static final String DEVICE_PROVIDER_PACKAGE = "org.onosproject.netconf.provider.device";
115 private static final String UNKNOWN = "unknown";
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700116 protected static final String ISNULL = "NetconfDeviceInfo is null";
117 private static final String IPADDRESS = "ipaddress";
118 private static final String NETCONF = "netconf";
119 private static final String PORT = "port";
helenyrwufd296b62016-06-22 17:43:02 -0700120 private static final int CORE_POOL_SIZE = 10;
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700121 //FIXME eventually a property
122 private static final int ISREACHABLE_TIMEOUT = 2000;
helenyrwufd296b62016-06-22 17:43:02 -0700123 private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 30;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530124
Andrea Campanella5c999e22016-03-01 15:12:53 -0800125 private final ExecutorService executor =
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700126 Executors.newFixedThreadPool(5, groupedThreads("onos/netconfdeviceprovider",
127 "device-installer-%d", log));
helenyrwufd296b62016-06-22 17:43:02 -0700128 protected ScheduledExecutorService connectionExecutor = Executors.newScheduledThreadPool(CORE_POOL_SIZE);
Andrea Campanella5c999e22016-03-01 15:12:53 -0800129
andreaeb70a942015-10-16 21:34:46 -0700130 private DeviceProviderService providerService;
131 private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener();
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700132 private InternalDeviceListener deviceListener = new InternalDeviceListener();
133 private NodeId localNodeId;
helenyrwufd296b62016-06-22 17:43:02 -0700134 private ScheduledFuture<?> scheduledTask;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530135
andreaeb70a942015-10-16 21:34:46 -0700136 private final ConfigFactory factory =
137 new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY,
138 NetconfProviderConfig.class,
139 "devices",
140 true) {
141 @Override
142 public NetconfProviderConfig createConfig() {
143 return new NetconfProviderConfig();
144 }
145 };
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700146 private final NetworkConfigListener cfgListener = new InternalNetworkConfigListener();
andreaeb70a942015-10-16 21:34:46 -0700147 private ApplicationId appId;
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700148 private boolean active;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530149
Sanjay Se8dcfee2015-04-23 10:07:08 +0530150
151 @Activate
andreaeb70a942015-10-16 21:34:46 -0700152 public void activate() {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700153 active = true;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530154 providerService = providerRegistry.register(this);
Andrea Campanella101417d2015-12-11 17:58:07 -0800155 appId = coreService.registerApplication(APP_NAME);
andreaeb70a942015-10-16 21:34:46 -0700156 cfgService.registerConfigFactory(factory);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700157 cfgService.addListener(cfgListener);
andreaeb70a942015-10-16 21:34:46 -0700158 controller.addDeviceListener(innerNodeListener);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700159 deviceService.addListener(deviceListener);
Andrea Campanella7d8449b2016-03-02 10:16:42 -0800160 executor.execute(NetconfDeviceProvider.this::connectDevices);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700161 localNodeId = clusterService.getLocalNode().id();
helenyrwufd296b62016-06-22 17:43:02 -0700162 scheduledTask = schedulePolling();
Thomas Vachuskad6811712015-04-29 21:37:04 -0700163 log.info("Started");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530164 }
165
andreaeb70a942015-10-16 21:34:46 -0700166
Sanjay Se8dcfee2015-04-23 10:07:08 +0530167 @Deactivate
andreaeb70a942015-10-16 21:34:46 -0700168 public void deactivate() {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700169 deviceService.removeListener(deviceListener);
170 active = false;
171 controller.getNetconfDevices().forEach(id -> {
172 deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(id.toString()));
173 controller.disconnectDevice(id, true);
174 });
Andrea Campanella86294db2016-03-07 11:42:49 -0800175 controller.removeDeviceListener(innerNodeListener);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700176 deviceService.removeListener(deviceListener);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530177 providerRegistry.unregister(this);
178 providerService = null;
andreaeb70a942015-10-16 21:34:46 -0700179 cfgService.unregisterConfigFactory(factory);
helenyrwufd296b62016-06-22 17:43:02 -0700180 scheduledTask.cancel(true);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700181 executor.shutdown();
Sanjay Seb5eebb2015-04-24 15:44:50 +0530182 log.info("Stopped");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530183 }
184
andreaeb70a942015-10-16 21:34:46 -0700185 public NetconfDeviceProvider() {
Andrea Campanella101417d2015-12-11 17:58:07 -0800186 super(new ProviderId(SCHEME_NAME, DEVICE_PROVIDER_PACKAGE));
Sanjay Se8dcfee2015-04-23 10:07:08 +0530187 }
188
helenyrwufd296b62016-06-22 17:43:02 -0700189 // Checks connection to devices in the config file
190 // every DEFAULT_POLL_FREQUENCY_SECONDS seconds.
191 private ScheduledFuture schedulePolling() {
192 return connectionExecutor.scheduleAtFixedRate(this::checkAndUpdateDevices,
193 DEFAULT_POLL_FREQUENCY_SECONDS / 10,
194 DEFAULT_POLL_FREQUENCY_SECONDS,
195 TimeUnit.SECONDS);
196 }
197
Sanjay Se8dcfee2015-04-23 10:07:08 +0530198 @Override
199 public void triggerProbe(DeviceId deviceId) {
andreaeb70a942015-10-16 21:34:46 -0700200 // TODO: This will be implemented later.
201 log.info("Triggering probe on device {}", deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530202 }
203
204 @Override
205 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700206 if (active) {
207 switch (newRole) {
208 case MASTER:
209 initiateConnection(deviceId, newRole);
210 log.debug("Accepting mastership role change to {} for device {}", newRole, deviceId);
211 break;
212 case STANDBY:
213 controller.disconnectDevice(deviceId, false);
214 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.STANDBY);
215 //else no-op
216 break;
217 case NONE:
218 controller.disconnectDevice(deviceId, false);
219 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.NONE);
220 break;
221 default:
222 log.error("Unimplemented Mastership state : {}", newRole);
223
224 }
225 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530226 }
227
228 @Override
229 public boolean isReachable(DeviceId deviceId) {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700230 //FIXME this is a workaround util device state is shared
231 // between controller instances.
232 Device device = deviceService.getDevice(deviceId);
233 String ip;
234 int port;
235 Socket socket = null;
236 if (device != null) {
237 ip = device.annotations().value(IPADDRESS);
238 port = Integer.parseInt(device.annotations().value(PORT));
239 } else {
240 String[] info = deviceId.toString().split(":");
241 if (info.length == 3) {
242 ip = info[1];
243 port = Integer.parseInt(info[2]);
244 } else {
245 ip = Arrays.asList(info).stream().filter(el -> !el.equals(info[0])
246 && !el.equals(info[info.length - 1]))
247 .reduce((t, u) -> t + ":" + u)
248 .get();
249 log.debug("ip v6 {}", ip);
250 port = Integer.parseInt(info[info.length - 1]);
251 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530252 }
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700253 //test connection to device opening a socket to it.
254 try {
255 socket = new Socket(ip, port);
256 log.debug("rechability of {}, {}, {}", deviceId, socket.isConnected() && !socket.isClosed());
257 return socket.isConnected() && !socket.isClosed();
258 } catch (IOException e) {
259 log.info("Device {} is not reachable", deviceId);
260 return false;
261 } finally {
262 if (socket != null) {
263 try {
264 socket.close();
265 } catch (IOException e) {
266 log.debug("Test Socket failed {} ", deviceId);
267 return false;
268 }
269 }
270 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530271 }
272
Saurav Dasa2d37502016-03-25 17:50:40 -0700273 @Override
274 public void changePortState(DeviceId deviceId, PortNumber portNumber,
275 boolean enable) {
276 // TODO if required
277 }
278
andreaeb70a942015-10-16 21:34:46 -0700279 private class InnerNetconfDeviceListener implements NetconfDeviceListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530280
Andrea Campanella101417d2015-12-11 17:58:07 -0800281
andreaeb70a942015-10-16 21:34:46 -0700282 @Override
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700283 public void deviceAdded(DeviceId deviceId) {
284 //no-op
285 log.debug("Netconf device {} added to Netconf subController", deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530286 }
287
288 @Override
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700289 public void deviceRemoved(DeviceId deviceId) {
290 Preconditions.checkNotNull(deviceId, ISNULL);
helenyrwufd296b62016-06-22 17:43:02 -0700291
292 if (deviceService.getDevice(deviceId) != null) {
293 providerService.deviceDisconnected(deviceId);
294 log.debug("Netconf device {} removed from Netconf subController", deviceId);
295 } else {
296 log.warn("Netconf device {} does not exist in the store, " +
297 "it may already have been removed", deviceId);
298 }
andreaeb70a942015-10-16 21:34:46 -0700299 }
300 }
301
andreaeb70a942015-10-16 21:34:46 -0700302 private void connectDevices() {
303 NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
304 if (cfg != null) {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530305 try {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700306 cfg.getDevicesAddresses().stream().forEach(addr -> {
307 DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
308 Preconditions.checkNotNull(deviceId, ISNULL);
309 //Netconf configuration object
310 ChassisId cid = new ChassisId();
311 String ipAddress = addr.ip().toString();
312 SparseAnnotations annotations = DefaultAnnotations.builder()
313 .set(IPADDRESS, ipAddress)
314 .set(PORT, String.valueOf(addr.port()))
315 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
316 .build();
317 DeviceDescription deviceDescription = new DefaultDeviceDescription(
318 deviceId.uri(),
319 Device.Type.SWITCH,
320 UNKNOWN, UNKNOWN,
321 UNKNOWN, UNKNOWN,
helenyrwufd296b62016-06-22 17:43:02 -0700322 cid, false,
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700323 annotations);
324 deviceKeyAdminService.addKey(
325 DeviceKey.createDeviceKeyUsingUsernamePassword(
326 DeviceKeyId.deviceKeyId(deviceId.toString()),
327 null, addr.name(), addr.password()));
helenyrwufd296b62016-06-22 17:43:02 -0700328 if (deviceService.getDevice(deviceId) == null) {
329 providerService.deviceConnected(deviceId, deviceDescription);
330 }
331 checkAndUpdateDevice(deviceId, deviceDescription);
332 });
333 } catch (ConfigException e) {
334 log.error("Cannot read config error " + e);
335 }
336 }
337 }
338
339 private void checkAndUpdateDevice(DeviceId deviceId, DeviceDescription deviceDescription) {
340 if (deviceService.getDevice(deviceId) == null) {
341 log.warn("Device {} has not been added to store, " +
342 "maybe due to a problem in connectivity", deviceId);
343 } else {
344 boolean isReachable = isReachable(deviceId);
345 if (isReachable && !deviceService.isAvailable(deviceId)) {
346 providerService.deviceConnected(
347 deviceId, new DefaultDeviceDescription(
348 deviceDescription, true, deviceDescription.annotations()));
349 } else if (!isReachable && deviceService.isAvailable(deviceId)) {
350 providerService.deviceDisconnected(deviceId);
351 }
352 }
353 }
354
355 private void checkAndUpdateDevices() {
356 NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
357 if (cfg != null) {
358 log.info("Checking connection to devices in configuration");
359 try {
360 cfg.getDevicesAddresses().stream().forEach(addr -> {
361 DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
362 Preconditions.checkNotNull(deviceId, ISNULL);
363 //Netconf configuration object
364 ChassisId cid = new ChassisId();
365 String ipAddress = addr.ip().toString();
366 SparseAnnotations annotations = DefaultAnnotations.builder()
367 .set(IPADDRESS, ipAddress)
368 .set(PORT, String.valueOf(addr.port()))
369 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
370 .build();
371 DeviceDescription deviceDescription = new DefaultDeviceDescription(
372 deviceId.uri(),
373 Device.Type.SWITCH,
374 UNKNOWN, UNKNOWN,
375 UNKNOWN, UNKNOWN,
376 cid, false,
377 annotations);
378 deviceKeyAdminService.addKey(
379 DeviceKey.createDeviceKeyUsingUsernamePassword(
380 DeviceKeyId.deviceKeyId(deviceId.toString()),
381 null, addr.name(), addr.password()));
382 checkAndUpdateDevice(deviceId, deviceDescription);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700383 });
andreaeb70a942015-10-16 21:34:46 -0700384 } catch (ConfigException e) {
385 log.error("Cannot read config error " + e);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530386 }
387 }
andreaeb70a942015-10-16 21:34:46 -0700388 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530389
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700390 private void initiateConnection(DeviceId deviceId, MastershipRole newRole) {
391 try {
392 if (isReachable(deviceId)) {
393 controller.connectDevice(deviceId);
394 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.MASTER);
395 } else {
396 return;
397 }
398 } catch (Exception e) {
399 if (deviceService.getDevice(deviceId) != null) {
400 providerService.deviceDisconnected(deviceId);
401 }
402 deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(deviceId.toString()));
403 throw new RuntimeException(new NetconfException(
404 "Can't connect to NETCONF " + "device on " + deviceId + ":" + deviceId, e));
405
406 }
407 }
408
409 private void discoverPorts(DeviceId deviceId) {
410 Device device = deviceService.getDevice(deviceId);
Andrea Campanella6c71a052016-04-22 11:56:31 -0700411 //TODO remove when PortDiscovery is removed from master
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700412 if (device.is(PortDiscovery.class)) {
413 PortDiscovery portConfig = device.as(PortDiscovery.class);
414 providerService.updatePorts(deviceId,
415 portConfig.getPorts());
Andrea Campanella6c71a052016-04-22 11:56:31 -0700416 } else if (device.is(DeviceDescriptionDiscovery.class)) {
417 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
418 device.as(DeviceDescriptionDiscovery.class);
419 providerService.updatePorts(deviceId,
420 deviceDescriptionDiscovery.discoverPortDetails());
421
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700422 } else {
423 log.warn("No portGetter behaviour for device {}", deviceId);
424 }
425 }
426
427 /**
428 * Return the DeviceId about the device containing the URI.
429 *
Andrea Campanella6c71a052016-04-22 11:56:31 -0700430 * @param ip IP address
Ray Milkeyd4334db2016-04-05 17:39:44 -0700431 * @param port port number
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700432 * @return DeviceId
433 */
434 public DeviceId getDeviceId(String ip, int port) {
435 try {
436 return DeviceId.deviceId(new URI(NETCONF, ip + ":" + port, null));
437 } catch (URISyntaxException e) {
438 throw new IllegalArgumentException("Unable to build deviceID for device "
439 + ip + ":" + port, e);
440 }
441 }
442
443 /**
444 * Listener for configuration events.
445 */
andreaeb70a942015-10-16 21:34:46 -0700446 private class InternalNetworkConfigListener implements NetworkConfigListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530447
andreaeb70a942015-10-16 21:34:46 -0700448
449 @Override
450 public void event(NetworkConfigEvent event) {
Andrea Campanella90f044f2016-03-02 09:14:57 -0800451 executor.execute(NetconfDeviceProvider.this::connectDevices);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530452 }
453
andreaeb70a942015-10-16 21:34:46 -0700454 @Override
455 public boolean isRelevant(NetworkConfigEvent event) {
andreaeb70a942015-10-16 21:34:46 -0700456 return event.configClass().equals(NetconfProviderConfig.class) &&
457 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
458 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530459 }
460 }
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700461
462 /**
463 * Listener for core device events.
464 */
465 private class InternalDeviceListener implements DeviceListener {
466 @Override
467 public void event(DeviceEvent event) {
468 if ((event.type() == DeviceEvent.Type.DEVICE_ADDED)) {
469 executor.execute(() -> discoverPorts(event.subject().id()));
470 } else if ((event.type() == DeviceEvent.Type.DEVICE_REMOVED)) {
471 log.debug("removing device {}", event.subject().id());
472 deviceService.getDevice(event.subject().id()).annotations().keys();
473 controller.disconnectDevice(event.subject().id(), true);
474 }
475 }
476
477 @Override
478 public boolean isRelevant(DeviceEvent event) {
479 if (mastershipService.getMasterFor(event.subject().id()) == null) {
480 return true;
481 }
482 return event.subject().annotations().value(AnnotationKeys.PROTOCOL)
483 .equals(SCHEME_NAME.toUpperCase()) &&
484 mastershipService.getMasterFor(event.subject().id()).equals(localNodeId);
485 }
486 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530487}