


How does Java interface with the Ansible automatic operation and maintenance platform?
Java connects to ansible automatic operation and maintenance platform to realize file collection and distribution
This connection mainly has the following two functions:
File Collection (batch operations on files, including batch collection of common files such as log files from multiple hosts)
File distribution (batch operations on files, including batch collection of files from multiple hosts) Distribute common files such as log files)
Scenario description and ansible yum installation
Because ansible does not have a Windows installation package, a Linux environment was built to facilitate testing. Carry out follow-up work.
This time, the yum method is used to install. When installing Ansible using yum method, first install the EPEL source.
yum install -y http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
View EPEL source Ansible version in
yum info ansible
Install this version directly. If there are other requirements, please adjust the source and install other ansible versions
yum install -y ansible
After the installation is complete, check the ansible version information
ansible --version
Configure the Ansible server list
Inventory file/etc/ansible/hosts, write the corresponding IP address and port of the node host in this file
I am just doing a demonstration here. After the IP, you can add the real SSH port of the node. There is a [] list above the defined content. The content inside is custom content. In order to operate the bound node host, I am used to calling it a group list
Simple authentication, ping the added host
Successfully installed ansible! !
Java code implements file distribution
As the name suggests, file distribution is to distribute local files to multiple hosts.
At this time, you need Apache POI (you can import the corresponding package) to create local files (the ansible Host configuration file is also created through POI)
POI creation file tool class
package com.tiduyun.cmp.operation.utils; import com.tiduyun.cmp.common.model.operation.HostInfo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @author huyuan@tiduyun.com ansible创建文件 */ @Slf4j @Component public class AnsibleCreateFileUtils { private final static String filename = "hosts"; public static String passWordConnect(List<HostInfo> hostInfo, String hostGroup , String directory) throws IOException{ /** 在本地新建一个文件夹 里面创建一个文件 向里面写入内容 */ // 创建文件夹对象 创建文件对象 File folder = new File(directory); // 如果文件夹不存在 就创建一个空的文件夹 if (!folder.exists()) { log.info("创建了文件夹{}" , folder); folder.mkdirs(); } File file = new File(directory, filename); // 如果文件不存在 就创建一个空的文件 if (!file.exists()) { try { log.info("创建了文件{}" , file); file.createNewFile(); } catch (IOException e) { log.error("error data{}" , e); } } // 写入数据 // 创建文件字节输出流 FileOutputStream fos = new FileOutputStream(file); try { List<String> list = new ArrayList<>(); for (HostInfo data : hostInfo) { // 开始写 String string = data.getHost() + " ansible_ssh_pass=" + data.getPasswd() + " ansible_ssh_user=" + data.getAccount() + " ansible_ssh_port=" + data.getPort(); list.add(string); } String splicingData = StringUtils.join(list, "\n"); String str = "[" + hostGroup + "]" + "\n" + splicingData; byte[] bytes = str.getBytes(); // 将byte数组中的所有数据全部写入 fos.write(bytes); fos.flush(); log.info("文件内容{}" , str); // 删除文件 // deleteFile(file); // 关闭流 } catch (IOException e) { log.error("error data{}" , e); throw e; }finally { if (fos != null) { fos.close(); } } return directory; } public static void deleteFile(File file) { if (file.exists()) {// 判断路径是否存在 if (file.isFile()) {// boolean isFile():测试此抽象路径名表示的文件是否是一个标准文件。 file.delete(); } else {// 不是文件,对于文件夹的操作 // 保存 路径D:/1/新建文件夹2 下的所有的文件和文件夹到listFiles数组中 File[] listFiles = file.listFiles();// listFiles方法:返回file路径下所有文件和文件夹的绝对路径 for (File file2 : listFiles) { /* * 递归作用:由外到内先一层一层删除里面的文件 再从最内层 反过来删除文件夹 * 注意:此时的文件夹在上一步的操作之后,里面的文件内容已全部删除 * 所以每一层的文件夹都是空的 ==》最后就可以直接删除了 */ deleteFile(file2); } } file.delete(); } else { log.error("该file路径不存在!!"); } } }
Create host group configuration file
Note: Ansible is divided into two connection methods. Key connection is used here, and the generated file has been spliced with the key! ! ! This will be used in subsequent collection and distribution. (If you don’t understand, you can look up the connection method of ansible)
@Override public void ansibleCreateHost(HostInfo hostInfo, String Key) { ParamCheckUtils.notNull(hostInfo, "hostInfo"); List<HostInfo> HostIp = Arrays.asList(hostInfo); for (HostInfo data : HostIp) { String ansiblePassWd = data.getPasswd(); String PassWd = hostInfoService.decode(ansiblePassWd); data.setPasswd(PassWd); } try { AnsibleCreateFileUtils.passWordConnect(HostIp, ansibleConfigurationItemVo.getHostGroup(), ansibleConfigurationItemVo.getDirectory()); } catch (IOException e) { log.error("Failed to create host configuration{}", e); } }
Implement file distribution
The host configuration file has been configured, and the next step is to execute the corresponding command of ansible. Splicing ansible commands through Java.
Execution command tool class
<br/>
package com.tiduyun.cmp.operation.utils; import lombok.extern.slf4j.Slf4j; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import static cn.hutool.db.DbUtil.close; /** * @author huyuan@tiduyun.com ansible执行命令工具类 * upload 上传文件 * createRemoteDirectory 创建远程目录 */ @Slf4j public class AnsibleExecuteTheOrderUtils { private final static String commandBin = "/bin/sh"; private final static String commandC = "-c"; /** * 创建远程目录 */ public static void createRemoteDirectory(String hostGroup, String remotePath, String directory) throws IOException { Runtime run = Runtime.getRuntime(); String[] cmds = new String[3]; cmds[0] = commandBin; cmds[1] = commandC; cmds[2] = "ansible " + hostGroup + " -m command -a " + "\"mkdir " + remotePath + "\"" + " -i " + directory + "/hosts"; // 执行CMD命令 Process p = run.exec(cmds); log.info("ansible远程执行命令为{}", cmds[2]); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info(lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } /** * 文件分发 */ public static void upload(String hostGroup, String localPath, String remotePath, String directory) throws IOException { Runtime run = Runtime.getRuntime(); String[] cmds = new String[3]; cmds[0] = commandBin; cmds[1] = commandC; cmds[2] = "ansible " + hostGroup + " -m copy -a " + "\"src=" + localPath + " dest=" + remotePath + "\"" + " -i " + directory + "/hosts"; // 执行CMD命令 Process p = run.exec(cmds); log.info("ansible命令为{}", cmds[2]); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info("ansible输出信息为 :" + lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } /** * 文件采集 */ public static void fileCollection(String hostGroup, String remotePath, String localPath , String directory) throws IOException { Runtime run = Runtime.getRuntime(); String[] cmds = new String[3]; cmds[0] = commandBin; cmds[1] = commandC; cmds[2] = "ansible " + hostGroup + " -m fetch -a " + "\"src=" + remotePath + " dest=" + localPath + " force=yes backup=yes\"" + " -i " + directory + "/hosts"; // 执行CMD命令 Process p = run.exec(cmds); log.info("ansible远程采集文件命令为{}", cmds[2]); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info(lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } public static void ExecuteTheOrder(String command) throws IOException { log.info("start execute cmd {}", command); String[] cmd = new String[] {"/bin/bash", "-c", command}; Runtime run = Runtime.getRuntime(); Process p = run.exec(cmd); // 执行CMD命令 BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), Charset.forName("UTF-8"))); try { String lineMes; while ((lineMes = br.readLine()) != null) log.info("输出信息为 {}", lineMes);// 打印输出信息 try { // 检查命令是否执行失败。 if (p.waitFor() != 0) { if (p.exitValue() == 1)// 0表示正常结束,1:非正常结束 log.error("命令执行失败"); } } catch (InterruptedException e) { log.error("error data{}", e); } } catch (IOException e) { log.error("fail to carry out command{}", e); throw e; } finally { if (br != null) { br.close(); } } } public static void disconnect() { try { close(); } catch (Exception ex) { // Ignore because disconnection is quietly } } // public void execute(String command) throws Exception { // log.info("start execute cmd {}", command); // try (Session session = sshClient.startSession()) { // Session.Command exec = session.exec(command); // // Integer readLineCount = 0; // InputStream in = exec.getInputStream(); // log.info(IOUtils.readFully(in).toString()); // String errorMessage = IOUtils.readFully(exec.getErrorStream(), LoggerFactory.DEFAULT).toString(); // log.info(errorMessage); // if (exec.getExitStatus() != null && exec.getExitStatus() != 0) { // throw new RuntimeException( // "exec " + command + " error,error message is " + errorMessage + ",error code " + exec.getExitStatus()); // } // log.info("exec result code {}", exec.getExitStatus()); // // } // // } }
The next step is to call
package com.tiduyun.cmp.operation.service.impl; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import com.tiduyun.cmp.common.model.flow.UploadFile; import com.tiduyun.cmp.common.model.operation.ComponentInfo; import com.tiduyun.cmp.common.model.operation.HostInfo; import com.tiduyun.cmp.common.provider.service.ExceptionBuildService; import com.tiduyun.cmp.operation.constant.OperationExceptionCode; import com.tiduyun.cmp.operation.constant.StartCmdSeparate; import com.tiduyun.cmp.operation.model.AnsibleConfigurationItemVo; import com.tiduyun.cmp.operation.model.vo.FileQueryVo; import com.tiduyun.cmp.operation.service.AnsibleTaskRecordService; import com.tiduyun.cmp.operation.service.ComposerDeployService; import com.tiduyun.cmp.operation.service.HostInfoService; import com.tiduyun.cmp.operation.service.UploadFileService; import com.tiduyun.cmp.operation.utils.AnsibleExecuteTheOrderUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Slf4j @Service public class AnsibleDeployServiceImpl implements ComposerDeployService { @Value(value = "${cmp.operation.commandHeader:cmd /c}") private String commandHeader; @Value(value = "${cmp.operation.filePath:/data/cmp/file}") private String filePath; @Value(value = "${cmp.operation.remoteFilePath:/tmp}") private String remoteFilePath; @Autowired private AnsibleTaskRecordService ansibleTaskRecordService; @Autowired private AnsibleConfigurationItemVo ansibleConfigurationItemVo; @Autowired private UploadFileService uploadFileService; @Autowired private HostInfoService hostInfoService; @Autowired private ExceptionBuildService exceptionBuildService; @Override public void deploy(HostInfo hostInfo, ComponentInfo componentInfo, String cpmposerName) { ansibleTaskRecordService.ansibleCreateHost(hostInfo, null); try { String remotePath = StringUtils.join(remoteFilePath, "/", cpmposerName, "-", componentInfo.getName(), "-", RandomUtil.randomString(3)); log.info("remote file path = {}", remotePath); List<Integer> fileIds = getFileIds(componentInfo.getFileUrl()); if (CollectionUtils.isNotEmpty(fileIds)) { FileQueryVo uploadFileQueryVo = new FileQueryVo(); uploadFileQueryVo.setIds(fileIds); List<UploadFile> uploadFiles = uploadFileService.query(uploadFileQueryVo); for (UploadFile uploadFile : uploadFiles) { String path = StringUtils.join(filePath, uploadFile.getFilePath()); File file = new File(path); if (!file.exists()) { log.error("file url is {}", file.getPath()); throw exceptionBuildService.buildException(OperationExceptionCode.FILE_NOT_EXIST, new Object[] {uploadFile.getFileName()}); } // 创建远程目录 AnsibleExecuteTheOrderUtils.createRemoteDirectory(ansibleConfigurationItemVo.getHostGroup(), StringUtils.join(remotePath), ansibleConfigurationItemVo.getDirectory()); // 分发文件 AnsibleExecuteTheOrderUtils.upload(ansibleConfigurationItemVo.getHostGroup(), path, StringUtils.join(remotePath, "/", uploadFile.getFileName()), ansibleConfigurationItemVo.getDirectory()); } } List<String> startCmds = getStartCmds(componentInfo.getStartCmd()); if (CollectionUtils.isNotEmpty(startCmds)) { String cdCmd = StringUtils.join("cd ", remotePath); String execCmd = StringUtils.join(startCmds, ";"); execCmd = StringUtils.join(cdCmd, ";", execCmd); log.info("execCmd= " + execCmd); // sshClient.execute(execCmd); AnsibleExecuteTheOrderUtils.ExecuteTheOrder(execCmd); } else { log.error("parse startCmd fail {}", componentInfo.getStartCmd()); } } catch (Exception e) { log.error("主机[{}]部署[{}]组件失败,主机ID[{}],组件ID[{}]:", hostInfo.getHost(), componentInfo.getName(), hostInfo.getId(), componentInfo.getId(), e); throw exceptionBuildService.buildException(OperationExceptionCode.EXECUTE_CMD_ERROR, new Object[] {e.getMessage()}); } finally { AnsibleExecuteTheOrderUtils.disconnect(); } } @Override public boolean isSupport(HostInfo hostInfo) { return true; } private List<Integer> getFileIds(String fileIds) { List<Integer> ids = new ArrayList<>(); if (fileIds == null) { return null; } String[] split = StringUtils.split(fileIds, ","); for (String s : split) { ids.add(Integer.parseInt(s)); } return ids; } private List<String> getStartCmds(String startCmd) { List<String> cmd = new ArrayList<>(); if (startCmd == null) { return cmd; } String[] split = StrUtil.split(startCmd, StartCmdSeparate.SIGN); cmd.addAll(Arrays.asList(split)); return cmd; } public static Boolean needCd(String s) { String[] splits = StrUtil.split(s, "&&"); int maxIndex = splits.length - 1; String cmd = splits[maxIndex]; if (StrUtil.startWith(cmd, "cd")) { return false; } else { return true; } } }
File collection
Same as above, Call two tool classes
@Override public void fileCollection(HostInfo hostInfo, String remotePath, String localPath) { ansibleCreateHost(hostInfo, null); try { log.info("remote file path = {}", remotePath); log.info("local file path = {}", localPath); // 文件采集 AnsibleExecuteTheOrderUtils.fileCollection(ansibleConfigurationItemVo.getHostGroup(), remotePath, localPath , ansibleConfigurationItemVo.getDirectory()); } catch (Exception e) { log.error("主机[{}]文件采集失败,主机ID[{}]:", hostInfo.getHost(), hostInfo.getId(), e); throw exceptionBuildService.buildException(OperationExceptionCode.EXECUTE_CMD_ERROR, new Object[] {e.getMessage()}); } finally { AnsibleExecuteTheOrderUtils.disconnect(); } }
The above is the detailed content of How does Java interface with the Ansible automatic operation and maintenance platform?. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Guide to Perfect Number in Java. Here we discuss the Definition, How to check Perfect number in Java?, examples with code implementation.

Guide to Weka in Java. Here we discuss the Introduction, how to use weka java, the type of platform, and advantages with examples.

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.
