blob: fd8d3b64f65cf548cbc9c5ad63abf50fdbb7cb8b [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 */
Jian Li5a38ab62018-07-02 22:34:11 +090016package org.onosproject.openstacknode.api;
Hyunsun Moon0d457362017-06-27 17:19:41 +090017
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;
Jian Li789fadb2018-07-10 13:59:47 +090027import org.onosproject.net.behaviour.ControllerInfo;
Hyunsun Moon0d457362017-06-27 17:19:41 +090028import org.onosproject.net.device.DeviceService;
29import org.onosproject.net.group.DefaultGroupKey;
30import org.onosproject.net.group.GroupKey;
Hyunsun Moon0d457362017-06-27 17:19:41 +090031
Jian Lie6312162018-03-21 21:41:00 +090032import java.util.ArrayList;
33import java.util.Collection;
Hyunsun Moon0d457362017-06-27 17:19:41 +090034import java.util.Objects;
daniel park796c2eb2018-03-22 17:01:51 +090035import java.util.Optional;
Hyunsun Moon0d457362017-06-27 17:19:41 +090036
37import static com.google.common.base.Preconditions.checkArgument;
38import static org.onosproject.net.AnnotationKeys.PORT_MAC;
39import static org.onosproject.net.AnnotationKeys.PORT_NAME;
40import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
41import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
42
43/**
44 * Representation of a openstack node.
45 */
Hyunsun Moon090d77d2017-07-05 17:48:37 +090046public class DefaultOpenstackNode implements OpenstackNode {
Hyunsun Moon0d457362017-06-27 17:19:41 +090047
48 private final String hostname;
49 private final NodeType type;
50 private final DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090051 private final IpAddress managementIp;
52 private final IpAddress dataIp;
53 private final String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090054 private final String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090055 private final NodeState state;
Jian Lie6312162018-03-21 21:41:00 +090056 private final Collection<OpenstackPhyInterface> phyIntfs;
Jian Li789fadb2018-07-10 13:59:47 +090057 private final Collection<ControllerInfo> controllers;
Jian Li27841662018-04-14 01:59:47 +090058 private final OpenstackAuth auth;
Jian Li92d42fc2018-05-25 16:23:49 +090059 private final String endPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +090060
Jian Li340165f2018-02-27 10:38:17 +090061 private static final String NOT_NULL_MSG = "Node % cannot be null";
62
daniel parkb18424c2018-02-05 15:43:43 +090063 private static final String OVSDB = "ovsdb:";
64
Jian Li340165f2018-02-27 10:38:17 +090065 /**
66 * A default constructor of Openstack Node.
67 *
68 * @param hostname hostname
69 * @param type node type
70 * @param intgBridge integration bridge
71 * @param managementIp management IP address
72 * @param dataIp data IP address
73 * @param vlanIntf VLAN interface
74 * @param uplinkPort uplink port name
75 * @param state node state
Jian Lie6312162018-03-21 21:41:00 +090076 * @param phyIntfs physical interfaces
Jian Li789fadb2018-07-10 13:59:47 +090077 * @param controllers customized controllers
Jian Li27841662018-04-14 01:59:47 +090078 * @param auth keystone authentication info
Jian Li92d42fc2018-05-25 16:23:49 +090079 * @param endPoint openstack endpoint URL
Jian Li340165f2018-02-27 10:38:17 +090080 */
daniel parkb18424c2018-02-05 15:43:43 +090081 protected DefaultOpenstackNode(String hostname, NodeType type,
82 DeviceId intgBridge,
83 IpAddress managementIp,
84 IpAddress dataIp,
85 String vlanIntf,
86 String uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +090087 NodeState state,
Jian Li27841662018-04-14 01:59:47 +090088 Collection<OpenstackPhyInterface> phyIntfs,
Jian Li789fadb2018-07-10 13:59:47 +090089 Collection<ControllerInfo> controllers,
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 Li789fadb2018-07-10 13:59:47 +0900101 this.controllers = controllers;
Jian Li27841662018-04-14 01:59:47 +0900102 this.auth = auth;
Jian Li92d42fc2018-05-25 16:23:49 +0900103 this.endPoint = endPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900104 }
105
106 @Override
107 public String hostname() {
108 return hostname;
109 }
110
111 @Override
112 public NodeType type() {
113 return type;
114 }
115
116 @Override
117 public DeviceId ovsdb() {
daniel parkb18424c2018-02-05 15:43:43 +0900118 return DeviceId.deviceId(OVSDB + managementIp().toString());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900119 }
120
121 @Override
122 public DeviceId intgBridge() {
123 return intgBridge;
124 }
125
126 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900127 public IpAddress managementIp() {
128 return managementIp;
129 }
130
131 @Override
132 public IpAddress dataIp() {
133 return dataIp;
134 }
135
136 @Override
137 public String vlanIntf() {
138 return vlanIntf;
139 }
140
141 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900142 public String uplinkPort() {
143 return uplinkPort;
144 }
145
146 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900147 public NodeState state() {
148 return state;
149 }
150
151 @Override
152 public GroupKey gatewayGroupKey(NetworkMode mode) {
153 return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
154 }
155
156 @Override
daniel parkb5817102018-02-15 00:18:51 +0900157 public PortNumber uplinkPortNum() {
158 if (uplinkPort == null) {
159 return null;
160 }
161
162 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
163 Port port = deviceService.getPorts(intgBridge).stream()
164 .filter(p -> p.isEnabled() &&
165 Objects.equals(p.annotations().value(PORT_NAME), uplinkPort))
166 .findAny().orElse(null);
167
168 return port != null ? port.number() : null;
169
170 }
171 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900172 public PortNumber tunnelPortNum() {
173 if (dataIp == null) {
174 return null;
175 }
176 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
177 Port port = deviceService.getPorts(intgBridge).stream()
178 .filter(p -> p.isEnabled() &&
179 Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
180 .findAny().orElse(null);
181 return port != null ? port.number() : null;
182 }
183
184 @Override
185 public PortNumber vlanPortNum() {
186 if (vlanIntf == null) {
187 return null;
188 }
189 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
190 Port port = deviceService.getPorts(intgBridge).stream()
191 .filter(p -> p.isEnabled() &&
192 Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
193 .findAny().orElse(null);
194 return port != null ? port.number() : null;
195 }
196
197 @Override
198 public PortNumber patchPortNum() {
199 if (type == NodeType.COMPUTE) {
200 return null;
201 }
202 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
203 Port port = deviceService.getPorts(intgBridge).stream()
204 .filter(p -> p.isEnabled() &&
205 Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
206 .findAny().orElse(null);
207 return port != null ? port.number() : null;
208 }
209
210 @Override
211 public MacAddress vlanPortMac() {
212 if (vlanIntf == null) {
213 return null;
214 }
215 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
216 Port port = deviceService.getPorts(intgBridge).stream()
217 .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
218 .findAny().orElse(null);
219 return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
220 }
221
222 @Override
223 public GroupId gatewayGroupId(NetworkMode mode) {
224 return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
225 }
226
227 @Override
228 public boolean equals(Object obj) {
229 if (this == obj) {
230 return true;
231 }
232
233 if (obj instanceof DefaultOpenstackNode) {
234 DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
Jian Li5afbea42018-02-28 10:37:03 +0900235 return Objects.equals(hostname, that.hostname) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900236 Objects.equals(type, that.type) &&
237 Objects.equals(intgBridge, that.intgBridge) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900238 Objects.equals(managementIp, that.managementIp) &&
239 Objects.equals(dataIp, that.dataIp) &&
daniel parkb18424c2018-02-05 15:43:43 +0900240 Objects.equals(uplinkPort, that.uplinkPort) &&
Jian Lie6312162018-03-21 21:41:00 +0900241 Objects.equals(vlanIntf, that.vlanIntf) &&
Jian Li27841662018-04-14 01:59:47 +0900242 Objects.equals(phyIntfs, that.phyIntfs) &&
Jian Li789fadb2018-07-10 13:59:47 +0900243 Objects.equals(controllers, that.controllers) &&
Jian Li92d42fc2018-05-25 16:23:49 +0900244 Objects.equals(auth, that.auth) &&
245 Objects.equals(endPoint, that.endPoint);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900246 }
247 return false;
248 }
249
250 @Override
251 public int hashCode() {
252 return Objects.hash(hostname,
253 type,
254 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900255 managementIp,
256 dataIp,
daniel parkb18424c2018-02-05 15:43:43 +0900257 vlanIntf,
Jian Lie6312162018-03-21 21:41:00 +0900258 uplinkPort,
Jian Li27841662018-04-14 01:59:47 +0900259 phyIntfs,
Jian Li789fadb2018-07-10 13:59:47 +0900260 controllers,
Jian Li92d42fc2018-05-25 16:23:49 +0900261 auth,
262 endPoint);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900263 }
264
265 @Override
266 public String toString() {
267 return MoreObjects.toStringHelper(getClass())
268 .add("hostname", hostname)
269 .add("type", type)
270 .add("integrationBridge", intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900271 .add("managementIp", managementIp)
272 .add("dataIp", dataIp)
273 .add("vlanIntf", vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900274 .add("uplinkPort", uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900275 .add("state", state)
Jian Lie6312162018-03-21 21:41:00 +0900276 .add("phyIntfs", phyIntfs)
Jian Li789fadb2018-07-10 13:59:47 +0900277 .add("controllers", controllers)
Jian Li27841662018-04-14 01:59:47 +0900278 .add("auth", auth)
Jian Li92d42fc2018-05-25 16:23:49 +0900279 .add("endpoint", endPoint)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900280 .toString();
281 }
282
283 @Override
284 public OpenstackNode updateState(NodeState newState) {
285 return new Builder()
286 .type(type)
287 .hostname(hostname)
288 .intgBridge(intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900289 .managementIp(managementIp)
290 .dataIp(dataIp)
291 .vlanIntf(vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900292 .uplinkPort(uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900293 .state(newState)
Jian Lie6312162018-03-21 21:41:00 +0900294 .phyIntfs(phyIntfs)
Jian Li789fadb2018-07-10 13:59:47 +0900295 .controllers(controllers)
Jian Li27841662018-04-14 01:59:47 +0900296 .authentication(auth)
Jian Li92d42fc2018-05-25 16:23:49 +0900297 .endPoint(endPoint)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900298 .build();
299 }
300
Jian Lie6312162018-03-21 21:41:00 +0900301 @Override
302 public Collection<OpenstackPhyInterface> phyIntfs() {
303
304 if (phyIntfs == null) {
305 return new ArrayList<>();
306 }
307
308 return phyIntfs;
309 }
310
Jian Li789fadb2018-07-10 13:59:47 +0900311
312 @Override
313 public Collection<ControllerInfo> controllers() {
314 if (controllers == null) {
315 return new ArrayList<>();
316 }
317
318 return controllers;
319 }
320
daniel park796c2eb2018-03-22 17:01:51 +0900321 @Override
322 public PortNumber phyIntfPortNum(String providerPhysnet) {
323 Optional<OpenstackPhyInterface> openstackPhyInterface =
324 phyIntfs.stream().filter(p -> p.network().equals(providerPhysnet)).findAny();
325
326 if (openstackPhyInterface.isPresent()) {
327 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
328 Port port = deviceService.getPorts(intgBridge).stream()
329 .filter(p -> p.isEnabled() &&
330 Objects.equals(p.annotations().value(PORT_NAME), openstackPhyInterface.get().intf()))
331 .findAny().orElse(null);
332
333 return port != null ? port.number() : null;
334 } else {
335 return null;
336 }
337
338 }
Jian Li27841662018-04-14 01:59:47 +0900339
340 @Override
341 public OpenstackAuth authentication() {
342 return auth;
343 }
344
Jian Li92d42fc2018-05-25 16:23:49 +0900345 @Override
346 public String endPoint() {
347 return endPoint;
348 }
349
Hyunsun Moon0d457362017-06-27 17:19:41 +0900350 /**
351 * Returns new builder instance.
352 *
353 * @return openstack node builder
354 */
355 public static Builder builder() {
356 return new Builder();
357 }
358
359 /**
360 * Returns new builder instance with the given node as a default value.
361 *
362 * @param osNode openstack node
363 * @return openstack node builder
364 */
365 public static Builder from(OpenstackNode osNode) {
366 return new Builder()
367 .hostname(osNode.hostname())
Hyunsun Moon090d77d2017-07-05 17:48:37 +0900368 .type(osNode.type())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900369 .intgBridge(osNode.intgBridge())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900370 .managementIp(osNode.managementIp())
371 .dataIp(osNode.dataIp())
372 .vlanIntf(osNode.vlanIntf())
daniel parkb18424c2018-02-05 15:43:43 +0900373 .uplinkPort(osNode.uplinkPort())
Jian Lie6312162018-03-21 21:41:00 +0900374 .state(osNode.state())
Jian Li27841662018-04-14 01:59:47 +0900375 .phyIntfs(osNode.phyIntfs())
Jian Li789fadb2018-07-10 13:59:47 +0900376 .controllers(osNode.controllers())
Jian Li92d42fc2018-05-25 16:23:49 +0900377 .authentication(osNode.authentication())
378 .endPoint(osNode.endPoint());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900379 }
380
Jian Li340165f2018-02-27 10:38:17 +0900381 /**
382 * A builder class for openstack Node.
383 */
Hyunsun Moon0d457362017-06-27 17:19:41 +0900384 public static final class Builder implements OpenstackNode.Builder {
385
386 private String hostname;
387 private NodeType type;
388 private DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900389 private IpAddress managementIp;
390 private IpAddress dataIp;
391 private String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +0900392 private String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900393 private NodeState state;
Jian Lie6312162018-03-21 21:41:00 +0900394 private Collection<OpenstackPhyInterface> phyIntfs;
Jian Li789fadb2018-07-10 13:59:47 +0900395 private Collection<ControllerInfo> controllers;
Jian Li27841662018-04-14 01:59:47 +0900396 private OpenstackAuth auth;
Jian Li92d42fc2018-05-25 16:23:49 +0900397 private String endPoint;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900398
Jian Li340165f2018-02-27 10:38:17 +0900399 // private constructor not intended to use from external
Hyunsun Moon0d457362017-06-27 17:19:41 +0900400 private Builder() {
401 }
402
403 @Override
404 public DefaultOpenstackNode build() {
Jian Li340165f2018-02-27 10:38:17 +0900405 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
406 checkArgument(type != null, NOT_NULL_MSG, "type");
Jian Li340165f2018-02-27 10:38:17 +0900407 checkArgument(state != null, NOT_NULL_MSG, "state");
Jian Li92d42fc2018-05-25 16:23:49 +0900408 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900409
Jian Li27841662018-04-14 01:59:47 +0900410 if (type != NodeType.CONTROLLER) {
411 checkArgument(intgBridge != null, NOT_NULL_MSG, "integration bridge");
412
413 if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
414 throw new IllegalArgumentException("Either data IP or VLAN interface is required");
415 }
416 } else {
Jian Li92d42fc2018-05-25 16:23:49 +0900417 checkArgument(endPoint != null, NOT_NULL_MSG, "endpoint URL");
Jian Li27841662018-04-14 01:59:47 +0900418 }
419
daniel parkb18424c2018-02-05 15:43:43 +0900420 if (type == NodeType.GATEWAY && uplinkPort == null) {
421 throw new IllegalArgumentException("Uplink port is required for gateway node");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900422 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900423
424 return new DefaultOpenstackNode(hostname,
425 type,
426 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900427 managementIp,
428 dataIp,
429 vlanIntf,
daniel parkb18424c2018-02-05 15:43:43 +0900430 uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +0900431 state,
Jian Li27841662018-04-14 01:59:47 +0900432 phyIntfs,
Jian Li789fadb2018-07-10 13:59:47 +0900433 controllers,
Jian Li92d42fc2018-05-25 16:23:49 +0900434 auth,
435 endPoint);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900436 }
437
438 @Override
439 public Builder hostname(String hostname) {
440 if (!Strings.isNullOrEmpty(hostname)) {
441 this.hostname = hostname;
442 }
443 return this;
444 }
445
446 @Override
447 public Builder type(NodeType type) {
448 this.type = type;
449 return this;
450 }
451
452 @Override
453 public Builder intgBridge(DeviceId intgBridge) {
454 this.intgBridge = intgBridge;
455 return this;
456 }
457
458 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900459 public Builder managementIp(IpAddress managementIp) {
460 this.managementIp = managementIp;
461 return this;
462 }
463
464 @Override
465 public Builder dataIp(IpAddress dataIp) {
466 this.dataIp = dataIp;
467 return this;
468 }
469
470 @Override
471 public Builder vlanIntf(String vlanIntf) {
472 this.vlanIntf = vlanIntf;
473 return this;
474 }
475
476 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900477 public Builder uplinkPort(String uplinkPort) {
478 this.uplinkPort = uplinkPort;
479 return this;
480 }
481
482 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900483 public Builder state(NodeState state) {
484 this.state = state;
485 return this;
486 }
Jian Lie6312162018-03-21 21:41:00 +0900487
488 @Override
489 public Builder phyIntfs(Collection<OpenstackPhyInterface> phyIntfs) {
490 this.phyIntfs = phyIntfs;
491 return this;
492 }
Jian Li27841662018-04-14 01:59:47 +0900493
494 @Override
Jian Li789fadb2018-07-10 13:59:47 +0900495 public Builder controllers(Collection<ControllerInfo> controllers) {
496 this.controllers = controllers;
497 return this;
498 }
499
500 @Override
Jian Li27841662018-04-14 01:59:47 +0900501 public Builder authentication(OpenstackAuth auth) {
502 this.auth = auth;
503 return this;
504 }
Jian Li92d42fc2018-05-25 16:23:49 +0900505
506 @Override
507 public Builder endPoint(String endPoint) {
508 this.endPoint = endPoint;
509 return this;
510 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900511 }
512}
513