blob: 35bb28895a1ebf4d486818a056d7b4583ee87b3b [file] [log] [blame]
Sanjay Se8dcfee2015-04-23 10:07:08 +05301/*
2 * Copyright 2015 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 */
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;
andreaeb70a942015-10-16 21:34:46 -070026import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
28import org.onosproject.incubator.net.config.basics.ConfigException;
Marc De Leenheerb0d131c2016-03-01 20:34:59 -080029import org.onosproject.net.AnnotationKeys;
andreaeb70a942015-10-16 21:34:46 -070030import org.onosproject.net.DefaultAnnotations;
Sanjay Se8dcfee2015-04-23 10:07:08 +053031import org.onosproject.net.Device;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.MastershipRole;
andreaeb70a942015-10-16 21:34:46 -070034import org.onosproject.net.SparseAnnotations;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080035import org.onosproject.net.behaviour.PortDiscovery;
andreaeb70a942015-10-16 21:34:46 -070036import org.onosproject.net.config.ConfigFactory;
37import org.onosproject.net.config.NetworkConfigEvent;
38import org.onosproject.net.config.NetworkConfigListener;
39import org.onosproject.net.config.NetworkConfigRegistry;
Sanjay Se8dcfee2015-04-23 10:07:08 +053040import org.onosproject.net.device.DefaultDeviceDescription;
41import org.onosproject.net.device.DeviceDescription;
42import org.onosproject.net.device.DeviceProvider;
43import org.onosproject.net.device.DeviceProviderRegistry;
44import org.onosproject.net.device.DeviceProviderService;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080045import org.onosproject.net.device.DeviceService;
46import org.onosproject.net.driver.DriverService;
Sanjay Se8dcfee2015-04-23 10:07:08 +053047import org.onosproject.net.provider.AbstractProvider;
48import org.onosproject.net.provider.ProviderId;
andreaeb70a942015-10-16 21:34:46 -070049import org.onosproject.netconf.NetconfController;
50import org.onosproject.netconf.NetconfDevice;
51import org.onosproject.netconf.NetconfDeviceInfo;
52import org.onosproject.netconf.NetconfDeviceListener;
Andrea Campanella8b1cb672016-01-25 13:58:58 -080053import org.onosproject.netconf.NetconfException;
Sanjay Se8dcfee2015-04-23 10:07:08 +053054import org.slf4j.Logger;
55
Andrea Campanella087ceb92015-12-07 09:58:34 -080056import java.io.IOException;
Andrea Campanella5c999e22016-03-01 15:12:53 -080057import java.util.concurrent.ExecutorService;
58import java.util.concurrent.Executors;
andreaeb70a942015-10-16 21:34:46 -070059
Andrea Campanella5c999e22016-03-01 15:12:53 -080060import static org.onlab.util.Tools.groupedThreads;
andreaeb70a942015-10-16 21:34:46 -070061import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
62import static org.slf4j.LoggerFactory.getLogger;
63
Sanjay Se8dcfee2015-04-23 10:07:08 +053064/**
andreaeb70a942015-10-16 21:34:46 -070065 * Provider which uses an NETCONF controller to detect device.
Sanjay Se8dcfee2015-04-23 10:07:08 +053066 */
67@Component(immediate = true)
68public class NetconfDeviceProvider extends AbstractProvider
69 implements DeviceProvider {
andreaeb70a942015-10-16 21:34:46 -070070 private final Logger log = getLogger(getClass());
Sanjay Se8dcfee2015-04-23 10:07:08 +053071
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected DeviceProviderRegistry providerRegistry;
74
andreaeb70a942015-10-16 21:34:46 -070075 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella101417d2015-12-11 17:58:07 -080076 protected NetconfController controller;
Sanjay Se8dcfee2015-04-23 10:07:08 +053077
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -070079 protected NetworkConfigRegistry cfgService;
Sanjay Se8dcfee2015-04-23 10:07:08 +053080
Thomas Vachuskad6811712015-04-29 21:37:04 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
andreaeb70a942015-10-16 21:34:46 -070082 protected CoreService coreService;
Thomas Vachuskad6811712015-04-29 21:37:04 -070083
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080084 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected DriverService driverService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected DeviceService deviceService;
89
Andrea Campanella101417d2015-12-11 17:58:07 -080090 private static final String APP_NAME = "org.onosproject.netconf";
91 private static final String SCHEME_NAME = "netconf";
92 private static final String DEVICE_PROVIDER_PACKAGE = "org.onosproject.netconf.provider.device";
93 private static final String UNKNOWN = "unknown";
Sanjay Se8dcfee2015-04-23 10:07:08 +053094
Andrea Campanella5c999e22016-03-01 15:12:53 -080095 private final ExecutorService executor =
Andrea Campanella90f044f2016-03-02 09:14:57 -080096 Executors.newFixedThreadPool(5, groupedThreads("onos/netconfdeviceprovider", "device-installer-%d", log));
Andrea Campanella5c999e22016-03-01 15:12:53 -080097
andreaeb70a942015-10-16 21:34:46 -070098 private DeviceProviderService providerService;
99 private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener();
Sanjay Se8dcfee2015-04-23 10:07:08 +0530100
andreaeb70a942015-10-16 21:34:46 -0700101 private final ConfigFactory factory =
102 new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY,
103 NetconfProviderConfig.class,
104 "devices",
105 true) {
106 @Override
107 public NetconfProviderConfig createConfig() {
108 return new NetconfProviderConfig();
109 }
110 };
111 private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener();
112 private ApplicationId appId;
Sanjay Se8dcfee2015-04-23 10:07:08 +0530113
Sanjay Se8dcfee2015-04-23 10:07:08 +0530114
115 @Activate
andreaeb70a942015-10-16 21:34:46 -0700116 public void activate() {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530117 providerService = providerRegistry.register(this);
Andrea Campanella101417d2015-12-11 17:58:07 -0800118 appId = coreService.registerApplication(APP_NAME);
andreaeb70a942015-10-16 21:34:46 -0700119 cfgService.registerConfigFactory(factory);
120 cfgService.addListener(cfgLister);
121 controller.addDeviceListener(innerNodeListener);
Andrea Campanella7d8449b2016-03-02 10:16:42 -0800122 executor.execute(NetconfDeviceProvider.this::connectDevices);
Thomas Vachuskad6811712015-04-29 21:37:04 -0700123 log.info("Started");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530124 }
125
andreaeb70a942015-10-16 21:34:46 -0700126
Sanjay Se8dcfee2015-04-23 10:07:08 +0530127 @Deactivate
andreaeb70a942015-10-16 21:34:46 -0700128 public void deactivate() {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530129 providerRegistry.unregister(this);
130 providerService = null;
andreaeb70a942015-10-16 21:34:46 -0700131 cfgService.unregisterConfigFactory(factory);
Andrea Campanella101417d2015-12-11 17:58:07 -0800132 controller.removeDeviceListener(innerNodeListener);
Sanjay Seb5eebb2015-04-24 15:44:50 +0530133 log.info("Stopped");
Sanjay Se8dcfee2015-04-23 10:07:08 +0530134 }
135
andreaeb70a942015-10-16 21:34:46 -0700136 public NetconfDeviceProvider() {
Andrea Campanella101417d2015-12-11 17:58:07 -0800137 super(new ProviderId(SCHEME_NAME, DEVICE_PROVIDER_PACKAGE));
Sanjay Se8dcfee2015-04-23 10:07:08 +0530138 }
139
140 @Override
141 public void triggerProbe(DeviceId deviceId) {
andreaeb70a942015-10-16 21:34:46 -0700142 // TODO: This will be implemented later.
143 log.info("Triggering probe on device {}", deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530144 }
145
146 @Override
147 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
andreaeb70a942015-10-16 21:34:46 -0700148 // TODO: This will be implemented later.
Sanjay Se8dcfee2015-04-23 10:07:08 +0530149 }
150
151 @Override
152 public boolean isReachable(DeviceId deviceId) {
Andrea Campanella8e290c52016-01-12 15:54:50 -0800153 NetconfDevice netconfDevice = controller.getNetconfDevice(deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530154 if (netconfDevice == null) {
Andrea Campanellad264b492016-03-01 09:46:06 -0800155 log.debug("Requested device id: {} is not associated to any " +
156 "NETCONF Device", deviceId.toString());
Sanjay Se8dcfee2015-04-23 10:07:08 +0530157 return false;
158 }
andreaeb70a942015-10-16 21:34:46 -0700159 return netconfDevice.isActive();
Sanjay Se8dcfee2015-04-23 10:07:08 +0530160 }
161
andreaeb70a942015-10-16 21:34:46 -0700162 private class InnerNetconfDeviceListener implements NetconfDeviceListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530163
Andrea Campanella101417d2015-12-11 17:58:07 -0800164 private static final String IPADDRESS = "ipaddress";
165 protected static final String ISNULL = "NetconfDeviceInfo is null";
166
andreaeb70a942015-10-16 21:34:46 -0700167 @Override
168 public void deviceAdded(NetconfDeviceInfo nodeId) {
Andrea Campanella101417d2015-12-11 17:58:07 -0800169 Preconditions.checkNotNull(nodeId, ISNULL);
andreaeb70a942015-10-16 21:34:46 -0700170 DeviceId deviceId = nodeId.getDeviceId();
andreaeb70a942015-10-16 21:34:46 -0700171 //Netconf configuration object
172 ChassisId cid = new ChassisId();
173 String ipAddress = nodeId.ip().toString();
174 SparseAnnotations annotations = DefaultAnnotations.builder()
Marc De Leenheerb0d131c2016-03-01 20:34:59 -0800175 .set(IPADDRESS, ipAddress)
176 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
177 .build();
andreaeb70a942015-10-16 21:34:46 -0700178 DeviceDescription deviceDescription = new DefaultDeviceDescription(
179 deviceId.uri(),
180 Device.Type.SWITCH,
181 UNKNOWN, UNKNOWN,
182 UNKNOWN, UNKNOWN,
183 cid,
184 annotations);
185 providerService.deviceConnected(deviceId, deviceDescription);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530186 }
187
188 @Override
andreaeb70a942015-10-16 21:34:46 -0700189 public void deviceRemoved(NetconfDeviceInfo nodeId) {
Andrea Campanella101417d2015-12-11 17:58:07 -0800190 Preconditions.checkNotNull(nodeId, ISNULL);
andreaeb70a942015-10-16 21:34:46 -0700191 DeviceId deviceId = nodeId.getDeviceId();
192 providerService.deviceDisconnected(deviceId);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530193
andreaeb70a942015-10-16 21:34:46 -0700194 }
195 }
196
andreaeb70a942015-10-16 21:34:46 -0700197 private void connectDevices() {
198 NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
199 if (cfg != null) {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530200 try {
Andrea Campanella087ceb92015-12-07 09:58:34 -0800201 cfg.getDevicesAddresses().stream()
202 .forEach(addr -> {
203 try {
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800204 NetconfDeviceInfo netconf = new NetconfDeviceInfo(addr.name(),
205 addr.password(),
206 addr.ip(),
207 addr.port());
208 controller.connectDevice(netconf);
209 Device device = deviceService.getDevice(netconf.getDeviceId());
210 if (device.is(PortDiscovery.class)) {
211 PortDiscovery portConfig = device.as(PortDiscovery.class);
212 if (portConfig != null) {
213 providerService.updatePorts(netconf.getDeviceId(),
214 portConfig.getPorts());
215 }
216 } else {
217 log.warn("No portGetter behaviour for device {}", netconf.getDeviceId());
218 }
219
Andrea Campanella087ceb92015-12-07 09:58:34 -0800220 } catch (IOException e) {
Andrea Campanella8b1cb672016-01-25 13:58:58 -0800221 throw new RuntimeException(
222 new NetconfException(
223 "Can't connect to NETCONF " +
224 "device on " + addr.ip() +
225 ":" + addr.port(), e));
Andrea Campanella087ceb92015-12-07 09:58:34 -0800226 }
227 }
228 );
229
andreaeb70a942015-10-16 21:34:46 -0700230 } catch (ConfigException e) {
231 log.error("Cannot read config error " + e);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530232 }
233 }
andreaeb70a942015-10-16 21:34:46 -0700234 }
Sanjay Se8dcfee2015-04-23 10:07:08 +0530235
andreaeb70a942015-10-16 21:34:46 -0700236 private class InternalNetworkConfigListener implements NetworkConfigListener {
Sanjay Se8dcfee2015-04-23 10:07:08 +0530237
andreaeb70a942015-10-16 21:34:46 -0700238
239 @Override
240 public void event(NetworkConfigEvent event) {
Andrea Campanella90f044f2016-03-02 09:14:57 -0800241 executor.execute(NetconfDeviceProvider.this::connectDevices);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530242 }
243
andreaeb70a942015-10-16 21:34:46 -0700244 @Override
245 public boolean isRelevant(NetworkConfigEvent event) {
246 //TODO refactor
247 return event.configClass().equals(NetconfProviderConfig.class) &&
248 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
249 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
Sanjay Se8dcfee2015-04-23 10:07:08 +0530250 }
251 }
252}