blob: 6650be6d2f91b36fae8893e53a23c48476f1b811 [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;
32
33import java.util.Objects;
34
35import static com.google.common.base.Preconditions.checkArgument;
36import static org.onosproject.net.AnnotationKeys.PORT_MAC;
37import static org.onosproject.net.AnnotationKeys.PORT_NAME;
38import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
39import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
40
41/**
42 * Representation of a openstack node.
43 */
Hyunsun Moon090d77d2017-07-05 17:48:37 +090044public class DefaultOpenstackNode implements OpenstackNode {
Hyunsun Moon0d457362017-06-27 17:19:41 +090045
46 private final String hostname;
47 private final NodeType type;
48 private final DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090049 private final IpAddress managementIp;
50 private final IpAddress dataIp;
51 private final String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090052 private final String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090053 private final NodeState state;
54
daniel parkb18424c2018-02-05 15:43:43 +090055 private static final String OVSDB = "ovsdb:";
56
57 protected DefaultOpenstackNode(String hostname, NodeType type,
58 DeviceId intgBridge,
59 IpAddress managementIp,
60 IpAddress dataIp,
61 String vlanIntf,
62 String uplinkPort,
63 NodeState state) {
Hyunsun Moon0d457362017-06-27 17:19:41 +090064 this.hostname = hostname;
65 this.type = type;
66 this.intgBridge = intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090067 this.managementIp = managementIp;
68 this.dataIp = dataIp;
69 this.vlanIntf = vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +090070 this.uplinkPort = uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +090071 this.state = state;
72 }
73
74 @Override
75 public String hostname() {
76 return hostname;
77 }
78
79 @Override
80 public NodeType type() {
81 return type;
82 }
83
84 @Override
85 public DeviceId ovsdb() {
daniel parkb18424c2018-02-05 15:43:43 +090086 return DeviceId.deviceId(OVSDB + managementIp().toString());
Hyunsun Moon0d457362017-06-27 17:19:41 +090087 }
88
89 @Override
90 public DeviceId intgBridge() {
91 return intgBridge;
92 }
93
94 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +090095 public IpAddress managementIp() {
96 return managementIp;
97 }
98
99 @Override
100 public IpAddress dataIp() {
101 return dataIp;
102 }
103
104 @Override
105 public String vlanIntf() {
106 return vlanIntf;
107 }
108
109 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900110 public String uplinkPort() {
111 return uplinkPort;
112 }
113
114 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900115 public NodeState state() {
116 return state;
117 }
118
119 @Override
120 public GroupKey gatewayGroupKey(NetworkMode mode) {
121 return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
122 }
123
124 @Override
125 public PortNumber tunnelPortNum() {
126 if (dataIp == null) {
127 return null;
128 }
129 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
130 Port port = deviceService.getPorts(intgBridge).stream()
131 .filter(p -> p.isEnabled() &&
132 Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
133 .findAny().orElse(null);
134 return port != null ? port.number() : null;
135 }
136
137 @Override
138 public PortNumber vlanPortNum() {
139 if (vlanIntf == null) {
140 return null;
141 }
142 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
143 Port port = deviceService.getPorts(intgBridge).stream()
144 .filter(p -> p.isEnabled() &&
145 Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
146 .findAny().orElse(null);
147 return port != null ? port.number() : null;
148 }
149
150 @Override
151 public PortNumber patchPortNum() {
152 if (type == NodeType.COMPUTE) {
153 return null;
154 }
155 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
156 Port port = deviceService.getPorts(intgBridge).stream()
157 .filter(p -> p.isEnabled() &&
158 Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
159 .findAny().orElse(null);
160 return port != null ? port.number() : null;
161 }
162
163 @Override
164 public MacAddress vlanPortMac() {
165 if (vlanIntf == null) {
166 return null;
167 }
168 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
169 Port port = deviceService.getPorts(intgBridge).stream()
170 .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
171 .findAny().orElse(null);
172 return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
173 }
174
175 @Override
176 public GroupId gatewayGroupId(NetworkMode mode) {
177 return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
178 }
179
180 @Override
181 public boolean equals(Object obj) {
182 if (this == obj) {
183 return true;
184 }
185
186 if (obj instanceof DefaultOpenstackNode) {
187 DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
188 if (Objects.equals(hostname, that.hostname) &&
189 Objects.equals(type, that.type) &&
190 Objects.equals(intgBridge, that.intgBridge) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900191 Objects.equals(managementIp, that.managementIp) &&
192 Objects.equals(dataIp, that.dataIp) &&
daniel parkb18424c2018-02-05 15:43:43 +0900193 Objects.equals(uplinkPort, that.uplinkPort) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900194 Objects.equals(vlanIntf, that.vlanIntf)) {
195 return true;
196 }
197 }
198 return false;
199 }
200
201 @Override
202 public int hashCode() {
203 return Objects.hash(hostname,
204 type,
205 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900206 managementIp,
207 dataIp,
daniel parkb18424c2018-02-05 15:43:43 +0900208 vlanIntf,
209 uplinkPort);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900210 }
211
212 @Override
213 public String toString() {
214 return MoreObjects.toStringHelper(getClass())
215 .add("hostname", hostname)
216 .add("type", type)
217 .add("integrationBridge", intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900218 .add("managementIp", managementIp)
219 .add("dataIp", dataIp)
220 .add("vlanIntf", vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900221 .add("uplinkPort", uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900222 .add("state", state)
223 .toString();
224 }
225
226 @Override
227 public OpenstackNode updateState(NodeState newState) {
228 return new Builder()
229 .type(type)
230 .hostname(hostname)
231 .intgBridge(intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900232 .managementIp(managementIp)
233 .dataIp(dataIp)
234 .vlanIntf(vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900235 .uplinkPort(uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900236 .state(newState)
237 .build();
238 }
239
240 /**
241 * Returns new builder instance.
242 *
243 * @return openstack node builder
244 */
245 public static Builder builder() {
246 return new Builder();
247 }
248
249 /**
250 * Returns new builder instance with the given node as a default value.
251 *
252 * @param osNode openstack node
253 * @return openstack node builder
254 */
255 public static Builder from(OpenstackNode osNode) {
256 return new Builder()
257 .hostname(osNode.hostname())
Hyunsun Moon090d77d2017-07-05 17:48:37 +0900258 .type(osNode.type())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900259 .intgBridge(osNode.intgBridge())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900260 .managementIp(osNode.managementIp())
261 .dataIp(osNode.dataIp())
262 .vlanIntf(osNode.vlanIntf())
daniel parkb18424c2018-02-05 15:43:43 +0900263 .uplinkPort(osNode.uplinkPort())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900264 .state(osNode.state());
265 }
266
267 public static final class Builder implements OpenstackNode.Builder {
268
269 private String hostname;
270 private NodeType type;
271 private DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900272 private IpAddress managementIp;
273 private IpAddress dataIp;
274 private String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +0900275 private String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900276 private NodeState state;
277
278 private Builder() {
279 }
280
281 @Override
282 public DefaultOpenstackNode build() {
283 checkArgument(hostname != null, "Node hostname cannot be null");
284 checkArgument(type != null, "Node type cannot be null");
285 checkArgument(intgBridge != null, "Node integration bridge cannot be null");
286 checkArgument(managementIp != null, "Node management IP cannot be null");
287 checkArgument(state != null, "Node state cannot be null");
288
daniel parkb18424c2018-02-05 15:43:43 +0900289 if (type == NodeType.GATEWAY && uplinkPort == null) {
290 throw new IllegalArgumentException("Uplink port is required for gateway node");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900291 }
292 if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
293 throw new IllegalArgumentException("Either data IP or VLAN interface is required");
294 }
295
296 return new DefaultOpenstackNode(hostname,
297 type,
298 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900299 managementIp,
300 dataIp,
301 vlanIntf,
daniel parkb18424c2018-02-05 15:43:43 +0900302 uplinkPort,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900303 state);
304 }
305
306 @Override
307 public Builder hostname(String hostname) {
308 if (!Strings.isNullOrEmpty(hostname)) {
309 this.hostname = hostname;
310 }
311 return this;
312 }
313
314 @Override
315 public Builder type(NodeType type) {
316 this.type = type;
317 return this;
318 }
319
320 @Override
321 public Builder intgBridge(DeviceId intgBridge) {
322 this.intgBridge = intgBridge;
323 return this;
324 }
325
326 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900327 public Builder managementIp(IpAddress managementIp) {
328 this.managementIp = managementIp;
329 return this;
330 }
331
332 @Override
333 public Builder dataIp(IpAddress dataIp) {
334 this.dataIp = dataIp;
335 return this;
336 }
337
338 @Override
339 public Builder vlanIntf(String vlanIntf) {
340 this.vlanIntf = vlanIntf;
341 return this;
342 }
343
344 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900345 public Builder uplinkPort(String uplinkPort) {
346 this.uplinkPort = uplinkPort;
347 return this;
348 }
349
350 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900351 public Builder state(NodeState state) {
352 this.state = state;
353 return this;
354 }
355 }
356}
357