blob: 78e261fc98aad7c8ee678b94cd173669b3f51f5c [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;
Daniel Parkdeefa702018-07-17 17:55:51 +090060 private final OpenstackSshAuth sshAuth;
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 Li789fadb2018-07-10 13:59:47 +090078 * @param controllers customized controllers
Jian Li27841662018-04-14 01:59:47 +090079 * @param auth keystone authentication info
Jian Li92d42fc2018-05-25 16:23:49 +090080 * @param endPoint openstack endpoint URL
Daniel Parkdeefa702018-07-17 17:55:51 +090081 * @param sshAuth ssh authentication info
Jian Li340165f2018-02-27 10:38:17 +090082 */
daniel parkb18424c2018-02-05 15:43:43 +090083 protected DefaultOpenstackNode(String hostname, NodeType type,
84 DeviceId intgBridge,
85 IpAddress managementIp,
86 IpAddress dataIp,
87 String vlanIntf,
88 String uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +090089 NodeState state,
Jian Li27841662018-04-14 01:59:47 +090090 Collection<OpenstackPhyInterface> phyIntfs,
Jian Li789fadb2018-07-10 13:59:47 +090091 Collection<ControllerInfo> controllers,
Jian Li92d42fc2018-05-25 16:23:49 +090092 OpenstackAuth auth,
Daniel Parkdeefa702018-07-17 17:55:51 +090093 String endPoint,
94 OpenstackSshAuth sshAuth) {
Hyunsun Moon0d457362017-06-27 17:19:41 +090095 this.hostname = hostname;
96 this.type = type;
97 this.intgBridge = intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +090098 this.managementIp = managementIp;
99 this.dataIp = dataIp;
100 this.vlanIntf = vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +0900101 this.uplinkPort = uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900102 this.state = state;
Jian Lie6312162018-03-21 21:41:00 +0900103 this.phyIntfs = phyIntfs;
Jian Li789fadb2018-07-10 13:59:47 +0900104 this.controllers = controllers;
Jian Li27841662018-04-14 01:59:47 +0900105 this.auth = auth;
Jian Li92d42fc2018-05-25 16:23:49 +0900106 this.endPoint = endPoint;
Daniel Parkdeefa702018-07-17 17:55:51 +0900107 this.sshAuth = sshAuth;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900108 }
109
110 @Override
111 public String hostname() {
112 return hostname;
113 }
114
115 @Override
116 public NodeType type() {
117 return type;
118 }
119
120 @Override
121 public DeviceId ovsdb() {
daniel parkb18424c2018-02-05 15:43:43 +0900122 return DeviceId.deviceId(OVSDB + managementIp().toString());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900123 }
124
125 @Override
126 public DeviceId intgBridge() {
127 return intgBridge;
128 }
129
130 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900131 public IpAddress managementIp() {
132 return managementIp;
133 }
134
135 @Override
136 public IpAddress dataIp() {
137 return dataIp;
138 }
139
140 @Override
141 public String vlanIntf() {
142 return vlanIntf;
143 }
144
145 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900146 public String uplinkPort() {
147 return uplinkPort;
148 }
149
150 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900151 public NodeState state() {
152 return state;
153 }
154
155 @Override
156 public GroupKey gatewayGroupKey(NetworkMode mode) {
157 return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
158 }
159
160 @Override
daniel parkb5817102018-02-15 00:18:51 +0900161 public PortNumber uplinkPortNum() {
162 if (uplinkPort == null) {
163 return null;
164 }
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), uplinkPort))
170 .findAny().orElse(null);
171
172 return port != null ? port.number() : null;
173
174 }
175 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900176 public PortNumber tunnelPortNum() {
177 if (dataIp == null) {
178 return null;
179 }
180 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
181 Port port = deviceService.getPorts(intgBridge).stream()
182 .filter(p -> p.isEnabled() &&
183 Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
184 .findAny().orElse(null);
185 return port != null ? port.number() : null;
186 }
187
188 @Override
189 public PortNumber vlanPortNum() {
190 if (vlanIntf == null) {
191 return null;
192 }
193 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
194 Port port = deviceService.getPorts(intgBridge).stream()
195 .filter(p -> p.isEnabled() &&
196 Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
197 .findAny().orElse(null);
198 return port != null ? port.number() : null;
199 }
200
201 @Override
202 public PortNumber patchPortNum() {
203 if (type == NodeType.COMPUTE) {
204 return null;
205 }
206 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
207 Port port = deviceService.getPorts(intgBridge).stream()
208 .filter(p -> p.isEnabled() &&
209 Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
210 .findAny().orElse(null);
211 return port != null ? port.number() : null;
212 }
213
214 @Override
215 public MacAddress vlanPortMac() {
216 if (vlanIntf == null) {
217 return null;
218 }
219 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
220 Port port = deviceService.getPorts(intgBridge).stream()
221 .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
222 .findAny().orElse(null);
223 return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
224 }
225
226 @Override
227 public GroupId gatewayGroupId(NetworkMode mode) {
228 return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
229 }
230
231 @Override
232 public boolean equals(Object obj) {
233 if (this == obj) {
234 return true;
235 }
236
237 if (obj instanceof DefaultOpenstackNode) {
238 DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
Jian Li5afbea42018-02-28 10:37:03 +0900239 return Objects.equals(hostname, that.hostname) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900240 Objects.equals(type, that.type) &&
241 Objects.equals(intgBridge, that.intgBridge) &&
Hyunsun Moon0d457362017-06-27 17:19:41 +0900242 Objects.equals(managementIp, that.managementIp) &&
243 Objects.equals(dataIp, that.dataIp) &&
daniel parkb18424c2018-02-05 15:43:43 +0900244 Objects.equals(uplinkPort, that.uplinkPort) &&
Jian Lie6312162018-03-21 21:41:00 +0900245 Objects.equals(vlanIntf, that.vlanIntf) &&
Jian Li27841662018-04-14 01:59:47 +0900246 Objects.equals(phyIntfs, that.phyIntfs) &&
Jian Li789fadb2018-07-10 13:59:47 +0900247 Objects.equals(controllers, that.controllers) &&
Jian Li92d42fc2018-05-25 16:23:49 +0900248 Objects.equals(auth, that.auth) &&
Daniel Parkdeefa702018-07-17 17:55:51 +0900249 Objects.equals(endPoint, that.endPoint) &&
250 Objects.equals(sshAuth, that.sshAuth);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900251 }
252 return false;
253 }
254
255 @Override
256 public int hashCode() {
257 return Objects.hash(hostname,
258 type,
259 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900260 managementIp,
261 dataIp,
daniel parkb18424c2018-02-05 15:43:43 +0900262 vlanIntf,
Jian Lie6312162018-03-21 21:41:00 +0900263 uplinkPort,
Jian Li27841662018-04-14 01:59:47 +0900264 phyIntfs,
Jian Li789fadb2018-07-10 13:59:47 +0900265 controllers,
Jian Li92d42fc2018-05-25 16:23:49 +0900266 auth,
Daniel Parkdeefa702018-07-17 17:55:51 +0900267 endPoint,
268 sshAuth);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900269 }
270
271 @Override
272 public String toString() {
273 return MoreObjects.toStringHelper(getClass())
274 .add("hostname", hostname)
275 .add("type", type)
276 .add("integrationBridge", intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900277 .add("managementIp", managementIp)
278 .add("dataIp", dataIp)
279 .add("vlanIntf", vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900280 .add("uplinkPort", uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900281 .add("state", state)
Jian Lie6312162018-03-21 21:41:00 +0900282 .add("phyIntfs", phyIntfs)
Jian Li789fadb2018-07-10 13:59:47 +0900283 .add("controllers", controllers)
Jian Li27841662018-04-14 01:59:47 +0900284 .add("auth", auth)
Jian Li92d42fc2018-05-25 16:23:49 +0900285 .add("endpoint", endPoint)
Daniel Parkdeefa702018-07-17 17:55:51 +0900286 .add("sshAuth", sshAuth)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900287 .toString();
288 }
289
290 @Override
291 public OpenstackNode updateState(NodeState newState) {
292 return new Builder()
293 .type(type)
294 .hostname(hostname)
295 .intgBridge(intgBridge)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900296 .managementIp(managementIp)
297 .dataIp(dataIp)
298 .vlanIntf(vlanIntf)
daniel parkb18424c2018-02-05 15:43:43 +0900299 .uplinkPort(uplinkPort)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900300 .state(newState)
Jian Lie6312162018-03-21 21:41:00 +0900301 .phyIntfs(phyIntfs)
Jian Li789fadb2018-07-10 13:59:47 +0900302 .controllers(controllers)
Jian Li27841662018-04-14 01:59:47 +0900303 .authentication(auth)
Jian Li92d42fc2018-05-25 16:23:49 +0900304 .endPoint(endPoint)
Daniel Parkdeefa702018-07-17 17:55:51 +0900305 .sshAuthInfo(sshAuth)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900306 .build();
307 }
308
Jian Lie6312162018-03-21 21:41:00 +0900309 @Override
310 public Collection<OpenstackPhyInterface> phyIntfs() {
311
312 if (phyIntfs == null) {
313 return new ArrayList<>();
314 }
315
316 return phyIntfs;
317 }
318
Jian Li789fadb2018-07-10 13:59:47 +0900319
320 @Override
321 public Collection<ControllerInfo> controllers() {
322 if (controllers == null) {
323 return new ArrayList<>();
324 }
325
326 return controllers;
327 }
328
daniel park796c2eb2018-03-22 17:01:51 +0900329 @Override
Daniel Parkdeefa702018-07-17 17:55:51 +0900330 public OpenstackSshAuth sshAuthInfo() {
331 return sshAuth;
332 }
333
334 @Override
daniel park796c2eb2018-03-22 17:01:51 +0900335 public PortNumber phyIntfPortNum(String providerPhysnet) {
336 Optional<OpenstackPhyInterface> openstackPhyInterface =
337 phyIntfs.stream().filter(p -> p.network().equals(providerPhysnet)).findAny();
338
339 if (openstackPhyInterface.isPresent()) {
340 DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
341 Port port = deviceService.getPorts(intgBridge).stream()
342 .filter(p -> p.isEnabled() &&
343 Objects.equals(p.annotations().value(PORT_NAME), openstackPhyInterface.get().intf()))
344 .findAny().orElse(null);
345
346 return port != null ? port.number() : null;
347 } else {
348 return null;
349 }
350
351 }
Jian Li27841662018-04-14 01:59:47 +0900352
353 @Override
354 public OpenstackAuth authentication() {
355 return auth;
356 }
357
Jian Li92d42fc2018-05-25 16:23:49 +0900358 @Override
359 public String endPoint() {
360 return endPoint;
361 }
362
Hyunsun Moon0d457362017-06-27 17:19:41 +0900363 /**
364 * Returns new builder instance.
365 *
366 * @return openstack node builder
367 */
368 public static Builder builder() {
369 return new Builder();
370 }
371
372 /**
373 * Returns new builder instance with the given node as a default value.
374 *
375 * @param osNode openstack node
376 * @return openstack node builder
377 */
378 public static Builder from(OpenstackNode osNode) {
379 return new Builder()
380 .hostname(osNode.hostname())
Hyunsun Moon090d77d2017-07-05 17:48:37 +0900381 .type(osNode.type())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900382 .intgBridge(osNode.intgBridge())
Hyunsun Moon0d457362017-06-27 17:19:41 +0900383 .managementIp(osNode.managementIp())
384 .dataIp(osNode.dataIp())
385 .vlanIntf(osNode.vlanIntf())
daniel parkb18424c2018-02-05 15:43:43 +0900386 .uplinkPort(osNode.uplinkPort())
Jian Lie6312162018-03-21 21:41:00 +0900387 .state(osNode.state())
Jian Li27841662018-04-14 01:59:47 +0900388 .phyIntfs(osNode.phyIntfs())
Jian Li789fadb2018-07-10 13:59:47 +0900389 .controllers(osNode.controllers())
Jian Li92d42fc2018-05-25 16:23:49 +0900390 .authentication(osNode.authentication())
Daniel Parkdeefa702018-07-17 17:55:51 +0900391 .endPoint(osNode.endPoint())
392 .sshAuthInfo(osNode.sshAuthInfo());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900393 }
394
Jian Li340165f2018-02-27 10:38:17 +0900395 /**
396 * A builder class for openstack Node.
397 */
Hyunsun Moon0d457362017-06-27 17:19:41 +0900398 public static final class Builder implements OpenstackNode.Builder {
399
400 private String hostname;
401 private NodeType type;
402 private DeviceId intgBridge;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900403 private IpAddress managementIp;
404 private IpAddress dataIp;
405 private String vlanIntf;
daniel parkb18424c2018-02-05 15:43:43 +0900406 private String uplinkPort;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900407 private NodeState state;
Jian Lie6312162018-03-21 21:41:00 +0900408 private Collection<OpenstackPhyInterface> phyIntfs;
Jian Li789fadb2018-07-10 13:59:47 +0900409 private Collection<ControllerInfo> controllers;
Jian Li27841662018-04-14 01:59:47 +0900410 private OpenstackAuth auth;
Jian Li92d42fc2018-05-25 16:23:49 +0900411 private String endPoint;
Daniel Parkdeefa702018-07-17 17:55:51 +0900412 private OpenstackSshAuth sshAuth;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900413
Jian Li340165f2018-02-27 10:38:17 +0900414 // private constructor not intended to use from external
Hyunsun Moon0d457362017-06-27 17:19:41 +0900415 private Builder() {
416 }
417
418 @Override
419 public DefaultOpenstackNode build() {
Jian Li340165f2018-02-27 10:38:17 +0900420 checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
421 checkArgument(type != null, NOT_NULL_MSG, "type");
Jian Li340165f2018-02-27 10:38:17 +0900422 checkArgument(state != null, NOT_NULL_MSG, "state");
Jian Li92d42fc2018-05-25 16:23:49 +0900423 checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900424
Jian Li27841662018-04-14 01:59:47 +0900425 if (type != NodeType.CONTROLLER) {
426 checkArgument(intgBridge != null, NOT_NULL_MSG, "integration bridge");
427
428 if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
429 throw new IllegalArgumentException("Either data IP or VLAN interface is required");
430 }
431 } else {
Jian Li92d42fc2018-05-25 16:23:49 +0900432 checkArgument(endPoint != null, NOT_NULL_MSG, "endpoint URL");
Jian Li27841662018-04-14 01:59:47 +0900433 }
434
daniel parkb18424c2018-02-05 15:43:43 +0900435 if (type == NodeType.GATEWAY && uplinkPort == null) {
436 throw new IllegalArgumentException("Uplink port is required for gateway node");
Hyunsun Moon0d457362017-06-27 17:19:41 +0900437 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900438
439 return new DefaultOpenstackNode(hostname,
440 type,
441 intgBridge,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900442 managementIp,
443 dataIp,
444 vlanIntf,
daniel parkb18424c2018-02-05 15:43:43 +0900445 uplinkPort,
Jian Lie6312162018-03-21 21:41:00 +0900446 state,
Jian Li27841662018-04-14 01:59:47 +0900447 phyIntfs,
Jian Li789fadb2018-07-10 13:59:47 +0900448 controllers,
Jian Li92d42fc2018-05-25 16:23:49 +0900449 auth,
Daniel Parkdeefa702018-07-17 17:55:51 +0900450 endPoint,
451 sshAuth);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900452 }
453
454 @Override
455 public Builder hostname(String hostname) {
456 if (!Strings.isNullOrEmpty(hostname)) {
457 this.hostname = hostname;
458 }
459 return this;
460 }
461
462 @Override
463 public Builder type(NodeType type) {
464 this.type = type;
465 return this;
466 }
467
468 @Override
469 public Builder intgBridge(DeviceId intgBridge) {
470 this.intgBridge = intgBridge;
471 return this;
472 }
473
474 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900475 public Builder managementIp(IpAddress managementIp) {
476 this.managementIp = managementIp;
477 return this;
478 }
479
480 @Override
481 public Builder dataIp(IpAddress dataIp) {
482 this.dataIp = dataIp;
483 return this;
484 }
485
486 @Override
487 public Builder vlanIntf(String vlanIntf) {
488 this.vlanIntf = vlanIntf;
489 return this;
490 }
491
492 @Override
daniel parkb18424c2018-02-05 15:43:43 +0900493 public Builder uplinkPort(String uplinkPort) {
494 this.uplinkPort = uplinkPort;
495 return this;
496 }
497
498 @Override
Hyunsun Moon0d457362017-06-27 17:19:41 +0900499 public Builder state(NodeState state) {
500 this.state = state;
501 return this;
502 }
Jian Lie6312162018-03-21 21:41:00 +0900503
504 @Override
505 public Builder phyIntfs(Collection<OpenstackPhyInterface> phyIntfs) {
506 this.phyIntfs = phyIntfs;
507 return this;
508 }
Jian Li27841662018-04-14 01:59:47 +0900509
510 @Override
Jian Li789fadb2018-07-10 13:59:47 +0900511 public Builder controllers(Collection<ControllerInfo> controllers) {
512 this.controllers = controllers;
513 return this;
514 }
515
516 @Override
Jian Li27841662018-04-14 01:59:47 +0900517 public Builder authentication(OpenstackAuth auth) {
518 this.auth = auth;
519 return this;
520 }
Jian Li92d42fc2018-05-25 16:23:49 +0900521
522 @Override
523 public Builder endPoint(String endPoint) {
524 this.endPoint = endPoint;
525 return this;
526 }
Daniel Parkdeefa702018-07-17 17:55:51 +0900527
528 @Override
529 public Builder sshAuthInfo(OpenstackSshAuth sshAuth) {
530 this.sshAuth = sshAuth;
531 return this;
532 }
Hyunsun Moon0d457362017-06-27 17:19:41 +0900533 }
534}
535