blob: 53693352657854388692b857ded2e5e404fc2ad4 [file] [log] [blame]
andreaeb70a942015-10-16 21:34:46 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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.ctl;
18
19import ch.ethz.ssh2.Connection;
20import ch.ethz.ssh2.Session;
21import com.google.common.base.Preconditions;
22import org.onosproject.netconf.NetconfDeviceInfo;
Andrea Campanella101417d2015-12-11 17:58:07 -080023import org.onosproject.netconf.NetconfDeviceOutputEvent;
24import org.onosproject.netconf.NetconfDeviceOutputEventListener;
25import org.onosproject.netconf.NetconfException;
andreaeb70a942015-10-16 21:34:46 -070026import org.onosproject.netconf.NetconfSession;
27import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
29
andreaeb70a942015-10-16 21:34:46 -070030import java.io.IOException;
Andreas Papazoisd4712e22016-02-10 15:59:55 +020031import java.util.ArrayList;
Andrea Campanella1cd641b2015-12-07 17:28:34 -080032import java.util.Collections;
Andrea Campanella101417d2015-12-11 17:58:07 -080033import java.util.HashMap;
andreaeb70a942015-10-16 21:34:46 -070034import java.util.List;
Andrea Campanella101417d2015-12-11 17:58:07 -080035import java.util.Map;
Andreas Papazoisd4712e22016-02-10 15:59:55 +020036import java.util.Optional;
Andrea Campanella101417d2015-12-11 17:58:07 -080037import java.util.concurrent.CompletableFuture;
Andrea Campanellab029b9e2016-01-29 11:05:36 -080038import java.util.concurrent.ExecutionException;
39import java.util.concurrent.TimeUnit;
40import java.util.concurrent.TimeoutException;
Andrea Campanella101417d2015-12-11 17:58:07 -080041import java.util.concurrent.atomic.AtomicInteger;
42
andreaeb70a942015-10-16 21:34:46 -070043
44/**
45 * Implementation of a NETCONF session to talk to a device.
46 */
47public class NetconfSessionImpl implements NetconfSession {
48
Andrea Campanella101417d2015-12-11 17:58:07 -080049 private static final Logger log = LoggerFactory
andreaeb70a942015-10-16 21:34:46 -070050 .getLogger(NetconfSessionImpl.class);
Andrea Campanella101417d2015-12-11 17:58:07 -080051
52
andreaeb70a942015-10-16 21:34:46 -070053 private static final int CONNECTION_TIMEOUT = 0;
Andrea Campanella101417d2015-12-11 17:58:07 -080054 private static final String ENDPATTERN = "]]>]]>";
Andrea Campanella101417d2015-12-11 17:58:07 -080055 private static final String MESSAGE_ID_STRING = "message-id";
56 private static final String HELLO = "hello";
57 private static final String NEW_LINE = "\n";
Andrea Campanellab029b9e2016-01-29 11:05:36 -080058 private static final int FUTURE_REPLY_TIMEOUT = 5000;
59 private static final String ERROR = "ERROR ";
60 private static final String END_OF_RPC_OPEN_TAG = "\">";
61 private static final String EQUAL = "=";
62 private static final String NUMBER_BETWEEN_QUOTES_MATCHER = "\"+([0-9]+)+\"";
63 private static final String XML_HEADER =
64 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
andreaeb70a942015-10-16 21:34:46 -070065
Andrea Campanellab029b9e2016-01-29 11:05:36 -080066 private final AtomicInteger messageIdInteger = new AtomicInteger(0);
andreaeb70a942015-10-16 21:34:46 -070067 private Connection netconfConnection;
68 private NetconfDeviceInfo deviceInfo;
69 private Session sshSession;
70 private boolean connectionActive;
andreaeb70a942015-10-16 21:34:46 -070071 private List<String> deviceCapabilities =
Andrea Campanella1cd641b2015-12-07 17:28:34 -080072 Collections.singletonList("urn:ietf:params:netconf:base:1.0");
andreaeb70a942015-10-16 21:34:46 -070073 private String serverCapabilities;
Andrea Campanella101417d2015-12-11 17:58:07 -080074 private NetconfStreamHandler t;
75 private Map<Integer, CompletableFuture<String>> replies;
Andreas Papazoisd4712e22016-02-10 15:59:55 +020076 private List<String> errorReplies;
andreaeb70a942015-10-16 21:34:46 -070077
78
Andrea Campanella101417d2015-12-11 17:58:07 -080079 public NetconfSessionImpl(NetconfDeviceInfo deviceInfo) throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -070080 this.deviceInfo = deviceInfo;
81 connectionActive = false;
Andrea Campanella101417d2015-12-11 17:58:07 -080082 replies = new HashMap<>();
Andreas Papazoisd4712e22016-02-10 15:59:55 +020083 errorReplies = new ArrayList<>();
andreaeb70a942015-10-16 21:34:46 -070084 startConnection();
85 }
86
87
Andrea Campanella101417d2015-12-11 17:58:07 -080088 private void startConnection() throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -070089 if (!connectionActive) {
90 netconfConnection = new Connection(deviceInfo.ip().toString(), deviceInfo.port());
Andrea Campanella101417d2015-12-11 17:58:07 -080091 try {
92 netconfConnection.connect(null, CONNECTION_TIMEOUT, 5000);
93 } catch (IOException e) {
94 throw new NetconfException("Cannot open a connection with device" + deviceInfo, e);
95 }
andreaeb70a942015-10-16 21:34:46 -070096 boolean isAuthenticated;
97 try {
98 if (deviceInfo.getKeyFile() != null) {
99 isAuthenticated = netconfConnection.authenticateWithPublicKey(
100 deviceInfo.name(), deviceInfo.getKeyFile(),
101 deviceInfo.password());
102 } else {
Andrea Campanella101417d2015-12-11 17:58:07 -0800103 log.debug("Authenticating to device {} with username {}",
Andrea Campanella50d25212016-02-26 13:06:23 -0800104 deviceInfo.getDeviceId(), deviceInfo.name());
andreaeb70a942015-10-16 21:34:46 -0700105 isAuthenticated = netconfConnection.authenticateWithPassword(
106 deviceInfo.name(), deviceInfo.password());
107 }
108 } catch (IOException e) {
Andrea Campanella101417d2015-12-11 17:58:07 -0800109 log.error("Authentication connection to device " +
110 deviceInfo.getDeviceId() + " failed:" +
111 e.getMessage());
112 throw new NetconfException("Authentication connection to device " +
113 deviceInfo.getDeviceId() + " failed", e);
andreaeb70a942015-10-16 21:34:46 -0700114 }
115
116 connectionActive = true;
117 Preconditions.checkArgument(isAuthenticated,
Andrea Campanella101417d2015-12-11 17:58:07 -0800118 "Authentication to device {} with username " +
119 "{} Failed",
Andrea Campanella50d25212016-02-26 13:06:23 -0800120 deviceInfo.getDeviceId(), deviceInfo.name());
andreaeb70a942015-10-16 21:34:46 -0700121 startSshSession();
122 }
123 }
124
Andrea Campanella101417d2015-12-11 17:58:07 -0800125 private void startSshSession() throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -0700126 try {
127 sshSession = netconfConnection.openSession();
128 sshSession.startSubSystem("netconf");
Andrea Campanella101417d2015-12-11 17:58:07 -0800129 t = new NetconfStreamThread(sshSession.getStdout(), sshSession.getStdin(),
130 sshSession.getStderr(), deviceInfo,
131 new NetconfSessionDelegateImpl());
132 this.addDeviceOutputListener(new NetconfDeviceOutputEventListenerImpl(deviceInfo));
andreaeb70a942015-10-16 21:34:46 -0700133 sendHello();
134 } catch (IOException e) {
Andrea Campanella101417d2015-12-11 17:58:07 -0800135 log.error("Failed to create ch.ethz.ssh2.Session session:" +
136 e.getMessage());
137 throw new NetconfException("Failed to create ch.ethz.ssh2.Session session with device" +
138 deviceInfo, e);
andreaeb70a942015-10-16 21:34:46 -0700139 }
140 }
141
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800142 private void sendHello() throws NetconfException {
Andrea Campanella101417d2015-12-11 17:58:07 -0800143 serverCapabilities = sendRequest(createHelloString());
andreaeb70a942015-10-16 21:34:46 -0700144 }
145
146 private String createHelloString() {
147 StringBuilder hellobuffer = new StringBuilder();
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800148 hellobuffer.append(XML_HEADER);
149 hellobuffer.append("\n");
andreaeb70a942015-10-16 21:34:46 -0700150 hellobuffer.append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
151 hellobuffer.append(" <capabilities>\n");
152 deviceCapabilities.forEach(
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800153 cap -> hellobuffer.append(" <capability>")
154 .append(cap)
155 .append("</capability>\n"));
andreaeb70a942015-10-16 21:34:46 -0700156 hellobuffer.append(" </capabilities>\n");
157 hellobuffer.append("</hello>\n");
Andrea Campanella101417d2015-12-11 17:58:07 -0800158 hellobuffer.append(ENDPATTERN);
andreaeb70a942015-10-16 21:34:46 -0700159 return hellobuffer.toString();
160
161 }
162
Andrea Campanella101417d2015-12-11 17:58:07 -0800163 private void checkAndRestablishSession() throws NetconfException {
Andrea Campanella1cd641b2015-12-07 17:28:34 -0800164 if (sshSession.getState() != 2) {
165 try {
166 startSshSession();
167 } catch (IOException e) {
Andrea Campanella101417d2015-12-11 17:58:07 -0800168 log.debug("The connection with {} had to be reopened", deviceInfo.getDeviceId());
Andrea Campanella1cd641b2015-12-07 17:28:34 -0800169 try {
170 startConnection();
171 } catch (IOException e2) {
Andrea Campanella50d25212016-02-26 13:06:23 -0800172 log.error("No connection {} for device", netconfConnection, e2);
Andrea Campanella101417d2015-12-11 17:58:07 -0800173 throw new NetconfException("Cannot re-open the connection with device" + deviceInfo, e);
Andrea Campanella1cd641b2015-12-07 17:28:34 -0800174 }
175 }
176 }
177 }
178
andreaeb70a942015-10-16 21:34:46 -0700179 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800180 public String requestSync(String request) throws NetconfException {
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800181 if (!request.contains(ENDPATTERN)) {
182 request = request + NEW_LINE + ENDPATTERN;
183 }
184 String reply = sendRequest(request);
185 return checkReply(reply) ? reply : ERROR + reply;
andreaeb70a942015-10-16 21:34:46 -0700186 }
187
188 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800189 public CompletableFuture<String> request(String request) {
190 CompletableFuture<String> ftrep = t.sendMessage(request);
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800191 replies.put(messageIdInteger.get(), ftrep);
Andrea Campanella101417d2015-12-11 17:58:07 -0800192 return ftrep;
193 }
194
195 private String sendRequest(String request) throws NetconfException {
196 checkAndRestablishSession();
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800197 request = formatRequestMessageId(request);
198 request = formatXmlHeader(request);
Andrea Campanella101417d2015-12-11 17:58:07 -0800199 CompletableFuture<String> futureReply = request(request);
Andreas Papazoisd4712e22016-02-10 15:59:55 +0200200 messageIdInteger.incrementAndGet();
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800201 String rp;
202 try {
203 rp = futureReply.get(FUTURE_REPLY_TIMEOUT, TimeUnit.MILLISECONDS);
204 } catch (InterruptedException | ExecutionException | TimeoutException e) {
Andreas Papazoisd4712e22016-02-10 15:59:55 +0200205 throw new NetconfException("No matching reply for request " + request, e);
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800206 }
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800207 log.debug("Result {} from request {} to device {}", rp, request, deviceInfo);
Andrea Campanella50d25212016-02-26 13:06:23 -0800208 return rp.trim();
Andrea Campanella101417d2015-12-11 17:58:07 -0800209 }
210
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800211 private String formatRequestMessageId(String request) {
212 if (request.contains(MESSAGE_ID_STRING)) {
213 //FIXME if application provieds his own counting of messages this fails that count
214 request = request.replaceFirst(MESSAGE_ID_STRING + EQUAL + NUMBER_BETWEEN_QUOTES_MATCHER,
215 MESSAGE_ID_STRING + EQUAL + "\"" + messageIdInteger.get() + "\"");
216 } else if (!request.contains(MESSAGE_ID_STRING) && !request.contains(HELLO)) {
217 //FIXME find out a better way to enforce the presence of message-id
218 request = request.replaceFirst(END_OF_RPC_OPEN_TAG, "\" " + MESSAGE_ID_STRING + EQUAL + "\""
219 + messageIdInteger.get() + "\"" + ">");
220 }
221 return request;
222 }
223
224 private String formatXmlHeader(String request) {
225 if (!request.contains(XML_HEADER)) {
226 //FIXME if application provieds his own XML header of different type there is a clash
227 request = XML_HEADER + "\n" + request;
228 }
229 return request;
230 }
231
Andrea Campanella101417d2015-12-11 17:58:07 -0800232 @Override
233 public String get(String request) throws NetconfException {
234 return requestSync(request);
235 }
236
237 @Override
238 public String getConfig(String targetConfiguration) throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -0700239 return getConfig(targetConfiguration, null);
240 }
241
242 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800243 public String getConfig(String targetConfiguration, String configurationSchema) throws NetconfException {
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800244 StringBuilder rpc = new StringBuilder(XML_HEADER);
245 rpc.append("<rpc ");
246 rpc.append(MESSAGE_ID_STRING);
247 rpc.append(EQUAL);
248 rpc.append("\"");
249 rpc.append(messageIdInteger.get());
250 rpc.append("\" ");
251 rpc.append("xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
andreaeb70a942015-10-16 21:34:46 -0700252 rpc.append("<get-config>\n");
253 rpc.append("<source>\n");
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800254 rpc.append("<").append(targetConfiguration).append("/>");
andreaeb70a942015-10-16 21:34:46 -0700255 rpc.append("</source>");
256 if (configurationSchema != null) {
257 rpc.append("<filter type=\"subtree\">\n");
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800258 rpc.append(configurationSchema).append("\n");
andreaeb70a942015-10-16 21:34:46 -0700259 rpc.append("</filter>\n");
260 }
261 rpc.append("</get-config>\n");
262 rpc.append("</rpc>\n");
Andrea Campanella101417d2015-12-11 17:58:07 -0800263 rpc.append(ENDPATTERN);
264 String reply = sendRequest(rpc.toString());
Andrea Campanella1cd641b2015-12-07 17:28:34 -0800265 return checkReply(reply) ? reply : "ERROR " + reply;
andreaeb70a942015-10-16 21:34:46 -0700266 }
267
268 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800269 public boolean editConfig(String newConfiguration) throws NetconfException {
270 newConfiguration = newConfiguration + ENDPATTERN;
271 return checkReply(sendRequest(newConfiguration));
andreaeb70a942015-10-16 21:34:46 -0700272 }
273
274 @Override
Andrea Campanellaf4fd0352015-12-14 17:03:05 -0800275 public boolean editConfig(String targetConfiguration, String mode, String newConfiguration)
Andrea Campanella101417d2015-12-11 17:58:07 -0800276 throws NetconfException {
Andrea Campanellaf4fd0352015-12-14 17:03:05 -0800277 newConfiguration = newConfiguration.trim();
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800278 StringBuilder rpc = new StringBuilder(XML_HEADER);
279 rpc.append("<rpc ");
280 rpc.append(MESSAGE_ID_STRING);
281 rpc.append(EQUAL);
282 rpc.append("\"");
283 rpc.append(messageIdInteger.get());
284 rpc.append("\" ");
285 rpc.append("xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n");
Andrea Campanella50d25212016-02-26 13:06:23 -0800286 rpc.append("<edit-config>\n");
Andrea Campanellaf4fd0352015-12-14 17:03:05 -0800287 rpc.append("<target>");
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800288 rpc.append("<").append(targetConfiguration).append("/>");
Andrea Campanella50d25212016-02-26 13:06:23 -0800289 rpc.append("</target>\n");
Andrea Campanellaf4fd0352015-12-14 17:03:05 -0800290 rpc.append("<default-operation>");
291 rpc.append(mode);
Andrea Campanella50d25212016-02-26 13:06:23 -0800292 rpc.append("</default-operation>\n");
293 rpc.append("<config>\n");
Andrea Campanellaf4fd0352015-12-14 17:03:05 -0800294 rpc.append(newConfiguration);
Andrea Campanella50d25212016-02-26 13:06:23 -0800295 rpc.append("</config>\n");
296 rpc.append("</edit-config>\n");
Andrea Campanellaf4fd0352015-12-14 17:03:05 -0800297 rpc.append("</rpc>");
Andrea Campanella101417d2015-12-11 17:58:07 -0800298 rpc.append(ENDPATTERN);
Andrea Campanella50d25212016-02-26 13:06:23 -0800299 log.info(rpc.toString());
Andrea Campanella101417d2015-12-11 17:58:07 -0800300 return checkReply(sendRequest(rpc.toString()));
Andrea Campanellaf4fd0352015-12-14 17:03:05 -0800301 }
302
303 @Override
Andrea Campanella1cd641b2015-12-07 17:28:34 -0800304 public boolean copyConfig(String targetConfiguration, String newConfiguration)
Andrea Campanella101417d2015-12-11 17:58:07 -0800305 throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -0700306 newConfiguration = newConfiguration.trim();
307 if (!newConfiguration.startsWith("<configuration>")) {
308 newConfiguration = "<configuration>" + newConfiguration
309 + "</configuration>";
310 }
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800311 StringBuilder rpc = new StringBuilder(XML_HEADER);
andreaeb70a942015-10-16 21:34:46 -0700312 rpc.append("<rpc>");
313 rpc.append("<copy-config>");
314 rpc.append("<target>");
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800315 rpc.append("<").append(targetConfiguration).append("/>");
andreaeb70a942015-10-16 21:34:46 -0700316 rpc.append("</target>");
317 rpc.append("<source>");
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800318 rpc.append("<").append(newConfiguration).append("/>");
andreaeb70a942015-10-16 21:34:46 -0700319 rpc.append("</source>");
320 rpc.append("</copy-config>");
321 rpc.append("</rpc>");
Andrea Campanella101417d2015-12-11 17:58:07 -0800322 rpc.append(ENDPATTERN);
323 return checkReply(sendRequest(rpc.toString()));
andreaeb70a942015-10-16 21:34:46 -0700324 }
325
326 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800327 public boolean deleteConfig(String targetConfiguration) throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -0700328 if (targetConfiguration.equals("running")) {
329 log.warn("Target configuration for delete operation can't be \"running\"",
330 targetConfiguration);
331 return false;
332 }
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800333 StringBuilder rpc = new StringBuilder(XML_HEADER);
andreaeb70a942015-10-16 21:34:46 -0700334 rpc.append("<rpc>");
335 rpc.append("<delete-config>");
336 rpc.append("<target>");
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800337 rpc.append("<").append(targetConfiguration).append("/>");
andreaeb70a942015-10-16 21:34:46 -0700338 rpc.append("</target>");
339 rpc.append("</delete-config>");
340 rpc.append("</rpc>");
Andrea Campanella101417d2015-12-11 17:58:07 -0800341 rpc.append(ENDPATTERN);
342 return checkReply(sendRequest(rpc.toString()));
andreaeb70a942015-10-16 21:34:46 -0700343 }
344
345 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800346 public boolean lock() throws NetconfException {
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800347 StringBuilder rpc = new StringBuilder(XML_HEADER);
andreaeb70a942015-10-16 21:34:46 -0700348 rpc.append("<rpc>");
349 rpc.append("<lock>");
350 rpc.append("<target>");
351 rpc.append("<candidate/>");
352 rpc.append("</target>");
353 rpc.append("</lock>");
354 rpc.append("</rpc>");
Andrea Campanella101417d2015-12-11 17:58:07 -0800355 rpc.append(ENDPATTERN);
356 return checkReply(sendRequest(rpc.toString()));
andreaeb70a942015-10-16 21:34:46 -0700357 }
358
359 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800360 public boolean unlock() throws NetconfException {
Andrea Campanellab029b9e2016-01-29 11:05:36 -0800361 StringBuilder rpc = new StringBuilder(XML_HEADER);
andreaeb70a942015-10-16 21:34:46 -0700362 rpc.append("<rpc>");
363 rpc.append("<unlock>");
364 rpc.append("<target>");
365 rpc.append("<candidate/>");
366 rpc.append("</target>");
367 rpc.append("</unlock>");
368 rpc.append("</rpc>");
Andrea Campanella101417d2015-12-11 17:58:07 -0800369 rpc.append(ENDPATTERN);
370 return checkReply(sendRequest(rpc.toString()));
andreaeb70a942015-10-16 21:34:46 -0700371 }
372
373 @Override
Andrea Campanella101417d2015-12-11 17:58:07 -0800374 public boolean close() throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -0700375 return close(false);
376 }
377
Andrea Campanella101417d2015-12-11 17:58:07 -0800378 private boolean close(boolean force) throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -0700379 StringBuilder rpc = new StringBuilder();
380 rpc.append("<rpc>");
381 if (force) {
382 rpc.append("<kill-configuration/>");
383 } else {
384 rpc.append("<close-configuration/>");
385 }
386 rpc.append("<close-configuration/>");
387 rpc.append("</rpc>");
Andrea Campanella101417d2015-12-11 17:58:07 -0800388 rpc.append(ENDPATTERN);
389 return checkReply(sendRequest(rpc.toString())) || close(true);
andreaeb70a942015-10-16 21:34:46 -0700390 }
391
392 @Override
393 public String getSessionId() {
394 if (serverCapabilities.contains("<session-id>")) {
395 String[] outer = serverCapabilities.split("<session-id>");
396 Preconditions.checkArgument(outer.length != 1,
397 "Error in retrieving the session id");
398 String[] value = outer[1].split("</session-id>");
399 Preconditions.checkArgument(value.length != 1,
400 "Error in retrieving the session id");
401 return value[0];
402 } else {
403 return String.valueOf(-1);
404 }
405 }
406
407 @Override
408 public String getServerCapabilities() {
409 return serverCapabilities;
410 }
411
412 @Override
413 public void setDeviceCapabilities(List<String> capabilities) {
414 deviceCapabilities = capabilities;
415 }
416
Andrea Campanella101417d2015-12-11 17:58:07 -0800417 @Override
418 public void addDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
419 t.addDeviceEventListener(listener);
420 }
421
422 @Override
423 public void removeDeviceOutputListener(NetconfDeviceOutputEventListener listener) {
424 t.removeDeviceEventListener(listener);
425 }
426
427 private boolean checkReply(String reply) throws NetconfException {
andreaeb70a942015-10-16 21:34:46 -0700428 if (reply != null) {
429 if (!reply.contains("<rpc-error>")) {
430 return true;
431 } else if (reply.contains("<ok/>")
432 || (reply.contains("<rpc-error>")
433 && reply.contains("warning"))) {
434 return true;
435 }
436 }
Andrea Campanella101417d2015-12-11 17:58:07 -0800437 log.warn("Device " + deviceInfo + "has error in reply {}", reply);
andreaeb70a942015-10-16 21:34:46 -0700438 return false;
439 }
440
Andrea Campanella101417d2015-12-11 17:58:07 -0800441 public class NetconfSessionDelegateImpl implements NetconfSessionDelegate {
andreaeb70a942015-10-16 21:34:46 -0700442
Andrea Campanella101417d2015-12-11 17:58:07 -0800443 @Override
Andreas Papazoisd4712e22016-02-10 15:59:55 +0200444 public void notify(NetconfDeviceOutputEvent event) {
445 Optional<Integer> messageId = event.getMessageID();
446 if (!messageId.isPresent()) {
447 errorReplies.add(event.getMessagePayload());
448 log.error("Device " + event.getDeviceInfo() +
449 " sent error reply " + event.getMessagePayload());
450 return;
451 }
452 CompletableFuture<String> completedReply =
453 replies.get(messageId.get());
Andrea Campanella101417d2015-12-11 17:58:07 -0800454 completedReply.complete(event.getMessagePayload());
andreaeb70a942015-10-16 21:34:46 -0700455 }
456 }
andreaeb70a942015-10-16 21:34:46 -0700457}