This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
nms-nmsserver/src/com/nms/server/thread/change/ChangePluginScriptFile.java
2018-11-23 18:23:25 +08:00

539 lines
17 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.nms.server.thread.change;
import static com.nms.server.common.Constants.WEB_SOCKET_IP;
import static com.nms.server.common.Constants.WEB_SOCKET_PORT;
import static com.nms.server.thread.socket.SocketCMD.DOWNLOAD_PLUGIN_SCRIPT;
import static com.nms.server.thread.socket.SocketCMD.SEND_PLUGIN_SCRIPT_FILE;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.google.common.collect.Sets;
import com.nms.server.bean.EventRecordLibrary;
import com.nms.server.bean.NodeModel;
import com.nms.server.bean.SetInfo;
import com.nms.server.common.Common;
import com.nms.server.common.Constants;
import com.nms.server.dao.CommonDao;
import com.nms.server.service.ChangeService;
import com.nms.server.service.CommonService;
import com.nms.server.util.FileUtils;
import com.nms.server.util.StringUtil;
import com.nms.server.util.socket.SSLSocketCallable;
import com.nms.server.util.socket.SocketUtils;
/**
* 下发第三方监测脚本文件
*/
public class ChangePluginScriptFile implements Runnable {
private static final Logger logger = Logger.getLogger(ChangePluginScriptFile.class);
/*
* 脚本文件临时存储目录
*/
private File pluginScriptDir;
/*
* 接收脚本文件的NC节点列表
*/
private Set<String> ncNodesIpStrSet;
/**
* 向DC管理的所有有效服务器节点发送脚本文件
*
* @param dpluginScriptDir 脚本文件临时存储目录
*/
public ChangePluginScriptFile(File pluginScriptDir) {
this.pluginScriptDir = pluginScriptDir;
}
/**
* 向指定的NC节点发送脚本文件
*
* @param pluginScriptDir 脚本文件临时存储目录
* @param ncNodesIpStrSet 待接收脚本的NC节点列表
*/
public ChangePluginScriptFile(File pluginScriptDir, Set<String> ncNodesIpStrSet) {
this.pluginScriptDir = pluginScriptDir;
this.ncNodesIpStrSet = ncNodesIpStrSet;
}
/*
* 用于统计向特定节点发送的脚本文件
*/
private Map<String, List<File>> sendRecordList = new HashMap<String, List<File>>();
/*
* 统计文件剩余发送次数用于清理DC临时脚本文件
*/
private Map<String, Integer> fileSendLastCount = new HashMap<String, Integer>();
@SuppressWarnings("unchecked")
public void run() {
CommonDao dao = null;
try {
dao = new CommonDao();
ChangeService changeService = new ChangeService(dao);
// Thread.currentThread().setName("发送监测脚本文件");
Thread.currentThread().setName("Send A Monitoring Script File");
Collection<File> files = FileUtils.listFiles(pluginScriptDir, null, false);
if (ncNodesIpStrSet == null) {
// 未指定接收的NC节点时根据检测设置确定待接收脚本的NC节点
Map<String, SetInfo> setInfoMap = new HashMap<String, SetInfo>();
List<SetInfo> setInfos = changeService.getAllSetInfo(1, 1);
for (SetInfo setInfo : setInfos) {
if("2".equals(setInfo.getIsControlStart())) {
setInfoMap.put(setInfo.getProcessIden(), setInfo);
}
}
for (File pluginFile : files) {
String processIden = pluginFile.getName().replaceAll("\\w+_(\\w+)\\.\\w+", "$1");
SetInfo setInfo = setInfoMap.get(processIden);
// 校验 变更范围的节点IP
List<NodeModel> ipNodeModelList = changeService.getNodeModelListBySetInfo(setInfo);
for (NodeModel ip : ipNodeModelList) {
// 仅向0服务器节点发送变更信息0服务器
if (ip != null && ip.getNodeIp() != null && ip.getNodeType().longValue() == 0l
&& Common.hasIpInIpSegment(ip.getNodeIp())) {
addToSendRecordList(ip.getNodeIp(), pluginFile); //
addTofileSendLastCount(pluginFile); //
}
}
}
ncNodesIpStrSet = sendRecordList.keySet();
} else {
// 已指定待接收脚本的NC节点
for (File pluginFile : files) {
for (String ip : ncNodesIpStrSet) {
addToSendRecordList(ip, pluginFile); // 统计向特定节点发送的脚本文件
addTofileSendLastCount(pluginFile); // 统计文件剩余发送次数
}
}
}
for (String ip : ncNodesIpStrSet) {
Common.runChangeRunnable(new SendPluginScriptFile(ip, sendRecordList.get(ip)));
}
// 延时清理脚本
new Thread(new DeletePluginScriptDirAfterSending()).start();
} catch (Exception e) {
logger.error("", e);
} finally {
if (dao != null) {
dao.close();
dao = null;
}
}
}
private void addTofileSendLastCount(File pluginFile) {
Integer count = fileSendLastCount.get(pluginFile.getName());
count = (count != null) ? count : 0;
fileSendLastCount.put(pluginFile.getName(), count + 1);
}
private void addToSendRecordList(String nodeIp, File pluginFile) {
if (sendRecordList.containsKey(nodeIp)) {
sendRecordList.get(nodeIp).add(pluginFile);
} else {
List<File> files = new ArrayList<File>();
files.add(pluginFile);
sendRecordList.put(nodeIp, files);
}
}
protected class SendPluginScriptFile extends SocketUtils implements Callable<Object> {
private String cmd;
private List<File> fileList;
public SendPluginScriptFile(String ip, List<File> fileList) {
super(ip, Constants.SSL_CLIENT_PORT);
this.cmd = SEND_PLUGIN_SCRIPT_FILE;
this.fileList = fileList;
}
@Override
public Object call() throws Exception {
// Thread.currentThread().setName("发送文件 To:>" + ip);
Thread.currentThread().setName("Send File To:>" + ip);
CommonDao dao = null;
try {
if(fileList == null || fileList.size()<1){
logger.info("没有脚本文件需要发送");
return null;
}
createClientSocket();
this.sendMessage(cmd);
logger.debug("cmd:> " + cmd + " 发送命令结果>> " + this.receiveMessage());
StringBuffer sb = new StringBuffer();
for (File file : fileList) {
sb.append(",").append(file.getName());
}
this.sendMessage(sb.substring(1));
this.receiveMessage();
this.bpSendFileByBath(fileList, pluginScriptDir.getCanonicalPath());
logger.debug("cmd:> " + cmd + " 发送脚本文件>> " + this.receiveMessage());
return true;
} catch (Exception e) {
String errorInfo = "Target communication:>" + ip + " create failure" + e.getMessage();
logger.error(errorInfo, e);
dao = new CommonDao();
ChangeService changeService = new ChangeService(dao);
Map<String, String> recordContent = new HashMap<String, String>();
HashSet<String> pluginFileNames = new HashSet<String>();
for (File pluginFile : fileList) {
pluginFileNames.add(pluginFile.getName());
}
String content = StringUtils.join(pluginFileNames.iterator(), "");
recordContent.put("scriptNames", content);
changeService.saveEventRecordLibrary(cmd, Common.getIpSeqIdMap().get(ip) + ""
, "S2C", JSONObject.fromObject(recordContent).toString());
return false;
} finally {
close(); // close socket
if(dao != null) {
dao.close();
dao = null;
}
// 文件剩余发送次数为0时由DeletePluginScriptDirAfterSending线程清理脚本
for (File file : fileList) {
fileSendLastCount.put(file.getName(), fileSendLastCount.get(file.getName()) - 1);
}
}
}
}
/**
* NC初始化时发送脚本文件
*
* @param ip 接收脚本的NC节点
*/
public static void sendPluginFileWhenNcInit(final String ip) {
ChangePluginScriptFile task = null;
File tempPluginDir = ChangePluginScriptFile.getNewTempPluginDirectory();
CommonDao dao = null;
List<String> prefixNameList = new ArrayList<String>();
try {
Set<String> ipList = new HashSet<String>(1);
ipList.add(ip);
task = new ChangePluginScriptFile(tempPluginDir, ipList);
dao = new CommonDao();
CommonService service = new CommonService(dao);
List<SetInfo> setInfoList = service.selectSetInfoList(1l, null, Common.getIpSeqIdMap().get(ip), null, null, 1l, null, 0l, true);
for (SetInfo setInfo : setInfoList) {
if("2".equals(setInfo.getIsControlStart())) {
String prefixName = setInfo.getCheckTypeName() + "_" + setInfo.getProcessIden() + ".";
prefixNameList.add(prefixName);
}
}
} catch (SQLException e) {
logger.error(e.getMessage(), e);
} finally {
if (dao != null) {
dao.close();
dao = null;
}
}
boolean bool = task.waitForGettingScriptFromWeb(tempPluginDir, prefixNameList);
if (bool) {
Common.service.execute(task);
} else { // 向Web请求脚本失败记录eventRecordLibrary
try {
dao = new CommonDao();
ChangeService changeService = new ChangeService(dao);
Map<String, String> recordContent = new HashMap<String, String>();
String content = StringUtils.join(prefixNameList.iterator(), "");
recordContent.put("scriptNames", content);
changeService.saveEventRecordLibrary(SEND_PLUGIN_SCRIPT_FILE, Common.getIpSeqIdMap().get(ip) + "",
"S2C", JSONObject.fromObject(recordContent).toString());
} catch (SQLException e) {
logger.error(e.getMessage(), e);
} finally {
if (dao != null) {
dao.close();
dao = null;
}
}
}
}
/**
* 解析失败暂存信息,重新发送脚本文件<br/>
*
* @param mrlList
*/
public static void sendPluginFileBaseOnEventRecord(List<EventRecordLibrary> recordList) {
if(recordList == null || recordList.isEmpty()) {
return;
}
// W2S [脚本名前缀,...]
Set<String> w2sDetecSetInfos = new HashSet<String>();
// S2C key:NC地址, value:[脚本名前缀,...]
Map<String, Set<String>> s2cDetecSetInfos = new HashMap<String, Set<String>>();
CommonDao dao = null;
try {
dao = new CommonDao();
ChangeService changeService = new ChangeService(dao);
for (EventRecordLibrary record : recordList) {
if (SEND_PLUGIN_SCRIPT_FILE.equalsIgnoreCase(record.getRecordCommand())) { // 脚本下发
Map<?, ?> map = StringUtil.getMapFromJsonObjStr(record.getRecordContent());
String recordType = record.getRecordType();
String scriptNames = (String) map.get("scriptNames");
if("W2S".equals(recordType)) {
for (String scriptName : scriptNames.split(",")) {
w2sDetecSetInfos.add(scriptName);
}
} else if("S2C".equals(recordType)) {
for (String scriptName : scriptNames.split(",")) {
String ip = Common.getNodeIpByUUID(record.getSeqId());
Set<String> scriptNameSet = s2cDetecSetInfos.get(ip);
if(scriptNameSet == null) {
scriptNameSet = new HashSet<String>();
}
scriptNameSet.add(scriptName);
s2cDetecSetInfos.put(ip, scriptNameSet);
}
}
}
changeService.deleteEventRecordByIds(record.getId() + "");
}
} catch (SQLException e) {
logger.error("Delete EventRecordLibrary", e);
} finally {
if (dao != null) {
dao.close();
dao = null;
}
}
// W2S, 向DC管理的所有有效节点发送脚本文件
if(!w2sDetecSetInfos.isEmpty()) {
File tempPluginDir = ChangePluginScriptFile.getNewTempPluginDirectory();
ChangePluginScriptFile task = new ChangePluginScriptFile(tempPluginDir);
boolean bool = task.waitForGettingScriptFromWeb(tempPluginDir, w2sDetecSetInfos);
if(bool) {
Common.service.execute(task);
} else { // 向Web请求脚本失败记录eventRecordLibrary
try {
dao = new CommonDao();
ChangeService changeService = new ChangeService(dao);
Map<String, String> recordContent = new HashMap<String, String>();
String content = StringUtils.join(w2sDetecSetInfos.iterator(), ",");
recordContent.put("scriptNames", content);
changeService.saveEventRecordLibrary(SEND_PLUGIN_SCRIPT_FILE, "",
"W2S", JSONObject.fromObject(recordContent).toString());
} catch (SQLException e) {
logger.error(e.getMessage(), e);
} finally {
if (dao != null) {
dao.close();
dao = null;
}
}
}
}
// S2C, 向指定节点发送脚本文件
Iterator<Entry<String, Set<String>>> it = s2cDetecSetInfos.entrySet().iterator();
while(it.hasNext()) {
Entry<String, Set<String>> entry = it.next();
Set<String> recvIpSet = Sets.newHashSet(entry.getKey());
File tempPluginDir = ChangePluginScriptFile.getNewTempPluginDirectory();
ChangePluginScriptFile task = new ChangePluginScriptFile(tempPluginDir, recvIpSet);
Set<String> prefixNames = entry.getValue();
boolean bool = task.waitForGettingScriptFromWeb(tempPluginDir, prefixNames);
bool = false;
if(bool) {
Common.service.execute(task);
} else { // 向Web请求脚本失败记录eventRecordLibrary
try {
dao = new CommonDao();
ChangeService changeService = new ChangeService(dao);
Map<String, String> recordContent = new HashMap<String, String>();
String content = StringUtils.join(prefixNames.iterator(), ",");
recordContent.put("scriptNames", content);
String ips = Common.getIpSeqIdMap().get(recvIpSet.iterator().next())+"";
changeService.saveEventRecordLibrary(SEND_PLUGIN_SCRIPT_FILE, ips,
"S2C", JSONObject.fromObject(recordContent).toString());
task.new DeletePluginScriptDirAfterSending().run();
} catch (SQLException e) {
logger.error(e.getMessage(), e);
} finally {
if (dao != null) {
dao.close();
dao = null;
}
}
}
}
}
/**
* 根据脚本名称从Web获取脚本文件并等待脚本获取完成
*
* @param dir
* @param prefixNames
* @return
*/
protected Boolean waitForGettingScriptFromWeb(File dir, Collection<String> prefixNames) {
GetScriptFileFromWeb task = null;
task = this.new GetScriptFileFromWeb(dir, prefixNames);
FutureTask<Object> future = new FutureTask<Object>(task);
new Thread(future).start();
try {
Object result = future.get();
if(result == null) {
logger.debug("从Web服务器获取脚本失败脚本列表" + prefixNames);
return false;
}
return (Boolean) result;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return false;
}
protected class GetScriptFileFromWeb extends SSLSocketCallable {
Logger logger = Logger.getLogger(GetScriptFileFromWeb.class);
private File tempPluginDir; // 脚本存储目录
private String prefixNames; // 脚本名称列表(逗号分隔)
public GetScriptFileFromWeb(File tempPluginDir, Collection<String> prefixNames) {
super(WEB_SOCKET_IP, WEB_SOCKET_PORT);
this.tempPluginDir = tempPluginDir;
if(prefixNames != null && prefixNames.size() > 0){
StringBuilder sb = new StringBuilder();
for(String s : prefixNames){
if(StringUtils.isNotBlank(s)){
sb.append(",");
sb.append(s);
}
}
if(sb.length() >0){
sb.deleteCharAt(0);
this.prefixNames = sb.toString();
}
}
}
@Override
protected Object toDo() throws Exception {
// Thread.currentThread().setName("下载第三方监测脚本文件");
Thread.currentThread().setName("Download Third Party Monitoring Script Files");
if(StringUtils.isBlank(prefixNames)){
return true;
}
this.sendMessage(DOWNLOAD_PLUGIN_SCRIPT);
this.receiveMessage();
this.sendMessage(prefixNames);
String fileName = this.receiveMessage();
// 重复请求脚本Web无对应脚本时返回为空
if(FAIL.equalsIgnoreCase(fileName) || StringUtils.isBlank(fileName)) {
logger.error("The Web server does not monitor " + prefixNames + "the corresponding script file");
return false;
} else {
this.sendMessage(SUCCESS);
this.bpReceiveFileByBath(tempPluginDir.getCanonicalPath());
logger.info("已接收脚本文件:" + Arrays.toString(tempPluginDir.list()));
return true;
}
}
}
protected class DeletePluginScriptDirAfterSending implements Runnable {
@Override
public void run() {
while (!fileSendLastCount.isEmpty()) {
Iterator<Entry<String, Integer>> iterator = fileSendLastCount.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, Integer> entry = iterator.next();
if(entry.getValue() == 0) {
iterator.remove();
}
}
try {
TimeUnit.SECONDS.sleep(2L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
logger.debug("删除临时目录" + pluginScriptDir.getAbsolutePath());
FileUtils.deleteAllFiles(pluginScriptDir, true);
}
}
/**
* web向DC下发脚本或DC向web请求脚本过程中每次都创建新的临时目录<br/>
* DC向NC下发脚本完成后将删除临时目录
*
* @return
*/
public static File getNewTempPluginDirectory() {
File tempPluginDir = new File(Constants.PLUGIN_SCRIPT_FILE_DIR, System.currentTimeMillis()+"");
if (!tempPluginDir.exists()) {
tempPluginDir.mkdirs();
logger.debug("创建临时目录" + tempPluginDir.getAbsolutePath());
}
return tempPluginDir;
}
}