1632ba70f8e1b5db41f4d68c400a951566e9b6bd
[appc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : APP-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                                              reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.openecomp.appc.adapter.netconf.jsch;
23
24 import com.jcraft.jsch.Channel;
25 import com.jcraft.jsch.ChannelSubsystem;
26 import com.jcraft.jsch.JSch;
27 import com.jcraft.jsch.Session;
28
29 import java.io.IOException;
30 import java.util.List;
31 import java.util.Properties;
32
33 import org.openecomp.appc.adapter.netconf.NetconfClient;
34 import org.openecomp.appc.adapter.netconf.NetconfConnectionDetails;
35 import org.openecomp.appc.adapter.netconf.internal.NetconfAdapter;
36 import org.openecomp.appc.adapter.netconf.internal.NetconfConstMessages;
37 import org.openecomp.appc.encryption.EncryptionTool;
38 import org.openecomp.appc.exceptions.APPCException;
39 import org.openecomp.appc.i18n.Msg;
40 import com.att.eelf.i18n.EELFResourceManager;
41
42 /**
43  * Implementation of NetconfClient interface based on JCraft jsch library.
44  */
45 public class NetconfClientJsch implements NetconfClient {
46
47     private static final int SESSION_CONNECT_TIMEOUT = 30000;
48     private static final int CHANNEL_CONNECT_TIMEOUT = 10000;
49
50     private Session session;
51     private Channel channel;
52     private NetconfAdapter netconfAdapter;
53
54
55     @Override
56     public void connect(NetconfConnectionDetails connectionDetails) throws APPCException {
57         String host = connectionDetails.getHost();
58         int port = connectionDetails.getPort();
59         String username = connectionDetails.getUsername();
60         String password = connectionDetails.getPassword();
61         try {
62             JSch.setLogger(new JSchLogger());
63             JSch jsch = new JSch();
64             session = jsch.getSession(EncryptionTool.getInstance().decrypt(username), host, port);
65             session.setPassword(EncryptionTool.getInstance().decrypt(password));
66             session.setConfig("StrictHostKeyChecking", "no");
67
68             Properties additionalProps = connectionDetails.getAdditionalProperties();
69             if((additionalProps != null) && !additionalProps.isEmpty()) {
70                 session.setConfig(additionalProps);
71             }
72
73             session.connect(SESSION_CONNECT_TIMEOUT);
74             session.setTimeout(10000);
75             try {
76 //                session.setServerAliveCountMax(0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
77                 channel = session.openChannel("subsystem");
78                 ((ChannelSubsystem)channel).setSubsystem("netconf");
79                 netconfAdapter = new NetconfAdapter(channel.getInputStream(), channel.getOutputStream());
80                 channel.connect(CHANNEL_CONNECT_TIMEOUT);
81                 hello(connectionDetails.getCapabilities());
82             } catch(Exception e) {
83                 disconnect();
84                 throw e;
85             }
86         } catch(Exception e) {
87             String message = EELFResourceManager.format(Msg.CANNOT_ESTABLISH_CONNECTION, host, String.valueOf(port), username);
88             throw new APPCException(message, e);
89         }
90     }
91
92     @Override
93     public String exchangeMessage(String message) throws APPCException {
94         try {
95             netconfAdapter.sendMessage(message);
96             return netconfAdapter.receiveMessage();
97         } catch(IOException e) {
98             throw new APPCException(e);
99         }
100     }
101
102     @Override
103     public void configure(String configuration) throws APPCException {
104         try {
105             isOk(exchangeMessage(configuration));
106         } catch(IOException e) {
107             throw new APPCException(e);
108         }
109     }
110
111     @Override
112     public String getConfiguration() throws APPCException {
113         return exchangeMessage(NetconfConstMessages.GET_RUNNING_CONFIG);
114     }
115
116     @Override
117     public void disconnect() {
118         try {
119             if((channel != null) && !channel.isClosed()) {
120                 netconfAdapter.sendMessage(NetconfConstMessages.CLOSE_SESSION);
121                 isOk(netconfAdapter.receiveMessage());
122             }
123         } catch(IOException e) {
124             throw new RuntimeException("Error closing netconf device", e);
125         } finally {
126             netconfAdapter = null;
127             if(channel != null) {
128                 channel.disconnect();
129                 channel = null;
130             }
131             if(session != null) {
132                 session.disconnect();
133                 session = null;
134             }
135         }
136     }
137
138     private void hello(List<String> capabilities) throws IOException {
139         String helloIn = netconfAdapter.receiveMessage();
140         if(helloIn == null) {
141             throw new IOException("Expected hello message, but nothing received error from netconf device");
142         }
143         if(helloIn.contains("<rpc-error>")) {
144             throw new IOException("Expected hello message, but received error from netconf device:\n" + helloIn);
145         }
146         StringBuilder sb = new StringBuilder();
147         sb.append(NetconfConstMessages.CAPABILITIES_START);
148         sb.append(NetconfConstMessages.CAPABILITIES_BASE);
149         if(capabilities != null) {
150             for(String capability: capabilities) {
151                 sb.append("    ").append(capability).append("\n");
152             }
153         }
154         sb.append(NetconfConstMessages.CAPABILITIES_END);
155         String helloOut = sb.toString();
156         netconfAdapter.sendMessage(helloOut);
157     }
158
159     private void isOk(String response) throws IOException {
160         if(response == null) {
161             throw new IOException("No response from netconf device");
162         }
163         if(!response.contains("<ok/>")) {
164             throw new IOException("Error response from netconf device: \n" + response);
165         }
166     }
167 }