blob: e38d0a4984fb2b68bc9c86ee460d473865694039 [file] [log] [blame]
Jian Li49109b52019-01-22 00:17:28 +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.k8snode.api;
17
18import com.google.common.base.MoreObjects;
19import org.onlab.osgi.DefaultServiceDirectory;
20import org.onlab.packet.IpAddress;
Jian Li7d111d72019-04-12 13:58:44 +090021import org.onlab.packet.MacAddress;
Jian Li49109b52019-01-22 00:17:28 +090022import org.onosproject.net.DeviceId;
23import org.onosproject.net.Port;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.device.DeviceService;
Jian Li7d111d72019-04-12 13:58:44 +090026import org.onosproject.ovsdb.controller.OvsdbClientService;
27import org.onosproject.ovsdb.controller.OvsdbController;
28import org.onosproject.ovsdb.controller.OvsdbNodeId;
29import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
30import org.onosproject.ovsdb.rfc.table.Interface;
Jian Li49109b52019-01-22 00:17:28 +090031
32import java.util.Objects;
33
34import static com.google.common.base.Preconditions.checkArgument;
35import static org.onosproject.k8snode.api.Constants.GENEVE_TUNNEL;
36import static org.onosproject.k8snode.api.Constants.GRE_TUNNEL;
Jian Li4aa17642019-01-30 00:01:11 +090037import static org.onosproject.k8snode.api.Constants.INTEGRATION_BRIDGE;
Jian Li49109b52019-01-22 00:17:28 +090038import static org.onosproject.k8snode.api.Constants.VXLAN_TUNNEL;
39import static org.onosproject.net.AnnotationKeys.PORT_NAME;
40
41/**
42 * Representation of a kubernetes node.
43 */
44public class DefaultK8sNode implements K8sNode {
45
Jian Li7d111d72019-04-12 13:58:44 +090046 private static final int DEFAULT_OVSDB_PORT = 6640;
47 private static final String MAC_ADDRESS = "mac_address";
48
Jian Li49109b52019-01-22 00:17:28 +090049 private final String hostname;
50 private final Type type;
51 private final DeviceId intgBridge;
Jian Libf562c22019-04-15 18:07:14 +090052 private final DeviceId extBridge;
Jian Li49109b52019-01-22 00:17:28 +090053 private final IpAddress managementIp;
54 private final IpAddress dataIp;
55 private final K8sNodeState state;
56
57 private static final String NOT_NULL_MSG = "Node % cannot be null";
58
59 private static final String OVSDB = "ovsdb:";
60
61 /**
62 * A default constructor of kubernetes Node.
63 *
64 * @param hostname hostname
65 * @param type node type
66 * @param intgBridge integration bridge
Jian Libf562c22019-04-15 18:07:14 +090067 * @param extBridge external bridge
Jian Li49109b52019-01-22 00:17:28 +090068 * @param managementIp management IP address
69 * @param dataIp data IP address
70 * @param state node state
71 */
72 protected DefaultK8sNode(String hostname, Type type, DeviceId intgBridge,
Jian Libf562c22019-04-15 18:07:14 +090073 DeviceId extBridge, IpAddress managementIp,
74 IpAddress dataIp, K8sNodeState state) {
Jian Li49109b52019-01-22 00:17:28 +090075 this.hostname = hostname;
76 this.type = type;
77 this.intgBridge = intgBridge;
Jian Libf562c22019-04-15 18:07:14 +090078 this.extBridge = extBridge;
Jian Li49109b52019-01-22 00:17:28 +090079 this.managementIp = managementIp;
80 this.dataIp = dataIp;
81 this.state = state;
82 }
83
84 @Override
85 public String hostname() {
86 return hostname;
87 }
88
89 @Override
90 public Type type() {
91 return type;
92 }
93
94 @Override
95 public DeviceId ovsdb() {
96 return DeviceId.deviceId(OVSDB + managementIp().toString());
97 }
98
99 @Override
100 public DeviceId intgBridge() {
101 return intgBridge;
102 }
103
104 @Override
Jian Libf562c22019-04-15 18:07:14 +0900105 public DeviceId extBridge() {
106 return extBridge;
107 }
108
109 @Override
Jian Li1cee9882019-02-13 11:25:25 +0900110 public K8sNode updateIntgBridge(DeviceId deviceId) {
111 return new Builder()
112 .hostname(hostname)
113 .type(type)
114 .intgBridge(deviceId)
Jian Libf562c22019-04-15 18:07:14 +0900115 .extBridge(extBridge)
116 .managementIp(managementIp)
117 .dataIp(dataIp)
118 .state(state)
119 .build();
120 }
121
122 @Override
123 public K8sNode updateExtBridge(DeviceId deviceId) {
124 return new Builder()
125 .hostname(hostname)
126 .type(type)
127 .intgBridge(intgBridge)
128 .extBridge(deviceId)
Jian Li1cee9882019-02-13 11:25:25 +0900129 .managementIp(managementIp)
130 .dataIp(dataIp)
131 .state(state)
132 .build();
133 }
134
135 @Override
Jian Li49109b52019-01-22 00:17:28 +0900136 public IpAddress managementIp() {
137 return managementIp;
138 }
139
140 @Override
141 public IpAddress dataIp() {
142 return dataIp;
143 }
144
145 @Override
146 public K8sNodeState state() {
147 return state;
148 }
149
150 @Override
151 public K8sNode updateState(K8sNodeState newState) {
152 return new Builder()
153 .hostname(hostname)
154 .type(type)
155 .intgBridge(intgBridge)
156 .managementIp(managementIp)
157 .dataIp(dataIp)
158 .state(newState)
159 .build();
160 }
161
162 @Override
163 public PortNumber grePortNum() {
164 return tunnelPortNum(GRE_TUNNEL);
165 }
166
167 @Override
168 public PortNumber vxlanPortNum() {
169 return tunnelPortNum(VXLAN_TUNNEL);
170 }
171
172 @Override
173 public PortNumber genevePortNum() {
174 return tunnelPortNum(GENEVE_TUNNEL);
175 }
176
177 @Override
Jian Li4aa17642019-01-30 00:01:11 +0900178 public PortNumber intBridgePortNum() {
179 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
180 Port port = deviceService.getPorts(intgBridge).stream()
181 .filter(p -> p.isEnabled() &&
182 Objects.equals(p.annotations().value(PORT_NAME), INTEGRATION_BRIDGE))
183 .findAny().orElse(null);
184 return port != null ? port.number() : null;
185 }
186
187 @Override
Jian Li7d111d72019-04-12 13:58:44 +0900188 public MacAddress intBridgeMac() {
189 OvsdbController ovsdbController =
190 DefaultServiceDirectory.getService(OvsdbController.class);
191 OvsdbNodeId ovsdb = new OvsdbNodeId(this.managementIp, DEFAULT_OVSDB_PORT);
192 OvsdbClientService client = ovsdbController.getOvsdbClient(ovsdb);
193 if (client == null) {
194 return null;
195 }
196
197 Interface iface = client.getInterface(INTEGRATION_BRIDGE);
198 OvsdbMap data = (OvsdbMap) iface.getExternalIdsColumn().data();
199 return MacAddress.valueOf((String) data.map().get(MAC_ADDRESS));
200 }
201
202 @Override
Jian Li49109b52019-01-22 00:17:28 +0900203 public boolean equals(Object obj) {
204 if (this == obj) {
205 return true;
206 }
207
208 if (obj instanceof DefaultK8sNode) {
209 DefaultK8sNode that = (DefaultK8sNode) obj;
210
211 return hostname.equals(that.hostname) &&
212 type == that.type &&
213 intgBridge.equals(that.intgBridge) &&
Jian Libf562c22019-04-15 18:07:14 +0900214 extBridge.equals(that.extBridge) &&
Jian Li49109b52019-01-22 00:17:28 +0900215 managementIp.equals(that.managementIp) &&
216 dataIp.equals(that.dataIp) &&
217 state == that.state;
218 }
219
220 return false;
221 }
222
223 @Override
224 public int hashCode() {
Jian Libf562c22019-04-15 18:07:14 +0900225 return Objects.hash(hostname, type, intgBridge, extBridge,
226 managementIp, dataIp, state);
Jian Li49109b52019-01-22 00:17:28 +0900227 }
228
229 @Override
230 public String toString() {
231 return MoreObjects.toStringHelper(this)
232 .add("hostname", hostname)
233 .add("type", type)
234 .add("intgBridge", intgBridge)
Jian Libf562c22019-04-15 18:07:14 +0900235 .add("extBridge", extBridge)
Jian Li49109b52019-01-22 00:17:28 +0900236 .add("managementIp", managementIp)
237 .add("dataIp", dataIp)
238 .add("state", state)
239 .toString();
240 }
241
242 private PortNumber tunnelPortNum(String tunnelType) {
243 if (dataIp == null) {
244 return null;
245 }
246 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
247 Port port = deviceService.getPorts(intgBridge).stream()
248 .filter(p -> p.isEnabled() &&
249 Objects.equals(p.annotations().value(PORT_NAME), tunnelType))
250 .findAny().orElse(null);
251 return port != null ? port.number() : null;
252 }
253
254 /**
255 * Returns new builder instance.
256 *
257 * @return kubernetes node builder
258 */
259 public static Builder builder() {
260 return new Builder();
261 }
262
263 /**
264 * Returns new builder instance with the given node as a default value.
265 *
266 * @param node kubernetes node
267 * @return kubernetes node builder
268 */
269 public static Builder from(K8sNode node) {
270 return new Builder()
271 .hostname(node.hostname())
272 .type(node.type())
273 .intgBridge(node.intgBridge())
Jian Libf562c22019-04-15 18:07:14 +0900274 .extBridge(node.extBridge())
Jian Li49109b52019-01-22 00:17:28 +0900275 .managementIp(node.managementIp())
276 .dataIp(node.dataIp())
277 .state(node.state());
278 }
279
280 public static final class Builder implements K8sNode.Builder {
281
282 private String hostname;
283 private Type type;
284 private DeviceId intgBridge;
Jian Libf562c22019-04-15 18:07:14 +0900285 private DeviceId extBridge;
Jian Li49109b52019-01-22 00:17:28 +0900286 private IpAddress managementIp;
287 private IpAddress dataIp;
288 private K8sNodeState state;
Jian Li3defa842019-02-12 00:31:35 +0900289 private K8sApiConfig apiConfig;
Jian Li49109b52019-01-22 00:17:28 +0900290
291 // private constructor not intended to use from external
292 private Builder() {
293 }
294
295 @Override
296 public K8sNode build() {
297 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
298 checkArgument(type != null, NOT_NULL_MSG, "type");
299 checkArgument(state != null, NOT_NULL_MSG, "state");
300 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
301
302 return new DefaultK8sNode(hostname,
303 type,
304 intgBridge,
Jian Libf562c22019-04-15 18:07:14 +0900305 extBridge,
Jian Li49109b52019-01-22 00:17:28 +0900306 managementIp,
307 dataIp,
308 state);
309 }
310
311 @Override
312 public Builder hostname(String hostname) {
313 this.hostname = hostname;
314 return this;
315 }
316
317 @Override
318 public Builder type(Type type) {
319 this.type = type;
320 return this;
321 }
322
323 @Override
324 public Builder intgBridge(DeviceId deviceId) {
325 this.intgBridge = deviceId;
326 return this;
327 }
328
329 @Override
Jian Libf562c22019-04-15 18:07:14 +0900330 public Builder extBridge(DeviceId deviceId) {
331 this.extBridge = deviceId;
332 return this;
333 }
334
335 @Override
Jian Li49109b52019-01-22 00:17:28 +0900336 public Builder managementIp(IpAddress managementIp) {
337 this.managementIp = managementIp;
338 return this;
339 }
340
341 @Override
342 public Builder dataIp(IpAddress dataIp) {
343 this.dataIp = dataIp;
344 return this;
345 }
346
347 @Override
348 public Builder state(K8sNodeState state) {
349 this.state = state;
350 return this;
351 }
352 }
353}