blob: 16f70347e713f1eff3e1736f6fc8c0885f90a856 [file] [log] [blame]
Jian Li4eb0cf42020-12-19 04:01:49 +09001/*
2 * Copyright 2020-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.kubevirtnode.api;
17
18import com.google.common.base.MoreObjects;
19import org.apache.commons.lang.StringUtils;
Jian Li858ccd72021-02-04 17:25:01 +090020import org.onlab.osgi.DefaultServiceDirectory;
Jian Li4eb0cf42020-12-19 04:01:49 +090021import org.onlab.packet.IpAddress;
Daniel Park734b5532022-09-26 15:13:59 +090022import org.onlab.packet.MacAddress;
Jian Li4eb0cf42020-12-19 04:01:49 +090023import org.onosproject.net.DeviceId;
Jian Li858ccd72021-02-04 17:25:01 +090024import org.onosproject.net.Port;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.device.DeviceService;
Jian Li4eb0cf42020-12-19 04:01:49 +090027
28import java.util.ArrayList;
29import java.util.Collection;
Jian Lif89d9602021-04-27 19:05:49 +090030import java.util.HashSet;
Jian Li4eb0cf42020-12-19 04:01:49 +090031import java.util.Objects;
Jian Lif89d9602021-04-27 19:05:49 +090032import java.util.Set;
Jian Li4eb0cf42020-12-19 04:01:49 +090033
34import static com.google.common.base.Preconditions.checkArgument;
35import static org.onosproject.kubevirtnode.api.Constants.DEFAULT_CLUSTER_NAME;
Jian Li858ccd72021-02-04 17:25:01 +090036import static org.onosproject.kubevirtnode.api.Constants.GENEVE;
37import static org.onosproject.kubevirtnode.api.Constants.GRE;
Jian Lif89d9602021-04-27 19:05:49 +090038import static org.onosproject.kubevirtnode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
Jian Li4b3436a2022-03-23 13:07:19 +090039import static org.onosproject.kubevirtnode.api.Constants.STT;
Jian Li858ccd72021-02-04 17:25:01 +090040import static org.onosproject.kubevirtnode.api.Constants.VXLAN;
41import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Jian Li4eb0cf42020-12-19 04:01:49 +090042
43/**
44 * Representation of a KubeVirt node.
45 */
46public class DefaultKubevirtNode implements KubevirtNode {
47
48 private static final String NOT_NULL_MSG = "Node % cannot be null";
49 private static final String OVSDB = "ovsdb:";
Jian Lif89d9602021-04-27 19:05:49 +090050 private static final int PORT_NAME_MAX_LENGTH = 15;
Jian Li4eb0cf42020-12-19 04:01:49 +090051
52 private final String clusterName;
53 private final String hostname;
54 private final Type type;
55 private final DeviceId intgBridge;
Jian Li4fe40e52021-01-06 03:29:58 +090056 private final DeviceId tunBridge;
Jian Li4eb0cf42020-12-19 04:01:49 +090057 private final IpAddress managementIp;
58 private final IpAddress dataIp;
59 private final KubevirtNodeState state;
60 private final Collection<KubevirtPhyInterface> phyIntfs;
Daniel Park515f5f32021-02-22 17:12:20 +090061 private final String gatewayBridgeName;
Daniel Park734b5532022-09-26 15:13:59 +090062 private final String elbBridgeName;
63 private final IpAddress elbIp;
64 private final IpAddress elbGwIp;
65 private final MacAddress elbGwMac;
Jian Li4eb0cf42020-12-19 04:01:49 +090066
67 /**
68 * A default constructor of kubevirt node.
69 *
70 * @param clusterName clusterName
71 * @param hostname hostname
72 * @param type node type
73 * @param intgBridge integration bridge
Jian Li4fe40e52021-01-06 03:29:58 +090074 * @param tunBridge tunnel bridge
Jian Li4eb0cf42020-12-19 04:01:49 +090075 * @param managementIp management IP address
76 * @param dataIp data IP address
77 * @param state node state
78 * @param phyIntfs physical interfaces
Daniel Park515f5f32021-02-22 17:12:20 +090079 * @param gatewayBridgeName gateway bridge name
Daniel Park734b5532022-09-26 15:13:59 +090080 * @param elbBridgeName elb bridge name
81 * @param elbIp elb IP address
82 * @param elbGwIp elb gw IP address
83 * @param elbGwMac elb gw MAC address
Jian Li4eb0cf42020-12-19 04:01:49 +090084 */
85 protected DefaultKubevirtNode(String clusterName, String hostname, Type type,
Jian Li4fe40e52021-01-06 03:29:58 +090086 DeviceId intgBridge, DeviceId tunBridge,
87 IpAddress managementIp, IpAddress dataIp,
88 KubevirtNodeState state,
Daniel Park515f5f32021-02-22 17:12:20 +090089 Collection<KubevirtPhyInterface> phyIntfs,
Daniel Park734b5532022-09-26 15:13:59 +090090 String gatewayBridgeName, String elbBridgeName, IpAddress elbIp,
91 IpAddress elbGwIp, MacAddress elbGwMac) {
Jian Li4eb0cf42020-12-19 04:01:49 +090092 this.clusterName = clusterName;
93 this.hostname = hostname;
94 this.type = type;
95 this.intgBridge = intgBridge;
Jian Li4fe40e52021-01-06 03:29:58 +090096 this.tunBridge = tunBridge;
Jian Li4eb0cf42020-12-19 04:01:49 +090097 this.managementIp = managementIp;
98 this.dataIp = dataIp;
99 this.state = state;
100 this.phyIntfs = phyIntfs;
Daniel Park515f5f32021-02-22 17:12:20 +0900101 this.gatewayBridgeName = gatewayBridgeName;
Daniel Park734b5532022-09-26 15:13:59 +0900102 this.elbBridgeName = elbBridgeName;
103 this.elbIp = elbIp;
104 this.elbGwIp = elbGwIp;
105 this.elbGwMac = elbGwMac;
Jian Li4eb0cf42020-12-19 04:01:49 +0900106 }
107
108 @Override
109 public String clusterName() {
110 return clusterName;
111 }
112
113 @Override
114 public String hostname() {
115 return hostname;
116 }
117
118 @Override
119 public Type type() {
120 return type;
121 }
122
123 @Override
124 public DeviceId ovsdb() {
125 return DeviceId.deviceId(OVSDB + managementIp().toString());
126 }
127
128 @Override
129 public DeviceId intgBridge() {
130 return intgBridge;
131 }
132
133 @Override
Jian Li4fe40e52021-01-06 03:29:58 +0900134 public DeviceId tunBridge() {
135 return tunBridge;
136 }
137
138 @Override
Jian Li4eb0cf42020-12-19 04:01:49 +0900139 public IpAddress managementIp() {
140 return managementIp;
141 }
142
143 @Override
144 public IpAddress dataIp() {
145 return dataIp;
146 }
147
148 @Override
149 public KubevirtNodeState state() {
150 return state;
151 }
152
153 @Override
154 public KubevirtNode updateState(KubevirtNodeState newState) {
155 return new Builder()
156 .hostname(hostname)
157 .clusterName(clusterName)
158 .type(type)
159 .intgBridge(intgBridge)
Jian Li4fe40e52021-01-06 03:29:58 +0900160 .tunBridge(tunBridge)
Jian Li4eb0cf42020-12-19 04:01:49 +0900161 .managementIp(managementIp)
162 .dataIp(dataIp)
163 .state(newState)
164 .phyIntfs(phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900165 .gatewayBridgeName(gatewayBridgeName)
Daniel Park734b5532022-09-26 15:13:59 +0900166 .elbBridgeName(elbBridgeName)
167 .elbIp(elbIp)
168 .elbGwIp(elbGwIp)
169 .elbGwMac(elbGwMac)
Jian Li4eb0cf42020-12-19 04:01:49 +0900170 .build();
171 }
172
173 @Override
Jian Lib230e07c2020-12-21 11:25:12 +0900174 public KubevirtNode updateIntgBridge(DeviceId deviceId) {
175 return new Builder()
176 .hostname(hostname)
177 .clusterName(clusterName)
178 .type(type)
179 .intgBridge(deviceId)
Jian Li4fe40e52021-01-06 03:29:58 +0900180 .tunBridge(tunBridge)
181 .managementIp(managementIp)
182 .dataIp(dataIp)
183 .state(state)
184 .phyIntfs(phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900185 .gatewayBridgeName(gatewayBridgeName)
Daniel Park734b5532022-09-26 15:13:59 +0900186 .elbBridgeName(elbBridgeName)
187 .elbIp(elbIp)
188 .elbGwIp(elbGwIp)
189 .elbGwMac(elbGwMac)
Jian Li4fe40e52021-01-06 03:29:58 +0900190 .build();
191 }
192
193 @Override
194 public KubevirtNode updateTunBridge(DeviceId deviceId) {
195 return new Builder()
196 .hostname(hostname)
197 .clusterName(clusterName)
198 .type(type)
199 .intgBridge(intgBridge)
200 .tunBridge(deviceId)
Jian Lib230e07c2020-12-21 11:25:12 +0900201 .managementIp(managementIp)
202 .dataIp(dataIp)
203 .state(state)
204 .phyIntfs(phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900205 .gatewayBridgeName(gatewayBridgeName)
Daniel Park734b5532022-09-26 15:13:59 +0900206 .elbBridgeName(elbBridgeName)
207 .elbIp(elbIp)
208 .elbGwIp(elbGwIp)
209 .elbGwMac(elbGwMac)
Jian Lib230e07c2020-12-21 11:25:12 +0900210 .build();
211 }
212
213 @Override
Jian Li4eb0cf42020-12-19 04:01:49 +0900214 public Collection<KubevirtPhyInterface> phyIntfs() {
215 if (phyIntfs == null) {
216 return new ArrayList<>();
217 }
218
219 return phyIntfs;
220 }
221
Jian Li858ccd72021-02-04 17:25:01 +0900222 @Override
Jian Lif89d9602021-04-27 19:05:49 +0900223 public Set<PortNumber> physPatchPorts() {
224 Set<PortNumber> portNumbers = new HashSet<>();
225 for (KubevirtPhyInterface phyIntf : this.phyIntfs()) {
226 String portName = structurePortName(
227 INTEGRATION_TO_PHYSICAL_PREFIX + phyIntf.network());
228 PortNumber portNumber = patchPort(portName);
229 if (portNumber != null) {
230 portNumbers.add(portNumber);
231 }
232 }
233 return portNumbers;
234 }
235
236 @Override
Jian Li858ccd72021-02-04 17:25:01 +0900237 public PortNumber vxlanPort() {
238 return tunnelPort(VXLAN);
239 }
240
241 @Override
242 public PortNumber grePort() {
243 return tunnelPort(GRE);
244 }
245
246 @Override
247 public PortNumber genevePort() {
248 return tunnelPort(GENEVE);
249 }
250
Daniel Park515f5f32021-02-22 17:12:20 +0900251 @Override
Jian Li4b3436a2022-03-23 13:07:19 +0900252 public PortNumber sttPort() {
253 return tunnelPort(STT);
254 }
255
256 @Override
Daniel Park515f5f32021-02-22 17:12:20 +0900257 public String gatewayBridgeName() {
258 return gatewayBridgeName;
259 }
260
Daniel Park734b5532022-09-26 15:13:59 +0900261 @Override
262 public String elbBridgeName() {
263 return elbBridgeName;
264 }
265
266 @Override
267 public IpAddress elbIp() {
268 return elbIp;
269 }
270
271 @Override
272 public IpAddress elbGwIp() {
273 return elbGwIp;
274 }
275
276 @Override
277 public MacAddress elbGwMac() {
278 return elbGwMac;
279 }
280
Jian Li858ccd72021-02-04 17:25:01 +0900281 private PortNumber tunnelPort(String tunnelType) {
282 if (dataIp == null) {
283 return null;
284 }
285 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
286 Port port = deviceService.getPorts(tunBridge).stream()
287 .filter(p -> p.isEnabled() &&
288 Objects.equals(p.annotations().value(PORT_NAME), tunnelType))
289 .findAny().orElse(null);
290 return port != null ? port.number() : null;
291 }
292
Jian Lif89d9602021-04-27 19:05:49 +0900293 private PortNumber patchPort(String portName) {
294 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
295 Port port = deviceService.getPorts(intgBridge).stream()
296 .filter(p -> p.isEnabled() &&
297 Objects.equals(p.annotations().value(PORT_NAME), portName))
298 .findAny().orElse(null);
299 return port != null ? port.number() : null;
300 }
301
302 /**
303 * Re-structures the OVS port name.
304 * The length of OVS port name should be not large than 15.
305 *
306 * @param portName original port name
307 * @return re-structured OVS port name
308 */
309 private String structurePortName(String portName) {
310
311 // The size of OVS port name should not be larger than 15
312 if (portName.length() > PORT_NAME_MAX_LENGTH) {
313 return StringUtils.substring(portName, 0, PORT_NAME_MAX_LENGTH);
314 }
315
316 return portName;
317 }
318
Jian Li4eb0cf42020-12-19 04:01:49 +0900319 /**
320 * Returns new builder instance.
321 *
322 * @return kubevirt node builder
323 */
324 public static Builder builder() {
325 return new Builder();
326 }
327
328 /**
329 * Returns new builder instance with the given node as a default value.
330 *
331 * @param node kubevirt node
332 * @return kubevirt node builder
333 */
334 public static Builder from(KubevirtNode node) {
335 return new Builder()
336 .hostname(node.hostname())
337 .clusterName(node.clusterName())
338 .type(node.type())
339 .intgBridge(node.intgBridge())
Jian Li4fe40e52021-01-06 03:29:58 +0900340 .tunBridge(node.tunBridge())
Jian Li4eb0cf42020-12-19 04:01:49 +0900341 .managementIp(node.managementIp())
342 .dataIp(node.dataIp())
Jian Li4fe40e52021-01-06 03:29:58 +0900343 .state(node.state())
Daniel Park515f5f32021-02-22 17:12:20 +0900344 .phyIntfs(node.phyIntfs())
Daniel Park734b5532022-09-26 15:13:59 +0900345 .gatewayBridgeName(node.gatewayBridgeName())
346 .elbBridgeName(node.elbBridgeName())
347 .elbIp(node.elbIp())
348 .elbGwIp(node.elbGwIp())
349 .elbGwMac(node.elbGwMac());
Jian Li4eb0cf42020-12-19 04:01:49 +0900350 }
351
352 @Override
353 public boolean equals(Object o) {
354 if (this == o) {
355 return true;
356 }
357 if (o == null || getClass() != o.getClass()) {
358 return false;
359 }
360 DefaultKubevirtNode that = (DefaultKubevirtNode) o;
361 return clusterName.equals(that.clusterName) &&
362 hostname.equals(that.hostname) &&
363 type == that.type &&
364 intgBridge.equals(that.intgBridge) &&
Jian Li4fe40e52021-01-06 03:29:58 +0900365 tunBridge.equals(that.tunBridge) &&
Jian Li4eb0cf42020-12-19 04:01:49 +0900366 managementIp.equals(that.managementIp) &&
367 dataIp.equals(that.dataIp);
368 }
369
370 @Override
371 public int hashCode() {
Jian Li4fe40e52021-01-06 03:29:58 +0900372 return Objects.hash(clusterName, hostname, type, intgBridge, tunBridge,
Jian Li4eb0cf42020-12-19 04:01:49 +0900373 managementIp, dataIp);
374 }
375
376 @Override
377 public String toString() {
378 return MoreObjects.toStringHelper(this)
379 .add("clusterName", clusterName)
380 .add("hostname", hostname)
381 .add("type", type)
382 .add("intgBridge", intgBridge)
Jian Li4fe40e52021-01-06 03:29:58 +0900383 .add("tunBridge", tunBridge)
Jian Li4eb0cf42020-12-19 04:01:49 +0900384 .add("managementIp", managementIp)
385 .add("dataIp", dataIp)
386 .add("state", state)
Jian Li4fe40e52021-01-06 03:29:58 +0900387 .add("phyIntfs", phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900388 .add("gatewayBridgeName", gatewayBridgeName)
Daniel Park734b5532022-09-26 15:13:59 +0900389 .add("elbBridgeName", elbBridgeName)
390 .add("elbIp", elbIp)
391 .add("elbGwIp", elbGwIp)
392 .add("elbGwMac", elbGwMac)
Jian Li4eb0cf42020-12-19 04:01:49 +0900393 .toString();
394 }
395
396 public static final class Builder implements KubevirtNode.Builder {
397
398 private String clusterName;
399 private String hostname;
400 private Type type;
401 private DeviceId intgBridge;
Jian Li4fe40e52021-01-06 03:29:58 +0900402 private DeviceId tunBridge;
Jian Li4eb0cf42020-12-19 04:01:49 +0900403 private IpAddress managementIp;
404 private IpAddress dataIp;
405 private KubevirtNodeState state;
406 private Collection<KubevirtPhyInterface> phyIntfs;
Daniel Park515f5f32021-02-22 17:12:20 +0900407 private String gatewayBridgeName;
Daniel Park734b5532022-09-26 15:13:59 +0900408 private String elbBridgeName;
409 private IpAddress elbIp;
410 private IpAddress elbGwIp;
411 private MacAddress elbGwMac;
Jian Li4eb0cf42020-12-19 04:01:49 +0900412
413 // private constructor not intended to use from external
414 private Builder() {
415 }
416
417 @Override
418 public KubevirtNode build() {
419 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
420 checkArgument(type != null, NOT_NULL_MSG, "type");
421 checkArgument(state != null, NOT_NULL_MSG, "state");
422 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
423
424 if (StringUtils.isEmpty(clusterName)) {
425 clusterName = DEFAULT_CLUSTER_NAME;
426 }
427
428 return new DefaultKubevirtNode(
429 clusterName,
430 hostname,
431 type,
432 intgBridge,
Jian Li4fe40e52021-01-06 03:29:58 +0900433 tunBridge,
Jian Li4eb0cf42020-12-19 04:01:49 +0900434 managementIp,
435 dataIp,
436 state,
Daniel Park515f5f32021-02-22 17:12:20 +0900437 phyIntfs,
Daniel Park734b5532022-09-26 15:13:59 +0900438 gatewayBridgeName,
439 elbBridgeName,
440 elbIp,
441 elbGwIp,
442 elbGwMac
Jian Li4eb0cf42020-12-19 04:01:49 +0900443 );
444 }
445
446 @Override
447 public Builder clusterName(String clusterName) {
448 this.clusterName = clusterName;
449 return this;
450 }
451
452 @Override
453 public Builder hostname(String hostname) {
454 this.hostname = hostname;
455 return this;
456 }
457
458 @Override
459 public Builder type(Type type) {
460 this.type = type;
461 return this;
462 }
463
464 @Override
465 public Builder intgBridge(DeviceId deviceId) {
466 this.intgBridge = deviceId;
467 return this;
468 }
469
470 @Override
Jian Li4fe40e52021-01-06 03:29:58 +0900471 public Builder tunBridge(DeviceId deviceId) {
472 this.tunBridge = deviceId;
473 return this;
474 }
475
476 @Override
Jian Li4eb0cf42020-12-19 04:01:49 +0900477 public Builder managementIp(IpAddress managementIp) {
478 this.managementIp = managementIp;
479 return this;
480 }
481
482 @Override
483 public Builder dataIp(IpAddress dataIp) {
484 this.dataIp = dataIp;
485 return this;
486 }
487
488 @Override
489 public Builder phyIntfs(Collection<KubevirtPhyInterface> phyIntfs) {
490 this.phyIntfs = phyIntfs;
491 return this;
492 }
493
494 @Override
495 public Builder state(KubevirtNodeState state) {
496 this.state = state;
497 return this;
498 }
Daniel Park515f5f32021-02-22 17:12:20 +0900499
500 @Override
501 public Builder gatewayBridgeName(String gatewayBridgeName) {
502 this.gatewayBridgeName = gatewayBridgeName;
503 return this;
504 }
Daniel Park734b5532022-09-26 15:13:59 +0900505
506 @Override
507 public Builder elbBridgeName(String elbBridgeName) {
508 this.elbBridgeName = elbBridgeName;
509 return this;
510 }
511
512 @Override
513 public Builder elbIp(IpAddress elbIp) {
514 this.elbIp = elbIp;
515 return this;
516 }
517
518 @Override
519 public Builder elbGwIp(IpAddress elbGwIp) {
520 this.elbGwIp = elbGwIp;
521 return this;
522 }
523
524 @Override
525 public Builder elbGwMac(MacAddress elbGwMac) {
526 this.elbGwMac = elbGwMac;
527 return this;
528 }
Jian Li4eb0cf42020-12-19 04:01:49 +0900529 }
530}