blob: 17849fc80ade9b173faa8ec7756f0c3c1a24b451 [file] [log] [blame]
andreaeb70a942015-10-16 21:34:46 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
andreaeb70a942015-10-16 21:34:46 -07003 *
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 */
16
17package org.onosproject.netconf;
18
David K. Bainbridge56e90232018-12-18 23:25:08 -080019import org.apache.commons.lang3.tuple.Triple;
andreaeb70a942015-10-16 21:34:46 -070020import org.onlab.packet.IpAddress;
21import org.onosproject.net.DeviceId;
Sean Condon54d82432017-07-26 22:27:25 +010022import org.onosproject.netconf.config.NetconfDeviceConfig;
23import org.onosproject.netconf.config.NetconfSshClientLib;
andreaeb70a942015-10-16 21:34:46 -070024import org.slf4j.Logger;
25import org.slf4j.LoggerFactory;
26
andreaeb70a942015-10-16 21:34:46 -070027import java.net.URI;
28import java.net.URISyntaxException;
29import java.util.Objects;
Sean Condon54d82432017-07-26 22:27:25 +010030import java.util.Optional;
31import java.util.OptionalInt;
andreaeb70a942015-10-16 21:34:46 -070032
Ray Milkeyd4b51c22018-02-08 11:36:43 -080033import static com.google.common.base.Preconditions.checkArgument;
34import static com.google.common.base.Preconditions.checkNotNull;
35
andreaeb70a942015-10-16 21:34:46 -070036/**
37 * Represents a Netconf device information.
38 */
39public class NetconfDeviceInfo {
40
41 public static final Logger log = LoggerFactory
42 .getLogger(NetconfDeviceInfo.class);
43
44 private String name;
45 private String password;
46 private IpAddress ipAddress;
47 private int port;
David K. Bainbridge56e90232018-12-18 23:25:08 -080048 private Optional<String> path;
Himanshu Ranjan7c2ee3c2017-02-13 05:10:08 -060049 private char[] key;
Sean Condon54d82432017-07-26 22:27:25 +010050 private Optional<NetconfSshClientLib> sshClientLib;
51 private OptionalInt connectTimeoutSec;
52 private OptionalInt replyTimeoutSec;
53 private OptionalInt idleTimeoutSec;
Andrea Campanella57efbb22016-02-11 14:21:41 -080054 private DeviceId deviceId;
andreaeb70a942015-10-16 21:34:46 -070055
andreaeb70a942015-10-16 21:34:46 -070056 /**
57 * Information for contacting the controller.
58 *
59 * @param name the connection type
60 * @param password the password for the device
61 * @param ipAddress the ip address
62 * @param port the tcp port
David K. Bainbridge56e90232018-12-18 23:25:08 -080063 * @param path the path part
andreaeb70a942015-10-16 21:34:46 -070064 */
65 public NetconfDeviceInfo(String name, String password, IpAddress ipAddress,
David K. Bainbridge56e90232018-12-18 23:25:08 -080066 int port, String path) {
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -070067 checkArgument(!name.equals(""), "Empty device username");
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -080068 checkArgument(port > 0, "Negative port");
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -070069 checkNotNull(ipAddress, "Null ip address");
andreaeb70a942015-10-16 21:34:46 -070070 this.name = name;
71 this.password = password;
72 this.ipAddress = ipAddress;
73 this.port = port;
David K. Bainbridge56e90232018-12-18 23:25:08 -080074 if (path == null || path.isEmpty()) {
75 this.path = Optional.empty();
76 } else {
77 this.path = Optional.of(path);
78 }
Sean Condon54d82432017-07-26 22:27:25 +010079 this.sshClientLib = Optional.empty();
80 this.connectTimeoutSec = OptionalInt.empty();
81 this.replyTimeoutSec = OptionalInt.empty();
82 this.idleTimeoutSec = OptionalInt.empty();
andreaeb70a942015-10-16 21:34:46 -070083 }
84
85 /**
86 * Information for contacting the controller.
87 *
88 * @param name the connection type
89 * @param password the password for the device
90 * @param ipAddress the ip address
91 * @param port the tcp port
David K. Bainbridge56e90232018-12-18 23:25:08 -080092 */
93 public NetconfDeviceInfo(String name, String password, IpAddress ipAddress,
94 int port) {
95 this(name, password, ipAddress, port, null);
96 }
97
98 /**
99 * Information for contacting the controller.
100 *
101 * @param name the connection type
102 * @param password the password for the device
103 * @param ipAddress the ip address
104 * @param port the tcp port
105 * @param path the path part
Andrea Campanellae7006dc2017-02-15 16:04:09 -0800106 * @param keyString the string containing a DSA or RSA private key
107 * of the user in OpenSSH key format
andreaeb70a942015-10-16 21:34:46 -0700108 */
109 public NetconfDeviceInfo(String name, String password, IpAddress ipAddress,
David K. Bainbridge56e90232018-12-18 23:25:08 -0800110 int port, String path, String keyString) {
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -0700111 checkArgument(!name.equals(""), "Empty device name");
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800112 checkArgument(port > 0, "Negative port");
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -0700113 checkNotNull(ipAddress, "Null ip address");
andreaeb70a942015-10-16 21:34:46 -0700114 this.name = name;
115 this.password = password;
116 this.ipAddress = ipAddress;
117 this.port = port;
David K. Bainbridge56e90232018-12-18 23:25:08 -0800118 this.path = Optional.ofNullable(path);
Himanshu Ranjan7c2ee3c2017-02-13 05:10:08 -0600119 this.key = keyString.toCharArray();
Sean Condon54d82432017-07-26 22:27:25 +0100120 this.sshClientLib = Optional.empty();
121 this.connectTimeoutSec = OptionalInt.empty();
122 this.replyTimeoutSec = OptionalInt.empty();
123 this.idleTimeoutSec = OptionalInt.empty();
124 }
125
126 /**
127 * Convenieince constructor that converts all known fields from NetCfg data.
128 * @param netconfConfig NetCf configuration
Anurag Chadhab6a6bcb2021-03-26 14:43:41 +0530129 * @param deviceId deviceId as per netcfg
Sean Condon54d82432017-07-26 22:27:25 +0100130 */
Anurag Chadhab6a6bcb2021-03-26 14:43:41 +0530131 public NetconfDeviceInfo(NetconfDeviceConfig netconfConfig, DeviceId deviceId) {
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -0700132 checkArgument(!netconfConfig.username().isEmpty(), "Empty device name");
Yuta HIGUCHIfbd9ae92018-01-24 23:39:06 -0800133 checkArgument(netconfConfig.port() > 0, "Negative port");
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -0700134 checkNotNull(netconfConfig.ip(), "Null ip address");
Sean Condon54d82432017-07-26 22:27:25 +0100135
136 this.name = netconfConfig.username();
137 this.password = netconfConfig.password();
138 this.ipAddress = netconfConfig.ip();
Anurag Chadhab6a6bcb2021-03-26 14:43:41 +0530139 this.deviceId = deviceId;
Sean Condon54d82432017-07-26 22:27:25 +0100140 this.port = netconfConfig.port();
David K. Bainbridge56e90232018-12-18 23:25:08 -0800141 this.path = netconfConfig.path();
Sean Condon54d82432017-07-26 22:27:25 +0100142 if (netconfConfig.sshKey() != null && !netconfConfig.sshKey().isEmpty()) {
143 this.key = netconfConfig.sshKey().toCharArray();
144 }
Sean Condon54d82432017-07-26 22:27:25 +0100145 if (netconfConfig.sshClient().isPresent()) {
146 this.sshClientLib = Optional.of(NetconfSshClientLib.getEnum(netconfConfig.sshClient().get()));
147 } else {
148 this.sshClientLib = Optional.empty();
149 }
150 this.connectTimeoutSec = netconfConfig.connectTimeout();
151 this.replyTimeoutSec = netconfConfig.replyTimeout();
152 this.idleTimeoutSec = netconfConfig.idleTimeout();
153 }
154
155 /**
156 * Allows the NETCONF SSH Client library to be set.
157 *
158 * @param sshClientLib An enumerated value
159 */
160 public void setSshClientLib(Optional<NetconfSshClientLib> sshClientLib) {
161 this.sshClientLib = sshClientLib;
162 }
163
164 /**
165 * Allows the NETCONF SSH session initial connect timeout to be set.
166 *
167 * @param connectTimeoutSec value in seconds
168 */
169 public void setConnectTimeoutSec(OptionalInt connectTimeoutSec) {
170 this.connectTimeoutSec = connectTimeoutSec;
171 }
172
173 /**
174 * Allows the NETCONF SSH session replies timeout to be set.
175 *
176 * @param replyTimeoutSec value in seconds
177 */
178 public void setReplyTimeoutSec(OptionalInt replyTimeoutSec) {
179 this.replyTimeoutSec = replyTimeoutSec;
180 }
181
182 /**
183 * Allows the NETCONF SSH session idle timeout to be set.
184 *
185 * @param idleTimeoutSec value in seconds
186 */
187 public void setIdleTimeoutSec(OptionalInt idleTimeoutSec) {
188 this.idleTimeoutSec = idleTimeoutSec;
andreaeb70a942015-10-16 21:34:46 -0700189 }
190
191 /**
David K. Bainbridge56e90232018-12-18 23:25:08 -0800192 * Allows the path aspect of the device URI to be set.
193 *
194 * @param path path aspect value
195 */
196 public void setPath(Optional<String> path) {
197 this.path = path;
198 }
199
200 /**
andreaeb70a942015-10-16 21:34:46 -0700201 * Exposes the name of the controller.
202 *
203 * @return String name
204 */
205 public String name() {
206 return name;
207 }
208
209 /**
210 * Exposes the password of the controller.
211 *
212 * @return String password
213 */
214 public String password() {
215 return password;
216 }
217
218 /**
219 * Exposes the ip address of the controller.
220 *
221 * @return IpAddress ip address
222 */
223 public IpAddress ip() {
224 return ipAddress;
225 }
226
227 /**
228 * Exposes the port of the controller.
229 *
Yuta HIGUCHIe3ae8212017-04-20 10:18:41 -0700230 * @return port number
andreaeb70a942015-10-16 21:34:46 -0700231 */
232 public int port() {
233 return port;
234 }
235
David K. Bainbridge56e90232018-12-18 23:25:08 -0800236 /*
237 * Exposes the path of the aspect.
238 *
239 * @return path aspect
240 */
241 public Optional<String> path() {
242 return path;
243 }
244
andreaeb70a942015-10-16 21:34:46 -0700245 /**
Himanshu Ranjan7c2ee3c2017-02-13 05:10:08 -0600246 * Exposes the key of the controller.
andreaeb70a942015-10-16 21:34:46 -0700247 *
Andrea Campanellae7006dc2017-02-15 16:04:09 -0800248 * @return {@code char[]} containing a DSA or RSA private key of the user
249 * in OpenSSH key format
250 * or null if device is not configured to use public key authentication
andreaeb70a942015-10-16 21:34:46 -0700251 */
Himanshu Ranjan7c2ee3c2017-02-13 05:10:08 -0600252 public char[] getKey() {
253 return key;
andreaeb70a942015-10-16 21:34:46 -0700254 }
255
256 /**
Sean Condon54d82432017-07-26 22:27:25 +0100257 * Exposes the Client library implementation.
258 *
259 * @return Enumerated value
260 */
261 public Optional<NetconfSshClientLib> sshClientLib() {
262 return sshClientLib;
263 }
264
265 /**
266 * Exposes the device specific connect timeout.
267 *
268 * @return The timeout value in seconds
269 */
270 public OptionalInt getConnectTimeoutSec() {
271 return connectTimeoutSec;
272 }
273
274 /**
275 * Exposes the device specific reply timeout.
276 *
277 * @return The timeout value in seconds
278 */
279 public OptionalInt getReplyTimeoutSec() {
280 return replyTimeoutSec;
281 }
282
283 /**
284 * Exposes the device specific idle timeout.
285 *
286 * @return The timeout value in seconds
287 */
288 public OptionalInt getIdleTimeoutSec() {
289 return idleTimeoutSec;
290 }
291
292 /**
andreaeb70a942015-10-16 21:34:46 -0700293 * Return the info about the device in a string.
294 * String format: "netconf:name@ip:port"
295 *
296 * @return String device info
297 */
Andrea Campanellae7006dc2017-02-15 16:04:09 -0800298 @Override
andreaeb70a942015-10-16 21:34:46 -0700299 public String toString() {
David K. Bainbridge9b582b02019-02-01 16:04:05 -0800300 return "netconf:" + name + "@" + ipAddress + ":" + port +
301 (path.isPresent() ? '/' + path.get() : "");
andreaeb70a942015-10-16 21:34:46 -0700302 }
303
304 /**
305 * Return the DeviceId about the device containing the URI.
306 *
307 * @return DeviceId
308 */
309 public DeviceId getDeviceId() {
Andrea Campanella57efbb22016-02-11 14:21:41 -0800310 if (deviceId == null) {
311 try {
David K. Bainbridge56e90232018-12-18 23:25:08 -0800312 deviceId = DeviceId.deviceId(new URI("netconf", ipAddress.toString() + ":" + port +
313 (path.isPresent() ? "/" + path.get() : ""), null));
Andrea Campanella57efbb22016-02-11 14:21:41 -0800314 } catch (URISyntaxException e) {
315 throw new IllegalArgumentException("Unable to build deviceID for device " + toString(), e);
316 }
andreaeb70a942015-10-16 21:34:46 -0700317 }
Andrea Campanella57efbb22016-02-11 14:21:41 -0800318 return deviceId;
andreaeb70a942015-10-16 21:34:46 -0700319 }
320
321 @Override
322 public int hashCode() {
David K. Bainbridge56e90232018-12-18 23:25:08 -0800323 if (path.isPresent()) {
324 return Objects.hash(ipAddress, port, path.get(), name);
325 } else {
326 return Objects.hash(ipAddress, port, name);
327 }
andreaeb70a942015-10-16 21:34:46 -0700328 }
329
330 @Override
331 public boolean equals(Object toBeCompared) {
332 if (toBeCompared instanceof NetconfDeviceInfo) {
333 NetconfDeviceInfo netconfDeviceInfo = (NetconfDeviceInfo) toBeCompared;
334 if (netconfDeviceInfo.name().equals(name)
335 && netconfDeviceInfo.ip().equals(ipAddress)
336 && netconfDeviceInfo.port() == port
David K. Bainbridge56e90232018-12-18 23:25:08 -0800337 && netconfDeviceInfo.path().equals(path)
andreaeb70a942015-10-16 21:34:46 -0700338 && netconfDeviceInfo.password().equals(password)) {
339 return true;
340 }
341 }
342 return false;
343 }
David K. Bainbridge56e90232018-12-18 23:25:08 -0800344
345 public static Triple<String, Integer, Optional<String>> extractIpPortPath(DeviceId deviceId) {
346 /*
347 * We can expect the following formats:
348 *
349 * netconf:ip:port/path
350 * netconf:ip:port
351 */
352 String string = deviceId.toString();
353
354 /*
355 * The first ':' is the separation between the scheme and the IP.
356 *
357 * The last ':' will represent the separator between the IP and the port.
358 */
359 int first = string.indexOf(':');
360 int last = string.lastIndexOf(':');
361 String ip = string.substring(first + 1, last);
362 String port = string.substring(last + 1);
363 String path = null;
364 int pathSep = port.indexOf('/');
365 if (pathSep != -1) {
366 path = port.substring(pathSep + 1);
367 port = port.substring(0, pathSep);
368 }
369
370 return Triple.of(ip, new Integer(port),
371 (path == null || path.isEmpty() ? Optional.empty() : Optional.of(path)));
372 }
andreaeb70a942015-10-16 21:34:46 -0700373}