blob: c63284721e4f46b8d42c47f70d83381a5fa950de [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;
31import org.onosproject.openstacknode.api.OpenstackNode;
Jian Lie6312162018-03-21 21:41:00 +090032import org.onosproject.openstacknode.api.OpenstackPhyInterface;
Hyunsun Moon0d457362017-06-27 17:19:41 +090033
Jian Lie6312162018-03-21 21:41:00 +090034import java.util.ArrayList;
35import java.util.Collection;
Hyunsun Moon0d457362017-06-27 17:19:41 +090036import java.util.Objects;
daniel park796c2eb2018-03-22 17:01:51 +090037import java.util.Optional;
Hyunsun Moon0d457362017-06-27 17:19:41 +090038
39import static com.google.common.base.Preconditions.checkArgument;
40import static org.onosproject.net.AnnotationKeys.PORT_MAC;
41import static org.onosproject.net.AnnotationKeys.PORT_NAME;
42import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
43import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
44
45/**
46 * Representation of a openstack node.
47 */
Hyunsun Moon090d77d2017-07-05 17:48:37 +090048public class DefaultOpenstackNode implements OpenstackNode {
Hyunsun Moon0d457362017-06-27 17:19:41 +090049
50 private final String hostname;
51 private final NodeType type;
52 private final DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090053 private final IpAddress managementIp;
54 private final IpAddress dataIp;
55 private final String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090056 private final String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090057 private final NodeState state;
Jian Lie6312162018-03-21 21:41:00 +090058 private final Collection<OpenstackPhyInterface> phyIntfs;
Hyunsun Moon0d457362017-06-27 17:19:41 +090059
Jian Li340165f2018-02-27 10:38:17 +090060 private static final String NOT_NULL_MSG = "Node % cannot be null";
61
daniel parkb18424c2018-02-05 15:43:43 +090062 private static final String OVSDB = "ovsdb:";
63
Jian Li340165f2018-02-27 10:38:17 +090064 /**
65 * A default constructor of Openstack Node.
66 *
67 * @param hostname hostname
68 * @param type node type
69 * @param intgBridge integration bridge
70 * @param managementIp management IP address
71 * @param dataIp data IP address
72 * @param vlanIntf VLAN interface
73 * @param uplinkPort uplink port name
74 * @param state node state
Jian Lie6312162018-03-21 21:41:00 +090075 * @param phyIntfs physical interfaces
Jian Li340165f2018-02-27 10:38:17 +090076 */
daniel parkb18424c2018-02-05 15:43:43 +090077 protected DefaultOpenstackNode(String hostname, NodeType type,
78 DeviceId intgBridge,
79 IpAddress managementIp,
80 IpAddress dataIp,
81 String vlanIntf,
82 String uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +090083 NodeState state,
84 Collection<OpenstackPhyInterface> phyIntfs) {
Hyunsun Moon0d457362017-06-27 17:19:41 +090085 this.hostname = hostname;
86 this.type = type;
87 this.intgBridge = intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090088 this.managementIp = managementIp;
89 this.dataIp = dataIp;
90 this.vlanIntf = vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090091 this.uplinkPort = uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090092 this.state = state;
Jian Lie6312162018-03-21 21:41:00 +090093 this.phyIntfs = phyIntfs;
Hyunsun Moon0d457362017-06-27 17:19:41 +090094 }
95
96 @Override
97 public String hostname() {
98 return hostname;
99 }
100
101 @Override
102 public NodeType type() {
103 return type;
104 }
105
106 @Override
107 public DeviceId ovsdb() {
daniel parkb18424c2018-02-05 15:43:43 +0900108 return DeviceId.deviceId(OVSDB + managementIp().toString());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900109 }
110
111 @Override
112 public DeviceId intgBridge() {
113 return intgBridge;
114 }
115
116 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900117 public IpAddress managementIp() {
118 return managementIp;
119 }
120
121 @Override
122 public IpAddress dataIp() {
123 return dataIp;
124 }
125
126 @Override
127 public String vlanIntf() {
128 return vlanIntf;
129 }
130
131 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900132 public String uplinkPort() {
133 return uplinkPort;
134 }
135
136 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900137 public NodeState state() {
138 return state;
139 }
140
141 @Override
142 public GroupKey gatewayGroupKey(NetworkMode mode) {
143 return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
144 }
145
146 @Override
daniel parkb5817102018-02-15 00:18:51 +0900147 public PortNumber uplinkPortNum() {
148 if (uplinkPort == null) {
149 return null;
150 }
151
152 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
153 Port port = deviceService.getPorts(intgBridge).stream()
154 .filter(p -> p.isEnabled() &&
155 Objects.equals(p.annotations().value(PORT_NAME), uplinkPort))
156 .findAny().orElse(null);
157
158 return port != null ? port.number() : null;
159
160 }
161 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900162 public PortNumber tunnelPortNum() {
163 if (dataIp == null) {
164 return null;
165 }
166 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
167 Port port = deviceService.getPorts(intgBridge).stream()
168 .filter(p -> p.isEnabled() &&
169 Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
170 .findAny().orElse(null);
171 return port != null ? port.number() : null;
172 }
173
174 @Override
175 public PortNumber vlanPortNum() {
176 if (vlanIntf == null) {
177 return null;
178 }
179 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
180 Port port = deviceService.getPorts(intgBridge).stream()
181 .filter(p -> p.isEnabled() &&
182 Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
183 .findAny().orElse(null);
184 return port != null ? port.number() : null;
185 }
186
187 @Override
188 public PortNumber patchPortNum() {
189 if (type == NodeType.COMPUTE) {
190 return null;
191 }
192 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
193 Port port = deviceService.getPorts(intgBridge).stream()
194 .filter(p -> p.isEnabled() &&
195 Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
196 .findAny().orElse(null);
197 return port != null ? port.number() : null;
198 }
199
200 @Override
201 public MacAddress vlanPortMac() {
202 if (vlanIntf == null) {
203 return null;
204 }
205 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
206 Port port = deviceService.getPorts(intgBridge).stream()
207 .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
208 .findAny().orElse(null);
209 return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
210 }
211
212 @Override
213 public GroupId gatewayGroupId(NetworkMode mode) {
214 return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
215 }
216
217 @Override
218 public boolean equals(Object obj) {
219 if (this == obj) {
220 return true;
221 }
222
223 if (obj instanceof DefaultOpenstackNode) {
224 DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
Jian Li5afbea42018-02-28 10:37:03 +0900225 return Objects.equals(hostname, that.hostname) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900226 Objects.equals(type, that.type) &&
227 Objects.equals(intgBridge, that.intgBridge) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900228 Objects.equals(managementIp, that.managementIp) &&
229 Objects.equals(dataIp, that.dataIp) &&
daniel parkb18424c2018-02-05 15:43:43 +0900230 Objects.equals(uplinkPort, that.uplinkPort) &&
Jian Lie6312162018-03-21 21:41:00 +0900231 Objects.equals(vlanIntf, that.vlanIntf) &&
232 Objects.equals(phyIntfs, that.phyIntfs);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900233 }
234 return false;
235 }
236
237 @Override
238 public int hashCode() {
239 return Objects.hash(hostname,
240 type,
241 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900242 managementIp,
243 dataIp,
daniel parkb18424c2018-02-05 15:43:43 +0900244 vlanIntf,
Jian Lie6312162018-03-21 21:41:00 +0900245 uplinkPort,
246 phyIntfs);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900247 }
248
249 @Override
250 public String toString() {
251 return MoreObjects.toStringHelper(getClass())
252 .add("hostname", hostname)
253 .add("type", type)
254 .add("integrationBridge", intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900255 .add("managementIp", managementIp)
256 .add("dataIp", dataIp)
257 .add("vlanIntf", vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900258 .add("uplinkPort", uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900259 .add("state", state)
Jian Lie6312162018-03-21 21:41:00 +0900260 .add("phyIntfs", phyIntfs)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900261 .toString();
262 }
263
264 @Override
265 public OpenstackNode updateState(NodeState newState) {
266 return new Builder()
267 .type(type)
268 .hostname(hostname)
269 .intgBridge(intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900270 .managementIp(managementIp)
271 .dataIp(dataIp)
272 .vlanIntf(vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900273 .uplinkPort(uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900274 .state(newState)
Jian Lie6312162018-03-21 21:41:00 +0900275 .phyIntfs(phyIntfs)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900276 .build();
277 }
278
Jian Lie6312162018-03-21 21:41:00 +0900279 @Override
280 public Collection<OpenstackPhyInterface> phyIntfs() {
281
282 if (phyIntfs == null) {
283 return new ArrayList<>();
284 }
285
286 return phyIntfs;
287 }
288
daniel park796c2eb2018-03-22 17:01:51 +0900289 @Override
290 public PortNumber phyIntfPortNum(String providerPhysnet) {
291 Optional<OpenstackPhyInterface> openstackPhyInterface =
292 phyIntfs.stream().filter(p -> p.network().equals(providerPhysnet)).findAny();
293
294 if (openstackPhyInterface.isPresent()) {
295 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
296 Port port = deviceService.getPorts(intgBridge).stream()
297 .filter(p -> p.isEnabled() &&
298 Objects.equals(p.annotations().value(PORT_NAME), openstackPhyInterface.get().intf()))
299 .findAny().orElse(null);
300
301 return port != null ? port.number() : null;
302 } else {
303 return null;
304 }
305
306 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900307 /**
308 * Returns new builder instance.
309 *
310 * @return openstack node builder
311 */
312 public static Builder builder() {
313 return new Builder();
314 }
315
316 /**
317 * Returns new builder instance with the given node as a default value.
318 *
319 * @param osNode openstack node
320 * @return openstack node builder
321 */
322 public static Builder from(OpenstackNode osNode) {
323 return new Builder()
324 .hostname(osNode.hostname())
Hyunsun Moon090d77d2017-07-05 17:48:37 +0900325 .type(osNode.type())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900326 .intgBridge(osNode.intgBridge())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900327 .managementIp(osNode.managementIp())
328 .dataIp(osNode.dataIp())
329 .vlanIntf(osNode.vlanIntf())
daniel parkb18424c2018-02-05 15:43:43 +0900330 .uplinkPort(osNode.uplinkPort())
Jian Lie6312162018-03-21 21:41:00 +0900331 .state(osNode.state())
332 .phyIntfs(osNode.phyIntfs());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900333 }
334
Jian Li340165f2018-02-27 10:38:17 +0900335 /**
336 * A builder class for openstack Node.
337 */
Hyunsun Moon0d457362017-06-27 17:19:41 +0900338 public static final class Builder implements OpenstackNode.Builder {
339
340 private String hostname;
341 private NodeType type;
342 private DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900343 private IpAddress managementIp;
344 private IpAddress dataIp;
345 private String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +0900346 private String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900347 private NodeState state;
Jian Lie6312162018-03-21 21:41:00 +0900348 private Collection<OpenstackPhyInterface> phyIntfs;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900349
Jian Li340165f2018-02-27 10:38:17 +0900350 // private constructor not intended to use from external
Hyunsun Moon0d457362017-06-27 17:19:41 +0900351 private Builder() {
352 }
353
354 @Override
355 public DefaultOpenstackNode build() {
Jian Li340165f2018-02-27 10:38:17 +0900356 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
357 checkArgument(type != null, NOT_NULL_MSG, "type");
358 checkArgument(intgBridge != null, NOT_NULL_MSG, "integration bridge");
359 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
360 checkArgument(state != null, NOT_NULL_MSG, "state");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900361
daniel parkb18424c2018-02-05 15:43:43 +0900362 if (type == NodeType.GATEWAY && uplinkPort == null) {
363 throw new IllegalArgumentException("Uplink port is required for gateway node");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900364 }
365 if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
366 throw new IllegalArgumentException("Either data IP or VLAN interface is required");
367 }
368
369 return new DefaultOpenstackNode(hostname,
370 type,
371 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900372 managementIp,
373 dataIp,
374 vlanIntf,
daniel parkb18424c2018-02-05 15:43:43 +0900375 uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +0900376 state,
377 phyIntfs);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900378 }
379
380 @Override
381 public Builder hostname(String hostname) {
382 if (!Strings.isNullOrEmpty(hostname)) {
383 this.hostname = hostname;
384 }
385 return this;
386 }
387
388 @Override
389 public Builder type(NodeType type) {
390 this.type = type;
391 return this;
392 }
393
394 @Override
395 public Builder intgBridge(DeviceId intgBridge) {
396 this.intgBridge = intgBridge;
397 return this;
398 }
399
400 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900401 public Builder managementIp(IpAddress managementIp) {
402 this.managementIp = managementIp;
403 return this;
404 }
405
406 @Override
407 public Builder dataIp(IpAddress dataIp) {
408 this.dataIp = dataIp;
409 return this;
410 }
411
412 @Override
413 public Builder vlanIntf(String vlanIntf) {
414 this.vlanIntf = vlanIntf;
415 return this;
416 }
417
418 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900419 public Builder uplinkPort(String uplinkPort) {
420 this.uplinkPort = uplinkPort;
421 return this;
422 }
423
424 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900425 public Builder state(NodeState state) {
426 this.state = state;
427 return this;
428 }
Jian Lie6312162018-03-21 21:41:00 +0900429
430 @Override
431 public Builder phyIntfs(Collection<OpenstackPhyInterface> phyIntfs) {
432 this.phyIntfs = phyIntfs;
433 return this;
434 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900435 }
436}
437