blob: 76f5abdb5a7bb2d13551441cdb2281a17fb09e91 [file] [log] [blame]
Andrea Campanella945ded22016-01-07 13:17:43 -08001/*
2 * Copyright 2016 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 */
16
17package org.onosproject.provider.rest.device.impl;
18
19import com.google.common.base.Preconditions;
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.onlab.packet.ChassisId;
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
28import org.onosproject.incubator.net.config.basics.ConfigException;
29import org.onosproject.net.DefaultAnnotations;
30import org.onosproject.net.Device;
31import org.onosproject.net.DeviceId;
32import org.onosproject.net.MastershipRole;
33import org.onosproject.net.SparseAnnotations;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080034import org.onosproject.net.behaviour.PortDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -080035import org.onosproject.net.config.ConfigFactory;
36import org.onosproject.net.config.NetworkConfigEvent;
37import org.onosproject.net.config.NetworkConfigListener;
38import org.onosproject.net.config.NetworkConfigRegistry;
39import org.onosproject.net.device.DefaultDeviceDescription;
40import org.onosproject.net.device.DeviceDescription;
41import org.onosproject.net.device.DeviceProvider;
42import org.onosproject.net.device.DeviceProviderRegistry;
43import org.onosproject.net.device.DeviceProviderService;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080044import org.onosproject.net.driver.DriverHandler;
45import org.onosproject.net.driver.DriverService;
Andrea Campanella945ded22016-01-07 13:17:43 -080046import org.onosproject.net.provider.AbstractProvider;
47import org.onosproject.net.provider.ProviderId;
48import org.onosproject.protocol.rest.RestSBController;
49import org.onosproject.protocol.rest.RestSBDevice;
50import org.slf4j.Logger;
51
52import java.io.IOException;
53import java.net.HttpURLConnection;
54import java.net.URL;
55import java.util.HashSet;
Andrea Campanella945ded22016-01-07 13:17:43 -080056import java.util.Set;
57
58import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
59import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
60import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
61import static org.slf4j.LoggerFactory.getLogger;
62
63/**
64 * Provider for devices that use REST as means of configuration communication.
65 */
66@Component(immediate = true)
67public class RestDeviceProvider extends AbstractProvider
68 implements DeviceProvider {
69 private static final String APP_NAME = "org.onosproject.restsb";
70 private static final String REST = "rest";
71 private static final String PROVIDER = "org.onosproject.provider.rest.device";
72 private static final String IPADDRESS = "ipaddress";
73 private static final int TEST_CONNECT_TIMEOUT = 1000;
74 private final Logger log = getLogger(getClass());
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected DeviceProviderRegistry providerRegistry;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected RestSBController controller;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected NetworkConfigRegistry cfgService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected CoreService coreService;
87
Andrea Campanellad8d92db2016-01-14 16:24:41 -080088 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected DriverService driverService;
90
Andrea Campanella945ded22016-01-07 13:17:43 -080091
92 private DeviceProviderService providerService;
93 protected static final String ISNOTNULL = "Rest device is not null";
94 private static final String UNKNOWN = "unknown";
95
96 private final ConfigFactory factory =
97 new ConfigFactory<ApplicationId, RestProviderConfig>(APP_SUBJECT_FACTORY,
98 RestProviderConfig.class,
99 "restDevices",
100 true) {
101 @Override
102 public RestProviderConfig createConfig() {
103 return new RestProviderConfig();
104 }
105 };
106 private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener();
107 private ApplicationId appId;
108
109
110 @Activate
111 public void activate() {
112 appId = coreService.registerApplication(APP_NAME);
113 providerService = providerRegistry.register(this);
114 cfgService.registerConfigFactory(factory);
115 cfgService.addListener(cfgLister);
116 connectDevices();
117 log.info("Started");
118 }
119
120
121 @Deactivate
122 public void deactivate() {
123 providerRegistry.unregister(this);
124 providerService = null;
125 cfgService.unregisterConfigFactory(factory);
126 cfgService.removeListener(cfgLister);
127 log.info("Stopped");
128 }
129
130 public RestDeviceProvider() {
131 super(new ProviderId(REST, PROVIDER));
132 }
133
134 @Override
135 public void triggerProbe(DeviceId deviceId) {
136 // TODO: This will be implemented later.
137 log.info("Triggering probe on device {}", deviceId);
138 }
139
140 @Override
141 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
142 // TODO: This will be implemented later.
143 }
144
145
146 @Override
147 public boolean isReachable(DeviceId deviceId) {
148 RestSBDevice restDevice = controller.getDevice(deviceId);
149 if (restDevice == null) {
150 log.warn("BAD REQUEST: the requested device id: " +
151 deviceId.toString() +
152 " is not associated to any REST Device");
153 return false;
154 }
155 return restDevice.isActive();
156 }
157
158 private void deviceAdded(RestSBDevice nodeId) {
159 Preconditions.checkNotNull(nodeId, ISNOTNULL);
160 DeviceId deviceId = nodeId.deviceId();
161 ChassisId cid = new ChassisId();
162 String ipAddress = nodeId.ip().toString();
163 SparseAnnotations annotations = DefaultAnnotations.builder()
164 .set(IPADDRESS, ipAddress).build();
165 DeviceDescription deviceDescription = new DefaultDeviceDescription(
166 deviceId.uri(),
167 Device.Type.SWITCH,
168 UNKNOWN, UNKNOWN,
169 UNKNOWN, UNKNOWN,
170 cid,
171 annotations);
172 providerService.deviceConnected(deviceId, deviceDescription);
173 nodeId.setActive(true);
174 controller.addDevice(nodeId);
175 }
176
Andrea Campanella945ded22016-01-07 13:17:43 -0800177 //when do I call it ?
178 public void deviceRemoved(RestSBDevice nodeId) {
179 Preconditions.checkNotNull(nodeId, ISNOTNULL);
180 DeviceId deviceId = nodeId.deviceId();
181 providerService.deviceDisconnected(deviceId);
182 controller.removeDevice(nodeId);
183 }
184
185 private void connectDevices() {
186 RestProviderConfig cfg = cfgService.getConfig(appId, RestProviderConfig.class);
187 try {
188 if (cfg != null && cfg.getDevicesAddresses() != null) {
189 //Precomputing the devices to be removed
190 Set<RestSBDevice> toBeRemoved = new HashSet<>(controller.getDevices().values());
191 toBeRemoved.removeAll(cfg.getDevicesAddresses());
192 //Adding new devices
193 cfg.getDevicesAddresses().stream()
194 .filter(device -> testDeviceConnection(device))
195 .forEach(device -> {
196 deviceAdded(device);
197 });
198 //Removing devices not wanted anymore
199 toBeRemoved.stream().forEach(device -> deviceRemoved(device));
200
201 }
202 } catch (ConfigException e) {
203 log.error("Configuration error {}", e);
204 }
205 log.info("REST Devices {}", controller.getDevices());
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800206 controller.getDevices().keySet().forEach(deviceId -> {
207 DriverHandler h = driverService.createHandler(deviceId);
208 PortDiscovery portConfig = h.behaviour(PortDiscovery.class);
209 if (portConfig != null) {
210 providerService.updatePorts(deviceId, portConfig.getPorts());
211 } else {
212 log.warn("No portGetter behaviour for device {}", deviceId);
213 }
214 });
Andrea Campanella945ded22016-01-07 13:17:43 -0800215 }
216
217 private boolean testDeviceConnection(RestSBDevice device) {
218 try {
219 URL url = new URL(device.protocol(), device.ip().toString(), device.port(), "/");
220 HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
221 urlConn.setConnectTimeout(TEST_CONNECT_TIMEOUT);
222 boolean open = urlConn.getResponseCode() == (HttpURLConnection.HTTP_OK);
223 urlConn.disconnect();
224 return open;
225 } catch (IOException e) {
226 log.error("Device {} not reachable, error creating HTTP connection", device, e);
227 }
228 return false;
229 }
230
231 private class InternalNetworkConfigListener implements NetworkConfigListener {
232
233
234 @Override
235 public void event(NetworkConfigEvent event) {
236 connectDevices();
237 }
238
239 @Override
240 public boolean isRelevant(NetworkConfigEvent event) {
241 //TODO refactor
242 return event.configClass().equals(RestProviderConfig.class) &&
243 (event.type() == CONFIG_ADDED ||
244 event.type() == CONFIG_UPDATED);
245 }
246 }
247}