blob: f05d58be4b2c276132cb92de4cd8d25d46d5138f [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;
Hyunsun Moon0d457362017-06-27 17:19:41 +090061
Jian Li340165f2018-02-27 10:38:17 +090062 private static final String NOT_NULL_MSG = "Node % cannot be null";
63
daniel parkb18424c2018-02-05 15:43:43 +090064 private static final String OVSDB = "ovsdb:";
65
Jian Li340165f2018-02-27 10:38:17 +090066 /**
67 * A default constructor of Openstack Node.
68 *
69 * @param hostname hostname
70 * @param type node type
71 * @param intgBridge integration bridge
72 * @param managementIp management IP address
73 * @param dataIp data IP address
74 * @param vlanIntf VLAN interface
75 * @param uplinkPort uplink port name
76 * @param state node state
Jian Lie6312162018-03-21 21:41:00 +090077 * @param phyIntfs physical interfaces
Jian Li27841662018-04-14 01:59:47 +090078 * @param auth keystone authentication info
Jian Li340165f2018-02-27 10:38:17 +090079 */
daniel parkb18424c2018-02-05 15:43:43 +090080 protected DefaultOpenstackNode(String hostname, NodeType type,
81 DeviceId intgBridge,
82 IpAddress managementIp,
83 IpAddress dataIp,
84 String vlanIntf,
85 String uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +090086 NodeState state,
Jian Li27841662018-04-14 01:59:47 +090087 Collection<OpenstackPhyInterface> phyIntfs,
88 OpenstackAuth auth) {
Hyunsun Moon0d457362017-06-27 17:19:41 +090089 this.hostname = hostname;
90 this.type = type;
91 this.intgBridge = intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090092 this.managementIp = managementIp;
93 this.dataIp = dataIp;
94 this.vlanIntf = vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090095 this.uplinkPort = uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090096 this.state = state;
Jian Lie6312162018-03-21 21:41:00 +090097 this.phyIntfs = phyIntfs;
Jian Li27841662018-04-14 01:59:47 +090098 this.auth = auth;
Hyunsun Moon0d457362017-06-27 17:19:41 +090099 }
100
101 @Override
102 public String hostname() {
103 return hostname;
104 }
105
106 @Override
107 public NodeType type() {
108 return type;
109 }
110
111 @Override
112 public DeviceId ovsdb() {
daniel parkb18424c2018-02-05 15:43:43 +0900113 return DeviceId.deviceId(OVSDB + managementIp().toString());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900114 }
115
116 @Override
117 public DeviceId intgBridge() {
118 return intgBridge;
119 }
120
121 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900122 public IpAddress managementIp() {
123 return managementIp;
124 }
125
126 @Override
127 public IpAddress dataIp() {
128 return dataIp;
129 }
130
131 @Override
132 public String vlanIntf() {
133 return vlanIntf;
134 }
135
136 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900137 public String uplinkPort() {
138 return uplinkPort;
139 }
140
141 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900142 public NodeState state() {
143 return state;
144 }
145
146 @Override
147 public GroupKey gatewayGroupKey(NetworkMode mode) {
148 return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
149 }
150
151 @Override
daniel parkb5817102018-02-15 00:18:51 +0900152 public PortNumber uplinkPortNum() {
153 if (uplinkPort == null) {
154 return null;
155 }
156
157 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
158 Port port = deviceService.getPorts(intgBridge).stream()
159 .filter(p -> p.isEnabled() &&
160 Objects.equals(p.annotations().value(PORT_NAME), uplinkPort))
161 .findAny().orElse(null);
162
163 return port != null ? port.number() : null;
164
165 }
166 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900167 public PortNumber tunnelPortNum() {
168 if (dataIp == null) {
169 return null;
170 }
171 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
172 Port port = deviceService.getPorts(intgBridge).stream()
173 .filter(p -> p.isEnabled() &&
174 Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
175 .findAny().orElse(null);
176 return port != null ? port.number() : null;
177 }
178
179 @Override
180 public PortNumber vlanPortNum() {
181 if (vlanIntf == null) {
182 return null;
183 }
184 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
185 Port port = deviceService.getPorts(intgBridge).stream()
186 .filter(p -> p.isEnabled() &&
187 Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
188 .findAny().orElse(null);
189 return port != null ? port.number() : null;
190 }
191
192 @Override
193 public PortNumber patchPortNum() {
194 if (type == NodeType.COMPUTE) {
195 return null;
196 }
197 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
198 Port port = deviceService.getPorts(intgBridge).stream()
199 .filter(p -> p.isEnabled() &&
200 Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
201 .findAny().orElse(null);
202 return port != null ? port.number() : null;
203 }
204
205 @Override
206 public MacAddress vlanPortMac() {
207 if (vlanIntf == null) {
208 return null;
209 }
210 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
211 Port port = deviceService.getPorts(intgBridge).stream()
212 .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
213 .findAny().orElse(null);
214 return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
215 }
216
217 @Override
218 public GroupId gatewayGroupId(NetworkMode mode) {
219 return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
220 }
221
222 @Override
223 public boolean equals(Object obj) {
224 if (this == obj) {
225 return true;
226 }
227
228 if (obj instanceof DefaultOpenstackNode) {
229 DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
Jian Li5afbea42018-02-28 10:37:03 +0900230 return Objects.equals(hostname, that.hostname) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900231 Objects.equals(type, that.type) &&
232 Objects.equals(intgBridge, that.intgBridge) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900233 Objects.equals(managementIp, that.managementIp) &&
234 Objects.equals(dataIp, that.dataIp) &&
daniel parkb18424c2018-02-05 15:43:43 +0900235 Objects.equals(uplinkPort, that.uplinkPort) &&
Jian Lie6312162018-03-21 21:41:00 +0900236 Objects.equals(vlanIntf, that.vlanIntf) &&
Jian Li27841662018-04-14 01:59:47 +0900237 Objects.equals(phyIntfs, that.phyIntfs) &&
238 Objects.equals(auth, that.auth);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900239 }
240 return false;
241 }
242
243 @Override
244 public int hashCode() {
245 return Objects.hash(hostname,
246 type,
247 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900248 managementIp,
249 dataIp,
daniel parkb18424c2018-02-05 15:43:43 +0900250 vlanIntf,
Jian Lie6312162018-03-21 21:41:00 +0900251 uplinkPort,
Jian Li27841662018-04-14 01:59:47 +0900252 phyIntfs,
253 auth);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900254 }
255
256 @Override
257 public String toString() {
258 return MoreObjects.toStringHelper(getClass())
259 .add("hostname", hostname)
260 .add("type", type)
261 .add("integrationBridge", intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900262 .add("managementIp", managementIp)
263 .add("dataIp", dataIp)
264 .add("vlanIntf", vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900265 .add("uplinkPort", uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900266 .add("state", state)
Jian Lie6312162018-03-21 21:41:00 +0900267 .add("phyIntfs", phyIntfs)
Jian Li27841662018-04-14 01:59:47 +0900268 .add("auth", auth)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900269 .toString();
270 }
271
272 @Override
273 public OpenstackNode updateState(NodeState newState) {
274 return new Builder()
275 .type(type)
276 .hostname(hostname)
277 .intgBridge(intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900278 .managementIp(managementIp)
279 .dataIp(dataIp)
280 .vlanIntf(vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900281 .uplinkPort(uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900282 .state(newState)
Jian Lie6312162018-03-21 21:41:00 +0900283 .phyIntfs(phyIntfs)
Jian Li27841662018-04-14 01:59:47 +0900284 .authentication(auth)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900285 .build();
286 }
287
Jian Lie6312162018-03-21 21:41:00 +0900288 @Override
289 public Collection<OpenstackPhyInterface> phyIntfs() {
290
291 if (phyIntfs == null) {
292 return new ArrayList<>();
293 }
294
295 return phyIntfs;
296 }
297
daniel park796c2eb2018-03-22 17:01:51 +0900298 @Override
299 public PortNumber phyIntfPortNum(String providerPhysnet) {
300 Optional<OpenstackPhyInterface> openstackPhyInterface =
301 phyIntfs.stream().filter(p -> p.network().equals(providerPhysnet)).findAny();
302
303 if (openstackPhyInterface.isPresent()) {
304 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
305 Port port = deviceService.getPorts(intgBridge).stream()
306 .filter(p -> p.isEnabled() &&
307 Objects.equals(p.annotations().value(PORT_NAME), openstackPhyInterface.get().intf()))
308 .findAny().orElse(null);
309
310 return port != null ? port.number() : null;
311 } else {
312 return null;
313 }
314
315 }
Jian Li27841662018-04-14 01:59:47 +0900316
317 @Override
318 public OpenstackAuth authentication() {
319 return auth;
320 }
321
Hyunsun Moon0d457362017-06-27 17:19:41 +0900322 /**
323 * Returns new builder instance.
324 *
325 * @return openstack node builder
326 */
327 public static Builder builder() {
328 return new Builder();
329 }
330
331 /**
332 * Returns new builder instance with the given node as a default value.
333 *
334 * @param osNode openstack node
335 * @return openstack node builder
336 */
337 public static Builder from(OpenstackNode osNode) {
338 return new Builder()
339 .hostname(osNode.hostname())
Hyunsun Moon090d77d2017-07-05 17:48:37 +0900340 .type(osNode.type())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900341 .intgBridge(osNode.intgBridge())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900342 .managementIp(osNode.managementIp())
343 .dataIp(osNode.dataIp())
344 .vlanIntf(osNode.vlanIntf())
daniel parkb18424c2018-02-05 15:43:43 +0900345 .uplinkPort(osNode.uplinkPort())
Jian Lie6312162018-03-21 21:41:00 +0900346 .state(osNode.state())
Jian Li27841662018-04-14 01:59:47 +0900347 .phyIntfs(osNode.phyIntfs())
348 .authentication(osNode.authentication());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900349 }
350
Jian Li340165f2018-02-27 10:38:17 +0900351 /**
352 * A builder class for openstack Node.
353 */
Hyunsun Moon0d457362017-06-27 17:19:41 +0900354 public static final class Builder implements OpenstackNode.Builder {
355
356 private String hostname;
357 private NodeType type;
358 private DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900359 private IpAddress managementIp;
360 private IpAddress dataIp;
361 private String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +0900362 private String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900363 private NodeState state;
Jian Lie6312162018-03-21 21:41:00 +0900364 private Collection<OpenstackPhyInterface> phyIntfs;
Jian Li27841662018-04-14 01:59:47 +0900365 private OpenstackAuth auth;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900366
Jian Li340165f2018-02-27 10:38:17 +0900367 // private constructor not intended to use from external
Hyunsun Moon0d457362017-06-27 17:19:41 +0900368 private Builder() {
369 }
370
371 @Override
372 public DefaultOpenstackNode build() {
Jian Li340165f2018-02-27 10:38:17 +0900373 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
374 checkArgument(type != null, NOT_NULL_MSG, "type");
Jian Li27841662018-04-14 01:59:47 +0900375
Jian Li340165f2018-02-27 10:38:17 +0900376 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
377 checkArgument(state != null, NOT_NULL_MSG, "state");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900378
Jian Li27841662018-04-14 01:59:47 +0900379 if (type != NodeType.CONTROLLER) {
380 checkArgument(intgBridge != null, NOT_NULL_MSG, "integration bridge");
381
382 if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
383 throw new IllegalArgumentException("Either data IP or VLAN interface is required");
384 }
385 } else {
386 // we force controller node to have COMPLETE state for now
387 state = NodeState.COMPLETE;
388 }
389
daniel parkb18424c2018-02-05 15:43:43 +0900390 if (type == NodeType.GATEWAY && uplinkPort == null) {
391 throw new IllegalArgumentException("Uplink port is required for gateway node");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900392 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900393
394 return new DefaultOpenstackNode(hostname,
395 type,
396 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900397 managementIp,
398 dataIp,
399 vlanIntf,
daniel parkb18424c2018-02-05 15:43:43 +0900400 uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +0900401 state,
Jian Li27841662018-04-14 01:59:47 +0900402 phyIntfs,
403 auth);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900404 }
405
406 @Override
407 public Builder hostname(String hostname) {
408 if (!Strings.isNullOrEmpty(hostname)) {
409 this.hostname = hostname;
410 }
411 return this;
412 }
413
414 @Override
415 public Builder type(NodeType type) {
416 this.type = type;
417 return this;
418 }
419
420 @Override
421 public Builder intgBridge(DeviceId intgBridge) {
422 this.intgBridge = intgBridge;
423 return this;
424 }
425
426 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900427 public Builder managementIp(IpAddress managementIp) {
428 this.managementIp = managementIp;
429 return this;
430 }
431
432 @Override
433 public Builder dataIp(IpAddress dataIp) {
434 this.dataIp = dataIp;
435 return this;
436 }
437
438 @Override
439 public Builder vlanIntf(String vlanIntf) {
440 this.vlanIntf = vlanIntf;
441 return this;
442 }
443
444 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900445 public Builder uplinkPort(String uplinkPort) {
446 this.uplinkPort = uplinkPort;
447 return this;
448 }
449
450 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900451 public Builder state(NodeState state) {
452 this.state = state;
453 return this;
454 }
Jian Lie6312162018-03-21 21:41:00 +0900455
456 @Override
457 public Builder phyIntfs(Collection<OpenstackPhyInterface> phyIntfs) {
458 this.phyIntfs = phyIntfs;
459 return this;
460 }
Jian Li27841662018-04-14 01:59:47 +0900461
462 @Override
463 public Builder authentication(OpenstackAuth auth) {
464 this.auth = auth;
465 return this;
466 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900467 }
468}
469