blob: b6c2f69645055ab67c009fc7ae2301344ddfa13b [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 Li85387732019-02-19 23:56:18 +090022import io.fabric8.kubernetes.client.ConfigBuilder;
23import io.fabric8.kubernetes.client.DefaultKubernetesClient;
24import io.fabric8.kubernetes.client.KubernetesClient;
25import org.apache.commons.lang3.StringUtils;
Jian Li9b199162019-02-10 18:00:35 +090026import org.apache.commons.net.util.SubnetUtils;
27import org.onlab.packet.IpAddress;
Jian Li4aa17642019-01-30 00:01:11 +090028import org.onosproject.cfg.ConfigProperty;
29import org.onosproject.k8snetworking.api.K8sNetwork;
30import org.onosproject.k8snetworking.api.K8sNetworkService;
Jian Li85387732019-02-19 23:56:18 +090031import org.onosproject.k8snode.api.K8sApiConfig;
Jian Li4aa17642019-01-30 00:01:11 +090032import org.onosproject.k8snode.api.K8sNode;
33import org.onosproject.net.PortNumber;
Jian Libde20bf2019-01-25 17:34:43 +090034import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37import java.io.IOException;
Jian Li9b199162019-02-10 18:00:35 +090038import java.util.Arrays;
39import java.util.HashSet;
Jian Li4aa17642019-01-30 00:01:11 +090040import java.util.Optional;
41import java.util.Set;
Jian Li9b199162019-02-10 18:00:35 +090042import java.util.stream.Collectors;
Jian Libde20bf2019-01-25 17:34:43 +090043
44import static org.onosproject.k8snetworking.api.Constants.PORT_NAME_PREFIX_CONTAINER;
45
46/**
47 * An utility that used in kubernetes networking app.
48 */
49public final class K8sNetworkingUtil {
50
51 private static final Logger log = LoggerFactory.getLogger(K8sNetworkingUtil.class);
52
Jian Li85387732019-02-19 23:56:18 +090053 private static final String COLON_SLASH = "://";
54 private static final String COLON = ":";
55
Jian Libde20bf2019-01-25 17:34:43 +090056 private K8sNetworkingUtil() {
57 }
58
59 /**
60 * Checks that whether the port is associated with container interface.
61 *
62 * @param portName port name
63 * @return true if the port is associated with container; false otherwise
64 */
65 public static boolean isContainer(String portName) {
Jian Li4aa17642019-01-30 00:01:11 +090066 return portName != null && portName.contains(PORT_NAME_PREFIX_CONTAINER);
67 }
68
69 /**
70 * Returns the tunnel port number with specified net ID and kubernetes node.
71 *
72 * @param netId network ID
73 * @param netService network service
74 * @param node kubernetes node
75 * @return tunnel port number
76 */
77 public static PortNumber tunnelPortNumByNetId(String netId,
78 K8sNetworkService netService,
79 K8sNode node) {
80 K8sNetwork.Type netType = netService.network(netId).type();
81
82 if (netType == null) {
83 return null;
84 }
85
86 return tunnelPortNumByNetType(netType, node);
87 }
88
89 /**
90 * Returns the tunnel port number with specified net type and kubernetes node.
91 *
92 * @param netType network type
93 * @param node kubernetes node
94 * @return tunnel port number
95 */
96 public static PortNumber tunnelPortNumByNetType(K8sNetwork.Type netType,
97 K8sNode node) {
98 switch (netType) {
99 case VXLAN:
100 return node.vxlanPortNum();
101 case GRE:
102 return node.grePortNum();
103 case GENEVE:
104 return node.genevePortNum();
105 default:
106 return null;
107 }
108 }
109
110 /**
111 * Obtains the property value with specified property key name.
112 *
113 * @param properties a collection of properties
114 * @param name key name
115 * @return mapping value
116 */
117 public static String getPropertyValue(Set<ConfigProperty> properties,
118 String name) {
119 Optional<ConfigProperty> property =
120 properties.stream().filter(p -> p.name().equals(name)).findFirst();
121 return property.map(ConfigProperty::value).orElse(null);
Jian Libde20bf2019-01-25 17:34:43 +0900122 }
123
124 /**
125 * Prints out the JSON string in pretty format.
126 *
127 * @param mapper Object mapper
128 * @param jsonString JSON string
129 * @return pretty formatted JSON string
130 */
131 public static String prettyJson(ObjectMapper mapper, String jsonString) {
132 try {
133 Object jsonObject = mapper.readValue(jsonString, Object.class);
134 return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
135 } catch (JsonParseException e) {
136 log.debug("JsonParseException caused by {}", e);
137 } catch (JsonMappingException e) {
138 log.debug("JsonMappingException caused by {}", e);
139 } catch (JsonProcessingException e) {
140 log.debug("JsonProcessingException caused by {}", e);
141 } catch (IOException e) {
142 log.debug("IOException caused by {}", e);
143 }
144 return null;
145 }
Jian Li9b199162019-02-10 18:00:35 +0900146
147 /**
148 * Obtains valid IP addresses of the given subnet.
149 *
150 * @param cidr CIDR
151 * @return set of IP addresses
152 */
153 public static Set<IpAddress> getSubnetIps(String cidr) {
154 SubnetUtils utils = new SubnetUtils(cidr);
155 utils.setInclusiveHostCount(true);
156 SubnetUtils.SubnetInfo info = utils.getInfo();
157 Set<String> allAddresses =
158 new HashSet<>(Arrays.asList(info.getAllAddresses()));
159
160 if (allAddresses.size() > 2) {
161 allAddresses.remove(info.getBroadcastAddress());
162 allAddresses.remove(info.getNetworkAddress());
163 }
164
165 return allAddresses.stream()
166 .map(IpAddress::valueOf).collect(Collectors.toSet());
167 }
Jian Li85387732019-02-19 23:56:18 +0900168
169 /**
170 * Generates endpoint URL by referring to scheme, ipAddress and port.
171 *
172 * @param scheme scheme
173 * @param ipAddress IP address
174 * @param port port number
175 * @return generated endpoint URL
176 */
177 public static String endpoint(K8sApiConfig.Scheme scheme, IpAddress ipAddress, int port) {
178 StringBuilder endpoint = new StringBuilder();
179 String protocol = StringUtils.lowerCase(scheme.name());
180
181 endpoint.append(protocol);
182 endpoint.append(COLON_SLASH);
183 endpoint.append(ipAddress.toString());
184 endpoint.append(COLON);
185 endpoint.append(port);
186
187 return endpoint.toString();
188 }
189
190 /**
191 * Generates endpoint URL by referring to scheme, ipAddress and port.
192 *
193 * @param apiConfig kubernetes API config
194 * @return generated endpoint URL
195 */
196 public static String endpoint(K8sApiConfig apiConfig) {
197 return endpoint(apiConfig.scheme(), apiConfig.ipAddress(), apiConfig.port());
198 }
199
200 /**
201 * Obtains workable kubernetes client.
202 *
203 * @param config kubernetes API config
204 * @return kubernetes client
205 */
206 public static KubernetesClient k8sClient(K8sApiConfig config) {
207 if (config == null) {
208 log.warn("Kubernetes API server config is empty.");
209 return null;
210 }
211
212 String endpoint = endpoint(config);
213
214 ConfigBuilder configBuilder = new ConfigBuilder().withMasterUrl(endpoint);
215
216 if (config.scheme() == K8sApiConfig.Scheme.HTTPS) {
217 configBuilder.withTrustCerts(true)
218 .withOauthToken(config.token())
219 .withCaCertData(config.caCertData())
220 .withClientCertData(config.clientCertData())
221 .withClientKeyData(config.clientKeyData());
222 }
223
224 return new DefaultKubernetesClient(configBuilder.build());
225 }
Jian Libde20bf2019-01-25 17:34:43 +0900226}