blob: 3055b1099a9a1e789f926dcd3b36234da22ffec2 [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
Yuta HIGUCHI1624df12016-07-21 16:54:33 -070074import static java.util.concurrent.Executors.newScheduledThreadPool;
Andrea Campanella5c999e22016-03-01 15:12:53 -080075import static org.onlab.util.Tools.groupedThreads;
andreaeb70a942015-10-16 21:34:46 -070076import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
77import static org.slf4j.LoggerFactory.getLogger;
78
Sanjay Se8dcfee2015-04-23 10:07:08 +053079/**
andreaeb70a942015-10-16 21:34:46 -070080 * Provider which uses an NETCONF controller to detect device.
Sanjay Se8dcfee2015-04-23 10:07:08 +053081 */
82@Component(immediate = true)
83public class NetconfDeviceProvider extends AbstractProvider
84 implements DeviceProvider {
Andrea Campanella7e6200a2016-03-21 09:48:40 -070085
86 public static final String ACTIVE = "active";
andreaeb70a942015-10-16 21:34:46 -070087 private final Logger log = getLogger(getClass());
Sanjay Se8dcfee2015-04-23 10:07:08 +053088
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected DeviceProviderRegistry providerRegistry;
91
andreaeb70a942015-10-16 21:34:46 -070092 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella101417d2015-12-11 17:58:07 -080093 protected NetconfController controller;
Sanjay Se8dcfee2015-04-23 10:07:08 +053094
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -070096 protected NetworkConfigRegistry cfgService;
Sanjay Se8dcfee2015-04-23 10:07:08 +053097
Thomas Vachuskad6811712015-04-29 21:37:04 -070098 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -070099 protected CoreService coreService;
Thomas Vachuskad6811712015-04-29 21:37:04 -0700100
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700102 protected DeviceService deviceService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700105 protected DeviceKeyAdminService deviceKeyAdminService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected MastershipService mastershipService;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected ClusterService clusterService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800112
Andrea Campanella101417d2015-12-11 17:58:07 -0800113 private static final String APP_NAME = "org.onosproject.netconf";
114 private static final String SCHEME_NAME = "netconf";
115 private static final String DEVICE_PROVIDER_PACKAGE = "org.onosproject.netconf.provider.device";
116 private static final String UNKNOWN = "unknown";
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700117 protected static final String ISNULL = "NetconfDeviceInfo is null";
118 private static final String IPADDRESS = "ipaddress";
119 private static final String NETCONF = "netconf";
120 private static final String PORT = "port";
helenyrwufd296b62016-06-22 17:43:02 -0700121 private static final int CORE_POOL_SIZE = 10;
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700122 //FIXME eventually a property
123 private static final int ISREACHABLE_TIMEOUT = 2000;
helenyrwufd296b62016-06-22 17:43:02 -0700124 private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 30;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530125
Andrea Campanella5c999e22016-03-01 15:12:53 -0800126 private final ExecutorService executor =
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700127 Executors.newFixedThreadPool(5, groupedThreads("onos/netconfdeviceprovider",
128 "device-installer-%d", log));
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700129 protected ScheduledExecutorService connectionExecutor
130 = newScheduledThreadPool(CORE_POOL_SIZE,
131 groupedThreads("onos/netconfdeviceprovider",
132 "connection-executor-%d", log));
Andrea Campanella5c999e22016-03-01 15:12:53 -0800133
andreaeb70a942015-10-16 21:34:46 -0700134 private DeviceProviderService providerService;
135 private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener();
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700136 private InternalDeviceListener deviceListener = new InternalDeviceListener();
137 private NodeId localNodeId;
helenyrwufd296b62016-06-22 17:43:02 -0700138 private ScheduledFuture<?> scheduledTask;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530139
andreaeb70a942015-10-16 21:34:46 -0700140 private final ConfigFactory factory =
141 new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY,
142 NetconfProviderConfig.class,
143 "devices",
144 true) {
145 @Override
146 public NetconfProviderConfig createConfig() {
147 return new NetconfProviderConfig();
148 }
149 };
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700150 private final NetworkConfigListener cfgListener = new InternalNetworkConfigListener();
andreaeb70a942015-10-16 21:34:46 -0700151 private ApplicationId appId;
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700152 private boolean active;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530153
Sanjay Se8dcfee2015-04-23 10:07:08 +0530154
155 @Activate
andreaeb70a942015-10-16 21:34:46 -0700156 public void activate() {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700157 active = true;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530158 providerService = providerRegistry.register(this);
Andrea Campanella101417d2015-12-11 17:58:07 -0800159 appId = coreService.registerApplication(APP_NAME);
andreaeb70a942015-10-16 21:34:46 -0700160 cfgService.registerConfigFactory(factory);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700161 cfgService.addListener(cfgListener);
andreaeb70a942015-10-16 21:34:46 -0700162 controller.addDeviceListener(innerNodeListener);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700163 deviceService.addListener(deviceListener);
Andrea Campanella7d8449b2016-03-02 10:16:42 -0800164 executor.execute(NetconfDeviceProvider.this::connectDevices);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700165 localNodeId = clusterService.getLocalNode().id();
helenyrwufd296b62016-06-22 17:43:02 -0700166 scheduledTask = schedulePolling();
Thomas Vachuskad6811712015-04-29 21:37:04 -0700167 log.info("Started");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530168 }
169
andreaeb70a942015-10-16 21:34:46 -0700170
Sanjay Se8dcfee2015-04-23 10:07:08 +0530171 @Deactivate
andreaeb70a942015-10-16 21:34:46 -0700172 public void deactivate() {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700173 deviceService.removeListener(deviceListener);
174 active = false;
175 controller.getNetconfDevices().forEach(id -> {
176 deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(id.toString()));
177 controller.disconnectDevice(id, true);
178 });
Andrea Campanella86294db2016-03-07 11:42:49 -0800179 controller.removeDeviceListener(innerNodeListener);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700180 deviceService.removeListener(deviceListener);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530181 providerRegistry.unregister(this);
182 providerService = null;
andreaeb70a942015-10-16 21:34:46 -0700183 cfgService.unregisterConfigFactory(factory);
helenyrwufd296b62016-06-22 17:43:02 -0700184 scheduledTask.cancel(true);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700185 executor.shutdown();
Sanjay Seb5eebb2015-04-24 15:44:50 +0530186 log.info("Stopped");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530187 }
188
andreaeb70a942015-10-16 21:34:46 -0700189 public NetconfDeviceProvider() {
Andrea Campanella101417d2015-12-11 17:58:07 -0800190 super(new ProviderId(SCHEME_NAME, DEVICE_PROVIDER_PACKAGE));
Sanjay Se8dcfee2015-04-23 10:07:08 +0530191 }
192
helenyrwufd296b62016-06-22 17:43:02 -0700193 // Checks connection to devices in the config file
194 // every DEFAULT_POLL_FREQUENCY_SECONDS seconds.
195 private ScheduledFuture schedulePolling() {
196 return connectionExecutor.scheduleAtFixedRate(this::checkAndUpdateDevices,
197 DEFAULT_POLL_FREQUENCY_SECONDS / 10,
198 DEFAULT_POLL_FREQUENCY_SECONDS,
199 TimeUnit.SECONDS);
200 }
201
Sanjay Se8dcfee2015-04-23 10:07:08 +0530202 @Override
203 public void triggerProbe(DeviceId deviceId) {
andreaeb70a942015-10-16 21:34:46 -0700204 // TODO: This will be implemented later.
205 log.info("Triggering probe on device {}", deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530206 }
207
208 @Override
209 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700210 if (active) {
211 switch (newRole) {
212 case MASTER:
213 initiateConnection(deviceId, newRole);
214 log.debug("Accepting mastership role change to {} for device {}", newRole, deviceId);
215 break;
216 case STANDBY:
217 controller.disconnectDevice(deviceId, false);
218 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.STANDBY);
219 //else no-op
220 break;
221 case NONE:
222 controller.disconnectDevice(deviceId, false);
223 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.NONE);
224 break;
225 default:
226 log.error("Unimplemented Mastership state : {}", newRole);
227
228 }
229 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530230 }
231
232 @Override
233 public boolean isReachable(DeviceId deviceId) {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700234 //FIXME this is a workaround util device state is shared
235 // between controller instances.
236 Device device = deviceService.getDevice(deviceId);
237 String ip;
238 int port;
239 Socket socket = null;
240 if (device != null) {
241 ip = device.annotations().value(IPADDRESS);
242 port = Integer.parseInt(device.annotations().value(PORT));
243 } else {
244 String[] info = deviceId.toString().split(":");
245 if (info.length == 3) {
246 ip = info[1];
247 port = Integer.parseInt(info[2]);
248 } else {
249 ip = Arrays.asList(info).stream().filter(el -> !el.equals(info[0])
250 && !el.equals(info[info.length - 1]))
251 .reduce((t, u) -> t + ":" + u)
252 .get();
253 log.debug("ip v6 {}", ip);
254 port = Integer.parseInt(info[info.length - 1]);
255 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530256 }
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700257 //test connection to device opening a socket to it.
258 try {
259 socket = new Socket(ip, port);
260 log.debug("rechability of {}, {}, {}", deviceId, socket.isConnected() && !socket.isClosed());
261 return socket.isConnected() && !socket.isClosed();
262 } catch (IOException e) {
263 log.info("Device {} is not reachable", deviceId);
264 return false;
265 } finally {
266 if (socket != null) {
267 try {
268 socket.close();
269 } catch (IOException e) {
270 log.debug("Test Socket failed {} ", deviceId);
271 return false;
272 }
273 }
274 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530275 }
276
Saurav Dasa2d37502016-03-25 17:50:40 -0700277 @Override
278 public void changePortState(DeviceId deviceId, PortNumber portNumber,
279 boolean enable) {
280 // TODO if required
281 }
282
andreaeb70a942015-10-16 21:34:46 -0700283 private class InnerNetconfDeviceListener implements NetconfDeviceListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530284
Andrea Campanella101417d2015-12-11 17:58:07 -0800285
andreaeb70a942015-10-16 21:34:46 -0700286 @Override
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700287 public void deviceAdded(DeviceId deviceId) {
288 //no-op
289 log.debug("Netconf device {} added to Netconf subController", deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530290 }
291
292 @Override
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700293 public void deviceRemoved(DeviceId deviceId) {
294 Preconditions.checkNotNull(deviceId, ISNULL);
helenyrwufd296b62016-06-22 17:43:02 -0700295
296 if (deviceService.getDevice(deviceId) != null) {
297 providerService.deviceDisconnected(deviceId);
298 log.debug("Netconf device {} removed from Netconf subController", deviceId);
299 } else {
300 log.warn("Netconf device {} does not exist in the store, " +
301 "it may already have been removed", deviceId);
302 }
andreaeb70a942015-10-16 21:34:46 -0700303 }
304 }
305
andreaeb70a942015-10-16 21:34:46 -0700306 private void connectDevices() {
307 NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
308 if (cfg != null) {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530309 try {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700310 cfg.getDevicesAddresses().stream().forEach(addr -> {
311 DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
312 Preconditions.checkNotNull(deviceId, ISNULL);
313 //Netconf configuration object
314 ChassisId cid = new ChassisId();
315 String ipAddress = addr.ip().toString();
316 SparseAnnotations annotations = DefaultAnnotations.builder()
317 .set(IPADDRESS, ipAddress)
318 .set(PORT, String.valueOf(addr.port()))
319 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
320 .build();
321 DeviceDescription deviceDescription = new DefaultDeviceDescription(
322 deviceId.uri(),
323 Device.Type.SWITCH,
324 UNKNOWN, UNKNOWN,
325 UNKNOWN, UNKNOWN,
helenyrwufd296b62016-06-22 17:43:02 -0700326 cid, false,
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700327 annotations);
328 deviceKeyAdminService.addKey(
329 DeviceKey.createDeviceKeyUsingUsernamePassword(
330 DeviceKeyId.deviceKeyId(deviceId.toString()),
331 null, addr.name(), addr.password()));
helenyrwufd296b62016-06-22 17:43:02 -0700332 if (deviceService.getDevice(deviceId) == null) {
333 providerService.deviceConnected(deviceId, deviceDescription);
334 }
335 checkAndUpdateDevice(deviceId, deviceDescription);
336 });
337 } catch (ConfigException e) {
338 log.error("Cannot read config error " + e);
339 }
340 }
341 }
342
343 private void checkAndUpdateDevice(DeviceId deviceId, DeviceDescription deviceDescription) {
344 if (deviceService.getDevice(deviceId) == null) {
345 log.warn("Device {} has not been added to store, " +
346 "maybe due to a problem in connectivity", deviceId);
347 } else {
348 boolean isReachable = isReachable(deviceId);
349 if (isReachable && !deviceService.isAvailable(deviceId)) {
Konstantinos Kanonakis4d67dd82016-08-05 12:18:52 -0500350 Device device = deviceService.getDevice(deviceId);
351 DeviceDescription updatedDeviceDescription = null;
352 if (device.is(DeviceDescriptionDiscovery.class)) {
353 if (mastershipService.isLocalMaster(deviceId)) {
354 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
355 device.as(DeviceDescriptionDiscovery.class);
356 updatedDeviceDescription = deviceDescriptionDiscovery.discoverDeviceDetails();
357 }
358 } else {
359 log.warn("No DeviceDescriptionDiscovery behaviour for device {}", deviceId);
360 }
361 if (updatedDeviceDescription == null) {
362 updatedDeviceDescription = deviceDescription;
363 }
helenyrwufd296b62016-06-22 17:43:02 -0700364 providerService.deviceConnected(
365 deviceId, new DefaultDeviceDescription(
Konstantinos Kanonakis4d67dd82016-08-05 12:18:52 -0500366 updatedDeviceDescription, true, updatedDeviceDescription.annotations()));
helenyrwufd296b62016-06-22 17:43:02 -0700367 } else if (!isReachable && deviceService.isAvailable(deviceId)) {
368 providerService.deviceDisconnected(deviceId);
369 }
370 }
371 }
372
373 private void checkAndUpdateDevices() {
374 NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
375 if (cfg != null) {
376 log.info("Checking connection to devices in configuration");
377 try {
378 cfg.getDevicesAddresses().stream().forEach(addr -> {
379 DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
380 Preconditions.checkNotNull(deviceId, ISNULL);
381 //Netconf configuration object
382 ChassisId cid = new ChassisId();
383 String ipAddress = addr.ip().toString();
384 SparseAnnotations annotations = DefaultAnnotations.builder()
385 .set(IPADDRESS, ipAddress)
386 .set(PORT, String.valueOf(addr.port()))
387 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
388 .build();
389 DeviceDescription deviceDescription = new DefaultDeviceDescription(
390 deviceId.uri(),
391 Device.Type.SWITCH,
392 UNKNOWN, UNKNOWN,
393 UNKNOWN, UNKNOWN,
394 cid, false,
395 annotations);
396 deviceKeyAdminService.addKey(
397 DeviceKey.createDeviceKeyUsingUsernamePassword(
398 DeviceKeyId.deviceKeyId(deviceId.toString()),
399 null, addr.name(), addr.password()));
400 checkAndUpdateDevice(deviceId, deviceDescription);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700401 });
andreaeb70a942015-10-16 21:34:46 -0700402 } catch (ConfigException e) {
403 log.error("Cannot read config error " + e);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530404 }
405 }
andreaeb70a942015-10-16 21:34:46 -0700406 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530407
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700408 private void initiateConnection(DeviceId deviceId, MastershipRole newRole) {
409 try {
410 if (isReachable(deviceId)) {
411 controller.connectDevice(deviceId);
412 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.MASTER);
413 } else {
414 return;
415 }
416 } catch (Exception e) {
417 if (deviceService.getDevice(deviceId) != null) {
418 providerService.deviceDisconnected(deviceId);
419 }
420 deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(deviceId.toString()));
421 throw new RuntimeException(new NetconfException(
422 "Can't connect to NETCONF " + "device on " + deviceId + ":" + deviceId, e));
423
424 }
425 }
426
427 private void discoverPorts(DeviceId deviceId) {
428 Device device = deviceService.getDevice(deviceId);
Andrea Campanella6c71a052016-04-22 11:56:31 -0700429 //TODO remove when PortDiscovery is removed from master
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700430 if (device.is(PortDiscovery.class)) {
431 PortDiscovery portConfig = device.as(PortDiscovery.class);
432 providerService.updatePorts(deviceId,
433 portConfig.getPorts());
Andrea Campanella6c71a052016-04-22 11:56:31 -0700434 } else if (device.is(DeviceDescriptionDiscovery.class)) {
435 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
436 device.as(DeviceDescriptionDiscovery.class);
437 providerService.updatePorts(deviceId,
438 deviceDescriptionDiscovery.discoverPortDetails());
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700439 } else {
440 log.warn("No portGetter behaviour for device {}", deviceId);
441 }
442 }
443
444 /**
445 * Return the DeviceId about the device containing the URI.
446 *
Andrea Campanella6c71a052016-04-22 11:56:31 -0700447 * @param ip IP address
Ray Milkeyd4334db2016-04-05 17:39:44 -0700448 * @param port port number
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700449 * @return DeviceId
450 */
451 public DeviceId getDeviceId(String ip, int port) {
452 try {
453 return DeviceId.deviceId(new URI(NETCONF, ip + ":" + port, null));
454 } catch (URISyntaxException e) {
455 throw new IllegalArgumentException("Unable to build deviceID for device "
456 + ip + ":" + port, e);
457 }
458 }
459
460 /**
461 * Listener for configuration events.
462 */
andreaeb70a942015-10-16 21:34:46 -0700463 private class InternalNetworkConfigListener implements NetworkConfigListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530464
andreaeb70a942015-10-16 21:34:46 -0700465
466 @Override
467 public void event(NetworkConfigEvent event) {
Andrea Campanella90f044f2016-03-02 09:14:57 -0800468 executor.execute(NetconfDeviceProvider.this::connectDevices);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530469 }
470
andreaeb70a942015-10-16 21:34:46 -0700471 @Override
472 public boolean isRelevant(NetworkConfigEvent event) {
andreaeb70a942015-10-16 21:34:46 -0700473 return event.configClass().equals(NetconfProviderConfig.class) &&
474 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
475 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530476 }
477 }
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700478
479 /**
480 * Listener for core device events.
481 */
482 private class InternalDeviceListener implements DeviceListener {
483 @Override
484 public void event(DeviceEvent event) {
485 if ((event.type() == DeviceEvent.Type.DEVICE_ADDED)) {
486 executor.execute(() -> discoverPorts(event.subject().id()));
487 } else if ((event.type() == DeviceEvent.Type.DEVICE_REMOVED)) {
488 log.debug("removing device {}", event.subject().id());
489 deviceService.getDevice(event.subject().id()).annotations().keys();
490 controller.disconnectDevice(event.subject().id(), true);
491 }
492 }
493
494 @Override
495 public boolean isRelevant(DeviceEvent event) {
496 if (mastershipService.getMasterFor(event.subject().id()) == null) {
497 return true;
498 }
499 return event.subject().annotations().value(AnnotationKeys.PROTOCOL)
500 .equals(SCHEME_NAME.toUpperCase()) &&
501 mastershipService.getMasterFor(event.subject().id()).equals(localNodeId);
502 }
503 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530504}