blob: 093d0c16f6b7f3c730c1cf1722cf802f56dc0902 [file] [log] [blame]
sanghoshinf25d2e02015-11-11 23:07:17 +09001/*
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 */
sangho0c2a3da2016-02-16 13:39:07 +090016package org.onosproject.openstacknetworking.web;
sanghoshinf25d2e02015-11-11 23:07:17 +090017
18import com.fasterxml.jackson.databind.ObjectMapper;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import com.google.common.collect.Lists;
22import com.sun.jersey.api.client.Client;
23import com.sun.jersey.api.client.WebResource;
sangho0c2a3da2016-02-16 13:39:07 +090024import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
27import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.apache.felix.scr.annotations.Service;
30import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
32import org.onosproject.net.Port;
33import org.onosproject.net.driver.DriverService;
34import org.onosproject.openstacknetworking.OpenstackNetwork;
35import org.onosproject.openstacknetworking.OpenstackNetworkingService;
36import org.onosproject.openstacknetworking.OpenstackPort;
37import org.onosproject.openstacknetworking.OpenstackPortInfo;
38import org.onosproject.openstacknetworking.OpenstackRouter;
39import org.onosproject.openstacknetworking.OpenstackSecurityGroup;
40import org.onosproject.openstacknetworking.OpenstackSubnet;
41import org.onosproject.openstacknetworking.OpenstackSwitchingService;
sanghoshinf25d2e02015-11-11 23:07:17 +090042import org.slf4j.Logger;
43import javax.ws.rs.core.MediaType;
44import java.io.IOException;
45import java.util.Collection;
Hyunsun Moonf7895202016-01-12 12:21:48 -080046import java.util.Collections;
sanghoshinf25d2e02015-11-11 23:07:17 +090047import java.util.List;
sangho0c2a3da2016-02-16 13:39:07 +090048import java.util.Map;
49import java.util.stream.Collectors;
sanghoshinf25d2e02015-11-11 23:07:17 +090050
51import static com.google.common.base.Preconditions.checkNotNull;
52import static com.google.common.net.MediaType.JSON_UTF_8;
53import static org.slf4j.LoggerFactory.getLogger;
54
55/**
56 * Handles REST Calls to Openstack Neutron.
57 *
58 */
sangho0c2a3da2016-02-16 13:39:07 +090059@Service
60@Component(immediate = true)
61public class OpenstackNetworkingManager implements OpenstackNetworkingService {
sanghoshinf25d2e02015-11-11 23:07:17 +090062
sangho5db8e052016-01-29 16:08:23 +090063 private static final String URI_NETWORKS = "networks";
64 private static final String URI_PORTS = "ports";
65 private static final String URI_SUBNETS = "subnets";
66 private static final String URI_SECURITY_GROUPS = "security-groups";
67 private static final String URI_TOKENS = "tokens";
68
Daniel Park3a06c522016-01-28 20:51:12 +090069 private static final String PATH_ROUTERS = "routers";
sangho5db8e052016-01-29 16:08:23 +090070 private static final String PATH_NETWORKS = "networks";
71 private static final String PATH_PORTS = "ports";
72 private static final String PATH_SUBNETS = "subnets";
73 private static final String PATH_ACCESS = "access";
74 private static final String PATH_TOKEN = "token";
75 private static final String PATH_ID = "id";
76
77 private static final String HEADER_AUTH_TOKEN = "X-Auth-Token";
78
sanghoshinf25d2e02015-11-11 23:07:17 +090079 private final Logger log = getLogger(getClass());
80 private String neutronUrl;
81 private String keystoneUrl;
82 private String tokenId;
83 private String userName;
84 private String pass;
85
sangho0c2a3da2016-02-16 13:39:07 +090086 private static final String PORT_NAME = "portName";
87
88 private ApplicationId appId;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected CoreService coreService;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected DriverService driverService;
95
96 protected OpenstackSwitchingService openstackSwitchingService;
97
98 @Activate
99 protected void activate() {
100 appId = coreService
101 .registerApplication("org.onosproject.openstacknetworking");
102
103 log.info("started");
104 }
105
106 @Deactivate
107 protected void deactivate() {
108 log.info("stopped");
sanghoshinf25d2e02015-11-11 23:07:17 +0900109 }
110
111 /**
112 * Returns network information stored in Neutron.
113 *
114 * @return List of OpenstackNetwork
115 */
116 public Collection<OpenstackNetwork> getNetworks() {
117
sangho5db8e052016-01-29 16:08:23 +0900118 WebResource.Builder builder = getClientBuilder(neutronUrl + URI_NETWORKS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900119 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
sangho5db8e052016-01-29 16:08:23 +0900120 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
sanghoshinf25d2e02015-11-11 23:07:17 +0900121
Hyunsun Moonf7895202016-01-12 12:21:48 -0800122 log.debug("networks response:" + response);
123
sanghoshinf25d2e02015-11-11 23:07:17 +0900124 ObjectMapper mapper = new ObjectMapper();
125 List<OpenstackNetwork> openstackNetworks = Lists.newArrayList();
126 try {
127 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900128 ArrayNode networkList = (ArrayNode) node.path(PATH_NETWORKS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900129 OpenstackNetworkCodec networkCodec = new OpenstackNetworkCodec();
130 networkList.forEach(n -> openstackNetworks.add(networkCodec.decode((ObjectNode) n, null)));
131 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800132 log.warn("getNetworks()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900133 }
134
Hyunsun Moonf7895202016-01-12 12:21:48 -0800135 openstackNetworks.removeAll(Collections.singleton(null));
sanghoshinf25d2e02015-11-11 23:07:17 +0900136 openstackNetworks.forEach(n -> log.debug("network ID: {}", n.id()));
137
138 return openstackNetworks;
139 }
140
141 /**
142 * Returns port information stored in Neutron.
143 *
144 * @return List of OpenstackPort
145 */
146 public Collection<OpenstackPort> getPorts() {
147
sangho5db8e052016-01-29 16:08:23 +0900148 WebResource.Builder builder = getClientBuilder(neutronUrl + URI_PORTS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900149 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
sangho5db8e052016-01-29 16:08:23 +0900150 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
sanghoshinf25d2e02015-11-11 23:07:17 +0900151
152 ObjectMapper mapper = new ObjectMapper();
153 List<OpenstackPort> openstackPorts = Lists.newArrayList();
154 try {
155 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900156 ArrayNode portList = (ArrayNode) node.path(PATH_PORTS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900157 OpenstackPortCodec portCodec = new OpenstackPortCodec();
158 portList.forEach(p -> openstackPorts.add(portCodec.decode((ObjectNode) p, null)));
159 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800160 log.warn("getPorts()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900161 }
162
163 log.debug("port response:" + response);
164 openstackPorts.forEach(n -> log.debug("port ID: {}", n.id()));
165
166 return openstackPorts;
167 }
168
Daniel Park3a06c522016-01-28 20:51:12 +0900169 public Collection<OpenstackRouter> getRouters() {
170 WebResource.Builder builder = getClientBuilder(neutronUrl + PATH_ROUTERS);
171 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
172 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
173
174 ObjectMapper mapper = new ObjectMapper();
175 List<OpenstackRouter> openstackRouters = Lists.newArrayList();
176
177 try {
178 ObjectNode node = (ObjectNode) mapper.readTree(response);
179 ArrayNode routerList = (ArrayNode) node.path(PATH_ROUTERS);
180 OpenstackRouterCodec openstackRouterCodec = new OpenstackRouterCodec();
181 routerList.forEach(r -> openstackRouters
182 .add(openstackRouterCodec.decode((ObjectNode) r, null)));
183 } catch (IOException e) {
184 log.warn("getRouters()", e);
185 }
186
187 log.debug("router response:" + response);
188 openstackRouters.forEach(r -> log.debug("router ID: {}", r.id()));
189
190 return openstackRouters;
191 }
192
sanghoshinf25d2e02015-11-11 23:07:17 +0900193 /**
194 * Returns Subnet information in Neutron.
195 *
196 * @return List of OpenstackSubnet
197 */
198 public Collection<OpenstackSubnet> getSubnets() {
199
sangho5db8e052016-01-29 16:08:23 +0900200 WebResource.Builder builder = getClientBuilder(neutronUrl + URI_SUBNETS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900201 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
sangho5db8e052016-01-29 16:08:23 +0900202 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
sanghoshinf25d2e02015-11-11 23:07:17 +0900203
204 ObjectMapper mapper = new ObjectMapper();
205 List<OpenstackSubnet> subnets = Lists.newArrayList();
206 try {
207 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900208 ArrayNode subnetList = (ArrayNode) node.path(PATH_SUBNETS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900209 OpenstackSubnetCodec subnetCodec = new OpenstackSubnetCodec();
210 subnetList.forEach(s -> subnets.add(subnetCodec.decode((ObjectNode) s, null)));
211 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800212 log.warn("getSubnets()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900213 }
214
215 log.debug("subnets response:" + response);
216 subnets.forEach(s -> log.debug("subnet ID: {}", s.id()));
217
218 return subnets;
219 }
220
sangho5db8e052016-01-29 16:08:23 +0900221 /**
222 * Extracts OpenstackSecurityGroup information for the ID.
223 *
224 * @param id Security Group ID
225 * @return OpenstackSecurityGroup object or null if fails
226 */
227 public OpenstackSecurityGroup getSecurityGroup(String id) {
228 WebResource.Builder builder = getClientBuilder(neutronUrl + URI_SECURITY_GROUPS + "/" + id);
229 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
230 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
231
232 ObjectMapper mapper = new ObjectMapper();
233 OpenstackSecurityGroup securityGroup = null;
234 try {
235 ObjectNode node = (ObjectNode) mapper.readTree(response);
236 OpenstackSecurityGroupCodec sgCodec = new OpenstackSecurityGroupCodec();
237 securityGroup = sgCodec.decode(node, null);
238 } catch (IOException e) {
239 log.warn("getSecurityGroup()", e);
240 }
241
242 return securityGroup;
243 }
244
sanghoshinf25d2e02015-11-11 23:07:17 +0900245 private WebResource.Builder getClientBuilder(String uri) {
246 Client client = Client.create();
247 WebResource resource = client.resource(uri);
248 return resource.accept(JSON_UTF_8.toString())
249 .type(JSON_UTF_8.toString());
250 }
251
252 private String getToken() {
253 if (isTokenInvalid()) {
254 String request = "{\"auth\": {\"tenantName\": \"admin\", " +
255 "\"passwordCredentials\": {\"username\": \"" +
256 userName + "\",\"password\": \"" + pass + "\"}}}";
sangho5db8e052016-01-29 16:08:23 +0900257 WebResource.Builder builder = getClientBuilder(keystoneUrl + URI_TOKENS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900258 String response = builder.accept(MediaType.APPLICATION_JSON).post(String.class, request);
259
260 ObjectMapper mapper = new ObjectMapper();
261 try {
262 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900263 tokenId = node.path(PATH_ACCESS).path(PATH_TOKEN).path(PATH_ID).asText();
sanghoshinf25d2e02015-11-11 23:07:17 +0900264 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800265 log.warn("getToken()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900266 }
267 log.debug("token response:" + response);
268 }
269
270 return tokenId;
271 }
272
273 private boolean isTokenInvalid() {
274 //TODO: validation check for the existing token
275 return true;
276 }
277
sangho0c2a3da2016-02-16 13:39:07 +0900278 @Override
279 public Collection<OpenstackPort> ports(String networkId) {
280 return getPorts().stream()
281 .filter(port -> port.networkId().equals(networkId))
282 .collect(Collectors.toList());
283 }
284
285 @Override
286 public Collection<OpenstackPort> ports() {
287 return getPorts();
288 }
289
290 @Override
291 public OpenstackPort port(Port port) {
292 String uuid = port.annotations().value(PORT_NAME).substring(3);
293 return getPorts().stream()
294 .filter(p -> p.id().startsWith(uuid))
295 .findAny().orElse(null);
296 }
297
298 @Override
299 public OpenstackPort port(String portId) {
300 return getPorts().stream()
301 .filter(p -> p.id().equals(portId))
302 .findAny().orElse(null);
303 }
304
305 @Override
306 public OpenstackNetwork network(String networkId) {
307 return getNetworks().stream()
308 .filter(n -> n.id().equals(networkId))
309 .findAny().orElse(null);
310 }
311
312 @Override
313 public Collection<OpenstackNetwork> networks() {
314 return getNetworks();
315 }
316
317 @Override
318 public OpenstackSubnet subnet(String subnetId) {
319 return getSubnets().stream()
320 .filter(subnet -> subnet.id().equals(subnetId))
321 .findAny().orElse(null);
322 }
323
324 @Override
325 public Collection<OpenstackSubnet> subnets() {
326 return getSubnets();
327 }
328
329 @Override
330 public Collection<OpenstackRouter> routers() {
331 return getRouters();
332 }
333
334 @Override
335 public OpenstackRouter router(String routerId) {
336 return getRouters().stream()
337 .filter(router -> router.id().equals(routerId))
338 .findAny().orElse(null);
339 }
340
341 @Override
342 public Map<String, OpenstackPortInfo> openstackPortInfo() {
343 return openstackSwitchingService.openstackPortInfo();
344 }
345
346 @Override
347 public void setConfigurations(String neutronUrl, String keystoneUrl, String userName, String pass) {
348 this.neutronUrl = checkNotNull(neutronUrl);
349 this.keystoneUrl = checkNotNull(keystoneUrl);
350 this.userName = checkNotNull(userName);
351 this.pass = checkNotNull(pass);
352 }
353}