Configure Cisco Routers/Switches Using SSH
I have some use cases where SSH is used to configure Cisco routers/switches. For example, to enable a WAN interface, the following commands are executed:en password configure terminal int Fa0/0/0 ip address 172.0.0.1255.255.255.252 description Link to 408 bandwidth 8000 service-policy output shape-8Mb no shutdown end copy run start exit
Apache Camel SSH Component
Apache Camel has a SSH component. However, I found that it did not work when configuring Cisco routers/switches.The problem is that it cannot execute the "en password" command.
Ganymed SSH2 Library
Fortunately I could solve it by using another SSH library called Ganymed.The following is the code I used to execute IOS commands.
private static final String PROMPT_SYMBOL = "%"; private static final char ERROR_SYMBOL = '^'; private static final String ACCESS_DENIED_MESSAGE = "Access denied"; private static final int MAX_OUTPUT_BUFFER_SIZE = 1024 * 1024; public void executeCommand(String host, String username, String password, int timeout, String command) throws IOException, AccessDeniedException { Connection connection = new Connection(host); connection.connect(null, timeout, timeout); boolean authenticated = connection.authenticateWithPassword(username, password); if (!authenticated) return; Session session = connection.openSession(); session.startShell(); executeCommand(session, timeout, command); }
private SshResponse executeCommand(Session session, int timeout, String command) throws IOException, AccessDeniedException { OutputStream in = session.getStdin(); in.write(command.getBytes()); InputStream stdout = session.getStdout(); InputStream stderr = session.getStderr(); StringBuilder sb = new StringBuilder(); boolean valid = false; String line = null; boolean flag = true; while (flag) { int conditions = session.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, timeout); if ((conditions & ChannelCondition.TIMEOUT) != 0) { break; } if ((conditions & ChannelCondition.EOF) != 0) { if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { break; } } BufferedReader reader = null; try { if ((ChannelCondition.STDOUT_DATA & conditions) != 0) { reader = new BufferedReader(new InputStreamReader(stdout)); } else { reader = new BufferedReader(new InputStreamReader(stderr)); } //Reader.readLine() may hang if 'exit' is not added to the command as the last line (use the 'exit' to exit the shell) boolean toAppend = true; while (true) { line = reader.readLine(); if (line == null) { valid = true; flag = false; break; } if (toAppend) { toAppend = this.append(sb, line); } if (line.trim().startsWith(PROMPT_SYMBOL)) { if (line.trim().indexOf(ERROR_SYMBOL) >= 0) { valid = false; flag = false; break; } else if (line.trim().contains(ACCESS_DENIED_MESSAGE)) { throw new AccessDeniedException(line.trim()); } } line = reader.readLine(); } } finally { if (reader != null) reader.close(); } } String message = sb.toString().trim(); SshResponse response = new SshResponse(); response.setCommand(command); response.setValid(valid); response.setOut(message); //keep all output //r4(config)#int Fastethernet1/0 // ^ //% Invalid input detected at '^' marker. response.setErr(message); return response; } private boolean append(StringBuilder sb, String line) { if (sb.length() >= MAX_OUTPUT_BUFFER_SIZE) { sb.setLength(MAX_OUTPUT_BUFFER_SIZE - 3); sb.append("..."); return false; } if (sb.length() + line.length() > MAX_OUTPUT_BUFFER_SIZE) { //Minimum abbreviation width is 4 if (MAX_OUTPUT_BUFFER_SIZE - sb.length() < 4) { sb.setLength(MAX_OUTPUT_BUFFER_SIZE - 3); sb.append("..."); } else { String abbreviated = StringUtils.abbreviate(line, MAX_OUTPUT_BUFFER_SIZE - sb.length()); sb.append(abbreviated); } sb.append('\n'); return false; } sb.append(line); sb.append('\n'); return true; }
Keep in mind that the last command "exit" should not be omitted otherwise the SSH session may hang up for ever.