Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package configurator; import ipcalc.IPv4; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.net.telnet.TelnetClient; /** * * @author rs */ public class Configurator { static Settings mainProperites = new Settings("configurator.conf"); private static final Logger LOG = Logger.getLogger(Snmp.class.getName()); /** * @param args the command line arguments */ public static void main(String[] args) throws FileNotFoundException, IOException { //worktest: String commandList = "config ports 1 state enable\nconfig ports 3 state disable"; AuthenticationData authData = new AuthenticationData("admin", "admin", "public", commandList); List<String> switchList = Arrays.asList("D-Link DES-1228/ME Metro Ethernet Switch", "D'link DES-3200"); Configurator cf = new Configurator(); cf.telnetWork("192.168.0.13", authData, switchList); } /** * The main method for telnet configuring the network devices. Prepare data * and create thread for each device * * @param ipText - List of ip ranges, subnets and single ip * @param authData - authorization data for work on devices * @param models list of models for telnet configure */ void telnetWork(String ipText, AuthenticationData authData, List<String> models) { try { List<String> ipList = parseIp(ipText); ExecutorService exec = Executors.newCachedThreadPool(); ipList.forEach((ip) -> { Snmp snmp = new Snmp(authData.getCommunity()); String modelOid = mainProperites.getProperty("Identifier_Oid"); String model = snmp.get(ip, modelOid).trim(); if (models.contains(model)) { try { String modelAddress = getAddressByModelName(model); if (modelAddress != null) { exec.execute(new TelnetConfigureThread(ip, authData, modelAddress)); } else { throw new FileNotFoundException(); } } catch (FileNotFoundException ex) { System.exit(0); } } else { } }); exec.shutdown(); } catch (Exception e) { System.out.println(e); //ip address is incorrect } } /** * Method for getting address of configuration file of device by name * * @param name name of device; * @return address of configuration file; * @throws FileNotFoundException */ String getAddressByModelName(String name) throws FileNotFoundException { Scanner switchReader = new Scanner(new FileReader("switchlist.txt")); String model; while (switchReader.hasNextLine()) { model = switchReader.nextLine(); if (model.contains(name)) { return model.split("->")[1]; } } return null; } /** * Thread for configuration single device */ class TelnetConfigureThread implements Runnable { AuthenticationData authData; String ip; String modelConfigurationAddress; TelnetConfigureThread(String ip, AuthenticationData authData, String modelConfigurationAddress) { this.ip = ip; this.authData = authData; this.modelConfigurationAddress = modelConfigurationAddress; } @Override public void run() { Device device = new Device(modelConfigurationAddress); String report = device.telnetConfigure(authData.getLogin(), authData.getPassword(), ip, authData.getCommandList()); //if develop, later will be pipped out System.out.println(report); } } /** * Method for transform ip text to list of ip addresses. Check recording * method and select the method of conversion. * * @param ipText List of ip ranges, subnets and single ip * @return list of ip addresses */ static List<String> parseIp(String ipText) { Scanner ipReader = new Scanner(ipText); List<String> ipList = new ArrayList<>(); String ipLine; while (ipReader.hasNext()) { ipLine = ipReader.nextLine().trim(); if (ipLine.contains("/")) { ipList.addAll(parseIpSubnet(ipLine)); } else if (ipLine.contains("-")) { ipList.addAll(parseIpRange(ipLine)); } else if (validateIP(ipLine)) { ipList.add(ipLine); } else { throw new NumberFormatException(); } } return ipList; } /** * Method for transform ip range like "192.168.0.1-192.168.0.254" to list of * ips. * * @param ipRange String with first and last ip * @return List<String> with ip addresses */ static List<String> parseIpRange(String ipRange) { List<String> ipList = new ArrayList<>(); String ips[] = ipRange.split("-"); if (!(validateIP(ips[0]) && validateIP(ips[1]))) { throw new NumberFormatException(); } String[] ipOctets = ips[0].split("\\."); int[] ip = new int[4]; for (int i = 0; i < 4; i++) { ip[i] = Integer.valueOf(ipOctets[i]); } ipList.add(ips[0]); while (!ips[0].equals(ips[1])) { ip[3]++; if (ip[3] == 0x100) { ip[3] = 0; ip[2]++; } if (ip[2] == 0x100) { ip[2] = 0; ip[1]++; } if (ip[1] > 254) { throw new NumberFormatException(); } ips[0] = ip[0] + "." + ip[1] + "." + ip[2] + "." + ip[3]; ipList.add(ips[0]); } return ipList; } /** * Method for transform "ip/netmask" like "192.168.0.1/24" to list of ips. * * @param ipSubnet - String with ip and netmask * @return List<String> with ip addresses */ static List<String> parseIpSubnet(String ipSubnet) { IPv4 ipv4 = new IPv4(ipSubnet); return ipv4.getAvailableIPs(ipv4.getNumberOfHosts()); } /** * Method for validate ip address * * @param ip - ip address for validate * @return true if ip is falid, else false; */ static boolean validateIP(String ip) { if (ip.startsWith("0")) { return false; } if (ip.isEmpty()) { return false; } return ip.matches("\\A(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z"); } } class Device { private final String usernamePrompt; private final String passwordPrompt; private final String commandPrompt; private final AnalysisMode analysisMode; private String answerValidation; private final Settings switchSettings; Device(String modelConfigurationFileAddress) { switchSettings = new Settings( "switches" + System.getProperty("file.separator") + modelConfigurationFileAddress); usernamePrompt = switchSettings.getProperty("Username_Prompt"); passwordPrompt = switchSettings.getProperty("Password_Prompt"); commandPrompt = switchSettings.getProperty("Command_Prompt"); if (switchSettings.getProperty("Success_Mode").equals("Success")) { analysisMode = AnalysisMode.SUCCESS; answerValidation = switchSettings.getProperty("Answer_Validation"); } else if (switchSettings.getProperty("Success_Mode").equals("Success")) { analysisMode = AnalysisMode.ERROR; } else { analysisMode = AnalysisMode.OFF; } } /** * Method for configuring device via telnet. Connect to device, authorizes, * and send to cli one by one line from command list, analyse every answer * and make report * * @param login username for authorization * @param password password for authorization * @param ip ip address of device * @param commandList command list for input on device * @return report of telnet configuring this device */ String telnetConfigure(String login, String password, String ip, String commandList) { StringBuilder report = new StringBuilder("Configure: "); report.append(ip); try { Telnet telnet = new Telnet(login, password, ip); telnet.init(usernamePrompt, passwordPrompt, commandPrompt); Scanner commandReader = new Scanner(commandList); while (commandReader.hasNextLine()) { final String command = commandReader.nextLine(); final String answer = telnet.sendCommand(command, commandPrompt); if (!(analysisMode == AnalysisMode.OFF)) { if (!answerAnalysis(answer)) { report.append("\n").append(command).append(":\n").append(answer); } } } report.append("\n").append("Complete"); } catch (IOException ex) { Logger.getLogger(Device.class.getName()).log(Level.SEVERE, null, ex); report.append("\nConnection problem"); } catch (LoginFailedException ex) { report.append("\nAutentification failed: ").append(ip).append(" login: ").append(login); } return report.toString(); } /** * Define the correctness of command input. If analysis mode by answer - * search word-confirmation on device answer. If analysis mode by error - * count value of line wrappings, if more than one - command not confirmed. * * @param answer - response from device for analysis * @return true if command is confirmed and false if command is not * confirmed. */ private boolean answerAnalysis(String answer) { if (analysisMode == AnalysisMode.SUCCESS) { return answer.contains(answerValidation); } else { int count = 0; for (int i = 0; i < answer.length(); i++) { if (answer.charAt(i) == '\n') { count++; } } return count <= 1; } } } class Telnet { TelnetClient telnet; private final InputStream in; private final PrintStream out; private final String login; private final String password; private final String solidMark; private final String ipMark; private static final Logger LOG = Logger.getLogger(Snmp.class.getName()); private final String ip; Telnet(String login, String password, String ip) throws IOException { solidMark = Configurator.mainProperites.getProperty("solid_command_mark"); ipMark = Configurator.mainProperites.getProperty("ip_command_mark"); this.login = login; this.password = password; this.ip = ip; int port = Integer.valueOf(Configurator.mainProperites.getProperty("Telnet_Port")); telnet = new TelnetClient(); telnet.connect(ip, port); in = telnet.getInputStream(); out = new PrintStream(telnet.getOutputStream()); } /** * To prepare divice for configuring via telnet * * @param userPrompt the combination of characters, which device output, * when be ready to take login * @param passwordPrompt the combination of characters, which device output, * when be ready to take password * @param commandPrompt the combination of characters, which device output, * when be ready to work via telnet * @throws IOException * @LoginFailedException login or password is incorrect */ void init(String userPrompt, String passwordPrompt, String commandPrompt) throws IOException, LoginFailedException { readUntil(userPrompt); write(login); readUntil(passwordPrompt); write(password); String report = readUntil(commandPrompt, userPrompt); if (report.endsWith(userPrompt)) { // ? //? ? ? telnet.disconnect(); LOG.log(Level.INFO, "Autorization Failder {0} {1}", new Object[] { ip, login }); throw new LoginFailedException(login, report); } } /** * ? ??. ? ? , * ?, ?? , ? - ?? * , ? , ? ??. * * @param command raw command * @param commandPrompt the combination of characters, which device output, * when be ready to take next command * @return response from device to entered command * @throws IOException */ String sendCommand(String command, String commandPrompt) throws IOException { if (command.contains(solidMark)) { return passSolidCommand(command, commandPrompt); } else if (command.contains(ipMark)) { return passIpCommand(command, commandPrompt); } else { return passCommand(command, commandPrompt); } } /** * Finish the telnet session */ void disconnect() throws IOException { LOG.log(Level.INFO, "Disconnect from {0}", ip); telnet.disconnect(); } /** * Send data to device. Pass data to output Stream and wait, when device to * be ready for next action * * @param command command for input on device * @param commandPrompt the combination of characters, which device output, * when be ready to take next command * @return response from device to entered command * @throws IOException */ private String passCommand(String command, String commandPrompt) throws IOException { write(command); return readUntil(commandPrompt); } /** * Send range of solid commands to device. "Solid command" - command, which * contain one or several "solidSymbols". Solid command split up into * several regular commands, which pass to device without command prompt. * Usually solid command use, when first part of solid command is require * addiction data and change command prompt * * @param solidCommand solid command * @param commandPrompt the combination of characters, which device output, * when be ready to take next * @return response from device to entered command * @throws IOException */ private String passSolidCommand(String solidCommand, String commandPrompt) throws IOException { String commands[] = solidCommand.split(solidMark); for (int i = 0; i < commands.length - 1; i++) { write(commands[i]); } return passCommand(commands[commands.length - 1], commandPrompt); } /** * Send to device command, which use ip address. Command must contain ipMark * (the combination of characters, which set in config file), define * position and value of octets of ip address. * * @param ipCommand command, whinch you want to add the ip * @param commandPrompt the combination of characters, which device output, * when be ready to take next * @return response from device to entered command * @throws IOException */ private String passIpCommand(String ipCommand, String commandPrompt) throws IOException { String ips[] = ip.split("\\."); if (ipCommand.contains(ipMark + "1")) { ipCommand = ipCommand.replaceAll(ipMark + "1", ips[3]); } else if (ipCommand.contains(ipMark + "2")) { ipCommand = ipCommand.replaceAll(ipMark + "2", ips[2] + "." + ips[3]); } else if (ipCommand.contains(ipMark + "3")) { ipCommand = ipCommand.replaceAll(ipMark + "3", ips[1] + "." + ips[2] + "." + ips[3]); } else if (ipCommand.contains(ipMark + "4")) { ipCommand = ipCommand.replaceAll(ipMark + "4", ip); } else { ipCommand = ipCommand.replaceAll(ipMark, ip); } return passCommand(ipCommand, commandPrompt); } /** * Analys of input stream and waiting for string prompt * * @param prompt string, which expected from device * @return response from device * @throws IOException */ private String readUntil(String prompt) throws IOException { StringBuilder sb = new StringBuilder(); while (!sb.toString().endsWith(prompt)) { sb.append((char) in.read()); } return sb.toString(); } /** * Analys of input stream and waiting for string prompt or reservePrompt * * @param prompt string, which expected from device * @param reservePrompt alternative expected string * @return response from device * @throws IOException */ private String readUntil(String prompt, String reservePrompt) throws IOException { StringBuilder sb = new StringBuilder(); while (!(sb.toString().endsWith(prompt) || sb.toString().endsWith(reservePrompt))) { sb.append((char) in.read()); } return sb.toString(); } /** * Send data to output stream for pass to devicee * * @param value data for out */ private void write(String value) { try { out.println(value); out.flush(); } catch (Exception e) { e.printStackTrace(); } } } /** * Ecxeption, when authorization is failed * * @author rs */ class LoginFailedException extends Exception { LoginFailedException(String login, String report) { super("Authorization failed, login: \"" + login + "\", status:" + report); } } /** * Enumiration types of error analysis. ERROR - if you have response - it's * error, SUCCESS - response contains string of Success, OFF - analysis is not * possible * * @author rs */ enum AnalysisMode { ERROR, SUCCESS, OFF; }