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