blob: 1eef7c88a6f19c31c4e890e890f64f737454ba3d [file] [log] [blame]
sanghoshinf25d2e02015-11-11 23:07:17 +09001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
sanghoshinf25d2e02015-11-11 23:07:17 +09003 *
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 */
Hyunsun Moon0dba61f2016-03-03 14:05:21 -080016package org.onosproject.openstackinterface.impl;
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;
Hyunsun Moonef6bad22016-07-19 16:25:43 -070021import com.google.common.base.Strings;
sangho93447f12016-02-24 00:33:22 +090022import com.google.common.collect.ImmutableSet;
sanghoshinf25d2e02015-11-11 23:07:17 +090023import com.google.common.collect.Lists;
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;
Hyunsun Moonef6bad22016-07-19 16:25:43 -070030import org.glassfish.jersey.client.ClientProperties;
sangho0c2a3da2016-02-16 13:39:07 +090031import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
33import org.onosproject.net.Port;
sangho93447f12016-02-24 00:33:22 +090034import org.onosproject.net.config.ConfigFactory;
35import org.onosproject.net.config.NetworkConfigEvent;
36import org.onosproject.net.config.NetworkConfigListener;
37import org.onosproject.net.config.NetworkConfigRegistry;
sanghod177f8f2016-06-29 21:52:23 +090038import org.onosproject.openstackinterface.OpenstackFloatingIP;
Hyunsun Moon0dba61f2016-03-03 14:05:21 -080039import org.onosproject.openstackinterface.OpenstackInterfaceService;
40import org.onosproject.openstackinterface.OpenstackNetwork;
sangho48907542016-03-28 16:07:07 +090041import org.onosproject.openstackinterface.OpenstackInterfaceConfig;
Hyunsun Moon0dba61f2016-03-03 14:05:21 -080042import org.onosproject.openstackinterface.OpenstackPort;
43import org.onosproject.openstackinterface.OpenstackRouter;
44import org.onosproject.openstackinterface.OpenstackSecurityGroup;
45import org.onosproject.openstackinterface.OpenstackSubnet;
sanghod177f8f2016-06-29 21:52:23 +090046import org.onosproject.openstackinterface.web.OpenstackFloatingIpCodec;
sangho93447f12016-02-24 00:33:22 +090047import org.onosproject.openstackinterface.web.OpenstackNetworkCodec;
48import org.onosproject.openstackinterface.web.OpenstackPortCodec;
49import org.onosproject.openstackinterface.web.OpenstackRouterCodec;
50import org.onosproject.openstackinterface.web.OpenstackSecurityGroupCodec;
51import org.onosproject.openstackinterface.web.OpenstackSubnetCodec;
sanghoshinf25d2e02015-11-11 23:07:17 +090052import org.slf4j.Logger;
Jian Li9d616492016-03-09 10:52:49 -080053
54import javax.ws.rs.client.Client;
55import javax.ws.rs.client.ClientBuilder;
56import javax.ws.rs.client.Entity;
57import javax.ws.rs.client.Invocation;
58import javax.ws.rs.client.WebTarget;
sanghoshinf25d2e02015-11-11 23:07:17 +090059import javax.ws.rs.core.MediaType;
60import java.io.IOException;
sangho9f189ec2016-04-05 14:22:17 +090061import java.text.ParseException;
62import java.text.SimpleDateFormat;
63import java.util.Calendar;
sanghoshinf25d2e02015-11-11 23:07:17 +090064import java.util.Collection;
Hyunsun Moonf7895202016-01-12 12:21:48 -080065import java.util.Collections;
sangho9f189ec2016-04-05 14:22:17 +090066import java.util.Date;
sanghoshinf25d2e02015-11-11 23:07:17 +090067import java.util.List;
sangho93447f12016-02-24 00:33:22 +090068import java.util.Set;
69import java.util.concurrent.ExecutorService;
70import java.util.concurrent.Executors;
sangho0c2a3da2016-02-16 13:39:07 +090071import java.util.stream.Collectors;
sanghoshinf25d2e02015-11-11 23:07:17 +090072
73import static com.google.common.base.Preconditions.checkNotNull;
74import static com.google.common.net.MediaType.JSON_UTF_8;
sangho93447f12016-02-24 00:33:22 +090075import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moonef6bad22016-07-19 16:25:43 -070076import static org.onosproject.net.AnnotationKeys.PORT_NAME;
sangho93447f12016-02-24 00:33:22 +090077import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
sanghoshinf25d2e02015-11-11 23:07:17 +090078import static org.slf4j.LoggerFactory.getLogger;
79
80/**
81 * Handles REST Calls to Openstack Neutron.
82 *
83 */
sangho0c2a3da2016-02-16 13:39:07 +090084@Service
85@Component(immediate = true)
sangho93447f12016-02-24 00:33:22 +090086public class OpenstackInterfaceManager implements OpenstackInterfaceService {
sanghoshinf25d2e02015-11-11 23:07:17 +090087
sangho5db8e052016-01-29 16:08:23 +090088 private static final String URI_NETWORKS = "networks";
89 private static final String URI_PORTS = "ports";
90 private static final String URI_SUBNETS = "subnets";
91 private static final String URI_SECURITY_GROUPS = "security-groups";
sanghod177f8f2016-06-29 21:52:23 +090092 private static final String URI_FLOATINGIPS = "floatingips";
sangho5db8e052016-01-29 16:08:23 +090093 private static final String URI_TOKENS = "tokens";
94
Daniel Park3a06c522016-01-28 20:51:12 +090095 private static final String PATH_ROUTERS = "routers";
sangho5db8e052016-01-29 16:08:23 +090096 private static final String PATH_NETWORKS = "networks";
97 private static final String PATH_PORTS = "ports";
98 private static final String PATH_SUBNETS = "subnets";
sanghod177f8f2016-06-29 21:52:23 +090099 private static final String PATH_FLOATINGIPS = "floatingips";
sangho5db8e052016-01-29 16:08:23 +0900100 private static final String PATH_ACCESS = "access";
101 private static final String PATH_TOKEN = "token";
102 private static final String PATH_ID = "id";
sangho9f189ec2016-04-05 14:22:17 +0900103 private static final String PATH_EXPIRES = "expires";
sangho5db8e052016-01-29 16:08:23 +0900104
105 private static final String HEADER_AUTH_TOKEN = "X-Auth-Token";
sangho9f189ec2016-04-05 14:22:17 +0900106 private static final String TOKEN_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700107 private static final int DEFAULT_TIMEOUT_MS = 2000;
sangho5db8e052016-01-29 16:08:23 +0900108
sanghoshinf25d2e02015-11-11 23:07:17 +0900109 private final Logger log = getLogger(getClass());
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700110 private final Client client = ClientBuilder.newClient();
111
sanghoshinf25d2e02015-11-11 23:07:17 +0900112 private String neutronUrl;
113 private String keystoneUrl;
114 private String tokenId;
sangho9f189ec2016-04-05 14:22:17 +0900115 private String tokenExpires;
sanghoshinf25d2e02015-11-11 23:07:17 +0900116 private String userName;
117 private String pass;
118
sangho0c2a3da2016-02-16 13:39:07 +0900119 private ApplicationId appId;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected CoreService coreService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho93447f12016-02-24 00:33:22 +0900125 protected NetworkConfigRegistry cfgService;
sangho0c2a3da2016-02-16 13:39:07 +0900126
sangho93447f12016-02-24 00:33:22 +0900127 private InternalConfigListener internalConfigListener = new InternalConfigListener();
128 private ExecutorService networkEventExcutorService =
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700129 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackinterface", "config-event", log));
sangho93447f12016-02-24 00:33:22 +0900130
131 private final Set<ConfigFactory> factories = ImmutableSet.of(
sangho48907542016-03-28 16:07:07 +0900132 new ConfigFactory<ApplicationId, OpenstackInterfaceConfig>(APP_SUBJECT_FACTORY,
133 OpenstackInterfaceConfig.class,
sangho93447f12016-02-24 00:33:22 +0900134 "openstackinterface") {
135 @Override
sangho48907542016-03-28 16:07:07 +0900136 public OpenstackInterfaceConfig createConfig() {
137 return new OpenstackInterfaceConfig();
sangho93447f12016-02-24 00:33:22 +0900138 }
139 }
140 );
141
sangho0c2a3da2016-02-16 13:39:07 +0900142 @Activate
143 protected void activate() {
144 appId = coreService
sangho93447f12016-02-24 00:33:22 +0900145 .registerApplication("org.onosproject.openstackinterface");
146
147 factories.forEach(cfgService::registerConfigFactory);
148 cfgService.addListener(internalConfigListener);
sangho0c2a3da2016-02-16 13:39:07 +0900149
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700150 client.property(ClientProperties.CONNECT_TIMEOUT, DEFAULT_TIMEOUT_MS);
151 client.property(ClientProperties.READ_TIMEOUT, DEFAULT_TIMEOUT_MS);
152
153 configureNetwork();
sangho0c2a3da2016-02-16 13:39:07 +0900154 log.info("started");
155 }
156
157 @Deactivate
158 protected void deactivate() {
sangho93447f12016-02-24 00:33:22 +0900159 cfgService.removeListener(internalConfigListener);
160 factories.forEach(cfgService::unregisterConfigFactory);
sangho0c2a3da2016-02-16 13:39:07 +0900161 log.info("stopped");
sanghoshinf25d2e02015-11-11 23:07:17 +0900162 }
163
164 /**
165 * Returns network information stored in Neutron.
166 *
167 * @return List of OpenstackNetwork
168 */
169 public Collection<OpenstackNetwork> getNetworks() {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700170 Invocation.Builder builder = getClientBuilder(neutronUrl, URI_NETWORKS);
171 if (builder == null) {
172 log.warn("Failed to get networks");
173 return Collections.EMPTY_LIST;
174 }
sanghoshinf25d2e02015-11-11 23:07:17 +0900175
sanghoshinf25d2e02015-11-11 23:07:17 +0900176 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
sangho5db8e052016-01-29 16:08:23 +0900177 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
Hyunsun Moonf7895202016-01-12 12:21:48 -0800178 log.debug("networks response:" + response);
179
sanghoshinf25d2e02015-11-11 23:07:17 +0900180 ObjectMapper mapper = new ObjectMapper();
181 List<OpenstackNetwork> openstackNetworks = Lists.newArrayList();
182 try {
183 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900184 ArrayNode networkList = (ArrayNode) node.path(PATH_NETWORKS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900185 OpenstackNetworkCodec networkCodec = new OpenstackNetworkCodec();
186 networkList.forEach(n -> openstackNetworks.add(networkCodec.decode((ObjectNode) n, null)));
187 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800188 log.warn("getNetworks()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900189 }
190
Hyunsun Moonf7895202016-01-12 12:21:48 -0800191 openstackNetworks.removeAll(Collections.singleton(null));
sanghoshinf25d2e02015-11-11 23:07:17 +0900192 openstackNetworks.forEach(n -> log.debug("network ID: {}", n.id()));
193
194 return openstackNetworks;
195 }
196
197 /**
198 * Returns port information stored in Neutron.
199 *
200 * @return List of OpenstackPort
201 */
202 public Collection<OpenstackPort> getPorts() {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700203 Invocation.Builder builder = getClientBuilder(neutronUrl, URI_PORTS);
204 if (builder == null) {
205 log.warn("Failed to get ports");
206 return Collections.EMPTY_LIST;
207 }
sanghoshinf25d2e02015-11-11 23:07:17 +0900208
sanghoshinf25d2e02015-11-11 23:07:17 +0900209 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
sangho5db8e052016-01-29 16:08:23 +0900210 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
sanghoshinf25d2e02015-11-11 23:07:17 +0900211
212 ObjectMapper mapper = new ObjectMapper();
213 List<OpenstackPort> openstackPorts = Lists.newArrayList();
214 try {
215 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900216 ArrayNode portList = (ArrayNode) node.path(PATH_PORTS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900217 OpenstackPortCodec portCodec = new OpenstackPortCodec();
218 portList.forEach(p -> openstackPorts.add(portCodec.decode((ObjectNode) p, null)));
219 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800220 log.warn("getPorts()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900221 }
222
223 log.debug("port response:" + response);
224 openstackPorts.forEach(n -> log.debug("port ID: {}", n.id()));
225
226 return openstackPorts;
227 }
228
Daniel Park3a06c522016-01-28 20:51:12 +0900229 public Collection<OpenstackRouter> getRouters() {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700230 Invocation.Builder builder = getClientBuilder(neutronUrl, PATH_ROUTERS);
231 if (builder == null) {
232 log.warn("Failed to get routers");
233 return Collections.EMPTY_LIST;
234 }
235
Daniel Park3a06c522016-01-28 20:51:12 +0900236 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
237 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
238
239 ObjectMapper mapper = new ObjectMapper();
240 List<OpenstackRouter> openstackRouters = Lists.newArrayList();
241
242 try {
243 ObjectNode node = (ObjectNode) mapper.readTree(response);
244 ArrayNode routerList = (ArrayNode) node.path(PATH_ROUTERS);
245 OpenstackRouterCodec openstackRouterCodec = new OpenstackRouterCodec();
246 routerList.forEach(r -> openstackRouters
247 .add(openstackRouterCodec.decode((ObjectNode) r, null)));
248 } catch (IOException e) {
249 log.warn("getRouters()", e);
250 }
251
252 log.debug("router response:" + response);
253 openstackRouters.forEach(r -> log.debug("router ID: {}", r.id()));
254
255 return openstackRouters;
256 }
257
sanghoshinf25d2e02015-11-11 23:07:17 +0900258 /**
259 * Returns Subnet information in Neutron.
260 *
261 * @return List of OpenstackSubnet
262 */
263 public Collection<OpenstackSubnet> getSubnets() {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700264 Invocation.Builder builder = getClientBuilder(neutronUrl, URI_SUBNETS);
265 if (builder == null) {
266 log.warn("Failed to get subnets");
267 return Collections.EMPTY_LIST;
268 }
269
sanghoshinf25d2e02015-11-11 23:07:17 +0900270 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
sangho5db8e052016-01-29 16:08:23 +0900271 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
sanghoshinf25d2e02015-11-11 23:07:17 +0900272
273 ObjectMapper mapper = new ObjectMapper();
274 List<OpenstackSubnet> subnets = Lists.newArrayList();
275 try {
276 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900277 ArrayNode subnetList = (ArrayNode) node.path(PATH_SUBNETS);
sanghoshinf25d2e02015-11-11 23:07:17 +0900278 OpenstackSubnetCodec subnetCodec = new OpenstackSubnetCodec();
279 subnetList.forEach(s -> subnets.add(subnetCodec.decode((ObjectNode) s, null)));
280 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800281 log.warn("getSubnets()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900282 }
283
284 log.debug("subnets response:" + response);
285 subnets.forEach(s -> log.debug("subnet ID: {}", s.id()));
286
287 return subnets;
288 }
289
sangho5db8e052016-01-29 16:08:23 +0900290 /**
291 * Extracts OpenstackSecurityGroup information for the ID.
292 *
293 * @param id Security Group ID
294 * @return OpenstackSecurityGroup object or null if fails
295 */
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700296 @Override
sanghod177f8f2016-06-29 21:52:23 +0900297 public OpenstackSecurityGroup securityGroup(String id) {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700298 Invocation.Builder builder = getClientBuilder(neutronUrl, URI_SECURITY_GROUPS + "/" + id);
299 if (builder == null) {
300 log.warn("Failed to get security group {}", id);
301 return null;
302 }
303
sangho5db8e052016-01-29 16:08:23 +0900304 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
305 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
306
307 ObjectMapper mapper = new ObjectMapper();
308 OpenstackSecurityGroup securityGroup = null;
309 try {
310 ObjectNode node = (ObjectNode) mapper.readTree(response);
311 OpenstackSecurityGroupCodec sgCodec = new OpenstackSecurityGroupCodec();
312 securityGroup = sgCodec.decode(node, null);
313 } catch (IOException e) {
sanghod177f8f2016-06-29 21:52:23 +0900314 log.warn("securityGroup()", e);
sangho5db8e052016-01-29 16:08:23 +0900315 }
316
317 return securityGroup;
318 }
319
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700320 private Invocation.Builder getClientBuilder(String baseUrl, String path) {
321 if (Strings.isNullOrEmpty(baseUrl)) {
322 log.warn("Keystone or Neutron URL is not set");
323 return null;
324 }
325
326 WebTarget wt = client.target(baseUrl + path);
Jian Li9d616492016-03-09 10:52:49 -0800327 return wt.request(JSON_UTF_8.toString());
sanghoshinf25d2e02015-11-11 23:07:17 +0900328 }
329
330 private String getToken() {
sangho9f189ec2016-04-05 14:22:17 +0900331 if (!isTokenValid()) {
sanghoshinf25d2e02015-11-11 23:07:17 +0900332 String request = "{\"auth\": {\"tenantName\": \"admin\", " +
333 "\"passwordCredentials\": {\"username\": \"" +
334 userName + "\",\"password\": \"" + pass + "\"}}}";
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700335 Invocation.Builder builder = getClientBuilder(keystoneUrl, URI_TOKENS);
336 if (builder == null) {
337 log.warn("Failed to get token");
338 return null;
339 }
sanghoshinf25d2e02015-11-11 23:07:17 +0900340
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700341 String response = builder.accept(MediaType.APPLICATION_JSON).post(Entity.json(request), String.class);
sanghoshinf25d2e02015-11-11 23:07:17 +0900342 ObjectMapper mapper = new ObjectMapper();
343 try {
344 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900345 tokenId = node.path(PATH_ACCESS).path(PATH_TOKEN).path(PATH_ID).asText();
sangho9f189ec2016-04-05 14:22:17 +0900346 tokenExpires = node.path(PATH_ACCESS).path(PATH_TOKEN).path(PATH_EXPIRES).asText();
sanghoshinf25d2e02015-11-11 23:07:17 +0900347 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800348 log.warn("getToken()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900349 }
350 log.debug("token response:" + response);
351 }
352
353 return tokenId;
354 }
355
sangho9f189ec2016-04-05 14:22:17 +0900356 private boolean isTokenValid() {
357
358 if (tokenExpires == null || tokenId == null || tokenExpires.isEmpty()) {
359 return false;
360 }
361
362 try {
363 SimpleDateFormat dateFormat = new SimpleDateFormat(TOKEN_DATE_FORMAT);
364 Date exireDate = dateFormat.parse(tokenExpires);
365
366 Calendar today = Calendar.getInstance();
367 if (exireDate.after(today.getTime())) {
368 return true;
369 }
370 } catch (ParseException e) {
371 log.error("Token parse exception error : {}", e.getMessage());
372 return false;
373 }
374
375 log.debug("token is Invalid");
376 return false;
sanghoshinf25d2e02015-11-11 23:07:17 +0900377 }
378
sangho0c2a3da2016-02-16 13:39:07 +0900379 @Override
380 public Collection<OpenstackPort> ports(String networkId) {
381 return getPorts().stream()
382 .filter(port -> port.networkId().equals(networkId))
383 .collect(Collectors.toList());
384 }
385
386 @Override
387 public Collection<OpenstackPort> ports() {
388 return getPorts();
389 }
390
391 @Override
392 public OpenstackPort port(Port port) {
393 String uuid = port.annotations().value(PORT_NAME).substring(3);
394 return getPorts().stream()
395 .filter(p -> p.id().startsWith(uuid))
396 .findAny().orElse(null);
397 }
398
399 @Override
400 public OpenstackPort port(String portId) {
401 return getPorts().stream()
402 .filter(p -> p.id().equals(portId))
403 .findAny().orElse(null);
404 }
405
406 @Override
407 public OpenstackNetwork network(String networkId) {
Hyunsun Moonb0f09be2016-02-23 04:21:42 -0800408 Collection<OpenstackSubnet> subnets = getSubnets().stream()
409 .filter(s -> s.networkId().equals(networkId))
410 .collect(Collectors.toList());
411
412 OpenstackNetwork openstackNetwork = getNetworks().stream()
sangho0c2a3da2016-02-16 13:39:07 +0900413 .filter(n -> n.id().equals(networkId))
414 .findAny().orElse(null);
Hyunsun Moonb0f09be2016-02-23 04:21:42 -0800415
416 if (openstackNetwork == null) {
417 return null;
418 }
419
420 return OpenstackNetwork.builder()
421 .id(openstackNetwork.id())
422 .name(openstackNetwork.name())
423 .networkType(openstackNetwork.networkType())
424 .segmentId(openstackNetwork.segmentId())
425 .tenantId(openstackNetwork.tenantId())
426 .subnets(subnets)
427 .build();
sangho0c2a3da2016-02-16 13:39:07 +0900428 }
429
430 @Override
431 public Collection<OpenstackNetwork> networks() {
432 return getNetworks();
433 }
434
435 @Override
436 public OpenstackSubnet subnet(String subnetId) {
437 return getSubnets().stream()
438 .filter(subnet -> subnet.id().equals(subnetId))
439 .findAny().orElse(null);
440 }
441
442 @Override
443 public Collection<OpenstackSubnet> subnets() {
444 return getSubnets();
445 }
446
447 @Override
448 public Collection<OpenstackRouter> routers() {
449 return getRouters();
450 }
451
452 @Override
453 public OpenstackRouter router(String routerId) {
454 return getRouters().stream()
455 .filter(router -> router.id().equals(routerId))
456 .findAny().orElse(null);
457 }
458
sanghod177f8f2016-06-29 21:52:23 +0900459 @Override
460 public Collection<OpenstackFloatingIP> floatingIps() {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700461 Invocation.Builder builder = getClientBuilder(neutronUrl, URI_FLOATINGIPS);
462 if (builder == null) {
463 log.warn("Failed to get floating IPs");
464 return Collections.EMPTY_LIST;
465 }
466
sanghod177f8f2016-06-29 21:52:23 +0900467 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
468 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
469
470 log.debug("floatingIps response:" + response);
471
472 ObjectMapper mapper = new ObjectMapper();
473 List<OpenstackFloatingIP> openstackFloatingIPs = Lists.newArrayList();
474 try {
475 ObjectNode node = (ObjectNode) mapper.readTree(response);
476 ArrayNode floatingIpList = (ArrayNode) node.path(PATH_FLOATINGIPS);
477 OpenstackFloatingIpCodec fipCodec = new OpenstackFloatingIpCodec();
478 floatingIpList.forEach(f -> openstackFloatingIPs.add(fipCodec.decode((ObjectNode) f, null)));
479 } catch (IOException e) {
480 log.warn("floatingIps()", e);
481 }
482
483 openstackFloatingIPs.removeAll(Collections.singleton(null));
484
485 return openstackFloatingIPs;
486 }
487
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700488 private void configureNetwork() {
489 OpenstackInterfaceConfig cfg =
490 cfgService.getConfig(appId, OpenstackInterfaceConfig.class);
491 if (cfg == null) {
492 log.error("There is no openstack server information in config.");
493 return;
sangho93447f12016-02-24 00:33:22 +0900494 }
495
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700496 neutronUrl = checkNotNull(cfg.neutronServer());
497 keystoneUrl = checkNotNull(cfg.keystoneServer());
498 userName = checkNotNull(cfg.userName());
499 pass = checkNotNull(cfg.password());
500 }
501
502 private class InternalConfigListener implements NetworkConfigListener {
503
sangho93447f12016-02-24 00:33:22 +0900504 @Override
505 public void event(NetworkConfigEvent event) {
506 if (((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
507 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) &&
sangho48907542016-03-28 16:07:07 +0900508 event.configClass().equals(OpenstackInterfaceConfig.class)) {
sangho93447f12016-02-24 00:33:22 +0900509
510 log.info("Network configuration changed");
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700511 networkEventExcutorService.execute(() -> configureNetwork());
sangho93447f12016-02-24 00:33:22 +0900512 }
513 }
sangho0c2a3da2016-02-16 13:39:07 +0900514 }
Jian Li9d616492016-03-09 10:52:49 -0800515}