blob: f6475036870ffdf0bdd81d87674635223d76097a [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;
22import org.onosproject.net.DeviceId;
Jian Li858ccd72021-02-04 17:25:01 +090023import org.onosproject.net.Port;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.device.DeviceService;
Jian Li4eb0cf42020-12-19 04:01:49 +090026
27import java.util.ArrayList;
28import java.util.Collection;
Jian Lif89d9602021-04-27 19:05:49 +090029import java.util.HashSet;
Jian Li4eb0cf42020-12-19 04:01:49 +090030import java.util.Objects;
Jian Lif89d9602021-04-27 19:05:49 +090031import java.util.Set;
Jian Li4eb0cf42020-12-19 04:01:49 +090032
33import static com.google.common.base.Preconditions.checkArgument;
34import static org.onosproject.kubevirtnode.api.Constants.DEFAULT_CLUSTER_NAME;
Jian Li858ccd72021-02-04 17:25:01 +090035import static org.onosproject.kubevirtnode.api.Constants.GENEVE;
36import static org.onosproject.kubevirtnode.api.Constants.GRE;
Jian Lif89d9602021-04-27 19:05:49 +090037import static org.onosproject.kubevirtnode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
Jian Li858ccd72021-02-04 17:25:01 +090038import static org.onosproject.kubevirtnode.api.Constants.VXLAN;
39import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Jian Li4eb0cf42020-12-19 04:01:49 +090040
41/**
42 * Representation of a KubeVirt node.
43 */
44public class DefaultKubevirtNode implements KubevirtNode {
45
46 private static final String NOT_NULL_MSG = "Node % cannot be null";
47 private static final String OVSDB = "ovsdb:";
Jian Lif89d9602021-04-27 19:05:49 +090048 private static final int PORT_NAME_MAX_LENGTH = 15;
Jian Li4eb0cf42020-12-19 04:01:49 +090049
50 private final String clusterName;
51 private final String hostname;
52 private final Type type;
53 private final DeviceId intgBridge;
Jian Li4fe40e52021-01-06 03:29:58 +090054 private final DeviceId tunBridge;
Jian Li4eb0cf42020-12-19 04:01:49 +090055 private final IpAddress managementIp;
56 private final IpAddress dataIp;
57 private final KubevirtNodeState state;
58 private final Collection<KubevirtPhyInterface> phyIntfs;
Daniel Park515f5f32021-02-22 17:12:20 +090059 private final String gatewayBridgeName;
Jian Li4eb0cf42020-12-19 04:01:49 +090060
61 /**
62 * A default constructor of kubevirt node.
63 *
64 * @param clusterName clusterName
65 * @param hostname hostname
66 * @param type node type
67 * @param intgBridge integration bridge
Jian Li4fe40e52021-01-06 03:29:58 +090068 * @param tunBridge tunnel bridge
Jian Li4eb0cf42020-12-19 04:01:49 +090069 * @param managementIp management IP address
70 * @param dataIp data IP address
71 * @param state node state
72 * @param phyIntfs physical interfaces
Daniel Park515f5f32021-02-22 17:12:20 +090073 * @param gatewayBridgeName gateway bridge name
Jian Li4eb0cf42020-12-19 04:01:49 +090074 */
75 protected DefaultKubevirtNode(String clusterName, String hostname, Type type,
Jian Li4fe40e52021-01-06 03:29:58 +090076 DeviceId intgBridge, DeviceId tunBridge,
77 IpAddress managementIp, IpAddress dataIp,
78 KubevirtNodeState state,
Daniel Park515f5f32021-02-22 17:12:20 +090079 Collection<KubevirtPhyInterface> phyIntfs,
80 String gatewayBridgeName) {
Jian Li4eb0cf42020-12-19 04:01:49 +090081 this.clusterName = clusterName;
82 this.hostname = hostname;
83 this.type = type;
84 this.intgBridge = intgBridge;
Jian Li4fe40e52021-01-06 03:29:58 +090085 this.tunBridge = tunBridge;
Jian Li4eb0cf42020-12-19 04:01:49 +090086 this.managementIp = managementIp;
87 this.dataIp = dataIp;
88 this.state = state;
89 this.phyIntfs = phyIntfs;
Daniel Park515f5f32021-02-22 17:12:20 +090090 this.gatewayBridgeName = gatewayBridgeName;
Jian Li4eb0cf42020-12-19 04:01:49 +090091 }
92
93 @Override
94 public String clusterName() {
95 return clusterName;
96 }
97
98 @Override
99 public String hostname() {
100 return hostname;
101 }
102
103 @Override
104 public Type type() {
105 return type;
106 }
107
108 @Override
109 public DeviceId ovsdb() {
110 return DeviceId.deviceId(OVSDB + managementIp().toString());
111 }
112
113 @Override
114 public DeviceId intgBridge() {
115 return intgBridge;
116 }
117
118 @Override
Jian Li4fe40e52021-01-06 03:29:58 +0900119 public DeviceId tunBridge() {
120 return tunBridge;
121 }
122
123 @Override
Jian Li4eb0cf42020-12-19 04:01:49 +0900124 public IpAddress managementIp() {
125 return managementIp;
126 }
127
128 @Override
129 public IpAddress dataIp() {
130 return dataIp;
131 }
132
133 @Override
134 public KubevirtNodeState state() {
135 return state;
136 }
137
138 @Override
139 public KubevirtNode updateState(KubevirtNodeState newState) {
140 return new Builder()
141 .hostname(hostname)
142 .clusterName(clusterName)
143 .type(type)
144 .intgBridge(intgBridge)
Jian Li4fe40e52021-01-06 03:29:58 +0900145 .tunBridge(tunBridge)
Jian Li4eb0cf42020-12-19 04:01:49 +0900146 .managementIp(managementIp)
147 .dataIp(dataIp)
148 .state(newState)
149 .phyIntfs(phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900150 .gatewayBridgeName(gatewayBridgeName)
Jian Li4eb0cf42020-12-19 04:01:49 +0900151 .build();
152 }
153
154 @Override
Jian Lib230e07c2020-12-21 11:25:12 +0900155 public KubevirtNode updateIntgBridge(DeviceId deviceId) {
156 return new Builder()
157 .hostname(hostname)
158 .clusterName(clusterName)
159 .type(type)
160 .intgBridge(deviceId)
Jian Li4fe40e52021-01-06 03:29:58 +0900161 .tunBridge(tunBridge)
162 .managementIp(managementIp)
163 .dataIp(dataIp)
164 .state(state)
165 .phyIntfs(phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900166 .gatewayBridgeName(gatewayBridgeName)
Jian Li4fe40e52021-01-06 03:29:58 +0900167 .build();
168 }
169
170 @Override
171 public KubevirtNode updateTunBridge(DeviceId deviceId) {
172 return new Builder()
173 .hostname(hostname)
174 .clusterName(clusterName)
175 .type(type)
176 .intgBridge(intgBridge)
177 .tunBridge(deviceId)
Jian Lib230e07c2020-12-21 11:25:12 +0900178 .managementIp(managementIp)
179 .dataIp(dataIp)
180 .state(state)
181 .phyIntfs(phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900182 .gatewayBridgeName(gatewayBridgeName)
Jian Lib230e07c2020-12-21 11:25:12 +0900183 .build();
184 }
185
186 @Override
Jian Li4eb0cf42020-12-19 04:01:49 +0900187 public Collection<KubevirtPhyInterface> phyIntfs() {
188 if (phyIntfs == null) {
189 return new ArrayList<>();
190 }
191
192 return phyIntfs;
193 }
194
Jian Li858ccd72021-02-04 17:25:01 +0900195 @Override
Jian Lif89d9602021-04-27 19:05:49 +0900196 public Set<PortNumber> physPatchPorts() {
197 Set<PortNumber> portNumbers = new HashSet<>();
198 for (KubevirtPhyInterface phyIntf : this.phyIntfs()) {
199 String portName = structurePortName(
200 INTEGRATION_TO_PHYSICAL_PREFIX + phyIntf.network());
201 PortNumber portNumber = patchPort(portName);
202 if (portNumber != null) {
203 portNumbers.add(portNumber);
204 }
205 }
206 return portNumbers;
207 }
208
209 @Override
Jian Li858ccd72021-02-04 17:25:01 +0900210 public PortNumber vxlanPort() {
211 return tunnelPort(VXLAN);
212 }
213
214 @Override
215 public PortNumber grePort() {
216 return tunnelPort(GRE);
217 }
218
219 @Override
220 public PortNumber genevePort() {
221 return tunnelPort(GENEVE);
222 }
223
Daniel Park515f5f32021-02-22 17:12:20 +0900224 @Override
225 public String gatewayBridgeName() {
226 return gatewayBridgeName;
227 }
228
Jian Li858ccd72021-02-04 17:25:01 +0900229 private PortNumber tunnelPort(String tunnelType) {
230 if (dataIp == null) {
231 return null;
232 }
233 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
234 Port port = deviceService.getPorts(tunBridge).stream()
235 .filter(p -> p.isEnabled() &&
236 Objects.equals(p.annotations().value(PORT_NAME), tunnelType))
237 .findAny().orElse(null);
238 return port != null ? port.number() : null;
239 }
240
Jian Lif89d9602021-04-27 19:05:49 +0900241 private PortNumber patchPort(String portName) {
242 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
243 Port port = deviceService.getPorts(intgBridge).stream()
244 .filter(p -> p.isEnabled() &&
245 Objects.equals(p.annotations().value(PORT_NAME), portName))
246 .findAny().orElse(null);
247 return port != null ? port.number() : null;
248 }
249
250 /**
251 * Re-structures the OVS port name.
252 * The length of OVS port name should be not large than 15.
253 *
254 * @param portName original port name
255 * @return re-structured OVS port name
256 */
257 private String structurePortName(String portName) {
258
259 // The size of OVS port name should not be larger than 15
260 if (portName.length() > PORT_NAME_MAX_LENGTH) {
261 return StringUtils.substring(portName, 0, PORT_NAME_MAX_LENGTH);
262 }
263
264 return portName;
265 }
266
Jian Li4eb0cf42020-12-19 04:01:49 +0900267 /**
268 * Returns new builder instance.
269 *
270 * @return kubevirt node builder
271 */
272 public static Builder builder() {
273 return new Builder();
274 }
275
276 /**
277 * Returns new builder instance with the given node as a default value.
278 *
279 * @param node kubevirt node
280 * @return kubevirt node builder
281 */
282 public static Builder from(KubevirtNode node) {
283 return new Builder()
284 .hostname(node.hostname())
285 .clusterName(node.clusterName())
286 .type(node.type())
287 .intgBridge(node.intgBridge())
Jian Li4fe40e52021-01-06 03:29:58 +0900288 .tunBridge(node.tunBridge())
Jian Li4eb0cf42020-12-19 04:01:49 +0900289 .managementIp(node.managementIp())
290 .dataIp(node.dataIp())
Jian Li4fe40e52021-01-06 03:29:58 +0900291 .state(node.state())
Daniel Park515f5f32021-02-22 17:12:20 +0900292 .phyIntfs(node.phyIntfs())
293 .gatewayBridgeName(node.gatewayBridgeName());
Jian Li4eb0cf42020-12-19 04:01:49 +0900294 }
295
296 @Override
297 public boolean equals(Object o) {
298 if (this == o) {
299 return true;
300 }
301 if (o == null || getClass() != o.getClass()) {
302 return false;
303 }
304 DefaultKubevirtNode that = (DefaultKubevirtNode) o;
305 return clusterName.equals(that.clusterName) &&
306 hostname.equals(that.hostname) &&
307 type == that.type &&
308 intgBridge.equals(that.intgBridge) &&
Jian Li4fe40e52021-01-06 03:29:58 +0900309 tunBridge.equals(that.tunBridge) &&
Jian Li4eb0cf42020-12-19 04:01:49 +0900310 managementIp.equals(that.managementIp) &&
311 dataIp.equals(that.dataIp);
312 }
313
314 @Override
315 public int hashCode() {
Jian Li4fe40e52021-01-06 03:29:58 +0900316 return Objects.hash(clusterName, hostname, type, intgBridge, tunBridge,
Jian Li4eb0cf42020-12-19 04:01:49 +0900317 managementIp, dataIp);
318 }
319
320 @Override
321 public String toString() {
322 return MoreObjects.toStringHelper(this)
323 .add("clusterName", clusterName)
324 .add("hostname", hostname)
325 .add("type", type)
326 .add("intgBridge", intgBridge)
Jian Li4fe40e52021-01-06 03:29:58 +0900327 .add("tunBridge", tunBridge)
Jian Li4eb0cf42020-12-19 04:01:49 +0900328 .add("managementIp", managementIp)
329 .add("dataIp", dataIp)
330 .add("state", state)
Jian Li4fe40e52021-01-06 03:29:58 +0900331 .add("phyIntfs", phyIntfs)
Daniel Park515f5f32021-02-22 17:12:20 +0900332 .add("gatewayBridgeName", gatewayBridgeName)
Jian Li4eb0cf42020-12-19 04:01:49 +0900333 .toString();
334 }
335
336 public static final class Builder implements KubevirtNode.Builder {
337
338 private String clusterName;
339 private String hostname;
340 private Type type;
341 private DeviceId intgBridge;
Jian Li4fe40e52021-01-06 03:29:58 +0900342 private DeviceId tunBridge;
Jian Li4eb0cf42020-12-19 04:01:49 +0900343 private IpAddress managementIp;
344 private IpAddress dataIp;
345 private KubevirtNodeState state;
346 private Collection<KubevirtPhyInterface> phyIntfs;
Daniel Park515f5f32021-02-22 17:12:20 +0900347 private String gatewayBridgeName;
Jian Li4eb0cf42020-12-19 04:01:49 +0900348
349 // private constructor not intended to use from external
350 private Builder() {
351 }
352
353 @Override
354 public KubevirtNode build() {
355 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
356 checkArgument(type != null, NOT_NULL_MSG, "type");
357 checkArgument(state != null, NOT_NULL_MSG, "state");
358 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
359
360 if (StringUtils.isEmpty(clusterName)) {
361 clusterName = DEFAULT_CLUSTER_NAME;
362 }
363
364 return new DefaultKubevirtNode(
365 clusterName,
366 hostname,
367 type,
368 intgBridge,
Jian Li4fe40e52021-01-06 03:29:58 +0900369 tunBridge,
Jian Li4eb0cf42020-12-19 04:01:49 +0900370 managementIp,
371 dataIp,
372 state,
Daniel Park515f5f32021-02-22 17:12:20 +0900373 phyIntfs,
374 gatewayBridgeName
Jian Li4eb0cf42020-12-19 04:01:49 +0900375 );
376 }
377
378 @Override
379 public Builder clusterName(String clusterName) {
380 this.clusterName = clusterName;
381 return this;
382 }
383
384 @Override
385 public Builder hostname(String hostname) {
386 this.hostname = hostname;
387 return this;
388 }
389
390 @Override
391 public Builder type(Type type) {
392 this.type = type;
393 return this;
394 }
395
396 @Override
397 public Builder intgBridge(DeviceId deviceId) {
398 this.intgBridge = deviceId;
399 return this;
400 }
401
402 @Override
Jian Li4fe40e52021-01-06 03:29:58 +0900403 public Builder tunBridge(DeviceId deviceId) {
404 this.tunBridge = deviceId;
405 return this;
406 }
407
408 @Override
Jian Li4eb0cf42020-12-19 04:01:49 +0900409 public Builder managementIp(IpAddress managementIp) {
410 this.managementIp = managementIp;
411 return this;
412 }
413
414 @Override
415 public Builder dataIp(IpAddress dataIp) {
416 this.dataIp = dataIp;
417 return this;
418 }
419
420 @Override
421 public Builder phyIntfs(Collection<KubevirtPhyInterface> phyIntfs) {
422 this.phyIntfs = phyIntfs;
423 return this;
424 }
425
426 @Override
427 public Builder state(KubevirtNodeState state) {
428 this.state = state;
429 return this;
430 }
Daniel Park515f5f32021-02-22 17:12:20 +0900431
432 @Override
433 public Builder gatewayBridgeName(String gatewayBridgeName) {
434 this.gatewayBridgeName = gatewayBridgeName;
435 return this;
436 }
Jian Li4eb0cf42020-12-19 04:01:49 +0900437 }
438}