blob: 152d3e2ad7de2bd66b4de12661aae81f46bc7774 [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 =
129 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackinterface", "config-event"));
130
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 */
sanghod177f8f2016-06-29 21:52:23 +0900296 public OpenstackSecurityGroup securityGroup(String id) {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700297 Invocation.Builder builder = getClientBuilder(neutronUrl, URI_SECURITY_GROUPS + "/" + id);
298 if (builder == null) {
299 log.warn("Failed to get security group {}", id);
300 return null;
301 }
302
sangho5db8e052016-01-29 16:08:23 +0900303 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
304 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
305
306 ObjectMapper mapper = new ObjectMapper();
307 OpenstackSecurityGroup securityGroup = null;
308 try {
309 ObjectNode node = (ObjectNode) mapper.readTree(response);
310 OpenstackSecurityGroupCodec sgCodec = new OpenstackSecurityGroupCodec();
311 securityGroup = sgCodec.decode(node, null);
312 } catch (IOException e) {
sanghod177f8f2016-06-29 21:52:23 +0900313 log.warn("securityGroup()", e);
sangho5db8e052016-01-29 16:08:23 +0900314 }
315
316 return securityGroup;
317 }
318
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700319 private Invocation.Builder getClientBuilder(String baseUrl, String path) {
320 if (Strings.isNullOrEmpty(baseUrl)) {
321 log.warn("Keystone or Neutron URL is not set");
322 return null;
323 }
324
325 WebTarget wt = client.target(baseUrl + path);
Jian Li9d616492016-03-09 10:52:49 -0800326 return wt.request(JSON_UTF_8.toString());
sanghoshinf25d2e02015-11-11 23:07:17 +0900327 }
328
329 private String getToken() {
sangho9f189ec2016-04-05 14:22:17 +0900330 if (!isTokenValid()) {
sanghoshinf25d2e02015-11-11 23:07:17 +0900331 String request = "{\"auth\": {\"tenantName\": \"admin\", " +
332 "\"passwordCredentials\": {\"username\": \"" +
333 userName + "\",\"password\": \"" + pass + "\"}}}";
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700334 Invocation.Builder builder = getClientBuilder(keystoneUrl, URI_TOKENS);
335 if (builder == null) {
336 log.warn("Failed to get token");
337 return null;
338 }
sanghoshinf25d2e02015-11-11 23:07:17 +0900339
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700340 String response = builder.accept(MediaType.APPLICATION_JSON).post(Entity.json(request), String.class);
sanghoshinf25d2e02015-11-11 23:07:17 +0900341 ObjectMapper mapper = new ObjectMapper();
342 try {
343 ObjectNode node = (ObjectNode) mapper.readTree(response);
sangho5db8e052016-01-29 16:08:23 +0900344 tokenId = node.path(PATH_ACCESS).path(PATH_TOKEN).path(PATH_ID).asText();
sangho9f189ec2016-04-05 14:22:17 +0900345 tokenExpires = node.path(PATH_ACCESS).path(PATH_TOKEN).path(PATH_EXPIRES).asText();
sanghoshinf25d2e02015-11-11 23:07:17 +0900346 } catch (IOException e) {
Ray Milkey4fd3ceb2015-12-10 14:43:08 -0800347 log.warn("getToken()", e);
sanghoshinf25d2e02015-11-11 23:07:17 +0900348 }
349 log.debug("token response:" + response);
350 }
351
352 return tokenId;
353 }
354
sangho9f189ec2016-04-05 14:22:17 +0900355 private boolean isTokenValid() {
356
357 if (tokenExpires == null || tokenId == null || tokenExpires.isEmpty()) {
358 return false;
359 }
360
361 try {
362 SimpleDateFormat dateFormat = new SimpleDateFormat(TOKEN_DATE_FORMAT);
363 Date exireDate = dateFormat.parse(tokenExpires);
364
365 Calendar today = Calendar.getInstance();
366 if (exireDate.after(today.getTime())) {
367 return true;
368 }
369 } catch (ParseException e) {
370 log.error("Token parse exception error : {}", e.getMessage());
371 return false;
372 }
373
374 log.debug("token is Invalid");
375 return false;
sanghoshinf25d2e02015-11-11 23:07:17 +0900376 }
377
sangho0c2a3da2016-02-16 13:39:07 +0900378 @Override
379 public Collection<OpenstackPort> ports(String networkId) {
380 return getPorts().stream()
381 .filter(port -> port.networkId().equals(networkId))
382 .collect(Collectors.toList());
383 }
384
385 @Override
386 public Collection<OpenstackPort> ports() {
387 return getPorts();
388 }
389
390 @Override
391 public OpenstackPort port(Port port) {
392 String uuid = port.annotations().value(PORT_NAME).substring(3);
393 return getPorts().stream()
394 .filter(p -> p.id().startsWith(uuid))
395 .findAny().orElse(null);
396 }
397
398 @Override
399 public OpenstackPort port(String portId) {
400 return getPorts().stream()
401 .filter(p -> p.id().equals(portId))
402 .findAny().orElse(null);
403 }
404
405 @Override
406 public OpenstackNetwork network(String networkId) {
Hyunsun Moonb0f09be2016-02-23 04:21:42 -0800407 Collection<OpenstackSubnet> subnets = getSubnets().stream()
408 .filter(s -> s.networkId().equals(networkId))
409 .collect(Collectors.toList());
410
411 OpenstackNetwork openstackNetwork = getNetworks().stream()
sangho0c2a3da2016-02-16 13:39:07 +0900412 .filter(n -> n.id().equals(networkId))
413 .findAny().orElse(null);
Hyunsun Moonb0f09be2016-02-23 04:21:42 -0800414
415 if (openstackNetwork == null) {
416 return null;
417 }
418
419 return OpenstackNetwork.builder()
420 .id(openstackNetwork.id())
421 .name(openstackNetwork.name())
422 .networkType(openstackNetwork.networkType())
423 .segmentId(openstackNetwork.segmentId())
424 .tenantId(openstackNetwork.tenantId())
425 .subnets(subnets)
426 .build();
sangho0c2a3da2016-02-16 13:39:07 +0900427 }
428
429 @Override
430 public Collection<OpenstackNetwork> networks() {
431 return getNetworks();
432 }
433
434 @Override
435 public OpenstackSubnet subnet(String subnetId) {
436 return getSubnets().stream()
437 .filter(subnet -> subnet.id().equals(subnetId))
438 .findAny().orElse(null);
439 }
440
441 @Override
442 public Collection<OpenstackSubnet> subnets() {
443 return getSubnets();
444 }
445
446 @Override
447 public Collection<OpenstackRouter> routers() {
448 return getRouters();
449 }
450
451 @Override
452 public OpenstackRouter router(String routerId) {
453 return getRouters().stream()
454 .filter(router -> router.id().equals(routerId))
455 .findAny().orElse(null);
456 }
457
sanghod177f8f2016-06-29 21:52:23 +0900458 @Override
459 public Collection<OpenstackFloatingIP> floatingIps() {
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700460 Invocation.Builder builder = getClientBuilder(neutronUrl, URI_FLOATINGIPS);
461 if (builder == null) {
462 log.warn("Failed to get floating IPs");
463 return Collections.EMPTY_LIST;
464 }
465
sanghod177f8f2016-06-29 21:52:23 +0900466 String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
467 header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
468
469 log.debug("floatingIps response:" + response);
470
471 ObjectMapper mapper = new ObjectMapper();
472 List<OpenstackFloatingIP> openstackFloatingIPs = Lists.newArrayList();
473 try {
474 ObjectNode node = (ObjectNode) mapper.readTree(response);
475 ArrayNode floatingIpList = (ArrayNode) node.path(PATH_FLOATINGIPS);
476 OpenstackFloatingIpCodec fipCodec = new OpenstackFloatingIpCodec();
477 floatingIpList.forEach(f -> openstackFloatingIPs.add(fipCodec.decode((ObjectNode) f, null)));
478 } catch (IOException e) {
479 log.warn("floatingIps()", e);
480 }
481
482 openstackFloatingIPs.removeAll(Collections.singleton(null));
483
484 return openstackFloatingIPs;
485 }
486
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700487 private void configureNetwork() {
488 OpenstackInterfaceConfig cfg =
489 cfgService.getConfig(appId, OpenstackInterfaceConfig.class);
490 if (cfg == null) {
491 log.error("There is no openstack server information in config.");
492 return;
sangho93447f12016-02-24 00:33:22 +0900493 }
494
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700495 neutronUrl = checkNotNull(cfg.neutronServer());
496 keystoneUrl = checkNotNull(cfg.keystoneServer());
497 userName = checkNotNull(cfg.userName());
498 pass = checkNotNull(cfg.password());
499 }
500
501 private class InternalConfigListener implements NetworkConfigListener {
502
sangho93447f12016-02-24 00:33:22 +0900503 @Override
504 public void event(NetworkConfigEvent event) {
505 if (((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
506 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) &&
sangho48907542016-03-28 16:07:07 +0900507 event.configClass().equals(OpenstackInterfaceConfig.class)) {
sangho93447f12016-02-24 00:33:22 +0900508
509 log.info("Network configuration changed");
Hyunsun Moonef6bad22016-07-19 16:25:43 -0700510 networkEventExcutorService.execute(() -> configureNetwork());
sangho93447f12016-02-24 00:33:22 +0900511 }
512 }
sangho0c2a3da2016-02-16 13:39:07 +0900513 }
Jian Li9d616492016-03-09 10:52:49 -0800514}