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