blob: b6937c5e99e97eb9098293a948b839843b3c19b5 [file] [log] [blame]
Jian Li091d8d22018-02-20 10:42:06 +09001/*
2 * Copyright 2018-present Open Networking Foundation
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 */
16package org.onosproject.openstacknetworking.util;
17
Daniel Park2ff66b42018-08-01 11:52:45 +090018import com.fasterxml.jackson.core.JsonParseException;
19import com.fasterxml.jackson.core.JsonProcessingException;
20import com.fasterxml.jackson.databind.JsonMappingException;
Jian Li091d8d22018-02-20 10:42:06 +090021import com.fasterxml.jackson.databind.JsonNode;
22import com.fasterxml.jackson.databind.ObjectMapper;
Jian Lieb9f77d2018-02-20 11:25:45 +090023import com.fasterxml.jackson.databind.node.ObjectNode;
Jian Li24ec59f2018-05-23 19:01:25 +090024import com.google.common.base.Strings;
Jian Li7f70bb72018-07-06 23:35:30 +090025import org.onosproject.cfg.ConfigProperty;
Jian Li1064e4f2018-05-29 16:16:53 +090026import org.onosproject.net.DeviceId;
Daniel Park95f73312018-07-31 15:48:34 +090027import org.onosproject.net.device.DeviceService;
Daniel Park7e8c4d82018-08-13 23:47:49 +090028import org.onosproject.openstacknetworking.api.Constants.VnicType;
Jian Lia171a432018-06-11 11:52:11 +090029import org.onosproject.openstacknetworking.api.InstancePort;
Jian Li24ec59f2018-05-23 19:01:25 +090030import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
Jian Li7f70bb72018-07-06 23:35:30 +090031import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
Jian Liec5c32b2018-07-13 14:28:58 +090032import org.onosproject.openstacknetworking.impl.DefaultInstancePort;
Jian Li51b844c2018-05-31 10:59:03 +090033import org.onosproject.openstacknode.api.OpenstackAuth;
34import org.onosproject.openstacknode.api.OpenstackAuth.Perspective;
Jian Li1064e4f2018-05-29 16:16:53 +090035import org.onosproject.openstacknode.api.OpenstackNode;
Jian Li51b844c2018-05-31 10:59:03 +090036import org.openstack4j.api.OSClient;
37import org.openstack4j.api.client.IOSClientBuilder;
38import org.openstack4j.api.exceptions.AuthenticationException;
39import org.openstack4j.api.types.Facing;
40import org.openstack4j.core.transport.Config;
Jian Li091d8d22018-02-20 10:42:06 +090041import org.openstack4j.core.transport.ObjectMapperSingleton;
42import org.openstack4j.model.ModelEntity;
Jian Li51b844c2018-05-31 10:59:03 +090043import org.openstack4j.model.common.Identifier;
Jian Li24ec59f2018-05-23 19:01:25 +090044import org.openstack4j.model.network.NetFloatingIP;
45import org.openstack4j.model.network.Network;
Jian Lia171a432018-06-11 11:52:11 +090046import org.openstack4j.model.network.Port;
Jian Li0b564282018-06-20 00:50:53 +090047import org.openstack4j.model.network.RouterInterface;
Jian Li51b844c2018-05-31 10:59:03 +090048import org.openstack4j.openstack.OSFactory;
Jian Li0b564282018-06-20 00:50:53 +090049import org.openstack4j.openstack.networking.domain.NeutronRouterInterface;
Jian Li091d8d22018-02-20 10:42:06 +090050import org.slf4j.Logger;
51import org.slf4j.LoggerFactory;
52
Jian Li51b844c2018-05-31 10:59:03 +090053import javax.net.ssl.HostnameVerifier;
54import javax.net.ssl.HttpsURLConnection;
55import javax.net.ssl.SSLContext;
56import javax.net.ssl.TrustManager;
57import javax.net.ssl.X509TrustManager;
Jian Li0b564282018-06-20 00:50:53 +090058import java.io.IOException;
Jian Li091d8d22018-02-20 10:42:06 +090059import java.io.InputStream;
Jian Li51b844c2018-05-31 10:59:03 +090060import java.security.cert.X509Certificate;
Jian Li1064e4f2018-05-29 16:16:53 +090061import java.util.HashMap;
62import java.util.Iterator;
63import java.util.Map;
Daniel Park95f73312018-07-31 15:48:34 +090064import java.util.Objects;
Jian Li7f70bb72018-07-06 23:35:30 +090065import java.util.Optional;
Jian Li1064e4f2018-05-29 16:16:53 +090066import java.util.Set;
67import java.util.TreeMap;
Jian Li091d8d22018-02-20 10:42:06 +090068
69import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
Daniel Park95f73312018-07-31 15:48:34 +090070import static com.google.common.base.Preconditions.checkNotNull;
Jian Li7f024de2018-07-07 03:51:02 +090071import static com.google.common.base.Strings.isNullOrEmpty;
Daniel Park95f73312018-07-31 15:48:34 +090072import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Daniel Parkc4d06402018-05-28 15:57:37 +090073import static org.onosproject.openstacknetworking.api.Constants.PCISLOT;
74import static org.onosproject.openstacknetworking.api.Constants.PCI_VENDOR_INFO;
Daniel Park7e8c4d82018-08-13 23:47:49 +090075import static org.onosproject.openstacknetworking.api.Constants.PORT_NAME_PREFIX_VM;
76import static org.onosproject.openstacknetworking.api.Constants.PORT_NAME_VHOST_USER_PREFIX_VM;
Daniel Parkec9d1132018-08-19 11:18:03 +090077import static org.onosproject.openstacknetworking.api.Constants.UNSUPPORTED_VENDOR;
Ray Milkey9dc57392018-06-08 08:52:31 -070078import static org.onosproject.openstacknetworking.api.Constants.portNamePrefixMap;
Jian Li0b564282018-06-20 00:50:53 +090079import static org.openstack4j.core.transport.ObjectMapperSingleton.getContext;
Jian Li091d8d22018-02-20 10:42:06 +090080
81/**
82 * An utility that used in openstack networking app.
83 */
Jian Lidea0fdb2018-04-02 19:02:48 +090084public final class OpenstackNetworkingUtil {
Jian Li091d8d22018-02-20 10:42:06 +090085
Daniel Park95985382018-07-23 11:38:07 +090086 private static final Logger log = LoggerFactory.getLogger(OpenstackNetworkingUtil.class);
Jian Li091d8d22018-02-20 10:42:06 +090087
Daniel Parkc4d06402018-05-28 15:57:37 +090088 private static final int HEX_RADIX = 16;
Jian Li51b844c2018-05-31 10:59:03 +090089 private static final String ZERO_FUNCTION_NUMBER = "0";
Daniel Parkc4d06402018-05-28 15:57:37 +090090 private static final String PREFIX_DEVICE_NUMBER = "s";
91 private static final String PREFIX_FUNCTION_NUMBER = "f";
92
Jian Li51b844c2018-05-31 10:59:03 +090093 // keystone endpoint related variables
94 private static final String DOMAIN_DEFAULT = "default";
95 private static final String KEYSTONE_V2 = "v2.0";
96 private static final String KEYSTONE_V3 = "v3";
Jian Li51b844c2018-05-31 10:59:03 +090097 private static final String SSL_TYPE = "SSL";
98
Jian Li7f024de2018-07-07 03:51:02 +090099 private static final String PROXY_MODE = "proxy";
100 private static final String BROADCAST_MODE = "broadcast";
101
Jian Li24ec59f2018-05-23 19:01:25 +0900102 private static final String ERR_FLOW = "Failed set flows for floating IP %s: ";
103
Jian Li091d8d22018-02-20 10:42:06 +0900104 /**
105 * Prevents object instantiation from external.
106 */
Jian Lidea0fdb2018-04-02 19:02:48 +0900107 private OpenstackNetworkingUtil() {
Jian Li091d8d22018-02-20 10:42:06 +0900108 }
109
110 /**
111 * Interprets JSON string to corresponding openstack model entity object.
112 *
113 * @param input JSON string
114 * @param entityClazz openstack model entity class
115 * @return openstack model entity object
116 */
117 public static ModelEntity jsonToModelEntity(InputStream input, Class entityClazz) {
118 ObjectMapper mapper = new ObjectMapper();
119 try {
120 JsonNode jsonTree = mapper.enable(INDENT_OUTPUT).readTree(input);
121 log.trace(new ObjectMapper().writeValueAsString(jsonTree));
122 return ObjectMapperSingleton.getContext(entityClazz)
123 .readerFor(entityClazz)
124 .readValue(jsonTree);
125 } catch (Exception e) {
126 throw new IllegalArgumentException();
127 }
128 }
Jian Lieb9f77d2018-02-20 11:25:45 +0900129
130 /**
131 * Converts openstack model entity object into JSON object.
132 *
133 * @param entity openstack model entity object
134 * @param entityClazz openstack model entity class
135 * @return JSON object
136 */
137 public static ObjectNode modelEntityToJson(ModelEntity entity, Class entityClazz) {
138 ObjectMapper mapper = new ObjectMapper();
139 try {
140 String strModelEntity = ObjectMapperSingleton.getContext(entityClazz)
141 .writerFor(entityClazz)
142 .writeValueAsString(entity);
143 log.trace(strModelEntity);
144 return (ObjectNode) mapper.readTree(strModelEntity.getBytes());
Daniel Park95985382018-07-23 11:38:07 +0900145 } catch (IOException e) {
146 log.error("IOException occurred because of {}", e.toString());
Jian Lieb9f77d2018-02-20 11:25:45 +0900147 throw new IllegalStateException();
148 }
149 }
Jian Li1064e4f2018-05-29 16:16:53 +0900150
151 /**
Jian Li24ec59f2018-05-23 19:01:25 +0900152 * Obtains a floating IP associated with the given instance port.
153 *
154 * @param port instance port
155 * @param fips a collection of floating IPs
156 * @return associated floating IP
157 */
158 public static NetFloatingIP associatedFloatingIp(InstancePort port,
159 Set<NetFloatingIP> fips) {
Daniel Park2ff66b42018-08-01 11:52:45 +0900160 for (NetFloatingIP fip : fips) {
161 if (Strings.isNullOrEmpty(fip.getFixedIpAddress())) {
162 continue;
Jian Li24ec59f2018-05-23 19:01:25 +0900163 }
Daniel Park2ff66b42018-08-01 11:52:45 +0900164 if (Strings.isNullOrEmpty(fip.getFloatingIpAddress())) {
165 continue;
166 }
167 if (fip.getFixedIpAddress().equals(port.ipAddress().toString())) {
168 return fip;
169 }
Jian Li24ec59f2018-05-23 19:01:25 +0900170 }
Daniel Park2ff66b42018-08-01 11:52:45 +0900171
Jian Li24ec59f2018-05-23 19:01:25 +0900172 return null;
173 }
174
175 /**
176 * Checks whether the given floating IP is associated with a VM.
177 *
178 * @param service openstack network service
179 * @param fip floating IP
180 * @return true if the given floating IP associated with a VM, false otherwise
181 */
182 public static boolean isAssociatedWithVM(OpenstackNetworkService service,
183 NetFloatingIP fip) {
184 Port osPort = service.port(fip.getPortId());
185 if (osPort == null) {
186 return false;
187 }
188
189 if (!Strings.isNullOrEmpty(osPort.getDeviceId())) {
190 Network osNet = service.network(osPort.getNetworkId());
191 if (osNet == null) {
192 final String errorFormat = ERR_FLOW + "no network(%s) exists";
193 final String error = String.format(errorFormat,
194 fip.getFloatingIpAddress(), osPort.getNetworkId());
195 throw new IllegalStateException(error);
196 }
197 return true;
198 } else {
199 return false;
200 }
201 }
202
203 /**
Jian Lia171a432018-06-11 11:52:11 +0900204 * Obtains the gateway node by instance port.
205 *
206 * @param gateways a collection of gateway nodes
207 * @param instPort instance port
208 * @return a gateway node
209 */
210 public static OpenstackNode getGwByInstancePort(Set<OpenstackNode> gateways,
211 InstancePort instPort) {
212 OpenstackNode gw = null;
213 if (instPort != null && instPort.deviceId() != null) {
214 gw = getGwByComputeDevId(gateways, instPort.deviceId());
215 }
216 return gw;
217 }
218
219 /**
Jian Li1064e4f2018-05-29 16:16:53 +0900220 * Obtains the gateway node by device in compute node. Note that the gateway
221 * node is determined by device's device identifier.
222 *
223 * @param gws a collection of gateway nodes
224 * @param deviceId device identifier
225 * @return a gateway node
226 */
227 public static OpenstackNode getGwByComputeDevId(Set<OpenstackNode> gws, DeviceId deviceId) {
228 int numOfGw = gws.size();
229
230 if (numOfGw == 0) {
231 return null;
232 }
233
234 int gwIndex = Math.abs(deviceId.hashCode()) % numOfGw;
235
236 return getGwByIndex(gws, gwIndex);
237 }
238
Jian Li51b844c2018-05-31 10:59:03 +0900239 /**
240 * Obtains a connected openstack client.
241 *
242 * @param osNode openstack node
243 * @return a connected openstack client
244 */
245 public static OSClient getConnectedClient(OpenstackNode osNode) {
246 OpenstackAuth auth = osNode.authentication();
247 String endpoint = buildEndpoint(osNode);
248 Perspective perspective = auth.perspective();
Jian Li1064e4f2018-05-29 16:16:53 +0900249
Jian Li51b844c2018-05-31 10:59:03 +0900250 Config config = getSslConfig();
Jian Li1064e4f2018-05-29 16:16:53 +0900251
Jian Li51b844c2018-05-31 10:59:03 +0900252 try {
253 if (endpoint.contains(KEYSTONE_V2)) {
254 IOSClientBuilder.V2 builder = OSFactory.builderV2()
255 .endpoint(endpoint)
256 .tenantName(auth.project())
257 .credentials(auth.username(), auth.password())
258 .withConfig(config);
259
260 if (perspective != null) {
261 builder.perspective(getFacing(perspective));
262 }
263
264 return builder.authenticate();
265 } else if (endpoint.contains(KEYSTONE_V3)) {
266
267 Identifier project = Identifier.byName(auth.project());
268 Identifier domain = Identifier.byName(DOMAIN_DEFAULT);
269
270 IOSClientBuilder.V3 builder = OSFactory.builderV3()
271 .endpoint(endpoint)
272 .credentials(auth.username(), auth.password(), domain)
273 .scopeToProject(project, domain)
274 .withConfig(config);
275
276 if (perspective != null) {
277 builder.perspective(getFacing(perspective));
278 }
279
280 return builder.authenticate();
281 } else {
282 log.warn("Unrecognized keystone version type");
283 return null;
Jian Li1064e4f2018-05-29 16:16:53 +0900284 }
Jian Li51b844c2018-05-31 10:59:03 +0900285 } catch (AuthenticationException e) {
286 log.error("Authentication failed due to {}", e.toString());
287 return null;
Jian Li1064e4f2018-05-29 16:16:53 +0900288 }
Jian Li1064e4f2018-05-29 16:16:53 +0900289 }
Daniel Parkc4d06402018-05-28 15:57:37 +0900290
291 /**
292 * Extract the interface name with the supplied port.
293 *
294 * @param port port
295 * @return interface name
296 */
297 public static String getIntfNameFromPciAddress(Port port) {
Daniel Park95985382018-07-23 11:38:07 +0900298 if (port.getProfile() == null || port.getProfile().isEmpty()) {
Jian Li51b844c2018-05-31 10:59:03 +0900299 log.error("Port profile is not found");
300 return null;
301 }
302
Daniel Park95985382018-07-23 11:38:07 +0900303 if (!port.getProfile().containsKey(PCISLOT) ||
304 Strings.isNullOrEmpty(port.getProfile().get(PCISLOT).toString())) {
Daniel Parkc4d06402018-05-28 15:57:37 +0900305 log.error("Failed to retrieve the interface name because of no pci_slot information from the port");
306 return null;
307 }
Jian Li51b844c2018-05-31 10:59:03 +0900308
Daniel Parkc4d06402018-05-28 15:57:37 +0900309 String busNumHex = port.getProfile().get(PCISLOT).toString().split(":")[1];
310 String busNumDecimal = String.valueOf(Integer.parseInt(busNumHex, HEX_RADIX));
311
312 String deviceNumHex = port.getProfile().get(PCISLOT).toString()
313 .split(":")[2]
314 .split("\\.")[0];
315 String deviceNumDecimal = String.valueOf(Integer.parseInt(deviceNumHex, HEX_RADIX));
316
317 String functionNumHex = port.getProfile().get(PCISLOT).toString()
318 .split(":")[2]
319 .split("\\.")[1];
320 String functionNumDecimal = String.valueOf(Integer.parseInt(functionNumHex, HEX_RADIX));
321
322 String intfName;
323
324 String vendorInfoForPort = String.valueOf(port.getProfile().get(PCI_VENDOR_INFO));
325
Daniel Park95985382018-07-23 11:38:07 +0900326 if (!portNamePrefixMap().containsKey(vendorInfoForPort)) {
Daniel Parkec9d1132018-08-19 11:18:03 +0900327 log.warn("Failed to retrieve the interface name because of unsupported prefix for vendor ID {}",
Daniel Park95985382018-07-23 11:38:07 +0900328 vendorInfoForPort);
Daniel Parkec9d1132018-08-19 11:18:03 +0900329 return UNSUPPORTED_VENDOR;
Daniel Parkc4d06402018-05-28 15:57:37 +0900330 }
Ray Milkey9dc57392018-06-08 08:52:31 -0700331 String portNamePrefix = portNamePrefixMap().get(vendorInfoForPort);
Jian Li51b844c2018-05-31 10:59:03 +0900332
Daniel Parkc4d06402018-05-28 15:57:37 +0900333 if (functionNumDecimal.equals(ZERO_FUNCTION_NUMBER)) {
334 intfName = portNamePrefix + busNumDecimal + PREFIX_DEVICE_NUMBER + deviceNumDecimal;
335 } else {
336 intfName = portNamePrefix + busNumDecimal + PREFIX_DEVICE_NUMBER + deviceNumDecimal
337 + PREFIX_FUNCTION_NUMBER + functionNumDecimal;
338 }
339
340 return intfName;
341 }
Jian Li51b844c2018-05-31 10:59:03 +0900342
343 /**
Daniel Park95f73312018-07-31 15:48:34 +0900344 * Check if the given interface is added to the given device or not.
345 *
346 * @param deviceId device ID
347 * @param intfName interface name
348 * @param deviceService device service
349 * @return true if the given interface is added to the given device or false otherwise
350 */
351 public static boolean hasIntfAleadyInDevice(DeviceId deviceId, String intfName, DeviceService deviceService) {
352 checkNotNull(deviceId);
353 checkNotNull(intfName);
354
355 return deviceService.getPorts(deviceId).stream()
356 .anyMatch(port -> Objects.equals(port.annotations().value(PORT_NAME), intfName));
357 }
358
359 /**
Jian Li0b564282018-06-20 00:50:53 +0900360 * Adds router interfaces to openstack admin service.
361 * TODO fix the logic to add router interface to router
362 *
363 * @param osPort port
364 * @param adminService openstack admin service
365 */
366 public static void addRouterIface(Port osPort, OpenstackRouterAdminService adminService) {
367 osPort.getFixedIps().forEach(p -> {
368 JsonNode jsonTree = new ObjectMapper().createObjectNode()
369 .put("id", osPort.getDeviceId())
370 .put("tenant_id", osPort.getTenantId())
371 .put("subnet_id", p.getSubnetId())
372 .put("port_id", osPort.getId());
373 try {
374 RouterInterface rIface = getContext(NeutronRouterInterface.class)
375 .readerFor(NeutronRouterInterface.class)
376 .readValue(jsonTree);
377 if (adminService.routerInterface(rIface.getPortId()) != null) {
378 adminService.updateRouterInterface(rIface);
379 } else {
380 adminService.addRouterInterface(rIface);
381 }
382 } catch (IOException ignore) {
Daniel Park2ff66b42018-08-01 11:52:45 +0900383 log.error("Exception occurred because of {}", ignore.toString());
Jian Li0b564282018-06-20 00:50:53 +0900384 }
385 });
386 }
387
388 /**
Jian Li7f70bb72018-07-06 23:35:30 +0900389 * Obtains the property value with specified property key name.
390 *
391 * @param properties a collection of properties
392 * @param name key name
393 * @return mapping value
394 */
395 public static String getPropertyValue(Set<ConfigProperty> properties, String name) {
396 Optional<ConfigProperty> property =
397 properties.stream().filter(p -> p.name().equals(name)).findFirst();
398 return property.map(ConfigProperty::value).orElse(null);
399 }
400
401 /**
Jian Lif1efbe52018-07-17 23:20:16 +0900402 * Prints out the JSON string in pretty format.
403 *
404 * @param mapper Object mapper
405 * @param jsonString JSON string
406 * @return pretty formatted JSON string
407 */
408 public static String prettyJson(ObjectMapper mapper, String jsonString) {
409 try {
410 Object jsonObject = mapper.readValue(jsonString, Object.class);
411 return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
Daniel Park2ff66b42018-08-01 11:52:45 +0900412 } catch (JsonParseException e) {
413 log.debug("JsonParseException caused by {}", e);
414 } catch (JsonMappingException e) {
415 log.debug("JsonMappingException caused by {}", e);
416 } catch (JsonProcessingException e) {
417 log.debug("JsonProcessingException caused by {}", e);
Jian Lif1efbe52018-07-17 23:20:16 +0900418 } catch (IOException e) {
Daniel Park2ff66b42018-08-01 11:52:45 +0900419 log.debug("IOException caused by {}", e);
Jian Lif1efbe52018-07-17 23:20:16 +0900420 }
421 return null;
422 }
423
424 /**
Jian Li7f024de2018-07-07 03:51:02 +0900425 * Checks the validity of ARP mode.
426 *
427 * @param arpMode ARP mode
428 * @return returns true if the ARP mode is valid, false otherwise
429 */
430 public static boolean checkArpMode(String arpMode) {
431
432 if (isNullOrEmpty(arpMode)) {
433 return false;
434 } else {
435 return arpMode.equals(PROXY_MODE) || arpMode.equals(BROADCAST_MODE);
436 }
437 }
438
439 /**
Jian Liec5c32b2018-07-13 14:28:58 +0900440 * Swaps current location with old location info.
441 * The revised instance port will be used to mod the flow rules after migration.
442 *
443 * @param instPort instance port
444 * @return location swapped instance port
445 */
446 public static InstancePort swapStaleLocation(InstancePort instPort) {
447 return DefaultInstancePort.builder()
448 .deviceId(instPort.oldDeviceId())
449 .portNumber(instPort.oldPortNumber())
450 .state(instPort.state())
451 .ipAddress(instPort.ipAddress())
452 .macAddress(instPort.macAddress())
453 .networkId(instPort.networkId())
454 .portId(instPort.portId())
455 .build();
456 }
457
458 /**
Daniel Park2ff66b42018-08-01 11:52:45 +0900459 * Compares two router interfaces are equal.
460 * Will be remove this after Openstack4j implements equals.
461 *
462 * @param routerInterface1 router interface
463 * @param routerInterface2 router interface
464 * @return returns true if two router interfaces are equal, false otherwise
465 */
466 public static boolean routerInterfacesEquals(RouterInterface routerInterface1, RouterInterface routerInterface2) {
467 return Objects.equals(routerInterface1.getId(), routerInterface2.getId()) &&
468 Objects.equals(routerInterface1.getPortId(), routerInterface2.getPortId()) &&
469 Objects.equals(routerInterface1.getSubnetId(), routerInterface2.getSubnetId()) &&
470 Objects.equals(routerInterface1.getTenantId(), routerInterface2.getTenantId());
471 }
472
Daniel Park7e8c4d82018-08-13 23:47:49 +0900473 public static VnicType vnicType(String portName) {
474 if (portName.startsWith(PORT_NAME_PREFIX_VM) ||
475 portName.startsWith(PORT_NAME_VHOST_USER_PREFIX_VM)) {
476 return VnicType.NORMAL;
477 } else if (isDirectPort(portName)) {
478 return VnicType.DIRECT;
479 } else {
480 return VnicType.UNSUPPORTED;
481 }
482 }
483
484 private static boolean isDirectPort(String portName) {
Daniel Parkec9d1132018-08-19 11:18:03 +0900485 return portNamePrefixMap().values().stream().anyMatch(p -> portName.startsWith(p));
Daniel Park7e8c4d82018-08-13 23:47:49 +0900486 }
487
Daniel Park2ff66b42018-08-01 11:52:45 +0900488 /**
Jian Li51b844c2018-05-31 10:59:03 +0900489 * Builds up and a complete endpoint URL from gateway node.
490 *
491 * @param node gateway node
492 * @return a complete endpoint URL
493 */
494 private static String buildEndpoint(OpenstackNode node) {
495
496 OpenstackAuth auth = node.authentication();
497
498 StringBuilder endpointSb = new StringBuilder();
499 endpointSb.append(auth.protocol().name().toLowerCase());
500 endpointSb.append("://");
Jian Li6d410362018-08-17 09:41:08 +0900501 endpointSb.append(node.endpoint());
Jian Li51b844c2018-05-31 10:59:03 +0900502 return endpointSb.toString();
503 }
504
505 /**
506 * Obtains the SSL config without verifying the certification.
507 *
508 * @return SSL config
509 */
510 private static Config getSslConfig() {
511 // we bypass the SSL certification verification for now
512 // TODO: verify server side SSL using a given certification
513 Config config = Config.newConfig().withSSLVerificationDisabled();
514
515 TrustManager[] trustAllCerts = new TrustManager[]{
516 new X509TrustManager() {
517 public X509Certificate[] getAcceptedIssuers() {
518 return null;
519 }
520
521 public void checkClientTrusted(X509Certificate[] certs,
522 String authType) {
523 }
524
525 public void checkServerTrusted(X509Certificate[] certs,
526 String authType) {
527 }
528 }
529 };
530
531 HostnameVerifier allHostsValid = (hostname, session) -> true;
532
533 try {
534 SSLContext sc = SSLContext.getInstance(SSL_TYPE);
535 sc.init(null, trustAllCerts,
536 new java.security.SecureRandom());
537 HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
538 HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
539
540 config.withSSLContext(sc);
541 } catch (Exception e) {
542 log.error("Failed to access OpenStack service due to {}", e.toString());
543 return null;
544 }
545
546 return config;
547 }
548
549 /**
550 * Obtains the facing object with given openstack perspective.
551 *
552 * @param perspective keystone perspective
553 * @return facing object
554 */
555 private static Facing getFacing(Perspective perspective) {
556
557 switch (perspective) {
558 case PUBLIC:
559 return Facing.PUBLIC;
560 case ADMIN:
561 return Facing.ADMIN;
562 case INTERNAL:
563 return Facing.INTERNAL;
564 default:
565 return null;
566 }
567 }
568
569 /**
570 * Obtains gateway instance by giving index number.
571 *
572 * @param gws a collection of gateway nodes
573 * @param index index number
574 * @return gateway instance
575 */
576 private static OpenstackNode getGwByIndex(Set<OpenstackNode> gws, int index) {
577 Map<String, OpenstackNode> hashMap = new HashMap<>();
578 gws.forEach(gw -> hashMap.put(gw.hostname(), gw));
579 TreeMap<String, OpenstackNode> treeMap = new TreeMap<>(hashMap);
580 Iterator<String> iteratorKey = treeMap.keySet().iterator();
581
582 int intIndex = 0;
583 OpenstackNode gw = null;
584 while (iteratorKey.hasNext()) {
585 String key = iteratorKey.next();
586
587 if (intIndex == index) {
588 gw = treeMap.get(key);
589 }
590 intIndex++;
591 }
592 return gw;
593 }
Jian Li091d8d22018-02-20 10:42:06 +0900594}