blob: e6592b056b6044bcbc740f8b3547cf505dcca2f7 [file] [log] [blame]
Hyunsun Moon0d457362017-06-27 17:19:41 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Hyunsun Moon0d457362017-06-27 17:19:41 +09003 *
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.openstacknode.impl;
17
18import com.google.common.base.MoreObjects;
19import com.google.common.base.Strings;
20import org.onlab.osgi.DefaultServiceDirectory;
21import org.onlab.packet.IpAddress;
22import org.onlab.packet.MacAddress;
23import org.onosproject.core.GroupId;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.Port;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.device.DeviceService;
28import org.onosproject.net.group.DefaultGroupKey;
29import org.onosproject.net.group.GroupKey;
30import org.onosproject.openstacknode.api.NodeState;
Jian Li27841662018-04-14 01:59:47 +090031import org.onosproject.openstacknode.api.OpenstackAuth;
Hyunsun Moon0d457362017-06-27 17:19:41 +090032import org.onosproject.openstacknode.api.OpenstackNode;
Jian Lie6312162018-03-21 21:41:00 +090033import org.onosproject.openstacknode.api.OpenstackPhyInterface;
Hyunsun Moon0d457362017-06-27 17:19:41 +090034
Jian Lie6312162018-03-21 21:41:00 +090035import java.util.ArrayList;
36import java.util.Collection;
Hyunsun Moon0d457362017-06-27 17:19:41 +090037import java.util.Objects;
daniel park796c2eb2018-03-22 17:01:51 +090038import java.util.Optional;
Hyunsun Moon0d457362017-06-27 17:19:41 +090039
40import static com.google.common.base.Preconditions.checkArgument;
41import static org.onosproject.net.AnnotationKeys.PORT_MAC;
42import static org.onosproject.net.AnnotationKeys.PORT_NAME;
43import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
44import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
45
46/**
47 * Representation of a openstack node.
48 */
Hyunsun Moon090d77d2017-07-05 17:48:37 +090049public class DefaultOpenstackNode implements OpenstackNode {
Hyunsun Moon0d457362017-06-27 17:19:41 +090050
51 private final String hostname;
52 private final NodeType type;
53 private final DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090054 private final IpAddress managementIp;
55 private final IpAddress dataIp;
56 private final String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090057 private final String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090058 private final NodeState state;
Jian Lie6312162018-03-21 21:41:00 +090059 private final Collection<OpenstackPhyInterface> phyIntfs;
Jian Li27841662018-04-14 01:59:47 +090060 private final OpenstackAuth auth;
Jian Li92d42fc2018-05-25 16:23:49 +090061 private final String endPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +090062
Jian Li340165f2018-02-27 10:38:17 +090063 private static final String NOT_NULL_MSG = "Node % cannot be null";
64
daniel parkb18424c2018-02-05 15:43:43 +090065 private static final String OVSDB = "ovsdb:";
66
Jian Li340165f2018-02-27 10:38:17 +090067 /**
68 * A default constructor of Openstack Node.
69 *
70 * @param hostname hostname
71 * @param type node type
72 * @param intgBridge integration bridge
73 * @param managementIp management IP address
74 * @param dataIp data IP address
75 * @param vlanIntf VLAN interface
76 * @param uplinkPort uplink port name
77 * @param state node state
Jian Lie6312162018-03-21 21:41:00 +090078 * @param phyIntfs physical interfaces
Jian Li27841662018-04-14 01:59:47 +090079 * @param auth keystone authentication info
Jian Li92d42fc2018-05-25 16:23:49 +090080 * @param endPoint openstack endpoint URL
Jian Li340165f2018-02-27 10:38:17 +090081 */
daniel parkb18424c2018-02-05 15:43:43 +090082 protected DefaultOpenstackNode(String hostname, NodeType type,
83 DeviceId intgBridge,
84 IpAddress managementIp,
85 IpAddress dataIp,
86 String vlanIntf,
87 String uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +090088 NodeState state,
Jian Li27841662018-04-14 01:59:47 +090089 Collection<OpenstackPhyInterface> phyIntfs,
Jian Li92d42fc2018-05-25 16:23:49 +090090 OpenstackAuth auth,
91 String endPoint) {
Hyunsun Moon0d457362017-06-27 17:19:41 +090092 this.hostname = hostname;
93 this.type = type;
94 this.intgBridge = intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090095 this.managementIp = managementIp;
96 this.dataIp = dataIp;
97 this.vlanIntf = vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090098 this.uplinkPort = uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090099 this.state = state;
Jian Lie6312162018-03-21 21:41:00 +0900100 this.phyIntfs = phyIntfs;
Jian Li27841662018-04-14 01:59:47 +0900101 this.auth = auth;
Jian Li92d42fc2018-05-25 16:23:49 +0900102 this.endPoint = endPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900103 }
104
105 @Override
106 public String hostname() {
107 return hostname;
108 }
109
110 @Override
111 public NodeType type() {
112 return type;
113 }
114
115 @Override
116 public DeviceId ovsdb() {
daniel parkb18424c2018-02-05 15:43:43 +0900117 return DeviceId.deviceId(OVSDB + managementIp().toString());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900118 }
119
120 @Override
121 public DeviceId intgBridge() {
122 return intgBridge;
123 }
124
125 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900126 public IpAddress managementIp() {
127 return managementIp;
128 }
129
130 @Override
131 public IpAddress dataIp() {
132 return dataIp;
133 }
134
135 @Override
136 public String vlanIntf() {
137 return vlanIntf;
138 }
139
140 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900141 public String uplinkPort() {
142 return uplinkPort;
143 }
144
145 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900146 public NodeState state() {
147 return state;
148 }
149
150 @Override
151 public GroupKey gatewayGroupKey(NetworkMode mode) {
152 return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
153 }
154
155 @Override
daniel parkb5817102018-02-15 00:18:51 +0900156 public PortNumber uplinkPortNum() {
157 if (uplinkPort == null) {
158 return null;
159 }
160
161 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
162 Port port = deviceService.getPorts(intgBridge).stream()
163 .filter(p -> p.isEnabled() &&
164 Objects.equals(p.annotations().value(PORT_NAME), uplinkPort))
165 .findAny().orElse(null);
166
167 return port != null ? port.number() : null;
168
169 }
170 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900171 public PortNumber tunnelPortNum() {
172 if (dataIp == null) {
173 return null;
174 }
175 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
176 Port port = deviceService.getPorts(intgBridge).stream()
177 .filter(p -> p.isEnabled() &&
178 Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
179 .findAny().orElse(null);
180 return port != null ? port.number() : null;
181 }
182
183 @Override
184 public PortNumber vlanPortNum() {
185 if (vlanIntf == null) {
186 return null;
187 }
188 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
189 Port port = deviceService.getPorts(intgBridge).stream()
190 .filter(p -> p.isEnabled() &&
191 Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
192 .findAny().orElse(null);
193 return port != null ? port.number() : null;
194 }
195
196 @Override
197 public PortNumber patchPortNum() {
198 if (type == NodeType.COMPUTE) {
199 return null;
200 }
201 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
202 Port port = deviceService.getPorts(intgBridge).stream()
203 .filter(p -> p.isEnabled() &&
204 Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
205 .findAny().orElse(null);
206 return port != null ? port.number() : null;
207 }
208
209 @Override
210 public MacAddress vlanPortMac() {
211 if (vlanIntf == null) {
212 return null;
213 }
214 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
215 Port port = deviceService.getPorts(intgBridge).stream()
216 .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
217 .findAny().orElse(null);
218 return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
219 }
220
221 @Override
222 public GroupId gatewayGroupId(NetworkMode mode) {
223 return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
224 }
225
226 @Override
227 public boolean equals(Object obj) {
228 if (this == obj) {
229 return true;
230 }
231
232 if (obj instanceof DefaultOpenstackNode) {
233 DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
Jian Li5afbea42018-02-28 10:37:03 +0900234 return Objects.equals(hostname, that.hostname) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900235 Objects.equals(type, that.type) &&
236 Objects.equals(intgBridge, that.intgBridge) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900237 Objects.equals(managementIp, that.managementIp) &&
238 Objects.equals(dataIp, that.dataIp) &&
daniel parkb18424c2018-02-05 15:43:43 +0900239 Objects.equals(uplinkPort, that.uplinkPort) &&
Jian Lie6312162018-03-21 21:41:00 +0900240 Objects.equals(vlanIntf, that.vlanIntf) &&
Jian Li27841662018-04-14 01:59:47 +0900241 Objects.equals(phyIntfs, that.phyIntfs) &&
Jian Li92d42fc2018-05-25 16:23:49 +0900242 Objects.equals(auth, that.auth) &&
243 Objects.equals(endPoint, that.endPoint);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900244 }
245 return false;
246 }
247
248 @Override
249 public int hashCode() {
250 return Objects.hash(hostname,
251 type,
252 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900253 managementIp,
254 dataIp,
daniel parkb18424c2018-02-05 15:43:43 +0900255 vlanIntf,
Jian Lie6312162018-03-21 21:41:00 +0900256 uplinkPort,
Jian Li27841662018-04-14 01:59:47 +0900257 phyIntfs,
Jian Li92d42fc2018-05-25 16:23:49 +0900258 auth,
259 endPoint);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900260 }
261
262 @Override
263 public String toString() {
264 return MoreObjects.toStringHelper(getClass())
265 .add("hostname", hostname)
266 .add("type", type)
267 .add("integrationBridge", intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900268 .add("managementIp", managementIp)
269 .add("dataIp", dataIp)
270 .add("vlanIntf", vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900271 .add("uplinkPort", uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900272 .add("state", state)
Jian Lie6312162018-03-21 21:41:00 +0900273 .add("phyIntfs", phyIntfs)
Jian Li27841662018-04-14 01:59:47 +0900274 .add("auth", auth)
Jian Li92d42fc2018-05-25 16:23:49 +0900275 .add("endpoint", endPoint)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900276 .toString();
277 }
278
279 @Override
280 public OpenstackNode updateState(NodeState newState) {
281 return new Builder()
282 .type(type)
283 .hostname(hostname)
284 .intgBridge(intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900285 .managementIp(managementIp)
286 .dataIp(dataIp)
287 .vlanIntf(vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900288 .uplinkPort(uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900289 .state(newState)
Jian Lie6312162018-03-21 21:41:00 +0900290 .phyIntfs(phyIntfs)
Jian Li27841662018-04-14 01:59:47 +0900291 .authentication(auth)
Jian Li92d42fc2018-05-25 16:23:49 +0900292 .endPoint(endPoint)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900293 .build();
294 }
295
Jian Lie6312162018-03-21 21:41:00 +0900296 @Override
297 public Collection<OpenstackPhyInterface> phyIntfs() {
298
299 if (phyIntfs == null) {
300 return new ArrayList<>();
301 }
302
303 return phyIntfs;
304 }
305
daniel park796c2eb2018-03-22 17:01:51 +0900306 @Override
307 public PortNumber phyIntfPortNum(String providerPhysnet) {
308 Optional<OpenstackPhyInterface> openstackPhyInterface =
309 phyIntfs.stream().filter(p -> p.network().equals(providerPhysnet)).findAny();
310
311 if (openstackPhyInterface.isPresent()) {
312 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
313 Port port = deviceService.getPorts(intgBridge).stream()
314 .filter(p -> p.isEnabled() &&
315 Objects.equals(p.annotations().value(PORT_NAME), openstackPhyInterface.get().intf()))
316 .findAny().orElse(null);
317
318 return port != null ? port.number() : null;
319 } else {
320 return null;
321 }
322
323 }
Jian Li27841662018-04-14 01:59:47 +0900324
325 @Override
326 public OpenstackAuth authentication() {
327 return auth;
328 }
329
Jian Li92d42fc2018-05-25 16:23:49 +0900330 @Override
331 public String endPoint() {
332 return endPoint;
333 }
334
Hyunsun Moon0d457362017-06-27 17:19:41 +0900335 /**
336 * Returns new builder instance.
337 *
338 * @return openstack node builder
339 */
340 public static Builder builder() {
341 return new Builder();
342 }
343
344 /**
345 * Returns new builder instance with the given node as a default value.
346 *
347 * @param osNode openstack node
348 * @return openstack node builder
349 */
350 public static Builder from(OpenstackNode osNode) {
351 return new Builder()
352 .hostname(osNode.hostname())
Hyunsun Moon090d77d2017-07-05 17:48:37 +0900353 .type(osNode.type())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900354 .intgBridge(osNode.intgBridge())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900355 .managementIp(osNode.managementIp())
356 .dataIp(osNode.dataIp())
357 .vlanIntf(osNode.vlanIntf())
daniel parkb18424c2018-02-05 15:43:43 +0900358 .uplinkPort(osNode.uplinkPort())
Jian Lie6312162018-03-21 21:41:00 +0900359 .state(osNode.state())
Jian Li27841662018-04-14 01:59:47 +0900360 .phyIntfs(osNode.phyIntfs())
Jian Li92d42fc2018-05-25 16:23:49 +0900361 .authentication(osNode.authentication())
362 .endPoint(osNode.endPoint());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900363 }
364
Jian Li340165f2018-02-27 10:38:17 +0900365 /**
366 * A builder class for openstack Node.
367 */
Hyunsun Moon0d457362017-06-27 17:19:41 +0900368 public static final class Builder implements OpenstackNode.Builder {
369
370 private String hostname;
371 private NodeType type;
372 private DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900373 private IpAddress managementIp;
374 private IpAddress dataIp;
375 private String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +0900376 private String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900377 private NodeState state;
Jian Lie6312162018-03-21 21:41:00 +0900378 private Collection<OpenstackPhyInterface> phyIntfs;
Jian Li27841662018-04-14 01:59:47 +0900379 private OpenstackAuth auth;
Jian Li92d42fc2018-05-25 16:23:49 +0900380 private String endPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900381
Jian Li340165f2018-02-27 10:38:17 +0900382 // private constructor not intended to use from external
Hyunsun Moon0d457362017-06-27 17:19:41 +0900383 private Builder() {
384 }
385
386 @Override
387 public DefaultOpenstackNode build() {
Jian Li340165f2018-02-27 10:38:17 +0900388 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
389 checkArgument(type != null, NOT_NULL_MSG, "type");
Jian Li340165f2018-02-27 10:38:17 +0900390 checkArgument(state != null, NOT_NULL_MSG, "state");
Jian Li92d42fc2018-05-25 16:23:49 +0900391 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900392
Jian Li27841662018-04-14 01:59:47 +0900393 if (type != NodeType.CONTROLLER) {
394 checkArgument(intgBridge != null, NOT_NULL_MSG, "integration bridge");
395
396 if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
397 throw new IllegalArgumentException("Either data IP or VLAN interface is required");
398 }
399 } else {
Jian Li92d42fc2018-05-25 16:23:49 +0900400 checkArgument(endPoint != null, NOT_NULL_MSG, "endpoint URL");
Jian Li27841662018-04-14 01:59:47 +0900401 }
402
daniel parkb18424c2018-02-05 15:43:43 +0900403 if (type == NodeType.GATEWAY && uplinkPort == null) {
404 throw new IllegalArgumentException("Uplink port is required for gateway node");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900405 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900406
407 return new DefaultOpenstackNode(hostname,
408 type,
409 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900410 managementIp,
411 dataIp,
412 vlanIntf,
daniel parkb18424c2018-02-05 15:43:43 +0900413 uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +0900414 state,
Jian Li27841662018-04-14 01:59:47 +0900415 phyIntfs,
Jian Li92d42fc2018-05-25 16:23:49 +0900416 auth,
417 endPoint);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900418 }
419
420 @Override
421 public Builder hostname(String hostname) {
422 if (!Strings.isNullOrEmpty(hostname)) {
423 this.hostname = hostname;
424 }
425 return this;
426 }
427
428 @Override
429 public Builder type(NodeType type) {
430 this.type = type;
431 return this;
432 }
433
434 @Override
435 public Builder intgBridge(DeviceId intgBridge) {
436 this.intgBridge = intgBridge;
437 return this;
438 }
439
440 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900441 public Builder managementIp(IpAddress managementIp) {
442 this.managementIp = managementIp;
443 return this;
444 }
445
446 @Override
447 public Builder dataIp(IpAddress dataIp) {
448 this.dataIp = dataIp;
449 return this;
450 }
451
452 @Override
453 public Builder vlanIntf(String vlanIntf) {
454 this.vlanIntf = vlanIntf;
455 return this;
456 }
457
458 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900459 public Builder uplinkPort(String uplinkPort) {
460 this.uplinkPort = uplinkPort;
461 return this;
462 }
463
464 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900465 public Builder state(NodeState state) {
466 this.state = state;
467 return this;
468 }
Jian Lie6312162018-03-21 21:41:00 +0900469
470 @Override
471 public Builder phyIntfs(Collection<OpenstackPhyInterface> phyIntfs) {
472 this.phyIntfs = phyIntfs;
473 return this;
474 }
Jian Li27841662018-04-14 01:59:47 +0900475
476 @Override
477 public Builder authentication(OpenstackAuth auth) {
478 this.auth = auth;
479 return this;
480 }
Jian Li92d42fc2018-05-25 16:23:49 +0900481
482 @Override
483 public Builder endPoint(String endPoint) {
484 this.endPoint = endPoint;
485 return this;
486 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900487 }
488}
489