blob: f02684aa191d29f09093a70d59bf963750b74654 [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;
49 private final DeviceId routerBridge;
50 private final IpAddress managementIp;
51 private final IpAddress dataIp;
52 private final String vlanIntf;
53 private final NodeState state;
54
Hyunsun Moon090d77d2017-07-05 17:48:37 +090055 protected DefaultOpenstackNode(String hostname,
Hyunsun Moon0d457362017-06-27 17:19:41 +090056 NodeType type,
57 DeviceId intgBridge,
58 DeviceId routerBridge,
59 IpAddress managementIp,
60 IpAddress dataIp,
61 String vlanIntf,
62 NodeState state) {
63 this.hostname = hostname;
64 this.type = type;
65 this.intgBridge = intgBridge;
66 this.routerBridge = routerBridge;
67 this.managementIp = managementIp;
68 this.dataIp = dataIp;
69 this.vlanIntf = vlanIntf;
70 this.state = state;
71 }
72
73 @Override
74 public String hostname() {
75 return hostname;
76 }
77
78 @Override
79 public NodeType type() {
80 return type;
81 }
82
83 @Override
84 public DeviceId ovsdb() {
85 return DeviceId.deviceId("ovsdb:" + managementIp().toString());
86 }
87
88 @Override
89 public DeviceId intgBridge() {
90 return intgBridge;
91 }
92
93 @Override
94 public DeviceId routerBridge() {
95 return routerBridge;
96 }
97
98 @Override
99 public IpAddress managementIp() {
100 return managementIp;
101 }
102
103 @Override
104 public IpAddress dataIp() {
105 return dataIp;
106 }
107
108 @Override
109 public String vlanIntf() {
110 return vlanIntf;
111 }
112
113 @Override
114 public NodeState state() {
115 return state;
116 }
117
118 @Override
119 public GroupKey gatewayGroupKey(NetworkMode mode) {
120 return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
121 }
122
123 @Override
124 public PortNumber tunnelPortNum() {
125 if (dataIp == null) {
126 return null;
127 }
128 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
129 Port port = deviceService.getPorts(intgBridge).stream()
130 .filter(p -> p.isEnabled() &&
131 Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
132 .findAny().orElse(null);
133 return port != null ? port.number() : null;
134 }
135
136 @Override
137 public PortNumber vlanPortNum() {
138 if (vlanIntf == null) {
139 return null;
140 }
141 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
142 Port port = deviceService.getPorts(intgBridge).stream()
143 .filter(p -> p.isEnabled() &&
144 Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
145 .findAny().orElse(null);
146 return port != null ? port.number() : null;
147 }
148
149 @Override
150 public PortNumber patchPortNum() {
151 if (type == NodeType.COMPUTE) {
152 return null;
153 }
154 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
155 Port port = deviceService.getPorts(intgBridge).stream()
156 .filter(p -> p.isEnabled() &&
157 Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
158 .findAny().orElse(null);
159 return port != null ? port.number() : null;
160 }
161
162 @Override
163 public MacAddress vlanPortMac() {
164 if (vlanIntf == null) {
165 return null;
166 }
167 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
168 Port port = deviceService.getPorts(intgBridge).stream()
169 .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
170 .findAny().orElse(null);
171 return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
172 }
173
174 @Override
175 public GroupId gatewayGroupId(NetworkMode mode) {
176 return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
177 }
178
179 @Override
180 public boolean equals(Object obj) {
181 if (this == obj) {
182 return true;
183 }
184
185 if (obj instanceof DefaultOpenstackNode) {
186 DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
187 if (Objects.equals(hostname, that.hostname) &&
188 Objects.equals(type, that.type) &&
189 Objects.equals(intgBridge, that.intgBridge) &&
190 Objects.equals(routerBridge, that.routerBridge) &&
191 Objects.equals(managementIp, that.managementIp) &&
192 Objects.equals(dataIp, that.dataIp) &&
193 Objects.equals(vlanIntf, that.vlanIntf)) {
194 return true;
195 }
196 }
197 return false;
198 }
199
200 @Override
201 public int hashCode() {
202 return Objects.hash(hostname,
203 type,
204 intgBridge,
205 routerBridge,
206 managementIp,
207 dataIp,
208 vlanIntf);
209 }
210
211 @Override
212 public String toString() {
213 return MoreObjects.toStringHelper(getClass())
214 .add("hostname", hostname)
215 .add("type", type)
216 .add("integrationBridge", intgBridge)
217 .add("routerBridge", routerBridge)
218 .add("managementIp", managementIp)
219 .add("dataIp", dataIp)
220 .add("vlanIntf", vlanIntf)
221 .add("state", state)
222 .toString();
223 }
224
225 @Override
226 public OpenstackNode updateState(NodeState newState) {
227 return new Builder()
228 .type(type)
229 .hostname(hostname)
230 .intgBridge(intgBridge)
231 .routerBridge(routerBridge)
232 .managementIp(managementIp)
233 .dataIp(dataIp)
234 .vlanIntf(vlanIntf)
235 .state(newState)
236 .build();
237 }
238
239 /**
240 * Returns new builder instance.
241 *
242 * @return openstack node builder
243 */
244 public static Builder builder() {
245 return new Builder();
246 }
247
248 /**
249 * Returns new builder instance with the given node as a default value.
250 *
251 * @param osNode openstack node
252 * @return openstack node builder
253 */
254 public static Builder from(OpenstackNode osNode) {
255 return new Builder()
256 .hostname(osNode.hostname())
Hyunsun Moon090d77d2017-07-05 17:48:37 +0900257 .type(osNode.type())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900258 .intgBridge(osNode.intgBridge())
259 .routerBridge(osNode.routerBridge())
260 .managementIp(osNode.managementIp())
261 .dataIp(osNode.dataIp())
262 .vlanIntf(osNode.vlanIntf())
263 .state(osNode.state());
264 }
265
266 public static final class Builder implements OpenstackNode.Builder {
267
268 private String hostname;
269 private NodeType type;
270 private DeviceId intgBridge;
271 private DeviceId routerBridge;
272 private IpAddress managementIp;
273 private IpAddress dataIp;
274 private String vlanIntf;
275 private NodeState state;
276
277 private Builder() {
278 }
279
280 @Override
281 public DefaultOpenstackNode build() {
282 checkArgument(hostname != null, "Node hostname cannot be null");
283 checkArgument(type != null, "Node type cannot be null");
284 checkArgument(intgBridge != null, "Node integration bridge cannot be null");
285 checkArgument(managementIp != null, "Node management IP cannot be null");
286 checkArgument(state != null, "Node state cannot be null");
287
288 if (type == NodeType.GATEWAY && routerBridge == null) {
289 throw new IllegalArgumentException("Router bridge is required for gateway node");
290 }
291 if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
292 throw new IllegalArgumentException("Either data IP or VLAN interface is required");
293 }
294
295 return new DefaultOpenstackNode(hostname,
296 type,
297 intgBridge,
298 routerBridge,
299 managementIp,
300 dataIp,
301 vlanIntf,
302 state);
303 }
304
305 @Override
306 public Builder hostname(String hostname) {
307 if (!Strings.isNullOrEmpty(hostname)) {
308 this.hostname = hostname;
309 }
310 return this;
311 }
312
313 @Override
314 public Builder type(NodeType type) {
315 this.type = type;
316 return this;
317 }
318
319 @Override
320 public Builder intgBridge(DeviceId intgBridge) {
321 this.intgBridge = intgBridge;
322 return this;
323 }
324
325 @Override
326 public Builder routerBridge(DeviceId routerBridge) {
327 this.routerBridge = routerBridge;
328 return this;
329 }
330
331 @Override
332 public Builder managementIp(IpAddress managementIp) {
333 this.managementIp = managementIp;
334 return this;
335 }
336
337 @Override
338 public Builder dataIp(IpAddress dataIp) {
339 this.dataIp = dataIp;
340 return this;
341 }
342
343 @Override
344 public Builder vlanIntf(String vlanIntf) {
345 this.vlanIntf = vlanIntf;
346 return this;
347 }
348
349 @Override
350 public Builder state(NodeState state) {
351 this.state = state;
352 return this;
353 }
354 }
355}
356