blob: 2647d705c2492f9a1c3b120f88b797caec5dc498 [file] [log] [blame]
Jian Libde20bf2019-01-25 17:34:43 +09001/*
2 * Copyright 2019-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.k8snetworking.util;
17
18import com.fasterxml.jackson.core.JsonParseException;
19import com.fasterxml.jackson.core.JsonProcessingException;
20import com.fasterxml.jackson.databind.JsonMappingException;
21import com.fasterxml.jackson.databind.ObjectMapper;
Jian Li2cc2b632019-02-18 00:56:40 +090022import com.google.common.collect.Maps;
Jian Li85387732019-02-19 23:56:18 +090023import io.fabric8.kubernetes.client.ConfigBuilder;
24import io.fabric8.kubernetes.client.DefaultKubernetesClient;
25import io.fabric8.kubernetes.client.KubernetesClient;
26import org.apache.commons.lang3.StringUtils;
Jian Li9b199162019-02-10 18:00:35 +090027import org.apache.commons.net.util.SubnetUtils;
28import org.onlab.packet.IpAddress;
Jian Li4aa17642019-01-30 00:01:11 +090029import org.onosproject.cfg.ConfigProperty;
30import org.onosproject.k8snetworking.api.K8sNetwork;
31import org.onosproject.k8snetworking.api.K8sNetworkService;
Jian Li85387732019-02-19 23:56:18 +090032import org.onosproject.k8snode.api.K8sApiConfig;
Jian Li3d1111e2019-02-22 02:02:13 +090033import org.onosproject.k8snode.api.K8sApiConfigService;
Jian Li4aa17642019-01-30 00:01:11 +090034import org.onosproject.k8snode.api.K8sNode;
Jian Li2cc2b632019-02-18 00:56:40 +090035import org.onosproject.k8snode.api.K8sNodeService;
Jian Li4aa17642019-01-30 00:01:11 +090036import org.onosproject.net.PortNumber;
Jian Li2cc2b632019-02-18 00:56:40 +090037import org.onosproject.net.group.DefaultGroupKey;
38import org.onosproject.net.group.GroupKey;
Jian Libde20bf2019-01-25 17:34:43 +090039import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
42import java.io.IOException;
Jian Li9b199162019-02-10 18:00:35 +090043import java.util.Arrays;
44import java.util.HashSet;
Jian Li2cc2b632019-02-18 00:56:40 +090045import java.util.Map;
Jian Li4aa17642019-01-30 00:01:11 +090046import java.util.Optional;
47import java.util.Set;
Jian Li9b199162019-02-10 18:00:35 +090048import java.util.stream.Collectors;
Jian Libde20bf2019-01-25 17:34:43 +090049
50import static org.onosproject.k8snetworking.api.Constants.PORT_NAME_PREFIX_CONTAINER;
51
52/**
53 * An utility that used in kubernetes networking app.
54 */
55public final class K8sNetworkingUtil {
56
57 private static final Logger log = LoggerFactory.getLogger(K8sNetworkingUtil.class);
58
Jian Li85387732019-02-19 23:56:18 +090059 private static final String COLON_SLASH = "://";
60 private static final String COLON = ":";
61
Jian Libde20bf2019-01-25 17:34:43 +090062 private K8sNetworkingUtil() {
63 }
64
65 /**
66 * Checks that whether the port is associated with container interface.
67 *
68 * @param portName port name
69 * @return true if the port is associated with container; false otherwise
70 */
71 public static boolean isContainer(String portName) {
Jian Li4aa17642019-01-30 00:01:11 +090072 return portName != null && portName.contains(PORT_NAME_PREFIX_CONTAINER);
73 }
74
75 /**
76 * Returns the tunnel port number with specified net ID and kubernetes node.
77 *
78 * @param netId network ID
79 * @param netService network service
80 * @param node kubernetes node
81 * @return tunnel port number
82 */
83 public static PortNumber tunnelPortNumByNetId(String netId,
84 K8sNetworkService netService,
85 K8sNode node) {
86 K8sNetwork.Type netType = netService.network(netId).type();
87
88 if (netType == null) {
89 return null;
90 }
91
92 return tunnelPortNumByNetType(netType, node);
93 }
94
95 /**
96 * Returns the tunnel port number with specified net type and kubernetes node.
97 *
98 * @param netType network type
99 * @param node kubernetes node
100 * @return tunnel port number
101 */
102 public static PortNumber tunnelPortNumByNetType(K8sNetwork.Type netType,
103 K8sNode node) {
104 switch (netType) {
105 case VXLAN:
106 return node.vxlanPortNum();
107 case GRE:
108 return node.grePortNum();
109 case GENEVE:
110 return node.genevePortNum();
111 default:
112 return null;
113 }
114 }
115
116 /**
117 * Obtains the property value with specified property key name.
118 *
119 * @param properties a collection of properties
120 * @param name key name
121 * @return mapping value
122 */
123 public static String getPropertyValue(Set<ConfigProperty> properties,
124 String name) {
125 Optional<ConfigProperty> property =
126 properties.stream().filter(p -> p.name().equals(name)).findFirst();
127 return property.map(ConfigProperty::value).orElse(null);
Jian Libde20bf2019-01-25 17:34:43 +0900128 }
129
130 /**
131 * Prints out the JSON string in pretty format.
132 *
133 * @param mapper Object mapper
134 * @param jsonString JSON string
135 * @return pretty formatted JSON string
136 */
137 public static String prettyJson(ObjectMapper mapper, String jsonString) {
138 try {
139 Object jsonObject = mapper.readValue(jsonString, Object.class);
140 return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
141 } catch (JsonParseException e) {
142 log.debug("JsonParseException caused by {}", e);
143 } catch (JsonMappingException e) {
144 log.debug("JsonMappingException caused by {}", e);
145 } catch (JsonProcessingException e) {
146 log.debug("JsonProcessingException caused by {}", e);
147 } catch (IOException e) {
148 log.debug("IOException caused by {}", e);
149 }
150 return null;
151 }
Jian Li9b199162019-02-10 18:00:35 +0900152
153 /**
154 * Obtains valid IP addresses of the given subnet.
155 *
156 * @param cidr CIDR
157 * @return set of IP addresses
158 */
159 public static Set<IpAddress> getSubnetIps(String cidr) {
160 SubnetUtils utils = new SubnetUtils(cidr);
161 utils.setInclusiveHostCount(true);
162 SubnetUtils.SubnetInfo info = utils.getInfo();
163 Set<String> allAddresses =
164 new HashSet<>(Arrays.asList(info.getAllAddresses()));
165
166 if (allAddresses.size() > 2) {
167 allAddresses.remove(info.getBroadcastAddress());
168 allAddresses.remove(info.getNetworkAddress());
169 }
170
171 return allAddresses.stream()
172 .map(IpAddress::valueOf).collect(Collectors.toSet());
173 }
Jian Li85387732019-02-19 23:56:18 +0900174
175 /**
Jian Li2cc2b632019-02-18 00:56:40 +0900176 * Obtains flow group key from the given id.
177 *
178 * @param groupId flow group identifier
179 * @return flow group key
180 */
181 public static GroupKey getGroupKey(int groupId) {
182 return new DefaultGroupKey((Integer.toString(groupId)).getBytes());
183 }
184
185 /**
Jian Li85387732019-02-19 23:56:18 +0900186 * Generates endpoint URL by referring to scheme, ipAddress and port.
187 *
188 * @param scheme scheme
189 * @param ipAddress IP address
190 * @param port port number
191 * @return generated endpoint URL
192 */
193 public static String endpoint(K8sApiConfig.Scheme scheme, IpAddress ipAddress, int port) {
194 StringBuilder endpoint = new StringBuilder();
195 String protocol = StringUtils.lowerCase(scheme.name());
196
197 endpoint.append(protocol);
198 endpoint.append(COLON_SLASH);
199 endpoint.append(ipAddress.toString());
200 endpoint.append(COLON);
201 endpoint.append(port);
202
203 return endpoint.toString();
204 }
205
206 /**
207 * Generates endpoint URL by referring to scheme, ipAddress and port.
208 *
209 * @param apiConfig kubernetes API config
210 * @return generated endpoint URL
211 */
212 public static String endpoint(K8sApiConfig apiConfig) {
213 return endpoint(apiConfig.scheme(), apiConfig.ipAddress(), apiConfig.port());
214 }
215
216 /**
217 * Obtains workable kubernetes client.
218 *
219 * @param config kubernetes API config
220 * @return kubernetes client
221 */
222 public static KubernetesClient k8sClient(K8sApiConfig config) {
223 if (config == null) {
224 log.warn("Kubernetes API server config is empty.");
225 return null;
226 }
227
228 String endpoint = endpoint(config);
229
230 ConfigBuilder configBuilder = new ConfigBuilder().withMasterUrl(endpoint);
231
232 if (config.scheme() == K8sApiConfig.Scheme.HTTPS) {
233 configBuilder.withTrustCerts(true)
234 .withOauthToken(config.token())
235 .withCaCertData(config.caCertData())
236 .withClientCertData(config.clientCertData())
237 .withClientKeyData(config.clientKeyData());
238 }
239
240 return new DefaultKubernetesClient(configBuilder.build());
241 }
Jian Li3d1111e2019-02-22 02:02:13 +0900242
243 /**
244 * Obtains workable kubernetes client.
245 *
246 * @param service kubernetes API service
247 * @return kubernetes client
248 */
249 public static KubernetesClient k8sClient(K8sApiConfigService service) {
250 K8sApiConfig config =
251 service.apiConfigs().stream().findAny().orElse(null);
252 if (config == null) {
253 log.error("Failed to find valid kubernetes API configuration.");
254 return null;
255 }
256
257 KubernetesClient client = k8sClient(config);
258
259 if (client == null) {
260 log.error("Failed to connect to kubernetes API server.");
261 return null;
262 }
263
264 return client;
265 }
Jian Li2cc2b632019-02-18 00:56:40 +0900266
267 /**
268 * Obtains the kubernetes node IP and kubernetes network gateway IP map.
269 *
270 * @param nodeService kubernetes node service
271 * @param networkService kubernetes network service
272 * @return kubernetes node IP and kubernetes network gateway IP map
273 */
274 public static Map<String, String> nodeIpGatewayIpMap(K8sNodeService nodeService,
275 K8sNetworkService networkService) {
276 Map<String, String> ipMap = Maps.newConcurrentMap();
277
278 nodeService.completeNodes().forEach(n -> {
279 K8sNetwork network = networkService.network(n.hostname());
280 if (network != null) {
281 ipMap.put(n.dataIp().toString(), network.gatewayIp().toString());
282 }
283 });
284
285 return ipMap;
286 }
Jian Libde20bf2019-01-25 17:34:43 +0900287}