blob: 96dd14f850390f136ca0e7ba14d9755042747265 [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
Michele Santuari00cc1f72016-09-08 17:05:24 +020019import com.google.common.base.Objects;
andreaeb70a942015-10-16 21:34:46 -070020import com.google.common.base.Preconditions;
Sanjay Se8dcfee2015-04-23 10:07:08 +053021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
Sanjay Se8dcfee2015-04-23 10:07:08 +053024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.onlab.packet.ChassisId;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070027import org.onosproject.cluster.ClusterService;
28import org.onosproject.cluster.NodeId;
andreaeb70a942015-10-16 21:34:46 -070029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
31import org.onosproject.incubator.net.config.basics.ConfigException;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070032import org.onosproject.mastership.MastershipService;
Marc De Leenheerb0d131c2016-03-01 20:34:59 -080033import org.onosproject.net.AnnotationKeys;
andreaeb70a942015-10-16 21:34:46 -070034import org.onosproject.net.DefaultAnnotations;
Sanjay Se8dcfee2015-04-23 10:07:08 +053035import org.onosproject.net.Device;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.MastershipRole;
Saurav Dasa2d37502016-03-25 17:50:40 -070038import org.onosproject.net.PortNumber;
andreaeb70a942015-10-16 21:34:46 -070039import org.onosproject.net.SparseAnnotations;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080040import org.onosproject.net.behaviour.PortDiscovery;
andreaeb70a942015-10-16 21:34:46 -070041import org.onosproject.net.config.ConfigFactory;
42import org.onosproject.net.config.NetworkConfigEvent;
43import org.onosproject.net.config.NetworkConfigListener;
44import org.onosproject.net.config.NetworkConfigRegistry;
Sanjay Se8dcfee2015-04-23 10:07:08 +053045import org.onosproject.net.device.DefaultDeviceDescription;
46import org.onosproject.net.device.DeviceDescription;
Andrea Campanella6c71a052016-04-22 11:56:31 -070047import org.onosproject.net.device.DeviceDescriptionDiscovery;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070048import org.onosproject.net.device.DeviceEvent;
49import org.onosproject.net.device.DeviceListener;
Sanjay Se8dcfee2015-04-23 10:07:08 +053050import org.onosproject.net.device.DeviceProvider;
51import org.onosproject.net.device.DeviceProviderRegistry;
52import org.onosproject.net.device.DeviceProviderService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080053import org.onosproject.net.device.DeviceService;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070054import org.onosproject.net.key.DeviceKey;
55import org.onosproject.net.key.DeviceKeyAdminService;
56import org.onosproject.net.key.DeviceKeyId;
Sanjay Se8dcfee2015-04-23 10:07:08 +053057import org.onosproject.net.provider.AbstractProvider;
58import org.onosproject.net.provider.ProviderId;
andreaeb70a942015-10-16 21:34:46 -070059import org.onosproject.netconf.NetconfController;
andreaeb70a942015-10-16 21:34:46 -070060import org.onosproject.netconf.NetconfDeviceListener;
Andrea Campanella8b1cb672016-01-25 13:58:58 -080061import org.onosproject.netconf.NetconfException;
Sanjay Se8dcfee2015-04-23 10:07:08 +053062import org.slf4j.Logger;
63
Andrea Campanella087ceb92015-12-07 09:58:34 -080064import java.io.IOException;
Andrea Campanella7e6200a2016-03-21 09:48:40 -070065import java.net.Socket;
66import java.net.URI;
67import java.net.URISyntaxException;
68import java.util.Arrays;
Andrea Campanella5c999e22016-03-01 15:12:53 -080069import java.util.concurrent.ExecutorService;
70import java.util.concurrent.Executors;
helenyrwufd296b62016-06-22 17:43:02 -070071import java.util.concurrent.ScheduledExecutorService;
72import java.util.concurrent.ScheduledFuture;
73import java.util.concurrent.TimeUnit;
andreaeb70a942015-10-16 21:34:46 -070074
Yuta HIGUCHI1624df12016-07-21 16:54:33 -070075import static java.util.concurrent.Executors.newScheduledThreadPool;
Andrea Campanella5c999e22016-03-01 15:12:53 -080076import static org.onlab.util.Tools.groupedThreads;
andreaeb70a942015-10-16 21:34:46 -070077import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
78import static org.slf4j.LoggerFactory.getLogger;
79
Sanjay Se8dcfee2015-04-23 10:07:08 +053080/**
andreaeb70a942015-10-16 21:34:46 -070081 * Provider which uses an NETCONF controller to detect device.
Sanjay Se8dcfee2015-04-23 10:07:08 +053082 */
83@Component(immediate = true)
84public class NetconfDeviceProvider extends AbstractProvider
85 implements DeviceProvider {
Andrea Campanella7e6200a2016-03-21 09:48:40 -070086
87 public static final String ACTIVE = "active";
andreaeb70a942015-10-16 21:34:46 -070088 private final Logger log = getLogger(getClass());
Sanjay Se8dcfee2015-04-23 10:07:08 +053089
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected DeviceProviderRegistry providerRegistry;
92
andreaeb70a942015-10-16 21:34:46 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella101417d2015-12-11 17:58:07 -080094 protected NetconfController controller;
Sanjay Se8dcfee2015-04-23 10:07:08 +053095
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -070097 protected NetworkConfigRegistry cfgService;
Sanjay Se8dcfee2015-04-23 10:07:08 +053098
Thomas Vachuskad6811712015-04-29 21:37:04 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -0700100 protected CoreService coreService;
Thomas Vachuskad6811712015-04-29 21:37:04 -0700101
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700103 protected DeviceService deviceService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700106 protected DeviceKeyAdminService deviceKeyAdminService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected MastershipService mastershipService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected ClusterService clusterService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800113
Andrea Campanella101417d2015-12-11 17:58:07 -0800114 private static final String APP_NAME = "org.onosproject.netconf";
115 private static final String SCHEME_NAME = "netconf";
116 private static final String DEVICE_PROVIDER_PACKAGE = "org.onosproject.netconf.provider.device";
117 private static final String UNKNOWN = "unknown";
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700118 protected static final String ISNULL = "NetconfDeviceInfo is null";
119 private static final String IPADDRESS = "ipaddress";
120 private static final String NETCONF = "netconf";
121 private static final String PORT = "port";
helenyrwufd296b62016-06-22 17:43:02 -0700122 private static final int CORE_POOL_SIZE = 10;
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700123 //FIXME eventually a property
124 private static final int ISREACHABLE_TIMEOUT = 2000;
helenyrwufd296b62016-06-22 17:43:02 -0700125 private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 30;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530126
Andrea Campanella5c999e22016-03-01 15:12:53 -0800127 private final ExecutorService executor =
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700128 Executors.newFixedThreadPool(5, groupedThreads("onos/netconfdeviceprovider",
129 "device-installer-%d", log));
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700130 protected ScheduledExecutorService connectionExecutor
131 = newScheduledThreadPool(CORE_POOL_SIZE,
132 groupedThreads("onos/netconfdeviceprovider",
133 "connection-executor-%d", log));
Andrea Campanella5c999e22016-03-01 15:12:53 -0800134
andreaeb70a942015-10-16 21:34:46 -0700135 private DeviceProviderService providerService;
136 private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener();
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700137 private InternalDeviceListener deviceListener = new InternalDeviceListener();
138 private NodeId localNodeId;
helenyrwufd296b62016-06-22 17:43:02 -0700139 private ScheduledFuture<?> scheduledTask;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530140
andreaeb70a942015-10-16 21:34:46 -0700141 private final ConfigFactory factory =
142 new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY,
143 NetconfProviderConfig.class,
144 "devices",
145 true) {
146 @Override
147 public NetconfProviderConfig createConfig() {
148 return new NetconfProviderConfig();
149 }
150 };
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700151 private final NetworkConfigListener cfgListener = new InternalNetworkConfigListener();
andreaeb70a942015-10-16 21:34:46 -0700152 private ApplicationId appId;
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700153 private boolean active;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530154
Sanjay Se8dcfee2015-04-23 10:07:08 +0530155
156 @Activate
andreaeb70a942015-10-16 21:34:46 -0700157 public void activate() {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700158 active = true;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530159 providerService = providerRegistry.register(this);
Andrea Campanella101417d2015-12-11 17:58:07 -0800160 appId = coreService.registerApplication(APP_NAME);
andreaeb70a942015-10-16 21:34:46 -0700161 cfgService.registerConfigFactory(factory);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700162 cfgService.addListener(cfgListener);
andreaeb70a942015-10-16 21:34:46 -0700163 controller.addDeviceListener(innerNodeListener);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700164 deviceService.addListener(deviceListener);
Andrea Campanella7d8449b2016-03-02 10:16:42 -0800165 executor.execute(NetconfDeviceProvider.this::connectDevices);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700166 localNodeId = clusterService.getLocalNode().id();
helenyrwufd296b62016-06-22 17:43:02 -0700167 scheduledTask = schedulePolling();
Thomas Vachuskad6811712015-04-29 21:37:04 -0700168 log.info("Started");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530169 }
170
andreaeb70a942015-10-16 21:34:46 -0700171
Sanjay Se8dcfee2015-04-23 10:07:08 +0530172 @Deactivate
andreaeb70a942015-10-16 21:34:46 -0700173 public void deactivate() {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700174 deviceService.removeListener(deviceListener);
175 active = false;
176 controller.getNetconfDevices().forEach(id -> {
177 deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(id.toString()));
178 controller.disconnectDevice(id, true);
179 });
Andrea Campanella86294db2016-03-07 11:42:49 -0800180 controller.removeDeviceListener(innerNodeListener);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700181 deviceService.removeListener(deviceListener);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530182 providerRegistry.unregister(this);
183 providerService = null;
andreaeb70a942015-10-16 21:34:46 -0700184 cfgService.unregisterConfigFactory(factory);
helenyrwufd296b62016-06-22 17:43:02 -0700185 scheduledTask.cancel(true);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700186 executor.shutdown();
Sanjay Seb5eebb2015-04-24 15:44:50 +0530187 log.info("Stopped");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530188 }
189
andreaeb70a942015-10-16 21:34:46 -0700190 public NetconfDeviceProvider() {
Andrea Campanella101417d2015-12-11 17:58:07 -0800191 super(new ProviderId(SCHEME_NAME, DEVICE_PROVIDER_PACKAGE));
Sanjay Se8dcfee2015-04-23 10:07:08 +0530192 }
193
helenyrwufd296b62016-06-22 17:43:02 -0700194 // Checks connection to devices in the config file
195 // every DEFAULT_POLL_FREQUENCY_SECONDS seconds.
196 private ScheduledFuture schedulePolling() {
197 return connectionExecutor.scheduleAtFixedRate(this::checkAndUpdateDevices,
198 DEFAULT_POLL_FREQUENCY_SECONDS / 10,
199 DEFAULT_POLL_FREQUENCY_SECONDS,
200 TimeUnit.SECONDS);
201 }
202
Sanjay Se8dcfee2015-04-23 10:07:08 +0530203 @Override
204 public void triggerProbe(DeviceId deviceId) {
andreaeb70a942015-10-16 21:34:46 -0700205 // TODO: This will be implemented later.
206 log.info("Triggering probe on device {}", deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530207 }
208
209 @Override
210 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700211 if (active) {
212 switch (newRole) {
213 case MASTER:
214 initiateConnection(deviceId, newRole);
215 log.debug("Accepting mastership role change to {} for device {}", newRole, deviceId);
216 break;
217 case STANDBY:
218 controller.disconnectDevice(deviceId, false);
219 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.STANDBY);
220 //else no-op
221 break;
222 case NONE:
223 controller.disconnectDevice(deviceId, false);
224 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.NONE);
225 break;
226 default:
227 log.error("Unimplemented Mastership state : {}", newRole);
228
229 }
230 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530231 }
232
233 @Override
234 public boolean isReachable(DeviceId deviceId) {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700235 //FIXME this is a workaround util device state is shared
236 // between controller instances.
237 Device device = deviceService.getDevice(deviceId);
238 String ip;
239 int port;
240 Socket socket = null;
241 if (device != null) {
242 ip = device.annotations().value(IPADDRESS);
243 port = Integer.parseInt(device.annotations().value(PORT));
244 } else {
245 String[] info = deviceId.toString().split(":");
246 if (info.length == 3) {
247 ip = info[1];
248 port = Integer.parseInt(info[2]);
249 } else {
250 ip = Arrays.asList(info).stream().filter(el -> !el.equals(info[0])
251 && !el.equals(info[info.length - 1]))
252 .reduce((t, u) -> t + ":" + u)
253 .get();
254 log.debug("ip v6 {}", ip);
255 port = Integer.parseInt(info[info.length - 1]);
256 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530257 }
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700258 //test connection to device opening a socket to it.
259 try {
260 socket = new Socket(ip, port);
261 log.debug("rechability of {}, {}, {}", deviceId, socket.isConnected() && !socket.isClosed());
262 return socket.isConnected() && !socket.isClosed();
263 } catch (IOException e) {
264 log.info("Device {} is not reachable", deviceId);
265 return false;
266 } finally {
267 if (socket != null) {
268 try {
269 socket.close();
270 } catch (IOException e) {
271 log.debug("Test Socket failed {} ", deviceId);
272 return false;
273 }
274 }
275 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530276 }
277
Saurav Dasa2d37502016-03-25 17:50:40 -0700278 @Override
279 public void changePortState(DeviceId deviceId, PortNumber portNumber,
280 boolean enable) {
281 // TODO if required
282 }
283
andreaeb70a942015-10-16 21:34:46 -0700284 private class InnerNetconfDeviceListener implements NetconfDeviceListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530285
Andrea Campanella101417d2015-12-11 17:58:07 -0800286
andreaeb70a942015-10-16 21:34:46 -0700287 @Override
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700288 public void deviceAdded(DeviceId deviceId) {
289 //no-op
290 log.debug("Netconf device {} added to Netconf subController", deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530291 }
292
293 @Override
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700294 public void deviceRemoved(DeviceId deviceId) {
295 Preconditions.checkNotNull(deviceId, ISNULL);
helenyrwufd296b62016-06-22 17:43:02 -0700296
297 if (deviceService.getDevice(deviceId) != null) {
298 providerService.deviceDisconnected(deviceId);
299 log.debug("Netconf device {} removed from Netconf subController", deviceId);
300 } else {
301 log.warn("Netconf device {} does not exist in the store, " +
302 "it may already have been removed", deviceId);
303 }
andreaeb70a942015-10-16 21:34:46 -0700304 }
305 }
306
andreaeb70a942015-10-16 21:34:46 -0700307 private void connectDevices() {
308 NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
309 if (cfg != null) {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530310 try {
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700311 cfg.getDevicesAddresses().forEach(addr -> {
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700312 DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
313 Preconditions.checkNotNull(deviceId, ISNULL);
314 //Netconf configuration object
315 ChassisId cid = new ChassisId();
316 String ipAddress = addr.ip().toString();
317 SparseAnnotations annotations = DefaultAnnotations.builder()
318 .set(IPADDRESS, ipAddress)
319 .set(PORT, String.valueOf(addr.port()))
320 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
321 .build();
322 DeviceDescription deviceDescription = new DefaultDeviceDescription(
323 deviceId.uri(),
324 Device.Type.SWITCH,
325 UNKNOWN, UNKNOWN,
326 UNKNOWN, UNKNOWN,
helenyrwufd296b62016-06-22 17:43:02 -0700327 cid, false,
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700328 annotations);
329 deviceKeyAdminService.addKey(
330 DeviceKey.createDeviceKeyUsingUsernamePassword(
331 DeviceKeyId.deviceKeyId(deviceId.toString()),
332 null, addr.name(), addr.password()));
helenyrwufd296b62016-06-22 17:43:02 -0700333 if (deviceService.getDevice(deviceId) == null) {
334 providerService.deviceConnected(deviceId, deviceDescription);
335 }
336 checkAndUpdateDevice(deviceId, deviceDescription);
337 });
338 } catch (ConfigException e) {
339 log.error("Cannot read config error " + e);
340 }
341 }
342 }
343
344 private void checkAndUpdateDevice(DeviceId deviceId, DeviceDescription deviceDescription) {
345 if (deviceService.getDevice(deviceId) == null) {
346 log.warn("Device {} has not been added to store, " +
347 "maybe due to a problem in connectivity", deviceId);
348 } else {
349 boolean isReachable = isReachable(deviceId);
350 if (isReachable && !deviceService.isAvailable(deviceId)) {
Konstantinos Kanonakis4d67dd82016-08-05 12:18:52 -0500351 Device device = deviceService.getDevice(deviceId);
Konstantinos Kanonakis4d67dd82016-08-05 12:18:52 -0500352 if (device.is(DeviceDescriptionDiscovery.class)) {
353 if (mastershipService.isLocalMaster(deviceId)) {
354 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
355 device.as(DeviceDescriptionDiscovery.class);
Michele Santuari00cc1f72016-09-08 17:05:24 +0200356 DeviceDescription updatedDeviceDescription = deviceDescriptionDiscovery.discoverDeviceDetails();
357 if (updatedDeviceDescription != null &&
358 !descriptionEquals(device, updatedDeviceDescription)) {
359 providerService.deviceConnected(
360 deviceId, new DefaultDeviceDescription(
361 updatedDeviceDescription, true, updatedDeviceDescription.annotations()));
362 }
363 //if ports are not discovered, retry the discovery
364 if (deviceService.getPorts(deviceId).isEmpty()) {
365 discoverPorts(deviceId);
366 }
Konstantinos Kanonakis4d67dd82016-08-05 12:18:52 -0500367 }
368 } else {
369 log.warn("No DeviceDescriptionDiscovery behaviour for device {}", deviceId);
370 }
helenyrwufd296b62016-06-22 17:43:02 -0700371 } else if (!isReachable && deviceService.isAvailable(deviceId)) {
372 providerService.deviceDisconnected(deviceId);
373 }
374 }
375 }
376
Michele Santuari00cc1f72016-09-08 17:05:24 +0200377 private boolean descriptionEquals(Device device, DeviceDescription updatedDeviceDescription) {
378 return Objects.equal(device.id(), updatedDeviceDescription.deviceUri())
379 && Objects.equal(device.type(), updatedDeviceDescription.type())
380 && Objects.equal(device.manufacturer(), updatedDeviceDescription.manufacturer())
381 && Objects.equal(device.hwVersion(), updatedDeviceDescription.hwVersion())
382 && Objects.equal(device.swVersion(), updatedDeviceDescription.swVersion())
383 && Objects.equal(device.serialNumber(), updatedDeviceDescription.serialNumber())
384 && Objects.equal(device.chassisId(), updatedDeviceDescription.chassisId())
385 && Objects.equal(device.annotations(), updatedDeviceDescription.annotations());
386 }
387
helenyrwufd296b62016-06-22 17:43:02 -0700388 private void checkAndUpdateDevices() {
389 NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
390 if (cfg != null) {
391 log.info("Checking connection to devices in configuration");
392 try {
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700393 cfg.getDevicesAddresses().forEach(addr -> {
helenyrwufd296b62016-06-22 17:43:02 -0700394 DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
395 Preconditions.checkNotNull(deviceId, ISNULL);
396 //Netconf configuration object
397 ChassisId cid = new ChassisId();
398 String ipAddress = addr.ip().toString();
399 SparseAnnotations annotations = DefaultAnnotations.builder()
400 .set(IPADDRESS, ipAddress)
401 .set(PORT, String.valueOf(addr.port()))
402 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
403 .build();
404 DeviceDescription deviceDescription = new DefaultDeviceDescription(
405 deviceId.uri(),
406 Device.Type.SWITCH,
407 UNKNOWN, UNKNOWN,
408 UNKNOWN, UNKNOWN,
409 cid, false,
410 annotations);
411 deviceKeyAdminService.addKey(
412 DeviceKey.createDeviceKeyUsingUsernamePassword(
413 DeviceKeyId.deviceKeyId(deviceId.toString()),
414 null, addr.name(), addr.password()));
415 checkAndUpdateDevice(deviceId, deviceDescription);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700416 });
andreaeb70a942015-10-16 21:34:46 -0700417 } catch (ConfigException e) {
418 log.error("Cannot read config error " + e);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530419 }
420 }
andreaeb70a942015-10-16 21:34:46 -0700421 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530422
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700423 private void initiateConnection(DeviceId deviceId, MastershipRole newRole) {
424 try {
425 if (isReachable(deviceId)) {
426 controller.connectDevice(deviceId);
427 providerService.receivedRoleReply(deviceId, newRole, MastershipRole.MASTER);
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700428 }
429 } catch (Exception e) {
430 if (deviceService.getDevice(deviceId) != null) {
431 providerService.deviceDisconnected(deviceId);
432 }
433 deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(deviceId.toString()));
434 throw new RuntimeException(new NetconfException(
435 "Can't connect to NETCONF " + "device on " + deviceId + ":" + deviceId, e));
436
437 }
438 }
439
440 private void discoverPorts(DeviceId deviceId) {
441 Device device = deviceService.getDevice(deviceId);
Andrea Campanella6c71a052016-04-22 11:56:31 -0700442 //TODO remove when PortDiscovery is removed from master
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700443 if (device.is(PortDiscovery.class)) {
444 PortDiscovery portConfig = device.as(PortDiscovery.class);
445 providerService.updatePorts(deviceId,
446 portConfig.getPorts());
Andrea Campanella6c71a052016-04-22 11:56:31 -0700447 } else if (device.is(DeviceDescriptionDiscovery.class)) {
448 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
449 device.as(DeviceDescriptionDiscovery.class);
450 providerService.updatePorts(deviceId,
451 deviceDescriptionDiscovery.discoverPortDetails());
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700452 } else {
453 log.warn("No portGetter behaviour for device {}", deviceId);
454 }
455 }
456
457 /**
458 * Return the DeviceId about the device containing the URI.
459 *
Andrea Campanella6c71a052016-04-22 11:56:31 -0700460 * @param ip IP address
Ray Milkeyd4334db2016-04-05 17:39:44 -0700461 * @param port port number
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700462 * @return DeviceId
463 */
464 public DeviceId getDeviceId(String ip, int port) {
465 try {
466 return DeviceId.deviceId(new URI(NETCONF, ip + ":" + port, null));
467 } catch (URISyntaxException e) {
468 throw new IllegalArgumentException("Unable to build deviceID for device "
469 + ip + ":" + port, e);
470 }
471 }
472
473 /**
474 * Listener for configuration events.
475 */
andreaeb70a942015-10-16 21:34:46 -0700476 private class InternalNetworkConfigListener implements NetworkConfigListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530477
andreaeb70a942015-10-16 21:34:46 -0700478
479 @Override
480 public void event(NetworkConfigEvent event) {
Andrea Campanella90f044f2016-03-02 09:14:57 -0800481 executor.execute(NetconfDeviceProvider.this::connectDevices);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530482 }
483
andreaeb70a942015-10-16 21:34:46 -0700484 @Override
485 public boolean isRelevant(NetworkConfigEvent event) {
andreaeb70a942015-10-16 21:34:46 -0700486 return event.configClass().equals(NetconfProviderConfig.class) &&
487 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
488 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530489 }
490 }
Andrea Campanella7e6200a2016-03-21 09:48:40 -0700491
492 /**
493 * Listener for core device events.
494 */
495 private class InternalDeviceListener implements DeviceListener {
496 @Override
497 public void event(DeviceEvent event) {
498 if ((event.type() == DeviceEvent.Type.DEVICE_ADDED)) {
499 executor.execute(() -> discoverPorts(event.subject().id()));
500 } else if ((event.type() == DeviceEvent.Type.DEVICE_REMOVED)) {
501 log.debug("removing device {}", event.subject().id());
502 deviceService.getDevice(event.subject().id()).annotations().keys();
503 controller.disconnectDevice(event.subject().id(), true);
504 }
505 }
506
507 @Override
508 public boolean isRelevant(DeviceEvent event) {
509 if (mastershipService.getMasterFor(event.subject().id()) == null) {
510 return true;
511 }
512 return event.subject().annotations().value(AnnotationKeys.PROTOCOL)
513 .equals(SCHEME_NAME.toUpperCase()) &&
514 mastershipService.getMasterFor(event.subject().id()).equals(localNodeId);
515 }
516 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530517}