blob: 4ee8fa23b0d2f604d49ef2406dc4ef644896d092 [file] [log] [blame]
Jian Li43244382021-01-09 00:19:02 +09001/*
2 * Copyright 2021-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.kubevirtnetworking.util;
17
Jian Lif97a07e2021-01-13 18:05:00 +090018import com.fasterxml.jackson.databind.ObjectMapper;
Jian Li556709c2021-02-03 17:54:28 +090019import com.google.common.base.Strings;
Jian Lid4296d02021-03-12 18:03:58 +090020import com.google.common.collect.ImmutableSet;
Jian Lica20b712021-01-18 00:19:31 +090021import io.fabric8.kubernetes.api.model.Pod;
Jian Li034820d2021-01-15 16:58:48 +090022import io.fabric8.kubernetes.client.ConfigBuilder;
23import io.fabric8.kubernetes.client.DefaultKubernetesClient;
24import io.fabric8.kubernetes.client.KubernetesClient;
Jian Li43244382021-01-09 00:19:02 +090025import org.apache.commons.lang.StringUtils;
Jian Li3ba5c582021-01-14 11:30:36 +090026import org.apache.commons.net.util.SubnetUtils;
Jian Lica20b712021-01-18 00:19:31 +090027import org.json.JSONArray;
28import org.json.JSONException;
29import org.json.JSONObject;
Jian Li858ccd72021-02-04 17:25:01 +090030import org.onlab.osgi.DefaultServiceDirectory;
Daniel Park2884b232021-03-04 18:58:47 +090031import org.onlab.packet.Ip4Address;
Jian Li3ba5c582021-01-14 11:30:36 +090032import org.onlab.packet.IpAddress;
Jian Lica20b712021-01-18 00:19:31 +090033import org.onlab.packet.MacAddress;
Jian Li43244382021-01-09 00:19:02 +090034import org.onosproject.cfg.ConfigProperty;
Jian Lica20b712021-01-18 00:19:31 +090035import org.onosproject.kubevirtnetworking.api.DefaultKubevirtPort;
36import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
Daniel Parkf3136042021-03-10 07:49:11 +090037import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
Jian Lica20b712021-01-18 00:19:31 +090038import org.onosproject.kubevirtnetworking.api.KubevirtPort;
Daniel Park2884b232021-03-04 18:58:47 +090039import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
40import org.onosproject.kubevirtnetworking.api.KubevirtRouterService;
Jian Li034820d2021-01-15 16:58:48 +090041import org.onosproject.kubevirtnode.api.KubevirtApiConfig;
42import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
Jian Li858ccd72021-02-04 17:25:01 +090043import org.onosproject.kubevirtnode.api.KubevirtNode;
Daniel Park2884b232021-03-04 18:58:47 +090044import org.onosproject.kubevirtnode.api.KubevirtNodeService;
Jian Lib6dc08f2021-03-24 15:24:18 +090045import org.onosproject.kubevirtnode.api.KubevirtPhyInterface;
Jian Li858ccd72021-02-04 17:25:01 +090046import org.onosproject.net.DeviceId;
47import org.onosproject.net.Port;
48import org.onosproject.net.PortNumber;
49import org.onosproject.net.device.DeviceService;
Jian Li43244382021-01-09 00:19:02 +090050import org.slf4j.Logger;
51import org.slf4j.LoggerFactory;
52
Jian Lif97a07e2021-01-13 18:05:00 +090053import java.io.IOException;
Jian Li3ba5c582021-01-14 11:30:36 +090054import java.util.Arrays;
55import java.util.HashSet;
Jian Lif97a07e2021-01-13 18:05:00 +090056import java.util.List;
Jian Lica20b712021-01-18 00:19:31 +090057import java.util.Map;
Jian Li858ccd72021-02-04 17:25:01 +090058import java.util.Objects;
Jian Li43244382021-01-09 00:19:02 +090059import java.util.Optional;
60import java.util.Set;
Jian Li3ba5c582021-01-14 11:30:36 +090061import java.util.stream.Collectors;
Jian Li43244382021-01-09 00:19:02 +090062
Jian Li858ccd72021-02-04 17:25:01 +090063import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
Daniel Park2884b232021-03-04 18:58:47 +090064import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
Jian Li858ccd72021-02-04 17:25:01 +090065import static org.onosproject.net.AnnotationKeys.PORT_NAME;
66
Jian Li43244382021-01-09 00:19:02 +090067/**
68 * An utility that used in KubeVirt networking app.
69 */
70public final class KubevirtNetworkingUtil {
71
72 private static final Logger log = LoggerFactory.getLogger(KubevirtNetworkingUtil.class);
73
74 private static final int PORT_NAME_MAX_LENGTH = 15;
Jian Li034820d2021-01-15 16:58:48 +090075 private static final String COLON_SLASH = "://";
76 private static final String COLON = ":";
Jian Li556709c2021-02-03 17:54:28 +090077 private static final String OF_PREFIX = "of:";
Jian Li43244382021-01-09 00:19:02 +090078
Jian Lica20b712021-01-18 00:19:31 +090079 private static final String NETWORK_STATUS_KEY = "k8s.v1.cni.cncf.io/network-status";
80 private static final String NAME = "name";
81 private static final String NETWORK_PREFIX = "default/";
82 private static final String MAC = "mac";
83 private static final String IPS = "ips";
Daniel Parkbabde9c2021-03-09 13:37:42 +090084 private static final String BR_INT = "br-int";
Jian Lica20b712021-01-18 00:19:31 +090085
Jian Li43244382021-01-09 00:19:02 +090086 /**
87 * Prevents object installation from external.
88 */
89 private KubevirtNetworkingUtil() {
90 }
91
92 /**
93 * Obtains the boolean property value with specified property key name.
94 *
Daniel Park2884b232021-03-04 18:58:47 +090095 * @param properties a collection of properties
96 * @param name key name
Jian Li43244382021-01-09 00:19:02 +090097 * @return mapping value
98 */
99 public static boolean getPropertyValueAsBoolean(Set<ConfigProperty> properties,
100 String name) {
101 Optional<ConfigProperty> property =
102 properties.stream().filter(p -> p.name().equals(name)).findFirst();
103
104 return property.map(ConfigProperty::asBoolean).orElse(false);
105 }
106
107 /**
108 * Re-structures the OVS port name.
109 * The length of OVS port name should be not large than 15.
110 *
Daniel Park2884b232021-03-04 18:58:47 +0900111 * @param portName original port name
Jian Li43244382021-01-09 00:19:02 +0900112 * @return re-structured OVS port name
113 */
114 public static String structurePortName(String portName) {
115
116 // The size of OVS port name should not be larger than 15
117 if (portName.length() > PORT_NAME_MAX_LENGTH) {
118 return StringUtils.substring(portName, 0, PORT_NAME_MAX_LENGTH);
119 }
120
121 return portName;
122 }
Jian Lif97a07e2021-01-13 18:05:00 +0900123
124 /**
125 * Generates string format based on the given string length list.
126 *
127 * @param stringLengths a list of string lengths
128 * @return string format (e.g., %-28s%-15s%-24s%-20s%-15s)
129 */
130 public static String genFormatString(List<Integer> stringLengths) {
131 StringBuilder fsb = new StringBuilder();
132 stringLengths.forEach(length -> {
133 fsb.append("%-");
134 fsb.append(length);
135 fsb.append("s");
136 });
137 return fsb.toString();
138 }
139
140 /**
Jian Li556709c2021-02-03 17:54:28 +0900141 * Auto generates DPID from the given name.
142 *
143 * @param name name
144 * @return auto generated DPID
145 */
146 public static String genDpidFromName(String name) {
147 if (name != null) {
148 String hexString = Integer.toHexString(name.hashCode());
149 return OF_PREFIX + Strings.padStart(hexString, 16, '0');
150 }
151
152 return null;
153 }
154
155 /**
Jian Lif97a07e2021-01-13 18:05:00 +0900156 * Prints out the JSON string in pretty format.
157 *
Daniel Park2884b232021-03-04 18:58:47 +0900158 * @param mapper Object mapper
159 * @param jsonString JSON string
Jian Lif97a07e2021-01-13 18:05:00 +0900160 * @return pretty formatted JSON string
161 */
162 public static String prettyJson(ObjectMapper mapper, String jsonString) {
163 try {
164 Object jsonObject = mapper.readValue(jsonString, Object.class);
165 return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
166 } catch (IOException e) {
167 log.debug("Json string parsing exception caused by {}", e);
168 }
169 return null;
170 }
Jian Li3ba5c582021-01-14 11:30:36 +0900171
172 /**
173 * Obtains valid IP addresses of the given subnet.
174 *
175 * @param cidr CIDR
176 * @return set of IP addresses
177 */
178 public static Set<IpAddress> getSubnetIps(String cidr) {
179 SubnetUtils utils = new SubnetUtils(cidr);
180 utils.setInclusiveHostCount(false);
181 SubnetUtils.SubnetInfo info = utils.getInfo();
182 Set<String> allAddresses =
183 new HashSet<>(Arrays.asList(info.getAllAddresses()));
184
185 if (allAddresses.size() > 2) {
186 allAddresses.remove(info.getLowAddress());
187 allAddresses.remove(info.getHighAddress());
188 }
189
190 return allAddresses.stream()
191 .map(IpAddress::valueOf).collect(Collectors.toSet());
192 }
193
194 /**
195 * Calculate the broadcast address from given IP address and subnet prefix length.
196 *
Daniel Park2884b232021-03-04 18:58:47 +0900197 * @param ipAddr IP address
198 * @param prefixLength subnet prefix length
Jian Li3ba5c582021-01-14 11:30:36 +0900199 * @return broadcast address
200 */
201 public static String getBroadcastAddr(String ipAddr, int prefixLength) {
202 String subnet = ipAddr + "/" + prefixLength;
203 SubnetUtils utils = new SubnetUtils(subnet);
204 return utils.getInfo().getBroadcastAddress();
205 }
Daniel Park2884b232021-03-04 18:58:47 +0900206
Jian Li034820d2021-01-15 16:58:48 +0900207 /**
208 * Generates endpoint URL by referring to scheme, ipAddress and port.
209 *
Daniel Park2884b232021-03-04 18:58:47 +0900210 * @param scheme scheme
211 * @param ipAddress IP address
212 * @param port port number
Jian Li034820d2021-01-15 16:58:48 +0900213 * @return generated endpoint URL
214 */
215 public static String endpoint(KubevirtApiConfig.Scheme scheme, IpAddress ipAddress, int port) {
216 StringBuilder endpoint = new StringBuilder();
217 String protocol = org.apache.commons.lang3.StringUtils.lowerCase(scheme.name());
218
219 endpoint.append(protocol);
220 endpoint.append(COLON_SLASH);
221 endpoint.append(ipAddress.toString());
222 endpoint.append(COLON);
223 endpoint.append(port);
224
225 return endpoint.toString();
226 }
227
228 /**
229 * Generates endpoint URL by referring to scheme, ipAddress and port.
230 *
Daniel Park2884b232021-03-04 18:58:47 +0900231 * @param apiConfig kubernetes API config
Jian Li034820d2021-01-15 16:58:48 +0900232 * @return generated endpoint URL
233 */
234 public static String endpoint(KubevirtApiConfig apiConfig) {
235 return endpoint(apiConfig.scheme(), apiConfig.ipAddress(), apiConfig.port());
236 }
237
238 /**
239 * Obtains workable kubernetes client.
240 *
241 * @param config kubernetes API config
242 * @return kubernetes client
243 */
244 public static KubernetesClient k8sClient(KubevirtApiConfig config) {
245 if (config == null) {
246 log.warn("Kubernetes API server config is empty.");
247 return null;
248 }
249
250 String endpoint = endpoint(config);
251
252 ConfigBuilder configBuilder = new ConfigBuilder().withMasterUrl(endpoint);
253
254 if (config.scheme() == KubevirtApiConfig.Scheme.HTTPS) {
255 configBuilder.withTrustCerts(true)
Jian Li034820d2021-01-15 16:58:48 +0900256 .withCaCertData(config.caCertData())
257 .withClientCertData(config.clientCertData())
258 .withClientKeyData(config.clientKeyData());
259 }
260
261 return new DefaultKubernetesClient(configBuilder.build());
262 }
263
264 /**
265 * Obtains workable kubernetes client.
266 *
267 * @param service kubernetes API service
268 * @return kubernetes client
269 */
270 public static KubernetesClient k8sClient(KubevirtApiConfigService service) {
271 KubevirtApiConfig config = service.apiConfig();
272 if (config == null) {
273 log.error("Failed to find valid kubernetes API configuration.");
274 return null;
275 }
276
277 KubernetesClient client = k8sClient(config);
278
279 if (client == null) {
280 log.error("Failed to connect to kubernetes API server.");
281 return null;
282 }
283
284 return client;
285 }
Jian Lica20b712021-01-18 00:19:31 +0900286
287 /**
Jian Li556709c2021-02-03 17:54:28 +0900288 * Obtains the hex string of the given segment ID with fixed padding.
289 *
290 * @param segIdStr segment identifier string
291 * @return hex string with padding
292 */
293 public static String segmentIdHex(String segIdStr) {
294 int segId = Integer.parseInt(segIdStr);
295 return String.format("%06x", segId).toLowerCase();
296 }
297
298 /**
Jian Li858ccd72021-02-04 17:25:01 +0900299 * Obtains the tunnel port number with the given network and node.
300 *
301 * @param network kubevirt network
Daniel Park2884b232021-03-04 18:58:47 +0900302 * @param node kubevirt node
Jian Li858ccd72021-02-04 17:25:01 +0900303 * @return tunnel port number
304 */
305 public static PortNumber tunnelPort(KubevirtNetwork network, KubevirtNode node) {
306 switch (network.type()) {
307 case VXLAN:
308 return node.vxlanPort();
309 case GRE:
310 return node.grePort();
311 case GENEVE:
312 return node.genevePort();
313 default:
314 break;
315 }
316 return null;
317 }
318
319 /**
Jian Lica20b712021-01-18 00:19:31 +0900320 * Obtains the kubevirt port from kubevirt POD.
321 *
Daniel Parkf3136042021-03-10 07:49:11 +0900322 * @param nodeService kubevirt node service
Jian Lica20b712021-01-18 00:19:31 +0900323 * @param networks set of existing kubevirt networks
Daniel Park2884b232021-03-04 18:58:47 +0900324 * @param pod kubevirt POD
Jian Lid4296d02021-03-12 18:03:58 +0900325 * @return kubevirt ports attached to the POD
Jian Lica20b712021-01-18 00:19:31 +0900326 */
Jian Lib6dc08f2021-03-24 15:24:18 +0900327 public static Set<KubevirtPort> getPorts(KubevirtNodeService nodeService,
328 Set<KubevirtNetwork> networks, Pod pod) {
Jian Lica20b712021-01-18 00:19:31 +0900329 try {
330 Map<String, String> annots = pod.getMetadata().getAnnotations();
Jian Li6e66a302021-01-21 20:30:52 +0900331 if (annots == null) {
Jian Lid4296d02021-03-12 18:03:58 +0900332 return ImmutableSet.of();
Jian Li6e66a302021-01-21 20:30:52 +0900333 }
334
Jian Li7a581b12021-02-18 14:24:32 +0900335 if (!annots.containsKey(NETWORK_STATUS_KEY)) {
Jian Lid4296d02021-03-12 18:03:58 +0900336 return ImmutableSet.of();
Jian Li7a581b12021-02-18 14:24:32 +0900337 }
338
Jian Lica20b712021-01-18 00:19:31 +0900339 String networkStatusStr = annots.get(NETWORK_STATUS_KEY);
340
341 if (networkStatusStr == null) {
Jian Lid4296d02021-03-12 18:03:58 +0900342 return ImmutableSet.of();
Jian Lica20b712021-01-18 00:19:31 +0900343 }
Jian Lib6dc08f2021-03-24 15:24:18 +0900344
Daniel Parkf3136042021-03-10 07:49:11 +0900345 KubevirtPort.Builder builder = DefaultKubevirtPort.builder();
346
347 KubevirtNode node = nodeService.node(pod.getSpec().getNodeName());
Jian Lib6dc08f2021-03-24 15:24:18 +0900348
Daniel Parkf3136042021-03-10 07:49:11 +0900349 if (node != null) {
350 builder.deviceId(node.intgBridge());
351 }
Jian Lica20b712021-01-18 00:19:31 +0900352
353 JSONArray networkStatus = new JSONArray(networkStatusStr);
Jian Lid4296d02021-03-12 18:03:58 +0900354 Set<KubevirtPort> ports = new HashSet<>();
Jian Lica20b712021-01-18 00:19:31 +0900355
356 for (int i = 0; i < networkStatus.length(); i++) {
357 JSONObject object = networkStatus.getJSONObject(i);
358 String name = object.getString(NAME);
359 KubevirtNetwork network = networks.stream()
360 .filter(n -> (NETWORK_PREFIX + n.name()).equals(name))
361 .findAny().orElse(null);
362 if (network != null) {
363 String mac = object.getString(MAC);
364
Daniel Parkf3136042021-03-10 07:49:11 +0900365 builder.macAddress(MacAddress.valueOf(mac))
Jian Lica20b712021-01-18 00:19:31 +0900366 .networkId(network.networkId());
367
Jian Lid4296d02021-03-12 18:03:58 +0900368 ports.add(builder.build());
Jian Lica20b712021-01-18 00:19:31 +0900369 }
370 }
371
Jian Lid4296d02021-03-12 18:03:58 +0900372 return ports;
373
Jian Lica20b712021-01-18 00:19:31 +0900374 } catch (JSONException e) {
375 log.error("Failed to parse network status object", e);
376 }
377
Jian Lid4296d02021-03-12 18:03:58 +0900378 return ImmutableSet.of();
Jian Lica20b712021-01-18 00:19:31 +0900379 }
Jian Li858ccd72021-02-04 17:25:01 +0900380
381 /**
382 * Obtains the tunnel bridge to tenant bridge patch port number.
383 *
Daniel Park2884b232021-03-04 18:58:47 +0900384 * @param node kubevirt node
Jian Li858ccd72021-02-04 17:25:01 +0900385 * @param network kubevirt network
386 * @return patch port number
387 */
388 public static PortNumber tunnelToTenantPort(KubevirtNode node, KubevirtNetwork network) {
389 if (network.segmentId() == null) {
390 return null;
391 }
392
393 if (node.tunBridge() == null) {
394 return null;
395 }
396
397 String tunToTenantPortName = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
398 return portNumber(node.tunBridge(), tunToTenantPortName);
399 }
400
401 /**
402 * Obtains the tunnel port number of the given node.
403 *
Daniel Park2884b232021-03-04 18:58:47 +0900404 * @param node kubevirt node
Jian Li858ccd72021-02-04 17:25:01 +0900405 * @param network kubevirt network
406 * @return tunnel port number
407 */
408 public static PortNumber tunnelPort(KubevirtNode node, KubevirtNetwork network) {
409 if (network.segmentId() == null) {
410 return null;
411 }
412
413 if (node.tunBridge() == null) {
414 return null;
415 }
416
417 switch (network.type()) {
418 case VXLAN:
419 return node.vxlanPort();
420 case GRE:
421 return node.grePort();
422 case GENEVE:
423 return node.genevePort();
424 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +0900425 case VLAN:
Jian Li858ccd72021-02-04 17:25:01 +0900426 default:
427 // do nothing
428 return null;
429 }
430 }
431
Jian Li810f58c2021-02-27 01:10:50 +0900432 public static String parseResourceName(String resource) {
433 try {
434 JSONObject json = new JSONObject(resource);
435 return json.getJSONObject("metadata").getString("name");
436 } catch (JSONException e) {
437 log.error("");
438 }
439 return "";
440 }
441
Daniel Parkf3136042021-03-10 07:49:11 +0900442 public static PortNumber portNumber(DeviceId deviceId, String portName) {
Jian Li858ccd72021-02-04 17:25:01 +0900443 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
444 Port port = deviceService.getPorts(deviceId).stream()
445 .filter(p -> p.isEnabled() &&
446 Objects.equals(p.annotations().value(PORT_NAME), portName))
447 .findAny().orElse(null);
448 return port != null ? port.number() : null;
449 }
450
Daniel Park2884b232021-03-04 18:58:47 +0900451 /**
452 * Returns the gateway node for the specified kubevirt router.
453 * Among gateways, only one gateway would act as a gateway per perter.
454 * Currently gateway node is selected based on modulo operation with router hashcode.
455 *
456 * @param nodeService kubevirt node service
457 * @param router kubevirt router
458 * @return elected gateway node
459 */
460 public static KubevirtNode gatewayNodeForSpecifiedRouter(KubevirtNodeService nodeService,
461 KubevirtRouter router) {
462 //TODO: enhance election logic for a better load balancing
463
464 int numOfGateways = nodeService.completeNodes(GATEWAY).size();
465 if (numOfGateways == 0) {
466 return null;
467 }
468 return (KubevirtNode) nodeService.completeNodes(GATEWAY).toArray()[router.hashCode() % numOfGateways];
469 }
470
471 /**
Daniel Parkf3136042021-03-10 07:49:11 +0900472 * Returns the mac address of the router.
473 *
474 * @param router kubevirt router
475 * @return macc address of the router
476 */
477 public static MacAddress getRouterMacAddress(KubevirtRouter router) {
478 if (router.mac() == null) {
479 log.warn("Failed to get mac address of router {}", router.name());
480 }
481
482 return router.mac();
Daniel Park2884b232021-03-04 18:58:47 +0900483 }
484
485 /**
486 * Returns the snat ip address with specified router.
487 *
488 * @param routerService router service
489 * @param internalNetworkId internal network id which is associated with the router
490 * @return snat ip address if exist, null otherwise
491 */
492 public static IpAddress getRouterSnatIpAddress(KubevirtRouterService routerService,
493 String internalNetworkId) {
494 KubevirtRouter router = routerService.routers().stream()
495 .filter(r -> r.internal().contains(internalNetworkId))
496 .findAny().orElse(null);
497
498 if (router == null) {
499 return null;
500 }
501
502 String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
503
504 if (routerSnatIp == null) {
505 return null;
506 }
507
508 return Ip4Address.valueOf(routerSnatIp);
509 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900510
511 /**
512 * Returns the kubevirt router with specified kubevirt port.
513 *
514 * @param routerService kubevirt router service
515 * @param kubevirtPort kubevirt port
516 * @return kubevirt router
517 */
518 public static KubevirtRouter getRouterForKubevirtPort(KubevirtRouterService routerService,
519 KubevirtPort kubevirtPort) {
520 if (kubevirtPort.ipAddress() != null) {
521 return routerService.routers().stream()
522 .filter(r -> r.internal().contains(kubevirtPort.networkId()))
523 .findAny().orElse(null);
524 }
525 return null;
526 }
527
528 /**
529 * Returns the kubevirt router with specified kubevirt network.
530 *
531 * @param routerService kubevirt router service
532 * @param kubevirtNetwork kubevirt network
533 * @return kubevirt router
534 */
535 public static KubevirtRouter getRouterForKubevirtNetwork(KubevirtRouterService routerService,
536 KubevirtNetwork kubevirtNetwork) {
537 return routerService.routers().stream()
538 .filter(router -> router.internal().contains(kubevirtNetwork.networkId()))
539 .findAny().orElse(null);
540 }
Daniel Parkf3136042021-03-10 07:49:11 +0900541
542 /**
543 * Returns the external patch port number with specified gateway.
544 *
545 * @param deviceService device service
Jian Li9793ec42021-03-19 15:03:32 +0900546 * @param gatewayNode gateway node
Daniel Parkf3136042021-03-10 07:49:11 +0900547 * @return external patch port number
548 */
549 public static PortNumber externalPatchPortNum(DeviceService deviceService, KubevirtNode gatewayNode) {
Jian Lib6dc08f2021-03-24 15:24:18 +0900550 KubevirtPhyInterface intf = gatewayNode.phyIntfs().stream().findFirst().orElse(null);
551 if (intf == null) {
Jian Li9793ec42021-03-19 15:03:32 +0900552 log.warn("No external interface is attached to gateway {}", gatewayNode.hostname());
553 return null;
554 }
555
Jian Lib6dc08f2021-03-24 15:24:18 +0900556 String patchPortName = "int-to-" + intf.network();
Daniel Parkf3136042021-03-10 07:49:11 +0900557 Port port = deviceService.getPorts(gatewayNode.intgBridge()).stream()
558 .filter(p -> p.isEnabled() &&
Jian Li9793ec42021-03-19 15:03:32 +0900559 Objects.equals(p.annotations().value(PORT_NAME), patchPortName))
Daniel Parkf3136042021-03-10 07:49:11 +0900560 .findAny().orElse(null);
561
562 return port != null ? port.number() : null;
563 }
564
565 public static KubevirtNetwork getExternalNetworkByRouter(KubevirtNetworkService networkService,
566 KubevirtRouter router) {
567 String networkId = router.external().values().stream().findAny().orElse(null);
568 if (networkId == null) {
569 return null;
570 }
571
572 return networkService.network(networkId);
573 }
Jian Li43244382021-01-09 00:19:02 +0900574}