blob: 87e1f1d6e4a165263f4a2ed0dd91f9e6d140e03b [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;
Jian Lieb488ea2019-04-16 01:50:02 +090035import static org.onosproject.k8snode.api.Constants.EXTERNAL_BRIDGE;
Jian Li49109b52019-01-22 00:17:28 +090036import static org.onosproject.k8snode.api.Constants.GENEVE_TUNNEL;
37import static org.onosproject.k8snode.api.Constants.GRE_TUNNEL;
Jian Li4aa17642019-01-30 00:01:11 +090038import static org.onosproject.k8snode.api.Constants.INTEGRATION_BRIDGE;
Jian Lieb488ea2019-04-16 01:50:02 +090039import static org.onosproject.k8snode.api.Constants.INTEGRATION_TO_EXTERNAL_BRIDGE;
40import static org.onosproject.k8snode.api.Constants.PHYSICAL_EXTERNAL_BRIDGE;
Jian Li49109b52019-01-22 00:17:28 +090041import static org.onosproject.k8snode.api.Constants.VXLAN_TUNNEL;
42import static org.onosproject.net.AnnotationKeys.PORT_NAME;
43
44/**
45 * Representation of a kubernetes node.
46 */
47public class DefaultK8sNode implements K8sNode {
48
Jian Li7d111d72019-04-12 13:58:44 +090049 private static final int DEFAULT_OVSDB_PORT = 6640;
Jian Lieb488ea2019-04-16 01:50:02 +090050 private static final String IP_ADDRESS = "ip_address";
Jian Li7d111d72019-04-12 13:58:44 +090051 private static final String MAC_ADDRESS = "mac_address";
Jian Lieb488ea2019-04-16 01:50:02 +090052 private static final String EXT_INTF = "ext_interface";
53 private static final String EXT_GW_IP = "ext_gw_ip_address";
54 private static final String EXT_GW_MAC = "ext_gw_mac_address";
Jian Li7d111d72019-04-12 13:58:44 +090055
Jian Li49109b52019-01-22 00:17:28 +090056 private final String hostname;
57 private final Type type;
58 private final DeviceId intgBridge;
Jian Libf562c22019-04-15 18:07:14 +090059 private final DeviceId extBridge;
Jian Li49109b52019-01-22 00:17:28 +090060 private final IpAddress managementIp;
61 private final IpAddress dataIp;
62 private final K8sNodeState state;
Jian Li1b08d652019-05-02 17:28:09 +090063 private final MacAddress extGatewayMac;
Jian Li49109b52019-01-22 00:17:28 +090064
65 private static final String NOT_NULL_MSG = "Node % cannot be null";
66
67 private static final String OVSDB = "ovsdb:";
68
69 /**
70 * A default constructor of kubernetes Node.
71 *
72 * @param hostname hostname
73 * @param type node type
74 * @param intgBridge integration bridge
Jian Libf562c22019-04-15 18:07:14 +090075 * @param extBridge external bridge
Jian Li49109b52019-01-22 00:17:28 +090076 * @param managementIp management IP address
77 * @param dataIp data IP address
78 * @param state node state
Jian Li1b08d652019-05-02 17:28:09 +090079 * @param extGatewayMac external gateway MAC address
Jian Li49109b52019-01-22 00:17:28 +090080 */
81 protected DefaultK8sNode(String hostname, Type type, DeviceId intgBridge,
Jian Libf562c22019-04-15 18:07:14 +090082 DeviceId extBridge, IpAddress managementIp,
Jian Li1b08d652019-05-02 17:28:09 +090083 IpAddress dataIp, K8sNodeState state,
84 MacAddress extGatewayMac) {
Jian Li49109b52019-01-22 00:17:28 +090085 this.hostname = hostname;
86 this.type = type;
87 this.intgBridge = intgBridge;
Jian Libf562c22019-04-15 18:07:14 +090088 this.extBridge = extBridge;
Jian Li49109b52019-01-22 00:17:28 +090089 this.managementIp = managementIp;
90 this.dataIp = dataIp;
91 this.state = state;
Jian Li1b08d652019-05-02 17:28:09 +090092 this.extGatewayMac = extGatewayMac;
Jian Li49109b52019-01-22 00:17:28 +090093 }
94
95 @Override
96 public String hostname() {
97 return hostname;
98 }
99
100 @Override
101 public Type type() {
102 return type;
103 }
104
105 @Override
106 public DeviceId ovsdb() {
107 return DeviceId.deviceId(OVSDB + managementIp().toString());
108 }
109
110 @Override
111 public DeviceId intgBridge() {
112 return intgBridge;
113 }
114
115 @Override
Jian Libf562c22019-04-15 18:07:14 +0900116 public DeviceId extBridge() {
117 return extBridge;
118 }
119
120 @Override
Jian Li1cee9882019-02-13 11:25:25 +0900121 public K8sNode updateIntgBridge(DeviceId deviceId) {
122 return new Builder()
123 .hostname(hostname)
124 .type(type)
125 .intgBridge(deviceId)
Jian Libf562c22019-04-15 18:07:14 +0900126 .extBridge(extBridge)
127 .managementIp(managementIp)
128 .dataIp(dataIp)
129 .state(state)
Jian Li1b08d652019-05-02 17:28:09 +0900130 .extGatewayMac(extGatewayMac)
Jian Libf562c22019-04-15 18:07:14 +0900131 .build();
132 }
133
134 @Override
135 public K8sNode updateExtBridge(DeviceId deviceId) {
136 return new Builder()
137 .hostname(hostname)
138 .type(type)
139 .intgBridge(intgBridge)
140 .extBridge(deviceId)
Jian Li1cee9882019-02-13 11:25:25 +0900141 .managementIp(managementIp)
142 .dataIp(dataIp)
143 .state(state)
Jian Li1b08d652019-05-02 17:28:09 +0900144 .extGatewayMac(extGatewayMac)
Jian Li1cee9882019-02-13 11:25:25 +0900145 .build();
146 }
147
148 @Override
Jian Li49109b52019-01-22 00:17:28 +0900149 public IpAddress managementIp() {
150 return managementIp;
151 }
152
153 @Override
154 public IpAddress dataIp() {
155 return dataIp;
156 }
157
158 @Override
159 public K8sNodeState state() {
160 return state;
161 }
162
163 @Override
164 public K8sNode updateState(K8sNodeState newState) {
165 return new Builder()
166 .hostname(hostname)
167 .type(type)
168 .intgBridge(intgBridge)
169 .managementIp(managementIp)
170 .dataIp(dataIp)
171 .state(newState)
Jian Li1b08d652019-05-02 17:28:09 +0900172 .extGatewayMac(extGatewayMac)
Jian Li49109b52019-01-22 00:17:28 +0900173 .build();
174 }
175
176 @Override
Jian Li1b08d652019-05-02 17:28:09 +0900177 public K8sNode updateExtGatewayMac(MacAddress newMac) {
178 return new Builder()
179 .hostname(hostname)
180 .type(type)
181 .intgBridge(intgBridge)
182 .managementIp(managementIp)
183 .dataIp(dataIp)
184 .state(state)
185 .extGatewayMac(newMac)
186 .build();
187
188 }
189
190 @Override
Jian Li49109b52019-01-22 00:17:28 +0900191 public PortNumber grePortNum() {
192 return tunnelPortNum(GRE_TUNNEL);
193 }
194
195 @Override
196 public PortNumber vxlanPortNum() {
197 return tunnelPortNum(VXLAN_TUNNEL);
198 }
199
200 @Override
201 public PortNumber genevePortNum() {
202 return tunnelPortNum(GENEVE_TUNNEL);
203 }
204
205 @Override
Jian Lieb488ea2019-04-16 01:50:02 +0900206 public PortNumber intgBridgePortNum() {
Jian Li4aa17642019-01-30 00:01:11 +0900207 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
208 Port port = deviceService.getPorts(intgBridge).stream()
209 .filter(p -> p.isEnabled() &&
210 Objects.equals(p.annotations().value(PORT_NAME), INTEGRATION_BRIDGE))
211 .findAny().orElse(null);
212 return port != null ? port.number() : null;
213 }
214
215 @Override
Jian Lieb488ea2019-04-16 01:50:02 +0900216 public MacAddress intgBridgeMac() {
217 OvsdbClientService client = getOvsClient();
218
Jian Li7d111d72019-04-12 13:58:44 +0900219 if (client == null) {
220 return null;
221 }
222
Jian Lieb488ea2019-04-16 01:50:02 +0900223 Interface iface = getOvsClient().getInterface(INTEGRATION_BRIDGE);
Jian Li7d111d72019-04-12 13:58:44 +0900224 OvsdbMap data = (OvsdbMap) iface.getExternalIdsColumn().data();
225 return MacAddress.valueOf((String) data.map().get(MAC_ADDRESS));
226 }
227
228 @Override
Jian Lieb488ea2019-04-16 01:50:02 +0900229 public IpAddress extBridgeIp() {
230 OvsdbClientService client = getOvsClient();
231
232 if (client == null) {
233 return null;
234 }
235
236 Interface iface = getOvsClient().getInterface(EXTERNAL_BRIDGE);
237 OvsdbMap data = (OvsdbMap) iface.getExternalIdsColumn().data();
238 return IpAddress.valueOf((String) data.map().get(IP_ADDRESS));
239 }
240
241 @Override
242 public MacAddress extBridgeMac() {
243 OvsdbClientService client = getOvsClient();
244
245 if (client == null) {
246 return null;
247 }
248
249 Interface iface = getOvsClient().getInterface(EXTERNAL_BRIDGE);
250 OvsdbMap data = (OvsdbMap) iface.getExternalIdsColumn().data();
251 return MacAddress.valueOf((String) data.map().get(MAC_ADDRESS));
252 }
253
254 @Override
255 public IpAddress extGatewayIp() {
256 OvsdbClientService client = getOvsClient();
257
258 if (client == null) {
259 return null;
260 }
261
262 Interface iface = getOvsClient().getInterface(EXTERNAL_BRIDGE);
263 OvsdbMap data = (OvsdbMap) iface.getExternalIdsColumn().data();
264 return IpAddress.valueOf((String) data.map().get(EXT_GW_IP));
265 }
266
267 @Override
268 public MacAddress extGatewayMac() {
Jian Li1b08d652019-05-02 17:28:09 +0900269 return extGatewayMac;
Jian Lieb488ea2019-04-16 01:50:02 +0900270 }
271
272 @Override
273 public PortNumber intgToExtPatchPortNum() {
274 return portNumber(intgBridge, INTEGRATION_TO_EXTERNAL_BRIDGE);
275 }
276
277 @Override
278 public PortNumber extToIntgPatchPortNum() {
279 return portNumber(extBridge, PHYSICAL_EXTERNAL_BRIDGE);
280 }
281
282 @Override
283 public PortNumber extBridgePortNum() {
284 OvsdbClientService client = getOvsClient();
285
286 if (client == null) {
287 return null;
288 }
289
290 Interface iface = getOvsClient().getInterface(EXTERNAL_BRIDGE);
291 OvsdbMap data = (OvsdbMap) iface.getExternalIdsColumn().data();
292 String extIface = (String) data.map().get(EXT_INTF);
293 if (extIface == null) {
294 return null;
295 }
296
297 return portNumber(extBridge, extIface);
298 }
299
300 @Override
Jian Li49109b52019-01-22 00:17:28 +0900301 public boolean equals(Object obj) {
302 if (this == obj) {
303 return true;
304 }
305
306 if (obj instanceof DefaultK8sNode) {
307 DefaultK8sNode that = (DefaultK8sNode) obj;
308
309 return hostname.equals(that.hostname) &&
310 type == that.type &&
311 intgBridge.equals(that.intgBridge) &&
Jian Libf562c22019-04-15 18:07:14 +0900312 extBridge.equals(that.extBridge) &&
Jian Li49109b52019-01-22 00:17:28 +0900313 managementIp.equals(that.managementIp) &&
314 dataIp.equals(that.dataIp) &&
315 state == that.state;
316 }
317
318 return false;
319 }
320
321 @Override
322 public int hashCode() {
Jian Libf562c22019-04-15 18:07:14 +0900323 return Objects.hash(hostname, type, intgBridge, extBridge,
Jian Li1b08d652019-05-02 17:28:09 +0900324 managementIp, dataIp, state, extGatewayMac);
Jian Li49109b52019-01-22 00:17:28 +0900325 }
326
327 @Override
328 public String toString() {
329 return MoreObjects.toStringHelper(this)
330 .add("hostname", hostname)
331 .add("type", type)
332 .add("intgBridge", intgBridge)
Jian Libf562c22019-04-15 18:07:14 +0900333 .add("extBridge", extBridge)
Jian Li49109b52019-01-22 00:17:28 +0900334 .add("managementIp", managementIp)
335 .add("dataIp", dataIp)
336 .add("state", state)
Jian Li1b08d652019-05-02 17:28:09 +0900337 .add("extGatewayMac", extGatewayMac)
Jian Li49109b52019-01-22 00:17:28 +0900338 .toString();
339 }
340
341 private PortNumber tunnelPortNum(String tunnelType) {
342 if (dataIp == null) {
343 return null;
344 }
Jian Lieb488ea2019-04-16 01:50:02 +0900345
346 return portNumber(intgBridge, tunnelType);
347 }
348
349 private PortNumber portNumber(DeviceId deviceId, String portName) {
Jian Li49109b52019-01-22 00:17:28 +0900350 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
Jian Lieb488ea2019-04-16 01:50:02 +0900351 Port port = deviceService.getPorts(deviceId).stream()
Jian Li49109b52019-01-22 00:17:28 +0900352 .filter(p -> p.isEnabled() &&
Jian Lieb488ea2019-04-16 01:50:02 +0900353 Objects.equals(p.annotations().value(PORT_NAME), portName))
Jian Li49109b52019-01-22 00:17:28 +0900354 .findAny().orElse(null);
355 return port != null ? port.number() : null;
356 }
357
Jian Lieb488ea2019-04-16 01:50:02 +0900358 private OvsdbClientService getOvsClient() {
359 OvsdbController ovsdbController =
360 DefaultServiceDirectory.getService(OvsdbController.class);
361 OvsdbNodeId ovsdb = new OvsdbNodeId(this.managementIp, DEFAULT_OVSDB_PORT);
362 OvsdbClientService client = ovsdbController.getOvsdbClient(ovsdb);
363 if (client == null) {
364 return null;
365 }
366
367 return client;
368 }
369
Jian Li49109b52019-01-22 00:17:28 +0900370 /**
371 * Returns new builder instance.
372 *
373 * @return kubernetes node builder
374 */
375 public static Builder builder() {
376 return new Builder();
377 }
378
379 /**
380 * Returns new builder instance with the given node as a default value.
381 *
382 * @param node kubernetes node
383 * @return kubernetes node builder
384 */
385 public static Builder from(K8sNode node) {
386 return new Builder()
387 .hostname(node.hostname())
388 .type(node.type())
389 .intgBridge(node.intgBridge())
Jian Libf562c22019-04-15 18:07:14 +0900390 .extBridge(node.extBridge())
Jian Li49109b52019-01-22 00:17:28 +0900391 .managementIp(node.managementIp())
392 .dataIp(node.dataIp())
Jian Li1b08d652019-05-02 17:28:09 +0900393 .state(node.state())
394 .extGatewayMac(node.extGatewayMac());
Jian Li49109b52019-01-22 00:17:28 +0900395 }
396
397 public static final class Builder implements K8sNode.Builder {
398
399 private String hostname;
400 private Type type;
401 private DeviceId intgBridge;
Jian Libf562c22019-04-15 18:07:14 +0900402 private DeviceId extBridge;
Jian Li49109b52019-01-22 00:17:28 +0900403 private IpAddress managementIp;
404 private IpAddress dataIp;
405 private K8sNodeState state;
Jian Li3defa842019-02-12 00:31:35 +0900406 private K8sApiConfig apiConfig;
Jian Li1b08d652019-05-02 17:28:09 +0900407 private MacAddress extGatewayMac;
Jian Li49109b52019-01-22 00:17:28 +0900408
409 // private constructor not intended to use from external
410 private Builder() {
411 }
412
413 @Override
414 public K8sNode build() {
415 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
416 checkArgument(type != null, NOT_NULL_MSG, "type");
417 checkArgument(state != null, NOT_NULL_MSG, "state");
418 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
419
420 return new DefaultK8sNode(hostname,
421 type,
422 intgBridge,
Jian Libf562c22019-04-15 18:07:14 +0900423 extBridge,
Jian Li49109b52019-01-22 00:17:28 +0900424 managementIp,
425 dataIp,
Jian Li1b08d652019-05-02 17:28:09 +0900426 state,
427 extGatewayMac);
Jian Li49109b52019-01-22 00:17:28 +0900428 }
429
430 @Override
431 public Builder hostname(String hostname) {
432 this.hostname = hostname;
433 return this;
434 }
435
436 @Override
437 public Builder type(Type type) {
438 this.type = type;
439 return this;
440 }
441
442 @Override
443 public Builder intgBridge(DeviceId deviceId) {
444 this.intgBridge = deviceId;
445 return this;
446 }
447
448 @Override
Jian Libf562c22019-04-15 18:07:14 +0900449 public Builder extBridge(DeviceId deviceId) {
450 this.extBridge = deviceId;
451 return this;
452 }
453
454 @Override
Jian Li49109b52019-01-22 00:17:28 +0900455 public Builder managementIp(IpAddress managementIp) {
456 this.managementIp = managementIp;
457 return this;
458 }
459
460 @Override
461 public Builder dataIp(IpAddress dataIp) {
462 this.dataIp = dataIp;
463 return this;
464 }
465
466 @Override
467 public Builder state(K8sNodeState state) {
468 this.state = state;
469 return this;
470 }
Jian Li1b08d652019-05-02 17:28:09 +0900471
472 @Override
473 public Builder extGatewayMac(MacAddress extGatewayMac) {
474 this.extGatewayMac = extGatewayMac;
475 return this;
476 }
Jian Li49109b52019-01-22 00:17:28 +0900477 }
478}