blob: d60800ac71d2c20cd3facaee5b76679a711db4e0 [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 Li6a53ae62022-10-18 22:43:15 +090018import com.eclipsesource.json.JsonArray;
Andrea Campanella36a57022022-06-09 08:11:25 -070019import com.eclipsesource.json.JsonObject;
Jian Li6a53ae62022-10-18 22:43:15 +090020import com.fasterxml.jackson.core.JsonProcessingException;
Jian Li0c656f02021-06-07 13:32:39 +090021import com.fasterxml.jackson.databind.JsonNode;
Jian Lif97a07e2021-01-13 18:05:00 +090022import com.fasterxml.jackson.databind.ObjectMapper;
Jian Li0c656f02021-06-07 13:32:39 +090023import com.fasterxml.jackson.databind.node.ArrayNode;
Jian Li556709c2021-02-03 17:54:28 +090024import com.google.common.base.Strings;
Jian Lid4296d02021-03-12 18:03:58 +090025import com.google.common.collect.ImmutableSet;
Jian Li6a53ae62022-10-18 22:43:15 +090026import io.fabric8.kubernetes.api.model.Node;
27import io.fabric8.kubernetes.api.model.NodeAddress;
28import io.fabric8.kubernetes.api.model.NodeSpec;
29import io.fabric8.kubernetes.api.model.Taint;
Jian Li034820d2021-01-15 16:58:48 +090030import io.fabric8.kubernetes.client.ConfigBuilder;
31import io.fabric8.kubernetes.client.DefaultKubernetesClient;
32import io.fabric8.kubernetes.client.KubernetesClient;
Jian Li43244382021-01-09 00:19:02 +090033import org.apache.commons.lang.StringUtils;
Jian Li3ba5c582021-01-14 11:30:36 +090034import org.apache.commons.net.util.SubnetUtils;
Daniel Park157947f2021-04-09 17:50:53 +090035import org.onlab.packet.ARP;
36import org.onlab.packet.Ethernet;
Daniel Park2884b232021-03-04 18:58:47 +090037import org.onlab.packet.Ip4Address;
Jian Li3ba5c582021-01-14 11:30:36 +090038import org.onlab.packet.IpAddress;
Jian Li6a53ae62022-10-18 22:43:15 +090039import org.onlab.packet.IpPrefix;
Jian Lica20b712021-01-18 00:19:31 +090040import org.onlab.packet.MacAddress;
Jian Li43244382021-01-09 00:19:02 +090041import org.onosproject.cfg.ConfigProperty;
Jian Li6a53ae62022-10-18 22:43:15 +090042import org.onosproject.kubevirtnetworking.api.DefaultKubevirtNetwork;
Jian Lica20b712021-01-18 00:19:31 +090043import org.onosproject.kubevirtnetworking.api.DefaultKubevirtPort;
Daniel Parkbd5d42b2022-09-26 15:13:59 +090044import org.onosproject.kubevirtnetworking.api.KubernetesExternalLb;
Jian Li6a53ae62022-10-18 22:43:15 +090045import org.onosproject.kubevirtnetworking.api.KubevirtHostRoute;
46import org.onosproject.kubevirtnetworking.api.KubevirtIpPool;
Daniel Park05a94582021-05-12 10:57:02 +090047import org.onosproject.kubevirtnetworking.api.KubevirtLoadBalancer;
48import org.onosproject.kubevirtnetworking.api.KubevirtLoadBalancerService;
Jian Lica20b712021-01-18 00:19:31 +090049import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
Daniel Parkf3136042021-03-10 07:49:11 +090050import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
Jian Lica20b712021-01-18 00:19:31 +090051import org.onosproject.kubevirtnetworking.api.KubevirtPort;
Daniel Park2884b232021-03-04 18:58:47 +090052import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
53import org.onosproject.kubevirtnetworking.api.KubevirtRouterService;
Jian Li6a53ae62022-10-18 22:43:15 +090054import org.onosproject.kubevirtnode.api.DefaultKubevirtNode;
55import org.onosproject.kubevirtnode.api.DefaultKubevirtPhyInterface;
Daniel Park8232cbd2022-10-26 11:57:34 +090056import org.onosproject.kubevirtnode.api.KubernetesExternalLbConfig;
Daniel Parkd846cb72022-09-26 22:58:53 +090057import org.onosproject.kubevirtnode.api.KubernetesExternalLbInterface;
Jian Li034820d2021-01-15 16:58:48 +090058import org.onosproject.kubevirtnode.api.KubevirtApiConfig;
59import org.onosproject.kubevirtnode.api.KubevirtApiConfigService;
Jian Li858ccd72021-02-04 17:25:01 +090060import org.onosproject.kubevirtnode.api.KubevirtNode;
Daniel Park2884b232021-03-04 18:58:47 +090061import org.onosproject.kubevirtnode.api.KubevirtNodeService;
Jian Li6a53ae62022-10-18 22:43:15 +090062import org.onosproject.kubevirtnode.api.KubevirtNodeState;
63import org.onosproject.kubevirtnode.api.KubevirtPhyInterface;
Jian Li858ccd72021-02-04 17:25:01 +090064import org.onosproject.net.DeviceId;
65import org.onosproject.net.Port;
66import org.onosproject.net.PortNumber;
67import org.onosproject.net.device.DeviceService;
Daniel Park05a94582021-05-12 10:57:02 +090068import org.onosproject.net.group.DefaultGroupKey;
69import org.onosproject.net.group.GroupKey;
Jian Li43244382021-01-09 00:19:02 +090070import org.slf4j.Logger;
71import org.slf4j.LoggerFactory;
Jian Li94b6d162021-04-15 17:09:11 +090072import org.xbill.DNS.Address;
Jian Li43244382021-01-09 00:19:02 +090073
Jian Lif97a07e2021-01-13 18:05:00 +090074import java.io.IOException;
Jian Li94b6d162021-04-15 17:09:11 +090075import java.net.InetAddress;
76import java.net.UnknownHostException;
Jian Li3ba5c582021-01-14 11:30:36 +090077import java.util.Arrays;
78import java.util.HashSet;
Jian Lif97a07e2021-01-13 18:05:00 +090079import java.util.List;
Jian Li6a53ae62022-10-18 22:43:15 +090080import java.util.Locale;
81import java.util.Map;
Jian Li858ccd72021-02-04 17:25:01 +090082import java.util.Objects;
Jian Li43244382021-01-09 00:19:02 +090083import java.util.Optional;
84import java.util.Set;
Jian Li3ba5c582021-01-14 11:30:36 +090085import java.util.stream.Collectors;
Jian Li43244382021-01-09 00:19:02 +090086
Jian Li858ccd72021-02-04 17:25:01 +090087import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
Jian Li6a53ae62022-10-18 22:43:15 +090088import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
89import static org.onosproject.kubevirtnode.api.Constants.SONA_PROJECT_DOMAIN;
Daniel Park2884b232021-03-04 18:58:47 +090090import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.GATEWAY;
Jian Li6a53ae62022-10-18 22:43:15 +090091import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.MASTER;
92import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.OTHER;
93import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
Daniel Parkd846cb72022-09-26 22:58:53 +090094import static org.onosproject.net.AnnotationKeys.PORT_MAC;
Jian Li858ccd72021-02-04 17:25:01 +090095import static org.onosproject.net.AnnotationKeys.PORT_NAME;
96
Jian Li43244382021-01-09 00:19:02 +090097/**
98 * An utility that used in KubeVirt networking app.
99 */
100public final class KubevirtNetworkingUtil {
101
102 private static final Logger log = LoggerFactory.getLogger(KubevirtNetworkingUtil.class);
103
104 private static final int PORT_NAME_MAX_LENGTH = 15;
Jian Li034820d2021-01-15 16:58:48 +0900105 private static final String COLON_SLASH = "://";
106 private static final String COLON = ":";
Jian Li556709c2021-02-03 17:54:28 +0900107 private static final String OF_PREFIX = "of:";
Jian Li43244382021-01-09 00:19:02 +0900108
Jian Lica20b712021-01-18 00:19:31 +0900109 private static final String NETWORK_STATUS_KEY = "k8s.v1.cni.cncf.io/network-status";
110 private static final String NAME = "name";
111 private static final String NETWORK_PREFIX = "default/";
112 private static final String MAC = "mac";
113 private static final String IPS = "ips";
Daniel Parkbabde9c2021-03-09 13:37:42 +0900114 private static final String BR_INT = "br-int";
Jian Li9557e902021-06-08 10:12:52 +0900115 private static final String METADATA = "metadata";
Jian Li0c656f02021-06-07 13:32:39 +0900116 private static final String STATUS = "status";
117 private static final String INTERFACES = "interfaces";
Jian Li0c656f02021-06-07 13:32:39 +0900118 private static final String NODE_NAME = "nodeName";
Jian Lica20b712021-01-18 00:19:31 +0900119
Jian Li6a53ae62022-10-18 22:43:15 +0900120 private static final String NETWORK_CONFIG = "network-config";
121 private static final String TYPE = "type";
122 private static final String MTU = "mtu";
123 private static final String SEGMENT_ID = "segmentId";
124 private static final String GATEWAY_IP = "gatewayIp";
125 private static final String DEFAULT_ROUTE = "defaultRoute";
126 private static final String CIDR = "cidr";
127 private static final String HOST_ROUTES = "hostRoutes";
128 private static final String DESTINATION = "destination";
129 private static final String NEXTHOP = "nexthop";
130 private static final String IP_POOL = "ipPool";
131 private static final String START = "start";
132 private static final String END = "end";
133 private static final String DNSES = "dnses";
134
135 private static final String INTERNAL_IP = "InternalIP";
136 private static final String K8S_ROLE = "node-role.kubernetes.io";
137 private static final String PHYSNET_CONFIG_KEY = SONA_PROJECT_DOMAIN + "/physnet-config";
138 private static final String DATA_IP_KEY = SONA_PROJECT_DOMAIN + "/data-ip";
139 private static final String GATEWAY_CONFIG_KEY = SONA_PROJECT_DOMAIN + "/gateway-config";
140 private static final String GATEWAY_BRIDGE_NAME = "gatewayBridgeName";
141 private static final String NETWORK_KEY = "network";
142 private static final String INTERFACE_KEY = "interface";
143 private static final String PHYS_BRIDGE_ID = "physBridgeId";
144
145 private static final String NO_SCHEDULE_EFFECT = "NoSchedule";
146 private static final String KUBEVIRT_IO_KEY = "kubevirt.io/drain";
147 private static final String DRAINING_VALUE = "draining";
148
Jian Li43244382021-01-09 00:19:02 +0900149 /**
150 * Prevents object installation from external.
151 */
152 private KubevirtNetworkingUtil() {
153 }
154
155 /**
156 * Obtains the boolean property value with specified property key name.
157 *
Daniel Park2884b232021-03-04 18:58:47 +0900158 * @param properties a collection of properties
159 * @param name key name
Jian Li43244382021-01-09 00:19:02 +0900160 * @return mapping value
161 */
162 public static boolean getPropertyValueAsBoolean(Set<ConfigProperty> properties,
163 String name) {
164 Optional<ConfigProperty> property =
165 properties.stream().filter(p -> p.name().equals(name)).findFirst();
166
167 return property.map(ConfigProperty::asBoolean).orElse(false);
168 }
169
170 /**
171 * Re-structures the OVS port name.
172 * The length of OVS port name should be not large than 15.
173 *
Daniel Park2884b232021-03-04 18:58:47 +0900174 * @param portName original port name
Jian Li43244382021-01-09 00:19:02 +0900175 * @return re-structured OVS port name
176 */
177 public static String structurePortName(String portName) {
178
179 // The size of OVS port name should not be larger than 15
180 if (portName.length() > PORT_NAME_MAX_LENGTH) {
181 return StringUtils.substring(portName, 0, PORT_NAME_MAX_LENGTH);
182 }
183
184 return portName;
185 }
Jian Lif97a07e2021-01-13 18:05:00 +0900186
187 /**
188 * Generates string format based on the given string length list.
189 *
190 * @param stringLengths a list of string lengths
191 * @return string format (e.g., %-28s%-15s%-24s%-20s%-15s)
192 */
193 public static String genFormatString(List<Integer> stringLengths) {
194 StringBuilder fsb = new StringBuilder();
195 stringLengths.forEach(length -> {
196 fsb.append("%-");
197 fsb.append(length);
198 fsb.append("s");
199 });
200 return fsb.toString();
201 }
202
203 /**
Jian Li556709c2021-02-03 17:54:28 +0900204 * Auto generates DPID from the given name.
205 *
206 * @param name name
207 * @return auto generated DPID
208 */
209 public static String genDpidFromName(String name) {
210 if (name != null) {
211 String hexString = Integer.toHexString(name.hashCode());
212 return OF_PREFIX + Strings.padStart(hexString, 16, '0');
213 }
214
215 return null;
216 }
217
218 /**
Jian Lif97a07e2021-01-13 18:05:00 +0900219 * Prints out the JSON string in pretty format.
220 *
Daniel Park2884b232021-03-04 18:58:47 +0900221 * @param mapper Object mapper
222 * @param jsonString JSON string
Jian Lif97a07e2021-01-13 18:05:00 +0900223 * @return pretty formatted JSON string
224 */
225 public static String prettyJson(ObjectMapper mapper, String jsonString) {
226 try {
227 Object jsonObject = mapper.readValue(jsonString, Object.class);
228 return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
229 } catch (IOException e) {
230 log.debug("Json string parsing exception caused by {}", e);
231 }
232 return null;
233 }
Jian Li3ba5c582021-01-14 11:30:36 +0900234
235 /**
236 * Obtains valid IP addresses of the given subnet.
237 *
238 * @param cidr CIDR
239 * @return set of IP addresses
240 */
241 public static Set<IpAddress> getSubnetIps(String cidr) {
242 SubnetUtils utils = new SubnetUtils(cidr);
243 utils.setInclusiveHostCount(false);
244 SubnetUtils.SubnetInfo info = utils.getInfo();
245 Set<String> allAddresses =
246 new HashSet<>(Arrays.asList(info.getAllAddresses()));
247
248 if (allAddresses.size() > 2) {
249 allAddresses.remove(info.getLowAddress());
250 allAddresses.remove(info.getHighAddress());
251 }
252
253 return allAddresses.stream()
254 .map(IpAddress::valueOf).collect(Collectors.toSet());
255 }
256
257 /**
258 * Calculate the broadcast address from given IP address and subnet prefix length.
259 *
Daniel Park2884b232021-03-04 18:58:47 +0900260 * @param ipAddr IP address
261 * @param prefixLength subnet prefix length
Jian Li3ba5c582021-01-14 11:30:36 +0900262 * @return broadcast address
263 */
264 public static String getBroadcastAddr(String ipAddr, int prefixLength) {
265 String subnet = ipAddr + "/" + prefixLength;
266 SubnetUtils utils = new SubnetUtils(subnet);
267 return utils.getInfo().getBroadcastAddress();
268 }
Daniel Park2884b232021-03-04 18:58:47 +0900269
Jian Li034820d2021-01-15 16:58:48 +0900270 /**
271 * Generates endpoint URL by referring to scheme, ipAddress and port.
272 *
Daniel Park2884b232021-03-04 18:58:47 +0900273 * @param scheme scheme
274 * @param ipAddress IP address
275 * @param port port number
Jian Li034820d2021-01-15 16:58:48 +0900276 * @return generated endpoint URL
277 */
278 public static String endpoint(KubevirtApiConfig.Scheme scheme, IpAddress ipAddress, int port) {
279 StringBuilder endpoint = new StringBuilder();
280 String protocol = org.apache.commons.lang3.StringUtils.lowerCase(scheme.name());
281
282 endpoint.append(protocol);
283 endpoint.append(COLON_SLASH);
284 endpoint.append(ipAddress.toString());
285 endpoint.append(COLON);
286 endpoint.append(port);
287
288 return endpoint.toString();
289 }
290
291 /**
292 * Generates endpoint URL by referring to scheme, ipAddress and port.
293 *
Daniel Park2884b232021-03-04 18:58:47 +0900294 * @param apiConfig kubernetes API config
Jian Li034820d2021-01-15 16:58:48 +0900295 * @return generated endpoint URL
296 */
297 public static String endpoint(KubevirtApiConfig apiConfig) {
298 return endpoint(apiConfig.scheme(), apiConfig.ipAddress(), apiConfig.port());
299 }
300
301 /**
302 * Obtains workable kubernetes client.
303 *
304 * @param config kubernetes API config
305 * @return kubernetes client
306 */
307 public static KubernetesClient k8sClient(KubevirtApiConfig config) {
308 if (config == null) {
309 log.warn("Kubernetes API server config is empty.");
310 return null;
311 }
312
313 String endpoint = endpoint(config);
314
315 ConfigBuilder configBuilder = new ConfigBuilder().withMasterUrl(endpoint);
316
317 if (config.scheme() == KubevirtApiConfig.Scheme.HTTPS) {
318 configBuilder.withTrustCerts(true)
Jian Li034820d2021-01-15 16:58:48 +0900319 .withCaCertData(config.caCertData())
320 .withClientCertData(config.clientCertData())
321 .withClientKeyData(config.clientKeyData());
322 }
323
324 return new DefaultKubernetesClient(configBuilder.build());
325 }
326
327 /**
328 * Obtains workable kubernetes client.
329 *
330 * @param service kubernetes API service
331 * @return kubernetes client
332 */
333 public static KubernetesClient k8sClient(KubevirtApiConfigService service) {
334 KubevirtApiConfig config = service.apiConfig();
335 if (config == null) {
336 log.error("Failed to find valid kubernetes API configuration.");
337 return null;
338 }
339
340 KubernetesClient client = k8sClient(config);
341
342 if (client == null) {
343 log.error("Failed to connect to kubernetes API server.");
344 return null;
345 }
346
347 return client;
348 }
Jian Lica20b712021-01-18 00:19:31 +0900349
350 /**
Jian Li556709c2021-02-03 17:54:28 +0900351 * Obtains the hex string of the given segment ID with fixed padding.
352 *
353 * @param segIdStr segment identifier string
354 * @return hex string with padding
355 */
356 public static String segmentIdHex(String segIdStr) {
357 int segId = Integer.parseInt(segIdStr);
358 return String.format("%06x", segId).toLowerCase();
359 }
360
361 /**
Jian Li858ccd72021-02-04 17:25:01 +0900362 * Obtains the tunnel port number with the given network and node.
363 *
364 * @param network kubevirt network
Daniel Park2884b232021-03-04 18:58:47 +0900365 * @param node kubevirt node
Jian Li858ccd72021-02-04 17:25:01 +0900366 * @return tunnel port number
367 */
368 public static PortNumber tunnelPort(KubevirtNetwork network, KubevirtNode node) {
369 switch (network.type()) {
370 case VXLAN:
371 return node.vxlanPort();
372 case GRE:
373 return node.grePort();
374 case GENEVE:
375 return node.genevePort();
Jian Li78e82f92022-03-23 13:07:19 +0900376 case STT:
377 return node.sttPort();
Jian Li858ccd72021-02-04 17:25:01 +0900378 default:
379 break;
380 }
381 return null;
382 }
383
384 /**
Jian Li0c656f02021-06-07 13:32:39 +0900385 * Obtains the kubevirt port from kubevirt VMI.
Jian Lica20b712021-01-18 00:19:31 +0900386 *
Daniel Parkf3136042021-03-10 07:49:11 +0900387 * @param nodeService kubevirt node service
Jian Lica20b712021-01-18 00:19:31 +0900388 * @param networks set of existing kubevirt networks
Jian Li0c656f02021-06-07 13:32:39 +0900389 * @param resource VMI definition
390 * @return kubevirt ports attached to the VMI
Jian Lica20b712021-01-18 00:19:31 +0900391 */
Jian Lib6dc08f2021-03-24 15:24:18 +0900392 public static Set<KubevirtPort> getPorts(KubevirtNodeService nodeService,
Jian Li0c656f02021-06-07 13:32:39 +0900393 Set<KubevirtNetwork> networks,
394 String resource) {
Jian Lica20b712021-01-18 00:19:31 +0900395 try {
Jian Li0c656f02021-06-07 13:32:39 +0900396 ObjectMapper mapper = new ObjectMapper();
397 JsonNode json = mapper.readTree(resource);
398 JsonNode statusJson = json.get(STATUS);
399 ArrayNode interfacesJson = (ArrayNode) statusJson.get(INTERFACES);
Jian Li9557e902021-06-08 10:12:52 +0900400 String vmName = parseResourceName(resource);
Jian Lib6dc08f2021-03-24 15:24:18 +0900401
Daniel Parkf3136042021-03-10 07:49:11 +0900402 KubevirtPort.Builder builder = DefaultKubevirtPort.builder();
Jian Li0c656f02021-06-07 13:32:39 +0900403 String nodeName = parseVmiNodeName(resource);
404 if (nodeName != null && nodeService.node(nodeName) != null) {
405 builder.deviceId(nodeService.node(nodeName).intgBridge());
Daniel Parkf3136042021-03-10 07:49:11 +0900406 }
Jian Lica20b712021-01-18 00:19:31 +0900407
Jian Li0c656f02021-06-07 13:32:39 +0900408 if (interfacesJson == null) {
409 return ImmutableSet.of();
410 }
Jian Lica20b712021-01-18 00:19:31 +0900411
Jian Li0c656f02021-06-07 13:32:39 +0900412 Set<KubevirtPort> ports = new HashSet<>();
413 for (JsonNode interfaceJson : interfacesJson) {
Jian Li56f241b2021-06-30 20:59:43 +0900414 JsonNode jsonName = interfaceJson.get(NAME);
415
416 // in some cases, name attribute may not be available from the
417 // interface, we skip inspect this interface
418 if (jsonName == null) {
419 continue;
420 }
421
422 String name = jsonName.asText();
Jian Lica20b712021-01-18 00:19:31 +0900423 KubevirtNetwork network = networks.stream()
Jian Li0c656f02021-06-07 13:32:39 +0900424 .filter(n -> (NETWORK_PREFIX + n.name()).equals(name) ||
425 (n.name() + "-net").equals(name))
Jian Lica20b712021-01-18 00:19:31 +0900426 .findAny().orElse(null);
Jian Li00694812024-03-19 20:49:10 +0900427 if (network != null && interfaceJson.get(MAC) != null) {
Jian Li0c656f02021-06-07 13:32:39 +0900428 // FIXME: we do not update IP address, as learning IP address
429 // requires much more time due to the lag from VM agent
430 String mac = interfaceJson.get(MAC).asText();
Jian Li9557e902021-06-08 10:12:52 +0900431 builder.vmName(vmName)
432 .macAddress(MacAddress.valueOf(mac))
Jian Lica20b712021-01-18 00:19:31 +0900433 .networkId(network.networkId());
Jian Lid4296d02021-03-12 18:03:58 +0900434 ports.add(builder.build());
Jian Lica20b712021-01-18 00:19:31 +0900435 }
436 }
Jian Lid4296d02021-03-12 18:03:58 +0900437 return ports;
Jian Li0c656f02021-06-07 13:32:39 +0900438 } catch (IOException e) {
439 log.error("Failed to parse port info from VMI object", e);
440 }
441 return ImmutableSet.of();
442 }
Jian Lid4296d02021-03-12 18:03:58 +0900443
Jian Li0c656f02021-06-07 13:32:39 +0900444 public static String parseVmiNodeName(String resource) {
445 String nodeName = null;
446 try {
447 ObjectMapper mapper = new ObjectMapper();
448 JsonNode json = mapper.readTree(resource);
449 JsonNode statusJson = json.get(STATUS);
450 JsonNode nodeNameJson = statusJson.get(NODE_NAME);
451 nodeName = nodeNameJson != null ? nodeNameJson.asText() : null;
452 } catch (IOException e) {
453 log.error("Failed to parse kubevirt VMI nodename");
Jian Lica20b712021-01-18 00:19:31 +0900454 }
455
Jian Li0c656f02021-06-07 13:32:39 +0900456 return nodeName;
Jian Lica20b712021-01-18 00:19:31 +0900457 }
Jian Li858ccd72021-02-04 17:25:01 +0900458
459 /**
Jian Lifb3bdbc2024-05-02 13:54:23 +0900460 * Gets the number of tenant networks which have the identical segmentation ID of the given network.
461 *
462 * @param networkService network service
463 * @param network kubevirt network
464 * @return number of tenant networks
465 */
466 public static long numOfDupSegNetworks(KubevirtNetworkService networkService, KubevirtNetwork network) {
467 return networkService.networks().stream()
468 .filter(n -> Objects.equals(network.segmentId(), n.segmentId()))
469 .filter(n -> !Objects.equals(network.networkId(), n.networkId())).count();
470 }
471
472 /**
Jian Li858ccd72021-02-04 17:25:01 +0900473 * Obtains the tunnel bridge to tenant bridge patch port number.
474 *
Jian Li34fff802021-07-01 10:04:04 +0900475 * @param deviceService device service
Daniel Park2884b232021-03-04 18:58:47 +0900476 * @param node kubevirt node
Jian Li858ccd72021-02-04 17:25:01 +0900477 * @param network kubevirt network
478 * @return patch port number
479 */
Jian Li34fff802021-07-01 10:04:04 +0900480 public static PortNumber tunnelToTenantPort(DeviceService deviceService,
481 KubevirtNode node, KubevirtNetwork network) {
Jian Li858ccd72021-02-04 17:25:01 +0900482 if (network.segmentId() == null) {
483 return null;
484 }
485
486 if (node.tunBridge() == null) {
487 return null;
488 }
489
490 String tunToTenantPortName = TUNNEL_TO_TENANT_PREFIX + segmentIdHex(network.segmentId());
Jian Li34fff802021-07-01 10:04:04 +0900491 return portNumber(deviceService, node.tunBridge(), tunToTenantPortName);
Jian Li858ccd72021-02-04 17:25:01 +0900492 }
493
494 /**
495 * Obtains the tunnel port number of the given node.
496 *
Daniel Park2884b232021-03-04 18:58:47 +0900497 * @param node kubevirt node
Jian Li858ccd72021-02-04 17:25:01 +0900498 * @param network kubevirt network
499 * @return tunnel port number
500 */
501 public static PortNumber tunnelPort(KubevirtNode node, KubevirtNetwork network) {
502 if (network.segmentId() == null) {
503 return null;
504 }
505
506 if (node.tunBridge() == null) {
507 return null;
508 }
509
510 switch (network.type()) {
511 case VXLAN:
512 return node.vxlanPort();
513 case GRE:
514 return node.grePort();
515 case GENEVE:
516 return node.genevePort();
Jian Li78e82f92022-03-23 13:07:19 +0900517 case STT:
518 return node.sttPort();
Jian Li858ccd72021-02-04 17:25:01 +0900519 case FLAT:
Jian Li2ce718e2021-02-17 20:42:15 +0900520 case VLAN:
Jian Li858ccd72021-02-04 17:25:01 +0900521 default:
522 // do nothing
523 return null;
524 }
525 }
526
Jian Li810f58c2021-02-27 01:10:50 +0900527 public static String parseResourceName(String resource) {
Andrea Campanella36a57022022-06-09 08:11:25 -0700528 JsonObject json = JsonObject.readFrom(resource);
529 JsonObject metadata = json.get("metadata").asObject();
530 return metadata != null ? metadata.get("name").asString() : "";
Jian Li810f58c2021-02-27 01:10:50 +0900531 }
532
Jian Li34fff802021-07-01 10:04:04 +0900533 public static PortNumber portNumber(DeviceService deviceService, DeviceId deviceId, String portName) {
Jian Li858ccd72021-02-04 17:25:01 +0900534 Port port = deviceService.getPorts(deviceId).stream()
535 .filter(p -> p.isEnabled() &&
536 Objects.equals(p.annotations().value(PORT_NAME), portName))
537 .findAny().orElse(null);
538 return port != null ? port.number() : null;
539 }
540
Daniel Park2884b232021-03-04 18:58:47 +0900541 /**
542 * Returns the gateway node for the specified kubevirt router.
543 * Among gateways, only one gateway would act as a gateway per perter.
544 * Currently gateway node is selected based on modulo operation with router hashcode.
545 *
546 * @param nodeService kubevirt node service
547 * @param router kubevirt router
548 * @return elected gateway node
549 */
550 public static KubevirtNode gatewayNodeForSpecifiedRouter(KubevirtNodeService nodeService,
551 KubevirtRouter router) {
552 //TODO: enhance election logic for a better load balancing
553
554 int numOfGateways = nodeService.completeNodes(GATEWAY).size();
555 if (numOfGateways == 0) {
556 return null;
557 }
Daniel Park17246aa2022-11-11 08:59:45 +0900558 return (KubevirtNode) nodeService.completeNodes(GATEWAY)
559 .toArray()[Math.floorMod(router.hashCode(), numOfGateways)];
Daniel Park2884b232021-03-04 18:58:47 +0900560 }
561
562 /**
Daniel Parkbd5d42b2022-09-26 15:13:59 +0900563 * Returns the gateway node for the specified kubernetes external lb.
564 * Among gateways, only one gateway would act as a gateway per external lb.
Daniel Parkd846cb72022-09-26 22:58:53 +0900565 * Currently gateway node is selected based on modulo operation with external lb hashcode.
Daniel Parkbd5d42b2022-09-26 15:13:59 +0900566 *
567 * @param nodeService kubevirt node service
568 * @param externalLb kubernetes external lb
569 * @return elected gateway node
570 */
571 public static KubevirtNode gatewayNodeForSpecifiedService(KubevirtNodeService nodeService,
572 KubernetesExternalLb externalLb) {
573 //TODO: enhance election logic for a better load balancing
Daniel Park17246aa2022-11-11 08:59:45 +0900574 try {
575 int numOfGateways = nodeService.completeExternalLbGatewayNodes().size();
576 if (numOfGateways == 0) {
577 return null;
578 }
Daniel Parkbd5d42b2022-09-26 15:13:59 +0900579
Daniel Park17246aa2022-11-11 08:59:45 +0900580 return (KubevirtNode) nodeService.completeExternalLbGatewayNodes()
581 .toArray()[Math.floorMod(externalLb.hashCode(), numOfGateways)];
582 } catch (IndexOutOfBoundsException e) {
583 log.error("IndexOutOfBoundsException occurred {}", e.toString());
Daniel Parkbd5d42b2022-09-26 15:13:59 +0900584 return null;
585 }
Daniel Parkbd5d42b2022-09-26 15:13:59 +0900586 }
587
588 /**
Daniel Park8232cbd2022-10-26 11:57:34 +0900589 * Returns whether a mac address in kubernetes external lb config is updated.
590 *
591 * @param externalLbConfig kubernetes external lb config
592 * @return true if a mac address is added
593 */
594 public static boolean configMapUpdated(KubernetesExternalLbConfig externalLbConfig) {
595 if (externalLbConfig == null) {
596 return false;
597 }
598
599 return externalLbConfig.configName() != null && externalLbConfig.globalIpRange() != null &&
600 externalLbConfig.loadBalancerGwIp() != null && externalLbConfig.loadBalancerGwMac() != null;
601 }
602
603
604 /**
Daniel Parkd846cb72022-09-26 22:58:53 +0900605 * Returns the worker node for the specified kubernetes external lb.
606 * Among worker nodes, only one worker would serve the traffic from and to the gateway.
607 * Currently worker node is selected based on modulo operation with external lb hashcode.
608 *
609 * @param nodeService kubevirt node service
610 * @param externalLb kubernetes external lb
611 * @return elected worker node
612 */
613 public static KubevirtNode workerNodeForSpecifiedService(KubevirtNodeService nodeService,
614 KubernetesExternalLb externalLb) {
615 //TODO: enhance election logic for a better load balancing
616
617 int numOfWorkers = nodeService.completeNodes(WORKER).size();
618 if (numOfWorkers == 0) {
619 return null;
620 }
621
622 return (KubevirtNode) nodeService.completeNodes(WORKER)
623 .toArray()[externalLb.hashCode() % numOfWorkers];
624 }
625
626 /**
Daniel Parkf3136042021-03-10 07:49:11 +0900627 * Returns the mac address of the router.
628 *
629 * @param router kubevirt router
630 * @return macc address of the router
631 */
632 public static MacAddress getRouterMacAddress(KubevirtRouter router) {
633 if (router.mac() == null) {
634 log.warn("Failed to get mac address of router {}", router.name());
635 }
636
637 return router.mac();
Daniel Park2884b232021-03-04 18:58:47 +0900638 }
639
640 /**
641 * Returns the snat ip address with specified router.
642 *
643 * @param routerService router service
644 * @param internalNetworkId internal network id which is associated with the router
645 * @return snat ip address if exist, null otherwise
646 */
647 public static IpAddress getRouterSnatIpAddress(KubevirtRouterService routerService,
648 String internalNetworkId) {
649 KubevirtRouter router = routerService.routers().stream()
650 .filter(r -> r.internal().contains(internalNetworkId))
651 .findAny().orElse(null);
652
653 if (router == null) {
654 return null;
655 }
656
657 String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
658
659 if (routerSnatIp == null) {
660 return null;
661 }
662
663 return Ip4Address.valueOf(routerSnatIp);
664 }
Daniel Parkbabde9c2021-03-09 13:37:42 +0900665
666 /**
667 * Returns the kubevirt router with specified kubevirt port.
668 *
669 * @param routerService kubevirt router service
670 * @param kubevirtPort kubevirt port
671 * @return kubevirt router
672 */
673 public static KubevirtRouter getRouterForKubevirtPort(KubevirtRouterService routerService,
674 KubevirtPort kubevirtPort) {
675 if (kubevirtPort.ipAddress() != null) {
676 return routerService.routers().stream()
677 .filter(r -> r.internal().contains(kubevirtPort.networkId()))
678 .findAny().orElse(null);
679 }
680 return null;
681 }
682
683 /**
684 * Returns the kubevirt router with specified kubevirt network.
685 *
686 * @param routerService kubevirt router service
687 * @param kubevirtNetwork kubevirt network
688 * @return kubevirt router
689 */
690 public static KubevirtRouter getRouterForKubevirtNetwork(KubevirtRouterService routerService,
691 KubevirtNetwork kubevirtNetwork) {
692 return routerService.routers().stream()
693 .filter(router -> router.internal().contains(kubevirtNetwork.networkId()))
694 .findAny().orElse(null);
695 }
Daniel Parkf3136042021-03-10 07:49:11 +0900696
697 /**
698 * Returns the external patch port number with specified gateway.
699 *
700 * @param deviceService device service
Jian Li9793ec42021-03-19 15:03:32 +0900701 * @param gatewayNode gateway node
Daniel Parkf3136042021-03-10 07:49:11 +0900702 * @return external patch port number
703 */
704 public static PortNumber externalPatchPortNum(DeviceService deviceService, KubevirtNode gatewayNode) {
Jian Li63f191f2021-03-25 17:14:40 +0900705 String gatewayBridgeName = gatewayNode.gatewayBridgeName();
706 if (gatewayBridgeName == null) {
Jian Li9793ec42021-03-19 15:03:32 +0900707 log.warn("No external interface is attached to gateway {}", gatewayNode.hostname());
708 return null;
709 }
710
Jian Li63f191f2021-03-25 17:14:40 +0900711 String patchPortName = "int-to-" + gatewayBridgeName;
Daniel Parkf3136042021-03-10 07:49:11 +0900712 Port port = deviceService.getPorts(gatewayNode.intgBridge()).stream()
713 .filter(p -> p.isEnabled() &&
Jian Li9793ec42021-03-19 15:03:32 +0900714 Objects.equals(p.annotations().value(PORT_NAME), patchPortName))
Daniel Parkf3136042021-03-10 07:49:11 +0900715 .findAny().orElse(null);
716
717 return port != null ? port.number() : null;
718 }
719
Daniel Park157947f2021-04-09 17:50:53 +0900720 /**
Daniel Parkd846cb72022-09-26 22:58:53 +0900721 * Returns the external lb patch port number with specified gateway.
722 *
723 * @param deviceService device service
724 * @param gateway gateway node
725 * @return external lb bridge patch port number
726 */
727 public static PortNumber elbPatchPortNum(DeviceService deviceService, KubevirtNode gateway) {
728 KubernetesExternalLbInterface kubernetesExternalLbInterface =
729 gateway.kubernetesExternalLbInterface();
730
731 if (kubernetesExternalLbInterface == null) {
732 log.warn("No elb interface is attached to gateway {}", gateway.hostname());
733 return null;
734 }
735
736 String elbBridgeName = kubernetesExternalLbInterface.externalLbBridgeName();
737
738 String patchPortName = "int-to-" + elbBridgeName;
739
740 Port port = deviceService.getPorts(gateway.intgBridge()).stream()
741 .filter(p -> p.isEnabled() &&
742 Objects.equals(p.annotations().value(PORT_NAME), patchPortName))
743 .findAny().orElse(null);
744
745 return port != null ? port.number() : null;
746 }
747
748 /**
749 * Returns the external lb patch port Mac with specified gateway.
750 *
751 * @param deviceService device service
752 * @param gateway gateway node
753 * @return external lb bridge patch Mac Address
754 */
755 public static MacAddress kubernetesElbMac(DeviceService deviceService, KubevirtNode gateway) {
756
757 KubernetesExternalLbInterface kubernetesExternalLbInterface =
758 gateway.kubernetesExternalLbInterface();
759
760 if (kubernetesExternalLbInterface == null) {
761 log.warn("No elb interface is attached to gateway {}", gateway.hostname());
762 return null;
763 }
764
765 String elbBridgeName = kubernetesExternalLbInterface.externalLbBridgeName();
766
767 String patchPortName = "int-to-" + elbBridgeName;
768
769 Port port = deviceService.getPorts(gateway.intgBridge()).stream()
770 .filter(p -> p.isEnabled() &&
771 Objects.equals(p.annotations().value(PORT_NAME), patchPortName))
772 .findAny().orElse(null);
773
774 if (port == null) {
775 return null;
776 }
777
778 String portMacStr = port.annotations().value(PORT_MAC);
779
780 if (portMacStr == null) {
781 return null;
782 }
783
784 return MacAddress.valueOf(portMacStr);
785 }
786
787 /**
Daniel Park157947f2021-04-09 17:50:53 +0900788 * Returns the kubevirt external network with specified router.
789 *
790 * @param networkService kubevirt network service
791 * @param router kubevirt router
792 * @return external network
793 */
Daniel Parkf3136042021-03-10 07:49:11 +0900794 public static KubevirtNetwork getExternalNetworkByRouter(KubevirtNetworkService networkService,
795 KubevirtRouter router) {
796 String networkId = router.external().values().stream().findAny().orElse(null);
797 if (networkId == null) {
798 return null;
799 }
800
801 return networkService.network(networkId);
802 }
Daniel Park157947f2021-04-09 17:50:53 +0900803
Jian Li94b6d162021-04-15 17:09:11 +0900804 /**
805 * Resolve a DNS with the given DNS server and hostname.
806 *
807 * @param hostname hostname to be resolved
808 * @return resolved IP address
809 */
810 public static IpAddress resolveHostname(String hostname) {
811 try {
812 InetAddress addr = Address.getByName(hostname);
813 return IpAddress.valueOf(IpAddress.Version.INET, addr.getAddress());
814 } catch (UnknownHostException e) {
815 log.warn("Failed to resolve IP address of host {}", hostname);
816 }
817 return null;
818 }
819
820 /**
821 * Builds a GARP packet using the given source MAC and source IP address.
822 *
823 * @param srcMac source MAC address
824 * @param srcIp source IP address
825 * @return GARP packet
826 */
Daniel Park157947f2021-04-09 17:50:53 +0900827 public static Ethernet buildGarpPacket(MacAddress srcMac, IpAddress srcIp) {
828 if (srcMac == null || srcIp == null) {
829 return null;
830 }
831
832 Ethernet ethernet = new Ethernet();
833 ethernet.setDestinationMACAddress(MacAddress.BROADCAST);
834 ethernet.setSourceMACAddress(srcMac);
835 ethernet.setEtherType(Ethernet.TYPE_ARP);
836
837 ARP arp = new ARP();
838 arp.setOpCode(ARP.OP_REPLY);
839 arp.setProtocolType(ARP.PROTO_TYPE_IP);
840 arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
841
842 arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
843 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
844
845 arp.setSenderHardwareAddress(srcMac.toBytes());
846 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
847
848 arp.setSenderProtocolAddress(srcIp.toOctets());
849 arp.setTargetProtocolAddress(srcIp.toOctets());
850
851 ethernet.setPayload(arp);
852
853 return ethernet;
854 }
Daniel Park05a94582021-05-12 10:57:02 +0900855
856 /**
857 * Obtains flow group key from the given id.
858 *
859 * @param groupId flow group identifier
860 * @return flow group key
861 */
862 public static GroupKey getGroupKey(int groupId) {
863 return new DefaultGroupKey((Integer.toString(groupId)).getBytes());
864 }
865
866 /**
867 * Obtains load balancer set from the given router.
868 *
869 * @param router kubevirt router
870 * @param lbService kubevirt loadbalancer service
871 * @return loadbalancer set
872 */
873 public static Set<KubevirtLoadBalancer> getLoadBalancerSetForRouter(KubevirtRouter router,
874 KubevirtLoadBalancerService lbService) {
875
876 return lbService.loadBalancers().stream()
877 .filter(lb -> router.internal().contains(lb.networkId()))
878 .collect(Collectors.toSet());
879 }
Jian Li0c656f02021-06-07 13:32:39 +0900880
881 /**
882 * Waits for the given length of time.
883 *
884 * @param timeSecond the amount of time for wait in second unit
885 */
886 public static void waitFor(int timeSecond) {
887 try {
888 Thread.sleep(timeSecond * 1000L);
889 } catch (Exception e) {
890 log.error(e.toString());
891 }
892 }
Jian Li6a53ae62022-10-18 22:43:15 +0900893
894 /**
895 * Returns the kubevirt node from the node.
896 *
897 * @param node a raw node object returned from a k8s client
898 * @return kubevirt node
899 */
900 public static KubevirtNode buildKubevirtNode(Node node) {
901 String hostname = node.getMetadata().getName();
902 IpAddress managementIp = null;
903 IpAddress dataIp = null;
904
905 for (NodeAddress nodeAddress:node.getStatus().getAddresses()) {
906 if (nodeAddress.getType().equals(INTERNAL_IP)) {
907 managementIp = IpAddress.valueOf(nodeAddress.getAddress());
908 dataIp = IpAddress.valueOf(nodeAddress.getAddress());
909 }
910 }
911
912 Set<String> rolesFull = node.getMetadata().getLabels().keySet().stream()
913 .filter(l -> l.contains(K8S_ROLE))
914 .collect(Collectors.toSet());
915
916 KubevirtNode.Type nodeType = WORKER;
917
918 for (String roleStr : rolesFull) {
919 String role = roleStr.split("/")[1];
920 if (MASTER.name().equalsIgnoreCase(role)) {
921 nodeType = MASTER;
922 break;
923 }
924 }
925
926 // start to parse kubernetes annotation
927 Map<String, String> annots = node.getMetadata().getAnnotations();
928 String physnetConfig = annots.get(PHYSNET_CONFIG_KEY);
929 String gatewayConfig = annots.get(GATEWAY_CONFIG_KEY);
930 String dataIpStr = annots.get(DATA_IP_KEY);
931 Set<KubevirtPhyInterface> phys = new HashSet<>();
932 String gatewayBridgeName = null;
933 try {
934 if (physnetConfig != null) {
935 JsonArray configJson = JsonArray.readFrom(physnetConfig);
936
937 for (int i = 0; i < configJson.size(); i++) {
938 JsonObject object = configJson.get(i).asObject();
939 String network = object.get(NETWORK_KEY).asString();
940 String intf = object.get(INTERFACE_KEY).asString();
941
942 if (network != null && intf != null) {
943 String physBridgeId;
944 if (object.get(PHYS_BRIDGE_ID) != null) {
945 physBridgeId = object.get(PHYS_BRIDGE_ID).asString();
946 } else {
947 physBridgeId = genDpidFromName(network + intf + hostname);
948 log.trace("host {} physnet dpid for network {} intf {} is null so generate dpid {}",
949 hostname, network, intf, physBridgeId);
950 }
951
952 phys.add(DefaultKubevirtPhyInterface.builder()
953 .network(network)
954 .intf(intf)
955 .physBridge(DeviceId.deviceId(physBridgeId))
956 .build());
957 }
958 }
959 }
960
961 if (dataIpStr != null) {
962 dataIp = IpAddress.valueOf(dataIpStr);
963 }
964
965 if (gatewayConfig != null) {
966 JsonNode jsonNode = new ObjectMapper().readTree(gatewayConfig);
967
968 nodeType = GATEWAY;
969 gatewayBridgeName = jsonNode.get(GATEWAY_BRIDGE_NAME).asText();
970 }
971 } catch (JsonProcessingException e) {
972 log.error("Failed to parse physnet config or gateway config object", e);
973 }
974
975 // if the node is taint with kubevirt.io key configured,
976 // we mark this node as OTHER type, and do not add it into the cluster
977 NodeSpec spec = node.getSpec();
978 if (spec.getTaints() != null) {
979 for (Taint taint : spec.getTaints()) {
980 String effect = taint.getEffect();
981 String key = taint.getKey();
982 String value = taint.getValue();
983
984 if (StringUtils.equals(effect, NO_SCHEDULE_EFFECT) &&
985 StringUtils.equals(key, KUBEVIRT_IO_KEY) &&
986 StringUtils.equals(value, DRAINING_VALUE)) {
987 nodeType = OTHER;
988 }
989 }
990 }
991
992 return DefaultKubevirtNode.builder()
993 .hostname(hostname)
994 .managementIp(managementIp)
995 .dataIp(dataIp)
996 .type(nodeType)
997 .state(KubevirtNodeState.ON_BOARDED)
998 .phyIntfs(phys)
999 .gatewayBridgeName(gatewayBridgeName)
1000 .build();
1001 }
1002
1003 /**
1004 * Parses kubevirt network resource.
1005 *
1006 * @param resource kubevirt network resource string
1007 * @return kubevirt network object
1008 */
1009 public static KubevirtNetwork parseKubevirtNetwork(String resource) {
1010 JsonObject json = JsonObject.readFrom(resource);
1011 String name = parseResourceName(resource);
1012 JsonObject annots = json.get("metadata").asObject().get("annotations").asObject();
1013 if (annots.get(NETWORK_CONFIG) == null) {
1014 // SR-IOV network does not contain network-config field
1015 return null;
1016 }
1017 String networkConfig = annots.get(NETWORK_CONFIG).asString();
1018 if (networkConfig != null) {
1019 KubevirtNetwork.Builder builder = DefaultKubevirtNetwork.builder();
1020
1021 JsonObject configJson = JsonObject.readFrom(networkConfig);
1022 String type = configJson.get(TYPE).asString().toUpperCase(Locale.ROOT);
1023 Integer mtu = configJson.get(MTU).asInt();
1024 String gatewayIp = configJson.getString(GATEWAY_IP, "");
1025 boolean defaultRoute = configJson.getBoolean(DEFAULT_ROUTE, false);
1026
1027 if (!type.equalsIgnoreCase(FLAT.name())) {
1028 builder.segmentId(configJson.getString(SEGMENT_ID, ""));
1029 }
1030
1031 String cidr = configJson.getString(CIDR, "");
1032
1033 JsonObject poolJson = configJson.get(IP_POOL).asObject();
1034 if (poolJson != null) {
1035 String start = poolJson.getString(START, "");
1036 String end = poolJson.getString(END, "");
1037 builder.ipPool(new KubevirtIpPool(
1038 IpAddress.valueOf(start), IpAddress.valueOf(end)));
1039 }
1040
1041 if (configJson.get(HOST_ROUTES) != null) {
1042 JsonArray routesJson = configJson.get(HOST_ROUTES).asArray();
1043 Set<KubevirtHostRoute> hostRoutes = new HashSet<>();
1044 if (routesJson != null) {
1045 for (int i = 0; i < routesJson.size(); i++) {
1046 JsonObject route = routesJson.get(i).asObject();
1047 String destinationStr = route.getString(DESTINATION, "");
1048 String nexthopStr = route.getString(NEXTHOP, "");
1049
1050 if (StringUtils.isNotEmpty(destinationStr) &&
1051 StringUtils.isNotEmpty(nexthopStr)) {
1052 hostRoutes.add(new KubevirtHostRoute(
1053 IpPrefix.valueOf(destinationStr),
1054 IpAddress.valueOf(nexthopStr)));
1055 }
1056 }
1057 }
1058 builder.hostRoutes(hostRoutes);
1059 }
1060
1061 if (configJson.get(DNSES) != null) {
1062 JsonArray dnsesJson = configJson.get(DNSES).asArray();
1063 Set<IpAddress> dnses = new HashSet<>();
1064 if (dnsesJson != null) {
1065 for (int i = 0; i < dnsesJson.size(); i++) {
1066 String dns = dnsesJson.get(i).asString();
1067 if (StringUtils.isNotEmpty(dns)) {
1068 dnses.add(IpAddress.valueOf(dns));
1069 }
1070 }
1071 }
1072 builder.dnses(dnses);
1073 }
1074
1075 builder.networkId(name).name(name).type(KubevirtNetwork.Type.valueOf(type))
1076 .mtu(mtu).gatewayIp(IpAddress.valueOf(gatewayIp))
1077 .defaultRoute(defaultRoute).cidr(cidr);
1078
1079 return builder.build();
1080 }
1081 return null;
1082 }
Jian Li43244382021-01-09 00:19:02 +09001083}