summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--appc-config/appc-config-adaptor/provider/src/main/java/org/onap/appc/ccadaptor/SshJcraftWrapper.java91
-rw-r--r--appc-config/appc-config-adaptor/provider/src/test/java/org/onap/appc/ccadaptor/SshJcraftWrapperTest.java214
2 files changed, 267 insertions, 38 deletions
diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/onap/appc/ccadaptor/SshJcraftWrapper.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/onap/appc/ccadaptor/SshJcraftWrapper.java
index 4d81b6c24..205924584 100644
--- a/appc-config/appc-config-adaptor/provider/src/main/java/org/onap/appc/ccadaptor/SshJcraftWrapper.java
+++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/onap/appc/ccadaptor/SshJcraftWrapper.java
@@ -91,6 +91,8 @@ public class SshJcraftWrapper {
private String passWord = null;
private int readIntervalMs = 500;
private int readBufferSizeBytes = 512_000;
+ private int charsChunkSize = 300_000;
+ private int sessionTimeoutMs = 9_000;
private char[] charBuffer;
private Runtime runtime = Runtime.getRuntime();
@@ -405,12 +407,19 @@ public class SshJcraftWrapper {
}
boolean isConnected() {
- return (channel != null && session != null);
+ return channel != null && session != null;
}
public void send(String cmd) throws IOException {
try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
- sendSshCommand(cmd, dos);
+ String command = enhanceCommandWithEOL(cmd);
+ int length = command.length();
+ log.debug("Sending ssh command: length={0}, payload: {1}", command.length(), command);
+ if(isCmdLengthEnoughToSendInChunks(length, charsChunkSize)) {
+ sendSshCommandInChunks(command, dos);
+ } else {
+ sendSshCommand(command, dos);
+ }
} catch (IOException e) {
log.error(Msg.SSH_DATA_EXCEPTION, e.getMessage());
throw e;
@@ -594,10 +603,11 @@ public class SshJcraftWrapper {
}
// Routine does reads until it has read 'nchars' or times out.
- public void receiveUntilBufferFlush(int ncharsSent, int timeout, String command) throws IOException {
+ public String receiveUntilBufferFlush(int ncharsSent, int timeout, String command) throws IOException {
log.debug("ncharsSent={0}, timeout={1}, message={2}", ncharsSent, timeout, command);
int ncharsTotalReceived = 0;
int ncharsRead = 0;
+ StringBuilder received = new StringBuilder();
long deadline = new Date().getTime() + timeout;
logMemoryUsage();
@@ -609,6 +619,9 @@ public class SshJcraftWrapper {
throw new TimedOutException("Routine has timed out");
}
ncharsRead = reader.read(charBuffer, 0, readBufferSizeBytes);
+ if(ncharsRead >=0) {
+ received.append(charBuffer, 0, ncharsRead);
+ }
if (listener != null) {
listener.receivedString(String.copyValueOf(charBuffer, 0, ncharsRead));
}
@@ -618,7 +631,7 @@ public class SshJcraftWrapper {
log.debug("Received the correct number of characters, ncharsSent={0}, ncharsTotalReceived={1}",
ncharsSent, ncharsTotalReceived);
logMemoryUsage();
- return;
+ return received.toString();
}
}
} catch (JSchException e) {
@@ -882,43 +895,55 @@ public class SshJcraftWrapper {
public String send(String cmd, String delimiter) throws IOException {
try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
- sendSshCommand(cmd, dos);
- return receiveUntil(delimiter, 300000, cmd);
+ String command = enhanceCommandWithEOL(cmd);
+ int length = command.length();
+ log.debug("Sending ssh command: length={0}, payload: {1}", command.length(), command);
+ if(isCmdLengthEnoughToSendInChunks(length, charsChunkSize)) {
+ return sendSshCommandInChunks(command, dos);
+ } else {
+ sendSshCommand(command, dos);
+ return receiveUntil(delimiter, 300000, cmd);
+ }
}
}
- private void sendSshCommand(@Nonnull String originalCommand, @Nonnull DataOutputStream channelOutputStream)
+ private void sendSshCommand(@Nonnull String command, @Nonnull DataOutputStream channelOutputStream)
throws IOException {
- String command = enhanceCommandWithEOL(originalCommand);
- int length = command.length(); // 2,937,706
- int charsChunkSize = 300000;
- int charsTotalSent = 0;
+ channelOutputStream.writeBytes(command);
+ channelOutputStream.flush();
+ }
- log.debug("Sending ssh command: length={0}, payload: {1}", length, command);
- if (isCmdLengthEnoughToSendInChunks(length, charsChunkSize)) {
- int timeout = 9000;
- for (int i = 0; i < length; i += charsChunkSize) {
- String commandChunk = command.substring(i, Math.min(length, i + charsChunkSize));
- int numCharsSentInChunk = commandChunk.length();
- charsTotalSent = charsTotalSent + commandChunk.length();
- log.debug("Iteration nr:{0}, sending command chunk: {1}", i, numCharsSentInChunk);
- channelOutputStream.writeBytes(commandChunk);
- channelOutputStream.flush();
- try {
- if (numCharsSentInChunk < length) {
- receiveUntilBufferFlush(numCharsSentInChunk, timeout, originalCommand);
- } else {
- log.trace("i={0}, flush immediately", i);
- channelOutputStream.flush();
- }
- } catch (IOException ex) {
- log.warn("IOException occurred: nothing to flush out", ex);
+ private String sendSshCommandInChunks(@Nonnull String command, @Nonnull DataOutputStream channelOutputStream) throws IOException {
+ StringBuilder received = new StringBuilder();
+ int charsTotalSent = 0;
+ int length = command.length();
+ for (int i = 0; i < length; i += charsChunkSize) {
+ String commandChunk = command.substring(i, Math.min(length, i + charsChunkSize));
+ int numCharsSentInChunk = commandChunk.length();
+ charsTotalSent = charsTotalSent + commandChunk.length();
+ log.debug("Iteration nr:{0}, sending command chunk: {1}", i, numCharsSentInChunk);
+ channelOutputStream.writeBytes(commandChunk);
+ channelOutputStream.flush();
+ try {
+ if (numCharsSentInChunk < length) {
+ received.append(receiveUntilBufferFlush(numCharsSentInChunk, sessionTimeoutMs, command));
+ } else {
+ log.trace("i={0}, flush immediately", i);
+ channelOutputStream.flush();
}
+ } catch (IOException ex) {
+ log.warn("IOException occurred: nothing to flush out", ex);
}
- } else {
- channelOutputStream.writeBytes(command);
}
- channelOutputStream.flush();
+ return received.toString();
+ }
+
+ public void setSessionTimeoutMs(int sessionTimeoutMs) {
+ this.sessionTimeoutMs = sessionTimeoutMs;
+ }
+
+ void setCharsChunkSize(int charsChunkSize) {
+ this.charsChunkSize = charsChunkSize;
}
private boolean isCmdLengthEnoughToSendInChunks(int length, int chunkSize) {
diff --git a/appc-config/appc-config-adaptor/provider/src/test/java/org/onap/appc/ccadaptor/SshJcraftWrapperTest.java b/appc-config/appc-config-adaptor/provider/src/test/java/org/onap/appc/ccadaptor/SshJcraftWrapperTest.java
index 76b4c628f..4047e9326 100644
--- a/appc-config/appc-config-adaptor/provider/src/test/java/org/onap/appc/ccadaptor/SshJcraftWrapperTest.java
+++ b/appc-config/appc-config-adaptor/provider/src/test/java/org/onap/appc/ccadaptor/SshJcraftWrapperTest.java
@@ -33,11 +33,14 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.ChannelSubsystem;
@@ -49,8 +52,10 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.net.URL;
+import org.apache.commons.lang.StringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
@@ -87,6 +92,8 @@ public class SshJcraftWrapperTest {
private ChannelSubsystem channelSubsystem;
@Mock
private InputStream channelIs;
+ @Mock
+ private OutputStream channelOs;
@Before
public void setUpTest() throws Exception {
@@ -121,14 +128,14 @@ public class SshJcraftWrapperTest {
public void testStripOffCmdFromRouterResponse(){
SshJcraftWrapper wrapper = new SshJcraftWrapper();
String result = wrapper.stripOffCmdFromRouterResponse("test\nsuccess");
- Assert.assertEquals("success\n", result);
+ Assert.assertEquals("success\n", result);
}
-
+
//@Test
public void testGetLastFewLinesOfFile() throws FileNotFoundException, IOException{
SshJcraftWrapper wrapper = new SshJcraftWrapper();
URL path = SshJcraftWrapperTest.class.getResource("Test");
- File file = new File(path.getFile());
+ File file = new File(path.getFile());
String value = wrapper.getLastFewLinesOfFile(file,1);
Assert.assertEquals("\nTest data 3", value);
}
@@ -137,7 +144,7 @@ public class SshJcraftWrapperTest {
@Test(expected=Exception.class)
public void testSetRouterCommandType() throws IOException{
SshJcraftWrapper wrapper = new SshJcraftWrapper();
- wrapper.setRouterCommandType("test");
+ wrapper.setRouterCommandType("test");
wrapper.receiveUntil("test", 2, "test");
}
@@ -164,7 +171,7 @@ public class SshJcraftWrapperTest {
StringBuilder sb = new StringBuilder();
sb.append("test");
wrapper.appendToRouterFile("Test.txt", sb);
- wrapper.receiveUntilBufferFlush(3, 4, "test");
+ wrapper.receiveUntilBufferFlush(3, 4, "test");
}
@Ignore
@@ -680,4 +687,201 @@ public class SshJcraftWrapperTest {
assertTrue(file.isFile());
}
+ @Test
+ public void send_withReceive_shouldWriteCommandToChannelOutputStream_andReturnReceivedCommand() throws Exception {
+ //given
+ String command = "sdc";
+ String delimiter = ":";
+ InOrder inOrder = inOrder(channelOs);
+ provideConnectedSubsystemInstanceWithStreamContent(command+delimiter);
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+
+ //when
+ String result = cut.send(command, delimiter);
+
+ //then
+ verifySdcCommandSent(inOrder);
+ assertEquals(command+delimiter, result);
+ }
+
+ @Test
+ public void send_shouldWriteCommandToChannelOutputStream() throws Exception {
+ //given
+ String command = "sdc";
+ InOrder inOrder = inOrder(channelOs);
+ provideConnectedSubsystemInstance();
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+
+ //when
+ cut.send(command);
+
+ //then
+ verifySdcCommandSent(inOrder);
+ }
+
+ private void verifySdcCommandSent(InOrder inOrder) throws IOException {
+ inOrder.verify(channelOs).write('s');
+ inOrder.verify(channelOs).write('d');
+ inOrder.verify(channelOs).write('c');
+ inOrder.verify(channelOs, atLeastOnce()).flush();
+ inOrder.verify(channelOs, atLeastOnce()).close();
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void send_withReceive_shouldWriteCommandInChunksToChannelOutputStream_andReturnReceivedCommand() throws Exception {
+ //given
+ cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+ cut.setCharsChunkSize(1);
+ String command = "sdc";
+ String delimiter = ":";
+ int timeout = 9000;
+ provideConnectedSubsystemInstanceWithStreamContent(command+delimiter+SshJcraftWrapper.EOL);
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+ InOrder inOrder = inOrder(channelOs, session);
+
+ //when
+ String result = cut.send(command, delimiter);
+
+ //then
+ verifySdcCommandSentInChunk(inOrder, timeout);
+ assertEquals(command+delimiter, result);
+ }
+
+ @Test
+ public void send_shouldWriteCommandInChunksToChannelOutputStream() throws Exception {
+ //given
+ cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+ cut.setCharsChunkSize(1);
+ String command = "sdc";
+ int timeout = 9000;
+ provideConnectedSubsystemInstanceWithStreamContent(command+SshJcraftWrapper.EOL);
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+ InOrder inOrder = inOrder(channelOs, session);
+
+ //when
+ cut.send(command);
+
+ //then
+ verifySdcCommandSentInChunk(inOrder, timeout);
+ }
+
+ private void verifySdcCommandSentInChunk(InOrder inOrder, int timeout) throws Exception{
+ inOrder.verify(channelOs).write('s');
+ inOrder.verify(channelOs).flush();
+ inOrder.verify(session).setTimeout(timeout);
+ inOrder.verify(channelOs).write('d');
+ inOrder.verify(channelOs).flush();
+ inOrder.verify(session).setTimeout(timeout);
+ inOrder.verify(channelOs).write('c');
+ inOrder.verify(channelOs).flush();
+ inOrder.verify(session).setTimeout(timeout);
+ inOrder.verify(channelOs, atLeastOnce()).flush();
+ inOrder.verify(channelOs, atLeastOnce()).close();
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void send_withReceive_shouldReturnActualResult_whenTimeoutReached() throws Exception {
+ //given
+ cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+ cut.setCharsChunkSize(1);
+ cut.setSessionTimeoutMs(-1);
+ String command = "sdc";
+ String delimiter = ":";
+ provideConnectedSubsystemInstanceWithStreamContent(command+SshJcraftWrapper.EOL);
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+
+ //when
+ String result = cut.send(command, delimiter);
+
+ //then
+ assertEquals(StringUtils.EMPTY, result);
+ }
+
+ @Test
+ public void send_withReceive_shouldReturnActualResult_whenCouldNotSetSessionTimeout() throws Exception {
+ //given
+ cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+ cut.setCharsChunkSize(1);
+ String command = "sdc";
+ String delimiter = ":";
+ provideConnectedSubsystemInstanceWithStreamContent(command+SshJcraftWrapper.EOL);
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+ doThrow(new JSchException("failed to set session timeout")).when(session).setTimeout(anyInt());
+
+ //when
+ String result = cut.send(command, delimiter);
+
+ //then
+ assertEquals(StringUtils.EMPTY, result);
+ }
+
+ @Test
+ public void sendChar_shouldWriteCharacterToChannelOutputStream() throws Exception {
+ //given
+ int charNum = 100;
+ provideConnectedSubsystemInstance();
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+ InOrder inOrder = inOrder(channelOs);
+
+ //when
+ cut.sendChar(charNum);
+
+ //then
+ inOrder.verify(channelOs).write(charNum);
+ inOrder.verify(channelOs, atLeastOnce()).flush();
+ inOrder.verify(channelOs, atLeastOnce()).close();
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test(expected = IOException.class)
+ public void sendChar_shouldRethrowIOException_whenOccurs() throws Exception {
+ //given
+ int charNum = 100;
+ provideConnectedSubsystemInstance();
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+ doThrow(new IOException()).when(channelOs).write(charNum);
+
+ //when
+ cut.sendChar(charNum);
+
+ //then
+ fail("IOException should be thrown");
+ }
+
+ @Test
+ public void send_withByteBuffer_shouldWriteBufferToChannelOutputStream() throws Exception {
+ //given
+ byte[] buffer = "Command".getBytes();
+ int offset = 5;
+ provideConnectedSubsystemInstance();
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+ InOrder inOrder = inOrder(channelOs);
+
+ //when
+ cut.send(buffer,offset,buffer.length);
+
+ //then
+ inOrder.verify(channelOs).write(buffer, offset, buffer.length);
+ inOrder.verify(channelOs, atLeastOnce()).flush();
+ inOrder.verify(channelOs, atLeastOnce()).close();
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test(expected = IOException.class)
+ public void send_withByteBuffer_shouldRethrowIOException_whenOccurs() throws Exception {
+ //given
+ byte[] buffer = "Command".getBytes();
+ int offset = 5;
+ provideConnectedSubsystemInstance();
+ given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+ doThrow(new IOException()).when(channelOs).write(buffer, offset, buffer.length);
+
+ //when
+ cut.send(buffer,offset,buffer.length);
+
+ //then
+ fail("IOException should be thrown");
+ }
}