diff options
| author | shizhendong <[email protected]> | 2021-03-19 17:07:37 +0800 |
|---|---|---|
| committer | shizhendong <[email protected]> | 2021-03-19 17:07:37 +0800 |
| commit | 060925e8b27669d39d89a13c5eea46e35388ca49 (patch) | |
| tree | b0c293e968c611ec931b6293c9b2ea54af7f9b7b | |
| parent | b6a868d8285e02d597725bbe4eefbee16a7a8772 (diff) | |
NEZ-514 feat: project module endpoint 接口重构
29 files changed, 2306 insertions, 29 deletions
diff --git a/nz-admin/src/main/java/com/nis/common/utils/Constant.java b/nz-admin/src/main/java/com/nis/common/utils/Constant.java index 2fb003da..9ac93e0f 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/Constant.java +++ b/nz-admin/src/main/java/com/nis/common/utils/Constant.java @@ -588,6 +588,9 @@ public class Constant { // endpoint 导入表头 public static final String SYSCONFIG_KEY_ENDPOINT_EXPORT_HEADER = "endpoint_export_header"; + // endpoint 导入表头 + public static final String SYSCONFIG_KEY_MONITORENDPOINT_EXPORT_HEADER = "monitor_endpoint_export_header"; + // expression template 导入表头 public static final String SYSCONFIG_KEY_EXPRETMPL_EXPORT_HEADER = "expretmpl_export_header"; diff --git a/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java b/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java index 21bfeb0d..43da8d03 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java +++ b/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java @@ -4,7 +4,9 @@ package com.nis.common.utils; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; +import com.nis.common.exception.NZException; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.IOUtils; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; @@ -13,6 +15,7 @@ import org.apache.poi.util.Units; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFRichTextString; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; @@ -261,4 +264,23 @@ public class ExcelUtils { } return headerFlag; } + + public static Workbook getWorkBookFromMultipartFile(MultipartFile excelFile) { + if (!ExcelUtils.validateFileType(excelFile.getOriginalFilename())) { + throw new NZException(RCode.IMPORT_EXCELFILE_TYPE); + } + + Workbook work = null; + try { + work = ExcelUtils.getWork(excelFile.getOriginalFilename(), excelFile.getInputStream()); + } catch (IOException e) { + throw new NZException(RCode.IMPORT_EXCELFILE_PARSE_ERROR); + } finally { + if (work != null) { + IOUtils.closeQuietly(work); + } + } + return work; + } + } diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/Asset.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/Asset.java index 9cc86128..1debce6c 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/Asset.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/Asset.java @@ -211,4 +211,6 @@ public class Asset implements Serializable { private Integer typeId; private Integer brandId; + + private String name; } diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/controller/MonitorEndpointController.java b/nz-admin/src/main/java/com/nis/modules/endpoint/controller/MonitorEndpointController.java new file mode 100644 index 00000000..2e669469 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/controller/MonitorEndpointController.java @@ -0,0 +1,131 @@ +package com.nis.modules.endpoint.controller; + +import com.nis.common.annotation.SysLog; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@RestController +@RequestMapping("/monitor") +public class MonitorEndpointController { + + @Autowired + private MonitorEndpointService monitorEndpointService; + + /** + * 详情 + * + * @param id + * @return + */ + @GetMapping("/endpoint/{id}") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.ENDPOINT) + public R queryEndpointEntity(@PathVariable("id") Integer id) { + return R.ok(monitorEndpointService.queryEndpointEntity(id)); + } + + @GetMapping("/endpoint") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.ENDPOINT) + public R queryEndpointPage(@RequestParam Map<String, Object> params) { + PageUtils page = monitorEndpointService.queryPage(params); + return R.ok(page); + } + + /** + * endpoint tree 三级列表 project -> module -> endpoint + * + * @param name + * @return + */ + @GetMapping("/endpoint/tree") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.ENDPOINT) + public R queryEndpointTree(String name) { + Map map = new HashMap(2); + map.put("list", monitorEndpointService.queryEndpointTree(name)); + return R.ok(map); + } + + @PostMapping("/endpoint") + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.ENDPOINT) + public R saveEndpoint(@RequestBody List<MonitorEndpoint> endpointList) { + monitorEndpointService.saveOrUpdateBatchEndpointList(endpointList); + return R.ok(); + } + + @PutMapping("/endpoint") + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.ENDPOINT) + public R modify(@RequestBody List<MonitorEndpoint> endpointList) { + for (MonitorEndpoint endpointEntity : endpointList) { + ValidateUtils.is(endpointEntity.getId()).notNull(RCode.ENDPOINT_ID_ISNULL); + } + monitorEndpointService.saveOrUpdateBatchEndpointList(endpointList); + return R.ok(); + } + + @DeleteMapping("/endpoint") + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.ENDPOINT) + public R remove(@RequestParam Integer... ids) { + ValidateUtils.is(ids).notNull(RCode.ENDPOINT_ID_ISNULL); + + monitorEndpointService.deleteEndpointByIds(Arrays.asList(ids)); + return R.ok(); + } + + @GetMapping("/endpoint/template") + public void getExportTemplateByLanguage(HttpServletResponse response, String language) { + if (ToolUtil.isEmpty(language)) throw new NZException(RCode.ENDPOINT_EXPORT_HEADER_LANGUAGE_ISNULL); + + monitorEndpointService.getExportTemplateByLanguage(response, language); + } + + /** + * 撤销导入操作 + * + * @param seq + * @return + */ + @DeleteMapping("/endpoint/cancelImport") + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.ENDPOINT) + public R cancelImport(String seq) { + ValidateUtils.is(seq).notNull(RCode.ENDPOINT_CANCELIMPORTSEQ_ISNULL); + + monitorEndpointService.cancelImport(seq); + return R.ok(); + } + + @PostMapping("/endpoint/import") + @SysLog(operation = OperationEnum.IMPORT, type = TypeEnum.ENDPOINT) + public R importEndpoint(MultipartFile excelFile, String language) { + ValidateUtils.is(excelFile).notNull(RCode.ENDPOINT_IMPORT_FILE_ISNULL) + .and(language).notNull(RCode.ENDPOINT_EXPORT_HEADER_LANGUAGE_ISNULL); + + Map map = monitorEndpointService.importEndpoint(excelFile, language); + return R.ok(map); + } + + /** + * 批量导出endpoint + * + * @param response + * @param params + */ + @GetMapping("/endpoint/export") + @SysLog(operation = OperationEnum.EXPORT, type = TypeEnum.ENDPOINT) + public void exportEndpointsFromExcel(HttpServletResponse response, @RequestParam Map<String, Object> params) { + monitorEndpointService.export(response, params); + } + +} + diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointDao.java b/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointDao.java new file mode 100644 index 00000000..469e21b9 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointDao.java @@ -0,0 +1,17 @@ +package com.nis.modules.endpoint.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +@Mapper +public interface MonitorEndpointDao extends BaseMapper<MonitorEndpoint> { + + List<MonitorEndpoint> queryPage(IPage<MonitorEndpoint> page, @Param("params") Map<String, Object> params); + +} diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpoint.java b/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpoint.java new file mode 100644 index 00000000..1727fe6b --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpoint.java @@ -0,0 +1,90 @@ +package com.nis.modules.endpoint.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.nis.modules.asset.entity.Asset; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.project.entity.MonitorProject; +import lombok.Data; + +import java.io.Serializable; + +@Data +@TableName("monitor_endpoint") +public class MonitorEndpoint implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 名称 + */ + private String name; + + /** + * 组件id + */ + private Integer moduleId; + + /** + * 资产id + */ + private Integer assetId; + + + /** + * exporter地址 + */ + private String host; + + /** + * export端口 + */ + private Integer port; + + /** + * 配置参数 当type=HTTP,默认为 module.configs + */ + private String configs; + + /** + * 计算 moduleId + assetId + host + port + configs 的hash值,用于确保相同配置不重复 + */ + private String hash; + + /** + * 是否启用 可选值 + * 0:停用 + * 1:启用 + */ + private Integer enabled; + + private String seq; + + @TableField(exist = false) + private Integer state; + + @TableField(exist = false) + private MonitorModule module; + + @TableField(exist = false) + private Asset asset; + + @TableField(exist = false) + private MonitorProject project; + + @TableField(exist = false) + private StateInfo stateInfo; + + @TableField(exist = false) + private EndpointState endpointState; + + @TableField(exist = false) + private Integer alertNum; +} diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointService.java b/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointService.java new file mode 100644 index 00000000..226e37af --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointService.java @@ -0,0 +1,32 @@ +package com.nis.modules.endpoint.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nis.common.utils.PageUtils; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.project.entity.MonitorProject; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Map; + +public interface MonitorEndpointService extends IService<MonitorEndpoint> { + + MonitorEndpoint queryEndpointEntity(Integer id); + + PageUtils queryPage(Map<String, Object> params); + + List<MonitorProject> queryEndpointTree(String name); + + void saveOrUpdateBatchEndpointList(List<MonitorEndpoint> endpointList); + + void deleteEndpointByIds(List<Integer> ids); + + void getExportTemplateByLanguage(HttpServletResponse response, String language); + + void cancelImport(String seq); + + Map importEndpoint(MultipartFile excelFile, String language); + + void export(HttpServletResponse response, Map<String, Object> params); +} diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceImpl.java new file mode 100644 index 00000000..015eb59c --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceImpl.java @@ -0,0 +1,613 @@ +package com.nis.modules.endpoint.service.impl; + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.Feature; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.alert.dao.AlertMessageDao; +import com.nis.modules.alert.entity.AlertMessageEntity; +import com.nis.modules.asset.entity.Asset; +import com.nis.modules.asset.service.AssetService; +import com.nis.modules.endpoint.dao.MonitorEndpointDao; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.module.service.MonitorModuleService; +import com.nis.modules.panel.service.ExpreTmplService; +import com.nis.modules.project.entity.MonitorProject; +import com.nis.modules.project.service.MonitorProjectService; +import com.nis.modules.sys.dao.SysConfigDao; +import com.nis.modules.sys.entity.SysConfigEntity; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.DigestUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Service +public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, MonitorEndpoint> implements MonitorEndpointService { + + private static Log log = Log.get(); + + @Autowired + private AssetService assetService; + + @Autowired + private SysConfigDao sysConfigDao; + + @Autowired + private AlertMessageDao alertMessageDao; + + @Autowired + private MonitorEndpointDao monitorEndpointDao; + + @Autowired + private MonitorModuleService monitorModuleService; + + @Autowired + private MonitorProjectService monitorProjectService; + + @Autowired + private ExpreTmplService expreTmplService; + + @Override + public MonitorEndpoint queryEndpointEntity(Integer id) { + MonitorEndpoint endpoint = this.getById(id); + if (ToolUtil.isEmpty(endpoint)) { + throw new NZException(RCode.ENDPOINT_NOTFOUND); + } + MonitorModule module = monitorModuleService.getById(endpoint.getModuleId()); + endpoint.setModule(module); + MonitorProject project = monitorProjectService.getById(module.getProjectId()); + endpoint.setProject(project); + Asset asset = assetService.getById(endpoint.getAssetId()); + endpoint.setAsset(asset); + + List<AlertMessageEntity> alerts = alertMessageDao.getAlertsStatColumn(); + alerts = alerts.stream().filter(alert -> ToolUtil.isNotEmpty(alert.getEndpointId())).collect(Collectors.toList()); + Map<Integer, List<AlertMessageEntity>> endpointIdAndAlersMap = alerts.stream().collect(Collectors.groupingBy(AlertMessageEntity::getEndpointId)); + + List<AlertMessageEntity> tempAlert = endpointIdAndAlersMap.get(endpoint.getId()); + if (CollectionUtils.isEmpty(tempAlert)) { + endpoint.setAlertNum(0); + } else { + endpoint.setAlertNum(tempAlert.size()); + } + return endpoint; + } + + private void handleEndpointsAlertNum(List<MonitorEndpoint> endpointList) { + if (CollectionUtils.isEmpty(endpointList)) return; + + List<AlertMessageEntity> alerts = alertMessageDao.getAlertsStatColumn(); + alerts = alerts.stream().filter(alert -> ToolUtil.isNotEmpty(alert.getEndpointId())).collect(Collectors.toList()); + Map<Integer, List<AlertMessageEntity>> endpointIdAndAlersMap = alerts.stream().collect(Collectors.groupingBy(AlertMessageEntity::getEndpointId)); + + List<AlertMessageEntity> tempAlert; + for (MonitorEndpoint endpoint : endpointList) { + tempAlert = endpointIdAndAlersMap.get(endpoint.getId()); + if (CollectionUtils.isEmpty(tempAlert)) { + endpoint.setAlertNum(0); + } else { + endpoint.setAlertNum(tempAlert.size()); + } + } + } + + @Override + public PageUtils queryPage(Map<String, Object> params) { + IPage<MonitorEndpoint> page = new Query<MonitorEndpoint>().getPage(params); + List<MonitorEndpoint> datas = monitorEndpointDao.queryPage(page, params); + + // endpoint 告警数量 + this.handleEndpointsAlertNum(datas); + + page.setRecords(datas); + return new PageUtils(page); + } + + @Override + public List<MonitorProject> queryEndpointTree(String name) { + List<MonitorEndpoint> endpointList = this.list(new LambdaQueryWrapper<MonitorEndpoint>().like(StringUtils.isNotEmpty(name), MonitorEndpoint::getName, name)); + if (CollectionUtils.isEmpty(endpointList)) { + return Collections.emptyList(); + } + List<Integer> moduleIdList = endpointList.stream().map(MonitorEndpoint::getModuleId).distinct().collect(Collectors.toList()); + List<MonitorModule> moduleList = monitorModuleService.list(new LambdaQueryWrapper<MonitorModule>().in(MonitorModule::getId, moduleIdList)); + + List<Integer> projectIdList = moduleList.stream().map(MonitorModule::getProjectId).distinct().collect(Collectors.toList()); + List<MonitorProject> projectList = monitorProjectService.list(new LambdaQueryWrapper<MonitorProject>().in(MonitorProject::getId, projectIdList)); + + + for (MonitorProject project : projectList) { + List<MonitorModule> projectModules = new ArrayList<>(); + + for (MonitorModule module : moduleList) { + List<MonitorEndpoint> moduleEndpoints = new ArrayList(); + for (MonitorEndpoint endpoint : endpointList) { + if (endpoint.getModuleId().equals(module.getId())) { + moduleEndpoints.add(endpoint); + } + } + module.setChildren(moduleEndpoints); + + if (module.getProjectId().equals(project.getId())) { + projectModules.add(module); + } + } + + project.setChildren(projectModules); + } + return projectList; + } + + private void validateParam(List<MonitorEndpoint> endpointList) { + List<MonitorModule> moduleList = monitorModuleService.list(); + List<Integer> moduleIdList = moduleList.stream().map(MonitorModule::getId).collect(Collectors.toList()); + + List<Asset> assetList = assetService.list(); + List<Integer> assetIdList = assetList.stream().map(Asset::getId).collect(Collectors.toList()); + + List<Integer> enabledList = Arrays.asList(new Integer[]{1, 0}); + //String name; + Integer moduleId, assetId, enabled; + for (MonitorEndpoint endpoint : endpointList) { + moduleId = endpoint.getModuleId(); + assetId = endpoint.getAssetId(); + + // 1. 非空校验 + ValidateUtils.is(moduleId).notNull(RCode.ENDPOINT_MODULEID_ISNULL) + .and(assetId).notNull(RCode.ENDPOINT_ASSETID_ISNULL) + .and(endpoint.getPort()).notNull(RCode.ENDPOINT_PORT_ISNULL); + + // 2. module 是否存在 + if (!moduleIdList.contains(moduleId)) { + throw new NZException(RCode.MODULE_NOTFOUND); + } + + // 3. asset 是否存在 + if (!assetIdList.contains(assetId)) { + throw new NZException(RCode.ASSET_NOT_EXIST); + } + + // 4. enabled 值是否有误 + enabled = endpoint.getEnabled(); + if (enabled != null && !enabledList.contains(enabled)) { + throw new NZException(RCode.ENDPOINT_ENABLED_INVALIDE); + } + + // 5. port 校验 + if (endpoint.getPort() != null) { + boolean flag = CommonUtils.checkPort(endpoint.getPort().toString()); + if (!flag) { + throw new NZException(RCode.ENDPOINT_PORT_ERROR); + } + } + + // 6. configs 校验 + if (endpoint.getConfigs() != null) { + try { + JSONObject.parseObject(endpoint.getConfigs(), Map.class); + } catch (JSONException e) { + throw new NZException(RCode.ENDPOINT_CONFIGS_FORMAT); + } + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveOrUpdateBatchEndpointList(List<MonitorEndpoint> endpointList) { + // 校验 + this.validateParam(endpointList); + + List<MonitorModule> moduleList = monitorModuleService.list(); + Map<Integer, MonitorModule> moduleIdAndModuleInfoMap = moduleList.stream().collect(Collectors.toMap(MonitorModule::getId, Function.identity())); + + List<Asset> assetList = assetService.list(); + Map<Integer, String> assetIdAndHostMap = assetList.stream().collect(Collectors.toMap(Asset::getId, Asset::getHost)); + + List<MonitorEndpoint> endpoints = this.list(); + Map<Integer, List<MonitorEndpoint>> moduleIdAndEndpointsMap = new HashMap<>(); + for (MonitorModule module : moduleList) { + List<MonitorEndpoint> moduleEndpoints = endpoints.stream().filter(endpoint -> endpoint.getModuleId().equals(module.getId())).collect(Collectors.toList()); + moduleIdAndEndpointsMap.put(module.getId(), ToolUtil.isEmpty(moduleEndpoints) ? new ArrayList<>() : moduleEndpoints); + } + + MonitorModule module; + for (MonitorEndpoint endpoint : endpointList) { + module = moduleIdAndModuleInfoMap.get(endpoint.getModuleId()); + if (ToolUtil.isEmpty(endpoint.getPort())) { + endpoint.setPort(module.getPort()); + } + if (ToolUtil.isEmpty(endpoint.getHost())) { + endpoint.setHost(assetIdAndHostMap.get(endpoint.getAssetId())); + } + if (ToolUtil.isEmpty(endpoint.getEnabled())) { + endpoint.setEnabled(1); + } + if (ToolUtil.isEmpty(endpoint.getConfigs())) { + endpoint.setConfigs(module.getConfigs()); + } + // 名称为空 则按照 module endpoint 名称模板生成对应名称 + if (ToolUtil.isEmpty(endpoint.getName())) { + String endpointNameTmpl = module.getEndpointNameTmpl(); + Map varsVal = new HashMap(4); + varsVal.put("asset.host", assetIdAndHostMap.get(endpoint.getAssetId())); + varsVal.put("module.name", module.getName()); + String generateEndpointName = expreTmplService.renderExpression(endpointNameTmpl, varsVal); + endpoint.setName(generateEndpointName); + } + + // 校验名称是否重复 + List<MonitorEndpoint> monitorEndpointList = moduleIdAndEndpointsMap.get(endpoint.getModuleId()); + MonitorEndpoint monitorEndpoint = monitorEndpointList.stream().filter(entity -> entity.getName().equals(endpoint.getName()) && !entity.getId().equals(endpoint.getId())).findAny().orElse(null); + if (ToolUtil.isNotEmpty(monitorEndpoint)) { + throw new NZException(RCode.ENDPOINT_NAME_DUPLICATE); + } + monitorEndpointList.add(endpoint); + moduleIdAndEndpointsMap.put(endpoint.getModuleId(), monitorEndpointList); + + String hash = endpoint.getModuleId() + endpoint.getAssetId() + endpoint.getHost() + endpoint.getPort() + endpoint.getConfigs(); + endpoint.setHash(DigestUtils.md5DigestAsHex(hash.getBytes())); + + // 保存 endpoint + this.saveOrUpdate(endpoint); + } + } + + @Override + public void deleteEndpointByIds(List<Integer> ids) { + // 删除 endpoint + this.removeByIds(ids); + } + + @Override + public void getExportTemplateByLanguage(HttpServletResponse response, String language) { + SysConfigEntity configEntity = sysConfigDao.selectOne(new LambdaQueryWrapper<SysConfigEntity>().eq(SysConfigEntity::getParamKey, Constant.SYSCONFIG_KEY_MONITORENDPOINT_EXPORT_HEADER)); + Map map = JSONObject.parseObject(configEntity.getParamValue(), Map.class, Feature.OrderedField); + Map<String, String> exportHeaderMap; + if (map.get(language) != null) { + exportHeaderMap = (Map) map.get(language); + } else { + throw new NZException(RCode.ENDPOINT_EXPORT_HEADER_LANGUAGE_ERROR); + } + SXSSFWorkbook workbook = null; + try { + workbook = ExcelUtils.createExcel07(exportHeaderMap, "Endpoint", true); + String fileName = "EndpointExportTemplate.xlsx"; + response.setContentType("application/excel"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8")); + workbook.write(response.getOutputStream()); + } catch (IOException e) { + log.error("endpoint 模板生成失败,错误信息是:" + e); + } catch (Exception e) { + log.error("获取 endpoint 导入模板失败,表头语言是:" + language + " ,错误信息是:" + e); + } finally { + if (workbook != null) { + IOUtils.closeQuietly(workbook); + } + } + } + + @Override + public void cancelImport(String seq) { + // 撤销导入 + this.remove(new LambdaQueryWrapper<MonitorEndpoint>().eq(MonitorEndpoint::getSeq, seq)); + } + + @Override + public Map importEndpoint(MultipartFile excelFile, String language) { + Workbook work = ExcelUtils.getWorkBookFromMultipartFile(excelFile); + + Sheet sheet = work.getSheetAt(0); + + // 表头校验 + SysConfigEntity config = sysConfigDao.selectOne(new QueryWrapper<SysConfigEntity>().lambda().eq(SysConfigEntity::getParamKey, Constant.SYSCONFIG_KEY_MONITORENDPOINT_EXPORT_HEADER)); + HashMap<String, Object> map = JSONObject.parseObject(config.getParamValue(), HashMap.class, Feature.OrderedField); + boolean headerFlag = ExcelUtils.validateExcelHeader(sheet, sheet.getFirstRowNum(), map.values()); + if (!headerFlag) { + throw new NZException(RCode.IMPORT_EXCELFILE_HEADER_TEMPLATE_ERROR); + } + + Map<String, String> exportHeader = (Map) map.get(language); + List<String> headerInfos = new ArrayList(exportHeader.keySet()); + // 预先查询出校验数据 避免循环查表 + List<Map> failDetails = new ArrayList<>(); + String seqUUID = UUID.randomUUID().toString(); + + int successNum = this.saveTmplsDataFromSheet(sheet, failDetails, headerInfos, seqUUID); + int totalNum = sheet.getLastRowNum() - sheet.getFirstRowNum(); + + Map resultMap = new HashMap(8); + resultMap.put("seq", seqUUID); + resultMap.put("totalNum", totalNum); + resultMap.put("successNum", successNum); + resultMap.put("failNum", totalNum - successNum); + resultMap.put("failDetail", CommonUtils.handleImportFailDetails(failDetails)); + return resultMap; + } + + @Override + public void export(HttpServletResponse response, Map<String, Object> params) { + IPage<MonitorEndpoint> page = new Query<MonitorEndpoint>().getPage(params); + List<MonitorEndpoint> list = monitorEndpointDao.queryPage(page, params); + + SXSSFWorkbook workbook = null; + try { + int rowNum = 0; + SysConfigEntity configEntity = sysConfigDao.selectOne(new LambdaQueryWrapper<SysConfigEntity>().eq(SysConfigEntity::getParamKey, Constant.SYSCONFIG_KEY_MONITORENDPOINT_EXPORT_HEADER)); + Map map = JSONObject.parseObject(configEntity.getParamValue(), Map.class, Feature.OrderedField); + + // 添加标题行 默认语言 en + String language = (String) params.get("language"); + language = ToolUtil.isEmpty(language) ? "en" : language; + Map<String, String> exportHeader = (Map) map.get(language); + + String sheetName = "Endpoints"; + workbook = ExcelUtils.createExcel07(exportHeader, sheetName, false); + SXSSFSheet sheet = workbook.getSheet(sheetName); + CellStyle dataStyle = ExcelUtils.createCellStyle(workbook, (short) 13, false); + + // 添加数据 + Row row1; + for (MonitorEndpoint endpoint : list) { + row1 = sheet.createRow(++rowNum); + + MonitorProject project = endpoint.getProject(); + MonitorModule module = endpoint.getModule(); + Asset asset = endpoint.getAsset(); + + // project name + row1.createCell(0).setCellValue(project.getName()); + // module name + row1.createCell(1).setCellValue(module.getName()); + // name + row1.createCell(2).setCellValue(endpoint.getName()); + // asset name + row1.createCell(3).setCellValue(asset.getName()); + // port + row1.createCell(4).setCellValue(endpoint.getPort()); + // config + row1.createCell(5).setCellValue(endpoint.getConfigs()); + // host + row1.createCell(6).setCellValue(endpoint.getHost()); + // enabled + row1.createCell(7).setCellValue(endpoint.getEnabled()); + + // 设置单元格样式 + ExcelUtils.setDataCellStyle(dataStyle, row1, 7); + } + + // 响应为流 + String fileName = "EndpointsExport.xlsx"; // 默认名称 + response.setContentType("application/excel"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8")); + workbook.write(response.getOutputStream()); + } catch (IOException e) { + log.error(e); + } catch (Exception e) { + log.error(e); + } finally { + if (workbook != null) { + IOUtils.closeQuietly(workbook); + } + } + } + + private int saveTmplsDataFromSheet(Sheet sheet, List<Map> failDetails, List<String> headerInfos, String seqUUID) { + List<MonitorProject> projectList = monitorProjectService.list(); + Map<String, Integer> projectNameAndIdMap = projectList.stream().collect(Collectors.toMap(MonitorProject::getName, MonitorProject::getId)); + + List<MonitorModule> moduleList = monitorModuleService.list(); + Map<String, MonitorModule> monitorModuleMap = moduleList.stream().collect(Collectors.toMap(MonitorModule::getName, Function.identity())); + + List<MonitorEndpoint> endpoints = this.list(); + Map<Integer, List<String>> moduleIdAndEndpointNamesMap = new HashMap<>(); + for (MonitorModule module : moduleList) { + List<String> endpointNames = endpoints.stream().filter(endpoint -> endpoint.getModuleId().equals(module.getId())).map(MonitorEndpoint::getName).collect(Collectors.toList()); + moduleIdAndEndpointNamesMap.put(module.getId(), ToolUtil.isEmpty(endpointNames) ? new ArrayList<>() : endpointNames); + } + + List<Asset> assets = assetService.list(); + Map<String, Integer> assetHostAndIdMap = assets.stream().collect(Collectors.toMap(Asset::getHost, Asset::getId)); + Map<String, Integer> assetNameAndIdMap = assets.stream().collect(Collectors.toMap(Asset::getName, Asset::getId)); + Map<Integer, String> assetIdAndHostMap = assets.stream().collect(Collectors.toMap(Asset::getId, Asset::getHost)); + + + int successNum = 0; + Row row; + for (int i = sheet.getFirstRowNum() + 1; i <= sheet.getLastRowNum(); i++) { + row = sheet.getRow(i); + if (row == null) continue; + + int dataFromExcelRowNum = i + 1; + boolean saveFlag = true; + Integer projectId = null; + String projectName = ExcelUtils.getCellValue(row.getCell(0)); + if (StringUtils.isEmpty(projectName)) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(0), RCode.PROJECT_NAME_ISNULL.getMsg()); + } else { + projectId = projectNameAndIdMap.get(projectName); + if (projectId == null) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(0), RCode.PROJECT_NOTFOUND.getMsg()); + } + } + MonitorModule module = null; + String moduleName = ExcelUtils.getCellValue(row.getCell(1)); + if (StringUtils.isEmpty(moduleName)) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(1), RCode.MODULE_NAME_ISNULL.getMsg()); + } else { + module = monitorModuleMap.get(moduleName); + if (module == null) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(1), RCode.MODULE_NOTFOUND.getMsg()); + } else { + if (projectId != null && !module.getProjectId().equals(projectId)) { + module = null; + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(1), RCode.MODULE_NOTEXIS_PROJECT.getMsg()); + } + } + } + + String assetName = ExcelUtils.getCellValue(row.getCell(3)); + String host = ExcelUtils.getCellValue(row.getCell(6)); + // asset name \ host 不可同时为空 + if (StringUtils.isEmpty(assetName) && StringUtils.isEmpty(host)) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), RCode.ENDPOINT_ASSET_NAME_HOST_ISNULL.getMsg()); + } else if (StringUtils.isNotEmpty(assetName) && StringUtils.isNotEmpty(host)) { + // 都不为空 校验 name 是否可以找到 asset , host 格式是否正确 + if (!CommonUtils.checkIp(host)) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(6), RCode.ASSET_HOST_FORMAT.getMsg()); + } + if (ToolUtil.isEmpty(assetNameAndIdMap.get(assetName))) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), RCode.ASSET_NOT_EXIST.getMsg()); + } + } else if (StringUtils.isNotEmpty(assetName) && StringUtils.isEmpty(host)) { + if (ToolUtil.isEmpty(assetNameAndIdMap.get(assetName))) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), RCode.ASSET_NOT_EXIST.getMsg()); + } + } else if (StringUtils.isEmpty(assetName) && StringUtils.isNotEmpty(host)) { + if (!CommonUtils.checkIp(host)) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(6), RCode.ASSET_HOST_FORMAT.getMsg()); + } + if (ToolUtil.isEmpty(assetHostAndIdMap.get(host))) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(6), RCode.ASSET_NOT_EXIST.getMsg()); + } + } + + String port = ExcelUtils.getCellValue(row.getCell(4)); + if (StringUtils.isNotEmpty(port)) { + try { + Double aDouble = Double.valueOf(port); + if (!CommonUtils.checkPort(String.valueOf(aDouble.intValue()))) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), RCode.MODULE_PORT_ERROR.getMsg()); + } + } catch (NumberFormatException e) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), RCode.MODULE_PORT_ERROR.getMsg()); + } + } + String configs = ExcelUtils.getCellValue(row.getCell(5)); + if (StringUtils.isNotEmpty(configs)) { + try { + JSONObject.parseObject(configs, Map.class); + } catch (JSONException e) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), RCode.ENDPOINT_CONFIGS_FORMAT.getMsg()); + } + } + + String enabled = ExcelUtils.getCellValue(row.getCell(7)); + if (StringUtils.isNotEmpty(enabled)) { + if (!"1".equals(enabled) && !"0".equals(enabled)) { + saveFlag = false; + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(7), RCode.ENDPOINT_ENABLED_INVALIDE.getMsg()); + } + } + + if (saveFlag) { + Integer assetIdByName = assetNameAndIdMap.get(assetName); + Integer assetIdByHost = assetHostAndIdMap.get(host); + + MonitorEndpoint monitorEndpoint = new MonitorEndpoint(); + + // endpoint asset_id endpoint_host + if (StringUtils.isNotEmpty(assetName) && StringUtils.isNotEmpty(host)) { + monitorEndpoint.setAssetId(assetIdByName); + monitorEndpoint.setHost(host); + } else if (StringUtils.isNotEmpty(assetName) && StringUtils.isEmpty(host)) { + monitorEndpoint.setAssetId(assetIdByName); + monitorEndpoint.setHost(assetIdAndHostMap.get(assetIdByName)); + } else if (StringUtils.isEmpty(assetName) && StringUtils.isNotEmpty(host)) { + monitorEndpoint.setAssetId(assetIdByHost); + monitorEndpoint.setHost(assetIdAndHostMap.get(assetIdByHost)); + } + + String name = ExcelUtils.getCellValue(row.getCell(2)); + if (StringUtils.isEmpty(name)) { + String endpointNameTmpl = module.getEndpointNameTmpl(); + Map varsVal = new HashMap(4); + varsVal.put("asset.host", assetIdAndHostMap.get(monitorEndpoint.getAssetId())); + varsVal.put("module.name", module.getName()); + name = expreTmplService.renderExpression(endpointNameTmpl, varsVal); + } + + List<String> monitorEndpointNameList = moduleIdAndEndpointNamesMap.get(module.getId()); + String tempName = name; + String monitorEndpointName = monitorEndpointNameList.stream().filter(s -> s.equals(tempName)).findAny().orElse(null); + if (ToolUtil.isNotEmpty(monitorEndpointName)) { + this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(2), RCode.ENDPOINT_NAME_DUPLICATE.getMsg()); + continue; + } + + + if (StringUtils.isEmpty(configs)) { + configs = module.getConfigs(); + } + + monitorEndpoint.setName(name); + monitorEndpoint.setConfigs(configs); + monitorEndpoint.setModuleId(module.getId()); + monitorEndpoint.setPort(ToolUtil.isEmpty(port) ? module.getPort() : Double.valueOf(port).intValue()); + monitorEndpoint.setEnabled(ToolUtil.isEmpty(enabled) ? 1 : Double.valueOf(enabled).intValue()); + monitorEndpoint.setSeq(seqUUID); + + String hash = module.getId() + monitorEndpoint.getAssetId() + monitorEndpoint.getHost() + monitorEndpoint.getPort() + monitorEndpoint.getConfigs(); + monitorEndpoint.setHash(DigestUtils.md5DigestAsHex(hash.getBytes())); + + try { + this.save(monitorEndpoint); + successNum++; + + monitorEndpointNameList.add(name); + moduleIdAndEndpointNamesMap.put(module.getId(), monitorEndpointNameList); + } catch (Exception e) { + log.error(String.format("endpoint 导入保存失败,表达式信息是:%s,错误信息是:%s", monitorEndpoint.toString(), e)); + this.addFailDetail(dataFromExcelRowNum, failDetails, "System", RCode.ENDPOINT_IMPORT_ERROR.getMsg()); + } + } + } + return successNum; + } + + private void addFailDetail(int i, List<Map> failDetails, String headerInfo, String msg) { + Map failDetail = new HashMap(4); + failDetail.put("lineNo", i); + failDetail.put("errorMsg", headerInfo + ": " + msg); + failDetails.add(failDetail); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/module/controller/MonitorModuleController.java b/nz-admin/src/main/java/com/nis/modules/module/controller/MonitorModuleController.java new file mode 100644 index 00000000..823846d0 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/module/controller/MonitorModuleController.java @@ -0,0 +1,99 @@ +package com.nis.modules.module.controller; + +import com.nis.common.annotation.SysLog; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.module.service.MonitorModuleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/monitor") +public class MonitorModuleController { + + @Autowired + private MonitorModuleService monitorModuleService; + + /** + * 详情 + * + * @param id + * @return + */ + @GetMapping("/module/{id}") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.MODULE) + public R queryModuleEntity(@PathVariable("id") Integer id) { + return R.ok(monitorModuleService.queryModuleEntity(id)); + } + + /** + * 列表 + * + * @param params + * @return + */ + @GetMapping("/module") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.MODULE) + public R queryModulePage(@RequestParam Map<String, Object> params) { + PageUtils page = monitorModuleService.queryPage(params); + return R.ok(page); + } + + /** + * module tree 两级列表 project -> module + * + * @param name + * @return + */ + @GetMapping("/module/tree") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.MODULE) + public R queryModuleTree(String name) { + Map map = new HashMap(2); + map.put("list", monitorModuleService.queryModuleTree(name)); + return R.ok(map); + } + + @PostMapping("/module") + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.MODULE) + public R saveModule(@RequestBody MonitorModule module) { + ValidateUtils.is(module.getProjectId()).notNull(RCode.MODULE_PROJECTID_ISNULL) + .and(module.getName()).notNull(RCode.MODULE_NAME_ISNULL) + .and(module.getEndpointNameTmpl()).notNull(RCode.MODULE_ENDPOINTNAMETMPL_ISNULL) + .and(module.getType()).notNull(RCode.MODULE_TYPE_ISNULL) + .and(module.getConfigs()).notNull(RCode.MODULE_CONFIGS_ISNULL); + + Map map = new HashMap(2); + map.put("id", monitorModuleService.saveModule(module)); + return R.ok(map); + } + + @PutMapping("/module") + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.MODULE) + public R editModule(@RequestBody MonitorModule module) { + ValidateUtils.is(module.getId()).notNull(RCode.MODULE_ID_ISNULL) + .and(module.getProjectId()).notNull(RCode.MODULE_PROJECTID_ISNULL) + .and(module.getName()).notNull(RCode.MODULE_NAME_ISNULL) + .and(module.getEndpointNameTmpl()).notNull(RCode.MODULE_ENDPOINTNAMETMPL_ISNULL) + .and(module.getType()).notNull(RCode.MODULE_TYPE_ISNULL) + .and(module.getConfigs()).notNull(RCode.MODULE_CONFIGS_ISNULL); + + Map map = new HashMap(2); + map.put("id", monitorModuleService.updateModule(module)); + return R.ok(map); + } + + + @DeleteMapping("/module") + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.MODULE) + public R remove(@RequestParam Integer... ids) { + ValidateUtils.is(ids).notNull(RCode.MODULE_ID_ISNULL); + monitorModuleService.removeModules(ids); + return R.ok(); + } + + +} diff --git a/nz-admin/src/main/java/com/nis/modules/module/dao/MonitorModuleDao.java b/nz-admin/src/main/java/com/nis/modules/module/dao/MonitorModuleDao.java new file mode 100644 index 00000000..22ba3887 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/module/dao/MonitorModuleDao.java @@ -0,0 +1,19 @@ +package com.nis.modules.module.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.nis.modules.module.entity.MonitorModule; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Mapper +@Repository +public interface MonitorModuleDao extends BaseMapper<MonitorModule> { + + List<MonitorModule> queryPage(IPage<MonitorModule> page, @Param("params") Map<String, Object> params); + +} diff --git a/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModule.java b/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModule.java new file mode 100644 index 00000000..0348266d --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModule.java @@ -0,0 +1,85 @@ +package com.nis.modules.module.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.project.entity.MonitorProject; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +@TableName("monitor_module") +public class MonitorModule implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 组件名称 + */ + private String name; + + /** + * 业务系统id + */ + private Integer projectId; + + /** + * modulle 类型 可选值 : http 、snmp + */ + private String type; + + /** + * endpoint name模板 + * 支持 {{}} 变量替换,asset,module + * 例:{{asset.name}}-{{module.name}} + * 最终endpoint的name为: 192.168.40.1-mysql + */ + private String endpointNameTmpl; + + /** + * 端口 + */ + private Integer port; + + + /** + * 描述 + */ + private String remark; + + /** + * 配置参数 + */ + private String configs; + + + /** + * snmp_exporter需要的配置部分, 由web端根据snmp_param生成 + */ + private String snmpYml; + + /** + * 是否内置 1:内置,0:非内置,默认:0 内置数据不允许删除 + */ + private Integer buildIn; + + private String seq; + + @TableField(exist = false) + private MonitorProject project; + + /** + * endpoint 列表 + */ + @TableField(exist = false) + private List<MonitorEndpoint> children; +} diff --git a/nz-admin/src/main/java/com/nis/modules/module/service/MonitorModuleService.java b/nz-admin/src/main/java/com/nis/modules/module/service/MonitorModuleService.java new file mode 100644 index 00000000..bfea6e9b --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/module/service/MonitorModuleService.java @@ -0,0 +1,24 @@ +package com.nis.modules.module.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nis.common.utils.PageUtils; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.project.entity.MonitorProject; + +import java.util.List; +import java.util.Map; + +public interface MonitorModuleService extends IService<MonitorModule> { + + MonitorModule queryModuleEntity(Integer id); + + PageUtils queryPage(Map<String, Object> params); + + List<MonitorProject> queryModuleTree(String name); + + Integer saveModule(MonitorModule module); + + Integer updateModule(MonitorModule module); + + void removeModules(Integer... ids); +} diff --git a/nz-admin/src/main/java/com/nis/modules/module/service/impl/MonitorModuleServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/module/service/impl/MonitorModuleServiceImpl.java new file mode 100644 index 00000000..0f37ab98 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/module/service/impl/MonitorModuleServiceImpl.java @@ -0,0 +1,313 @@ +package com.nis.modules.module.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.nis.common.exception.NZException; +import com.nis.common.utils.*; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import com.nis.modules.module.dao.MonitorModuleDao; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.module.service.MonitorModuleService; +import com.nis.modules.project.entity.MonitorProject; +import com.nis.modules.project.service.MonitorProjectService; +import com.nis.modules.project.service.TopoService; +import com.nis.modules.sys.entity.SysConfigEntity; +import com.nis.modules.sys.service.SysConfigService; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.util.*; +import java.util.stream.Collectors; + +@Service +public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, MonitorModule> implements MonitorModuleService { + + protected Log log = Log.get(); + + @Autowired + private YamlUtil yamlUtil; + + @Autowired + private TopoService topoService; + + @Autowired + private MonitorModuleDao monitorModuleDao; + + @Autowired + private SysConfigService sysConfigService; + + @Autowired + private MonitorProjectService monitorProjectService; + + @Autowired + private MonitorEndpointService monitorEndpointService; + + + @Override + public MonitorModule queryModuleEntity(Integer id) { + MonitorModule module = this.getById(id); + if (ToolUtil.isEmpty(module)) { + throw new NZException(RCode.MODULE_NOTFOUND); + } + MonitorProject project = monitorProjectService.getById(module.getProjectId()); + module.setProject(project); + return module; + } + + @Override + public PageUtils queryPage(Map<String, Object> params) { + IPage<MonitorModule> page = new Query<MonitorModule>().getPage(params); + List<MonitorModule> datas = monitorModuleDao.queryPage(page, params); + page.setRecords(datas); + return new PageUtils(page); + } + + @Override + public List<MonitorProject> queryModuleTree(String name) { + List<MonitorModule> moduleList = this.list(new LambdaQueryWrapper<MonitorModule>().like(StringUtils.isNotEmpty(name), MonitorModule::getName, name)); + if (CollectionUtils.isEmpty(moduleList)) { + return Collections.emptyList(); + } + + List<Integer> projectIdList = moduleList.stream().map(MonitorModule::getProjectId).distinct().collect(Collectors.toList()); + List<MonitorProject> projectList = monitorProjectService.list(new LambdaQueryWrapper<MonitorProject>().in(MonitorProject::getId, projectIdList)); + + List<MonitorModule> projectModules; + for (MonitorProject project : projectList) { + projectModules = new ArrayList<>(); + for (MonitorModule module : moduleList) { + if (project.getId().equals(module.getProjectId())) { + projectModules.add(module); + } + } + project.setChildren(projectModules); + } + return projectList; + } + + private void validateModuleInfo(MonitorModule module) { + // 1. 校验 project 是否存在 + MonitorProject project = monitorProjectService.getById(module.getProjectId()); + if (ToolUtil.isEmpty(project)) { + throw new NZException(RCode.PROJECT_NOTFOUND); + } + + // 2. 名称不能重复 + List<MonitorModule> list = this.list(new QueryWrapper<MonitorModule>().lambda().eq(MonitorModule::getName, module.getName())); + boolean flag = false; + // 当只有一个结果并且这个结果是自身时,或没有结果时,说明名称不重复 + if ((list == null || list.size() == 0) || + (list != null && list.size() == 1 && list.get(0).getId().equals(module.getId()))) { + flag = true; + } + + if (!flag) { + throw new NZException(RCode.MODULE_NAME_DUPLICATE); + } + + // 3.校验 type 类型是否在枚举范围内 + String type = module.getType(); + if (!StrUtil.equals(Constant.MODULE_TYPE_HTTP, type) && !StrUtil.equals(Constant.MODULE_TYPE_SNMP, type)) { + throw new NZException(RCode.MODULE_TYPE_INVALID); + } + + // 4. 端口校验 + if (module.getPort() != null) { + flag = CommonUtils.checkPort(module.getPort().toString()); + if (!flag) { + throw new NZException(RCode.MODULE_PORT_ERROR); + } + } + + // 5. config 格式校验 + Map configMap; + try { + configMap = JSONObject.parseObject(module.getConfigs(), Map.class); + } catch (JSONException e) { + throw new NZException(RCode.MODULE_CONFIGS_FORMAT); + } + + // snmp 类型校验 config + if (StrUtil.equals(Constant.MODULE_TYPE_SNMP, type)) { + // 注: snmp version 实际版本 为 1,2,3 ,此处只做 2,3 版本限制 + Integer version = (Integer) configMap.get("version"); + if (version != null) { + if (version < 2 || version > 3) { + // 版本不在可选范围内 + throw new NZException(RCode.MODULE_SNMPVERSION_INVALID); + } + + if (version.equals(3)) { + SnmpUtil.ValidateAuthForSnmpV3((Map<String, String>) configMap.get("auth")); + } + } + } + } + + @Override + public Integer saveModule(MonitorModule module) { + // 1. 校验 + this.validateModuleInfo(module); + + // 2. snmp 类型处理 + if (StrUtil.equals(Constant.MODULE_TYPE_SNMP, module.getType())) { + // port 缺省值 + if (ToolUtil.isEmpty(module.getPort())) { + module.setPort(Constant.SNMP_DEFAULT_PORT); + } + + // 处理snmYml字段 + String configs = module.getConfigs(); + String snmpYml = this.generateYmlFromSnmpParam(JSONObject.parseObject(configs, Map.class), module); + module.setSnmpYml(snmpYml); + } + + // 3. endpointNameTmpl + if (ToolUtil.isEmpty(module.getEndpointNameTmpl())) { + module.setEndpointNameTmpl("{{asse.host}}-{{module.name}}"); + } + + // 保存 + this.save(module); + return module.getId(); + } + + @Override + public Integer updateModule(MonitorModule moduleEntity) { + // 1. 内置 moduel 不允许修改 + MonitorModule oldModule = this.getById(moduleEntity.getId()); + if (ToolUtil.isEmpty(oldModule)) { + throw new NZException(RCode.MODULE_NOTFOUND); + } + + if (oldModule.getBuildIn().equals(1)) { + throw new NZException(RCode.MODULE_BUILDIN_CAN_NOT_REMOVE); + } + + // 2. 校验 + this.validateModuleInfo(moduleEntity); + + // 3. snmp 类型 , 处理 snmpYml 字段 , 如果 module 名称发生改动 + if (StrUtil.equals(Constant.MODULE_TYPE_SNMP, moduleEntity.getType())) { + String snmpYml = this.generateYmlFromSnmpParam(JSONObject.parseObject(moduleEntity.getConfigs(), Map.class), moduleEntity); + moduleEntity.setSnmpYml(snmpYml); + }else{ + moduleEntity.setSnmpYml("{}"); + } + + // 4. 修改了 project , 修改 topo config + if (!oldModule.getProjectId().equals(moduleEntity.getProjectId())) { + List<MonitorModule> modules = new ArrayList(); + modules.add(oldModule); + topoService.removeTopoConfigNodeAndLineByModules(modules); + } + + // 保存 + this.updateById(moduleEntity); + return moduleEntity.getId(); + } + + @Override + public void removeModules(Integer... ids) { + List<MonitorModule> list = this.list(); + + // 1. 内置的 配置不允许删除 + List<Integer> buildInIdList = list.stream().filter(assetTypeConf -> assetTypeConf.getBuildIn().equals(1)).map(MonitorModule::getId).collect(Collectors.toList()); + buildInIdList.retainAll(Arrays.asList(ids)); + if (CollectionUtils.isNotEmpty(buildInIdList)) { + throw new NZException("These modules are built-in and cannot be deleted. Details: " + buildInIdList.toString(), RCode.MODULE_BUILDIN_CAN_NOT_REMOVE.getCode()); + } + + // 2. 含有 endpoint 的 module 不允许删除 + List<MonitorEndpoint> monitorEndpointList = monitorEndpointService.list(); + List<Integer> userModuleIdList = monitorEndpointList.stream().map(MonitorEndpoint::getModuleId).distinct().collect(Collectors.toList()); + userModuleIdList.retainAll(Arrays.asList(ids)); + if (CollectionUtils.isNotEmpty(userModuleIdList)) { + throw new NZException("These modules have been used by endpoints and cannot be deleted. Details: " + userModuleIdList.toString(), RCode.MODULE_REMOVE_ERROR.getCode()); + } + + // 删除 + this.removeByIds(Arrays.asList(ids)); + } + + public String generateYmlFromSnmpParam(Map snmpParam, MonitorModule moduleEntity) { + // 取出generator路径 + SysConfigEntity entity = sysConfigService.getOne(new QueryWrapper<SysConfigEntity>().lambda().eq(SysConfigEntity::getParamKey, Constant.SYSCONFIG_KEY_GENERATOR_PATH)); + String generatorPath = entity.getParamValue(); + + Map modules = new HashMap(); + + Map module = new HashMap(); + module.put(moduleEntity.getName(), snmpParam); + + modules.put("modules", module); + + try { + log.debug("开始将 snmp参数写入 generator.yml 文件"); + + // 将json写入到generator.yml文件中 + yamlUtil.createYaml(generatorPath + File.separator + "generator.yml", JSONObject.toJSONString(modules)); + + log.debug("将 snmp参数成功写入 generator.yml 文件"); + } catch (JsonProcessingException e) { + log.error("将 snmp参数写入 generator.yml 文件失败,参数信息是:" + JSONObject.toJSONString(modules), e); + } catch (IOException e) { + log.error("将 snmp参数写入 generator.yml 文件失败,参数信息是:" + JSONObject.toJSONString(modules), e); + } + + StringReader result = null; + StringWriter sw = null; + try { + log.debug("开始生成 snmp.yml 文件"); + + // 先设置环境变量 然后 赋可执行权限 最后 执行生成命令 + String[] envp = {"MIBDIRS=" + generatorPath + File.separator + "mibs"}; + String generatorFile = generatorPath + File.separator + "generator"; + String[] chmodCommand = {"chmod", "+x", generatorFile}; + String[] generateCommand = {generatorFile, "generate"}; + result = RuntimeUtil.run(envp, new File(generatorPath), chmodCommand, generateCommand); + + sw = new StringWriter(); + char[] buf = new char[1024]; + while (result.read(buf) != -1) { + sw.write(buf); + } + + log.debug("成功生成 snmp.yml 文件 {}", sw.toString()); + } catch (Exception e) { + log.error("生成 snmp.yml 文件失败", e); + } finally { + if (sw != null) { + IOUtils.closeQuietly(sw); + } + if (result != null) { + IOUtils.closeQuietly(result); + } + } + + String snmpYml = null; + + try { + // 读取生成之后的snmp.yml 并以json格式 + snmpYml = yamlUtil.yamlToJson(generatorPath + File.separator + "snmp.yml"); + log.debug("读取 snmp.yml 文件的内容成功"); + } catch (FileNotFoundException e) { + log.error("无法读取snmp.yml文件的内容,找不到 snmp.yml 文件", e); + } catch (Exception e) { + log.error("无法读取snmp.yml文件的内容", e); + } + return snmpYml; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/ExpreTmplService.java b/nz-admin/src/main/java/com/nis/modules/panel/service/ExpreTmplService.java index 639d69ca..fd2f752a 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/ExpreTmplService.java +++ b/nz-admin/src/main/java/com/nis/modules/panel/service/ExpreTmplService.java @@ -31,6 +31,8 @@ public interface ExpreTmplService extends IService<ExpressionTmpl> { String renderExpression(ExpressionTmpl tmpl); + String renderExpression(String expression, Map varsVal); + void getExportTemplateByLanguage(HttpServletResponse response, String language); Map importExpreTmplsFromExcel(MultipartFile excelFile, String language); diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/ExpreTmplServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/panel/service/impl/ExpreTmplServiceImpl.java index f39b87d0..c753c179 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/ExpreTmplServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/panel/service/impl/ExpreTmplServiceImpl.java @@ -162,6 +162,17 @@ public class ExpreTmplServiceImpl extends ServiceImpl<ExpreTmplDao, ExpressionTm String expression = tmpl.getExpression(); Map varsVal = tmpl.getVarsVal(); + expression = this.generateExpression(expression, varsVal); + return expression; + } + + @Override + public String renderExpression(String expression, Map varsVal) { + expression = this.generateExpression(expression, varsVal); + return expression; + } + + private String generateExpression(String expression, Map varsVal) { String[] vars = this.parseExpre(expression); for (int i = 0; i < vars.length; i++) { Object o = varsVal.get(vars[i]); @@ -207,28 +218,9 @@ public class ExpreTmplServiceImpl extends ServiceImpl<ExpreTmplDao, ExpressionTm } } - private Workbook getWorkBookFromFile(MultipartFile excelFile) { - if (!ExcelUtils.validateFileType(excelFile.getOriginalFilename())) { - throw new NZException(RCode.EXPRETMPL_IMPORTFILE_TYPE); - } - - Workbook work = null; - try { - work = ExcelUtils.getWork(excelFile.getOriginalFilename(), excelFile.getInputStream()); - } catch (IOException e) { - logger.error("解析导入表达式模板文件格式有误", e); - throw new NZException(RCode.EXPRETMPL_IMPORTFILE_FAILED); - } finally { - if (work != null) { - IOUtils.closeQuietly(work); - } - } - return work; - } - @Override public Map importExpreTmplsFromExcel(MultipartFile excelFile, String language) { - Workbook work = this.getWorkBookFromFile(excelFile); + Workbook work = ExcelUtils.getWorkBookFromMultipartFile(excelFile); Sheet sheet = work.getSheetAt(0); diff --git a/nz-admin/src/main/java/com/nis/modules/project/controller/MonitorProjectController.java b/nz-admin/src/main/java/com/nis/modules/project/controller/MonitorProjectController.java new file mode 100644 index 00000000..b28d56c1 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/project/controller/MonitorProjectController.java @@ -0,0 +1,253 @@ +package com.nis.modules.project.controller; + +import com.nis.common.annotation.SysLog; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.project.entity.MonitorProject; +import com.nis.modules.project.entity.TopoIcon; +import com.nis.modules.project.service.MonitorProjectService; +import com.nis.modules.project.service.TopoIconService; +import com.nis.modules.project.service.TopoService; +import com.nis.modules.sys.controller.AbstractController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/monitor") +public class MonitorProjectController extends AbstractController { + + @Autowired + private TopoService topoService; + + @Autowired + private TopoIconService topoIconService; + + @Autowired + private MonitorProjectService monitorProjectService; + + /** + * 详情 + * + * @param id + * @return + */ + @GetMapping("/project/{id}") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.PROJECT) + public R queryProjectEntity(@PathVariable("id") Integer id) { + return R.ok(monitorProjectService.queryProjectEntity(id)); + } + + /** + * project 查询 + * + * @param params + * @return + */ + @GetMapping("/project") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.PROJECT) + public R queryProjectPage(@RequestParam Map<String, Object> params) { + PageUtils page = monitorProjectService.queryPage(params); + return R.ok(page); + } + + /** + * 新增 project + * + * @param project + * @return + */ + @PostMapping("/project") + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.PROJECT) + public R saveProject(@RequestBody MonitorProject project) { + ValidateUtils.is(project.getName()).notNull(RCode.PROJECT_NAME_ISNULL); + + Map map = new HashMap(2); + map.put("id", monitorProjectService.saveProject(project)); + return R.ok(map); + } + + /** + * 修改 project + * + * @param project + * @return + */ + @PutMapping("/project") + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.PROJECT) + public R editProject(@RequestBody MonitorProject project) { + ValidateUtils.is(project.getId()).notNull(RCode.PROJECT_ID_ISNULL) + .and(project.getName()).notNull(RCode.PROJECT_NAME_ISNULL); + + Map map = new HashMap(2); + map.put("id", monitorProjectService.updateProject(project)); + return R.ok(map); + } + + /** + * project 删除 + * @param ids + * @return + */ + @DeleteMapping("/project") + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.PROJECT) + public R deleteProjects(@RequestParam Integer... ids) { + ValidateUtils.is(ids).notNull(RCode.PROJECT_ID_ISNULL); + + monitorProjectService.delete(ids); + return R.ok(); + } + + /** + * project 详情,包含统计数据 + * @param id + * @return + */ + @GetMapping("/project/info") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.PROJECT) + public R queryProjectInfo(@RequestParam Integer id) { + ValidateUtils.is(id).notNull(RCode.PROJECT_ID_ISNULL); + + Map<String, Object> result = monitorProjectService.queryProjectInfo(id); + return R.ok(result); + } + + + /** + * icon unit 查询 + */ + @GetMapping("/project/topo/iconUnit") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TOPO) + public R queryTopoUnit(String name) { + List<String> result = topoIconService.queryTopoIconUnitName(name); + return R.ok(result); + } + + /** + * topo icon unit 删除 + * + * @param unit + * @return + */ + @DeleteMapping("/project/topo/iconUnit") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TOPO) + public R deleteTopoUnit(String unit) { + ValidateUtils.is(unit).notNull(RCode.PROJECT_TOPOICON_UNIT_ISNULL); + + topoIconService.deleteTopoIconByUnit(unit); + return R.ok(); + } + + + /** + * topo icon查询 + * + * @param params + * @return + */ + @GetMapping("/project/topo/icon") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.PROJECT) + public R queryIconList(@RequestParam Map<String, Object> params) { + Map result = new HashMap(2); + List<TopoIcon> topoIcons = topoIconService.queryIconList(params); + result.put("list", topoIcons); + return R.ok(result); + } + + /** + * topo icon新增 + * + * @param name + * @param file + * @return + */ + @PostMapping("/project/topo/icon") + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.PROJECT) + public R save(String name, @RequestParam(value = "file", required = false) MultipartFile file, String unit) { + ValidateUtils.is(name).notNull(RCode.PROJECT_TOPOICON_NAME_ISNULL) + .and(unit).notNull(RCode.PROJECT_TOPOICON_UNIT_ISNULL) + .and(file).notNull(RCode.PROJECT_TOPOICON_FILE_ISNULL); + + + try { + Integer iconId = topoIconService.saveTopoIcon(name, file, unit); + Map result = new HashMap(2); + result.put("id", iconId); + return R.ok(result); + } catch (IOException e) { + logger.error("拓朴图图标保存失败,错误信息是:" + e); + return R.error(RCode.ERROR); + } + } + + + /** + * topo icon删除 + * + * @param ids + * @return + */ + @DeleteMapping("/project/topo/icon") + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.PROJECT) + public R removeIcons(@RequestParam Integer... ids) { + ValidateUtils.is(ids).notNull(RCode.PROJECT_ID_ISNULL); + + topoIconService.removeIcons(ids); + return R.ok(); + } + + /** + * icon图标预览 + * + * @param id + * @param response + */ + @GetMapping("/project/topo/icon/{id}") + public void downloadIconFile(@PathVariable("id") Integer id, HttpServletResponse response) { + ValidateUtils.is(id).notNull(RCode.PROJECT_ICONID_ISNULL); + + topoIconService.downloadIconFileById(id, response); + } + + + /** + * 系统topo查询 + * + * @param projectId + */ + @GetMapping("/project/topo") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TOPO) + public R queryTopo(Integer projectId) { + ValidateUtils.is(projectId).notNull(RCode.PROJECT_ID_ISNULL); + + Map result = new HashMap(2); + result.put("topo", topoService.queryTopoByProjectId(projectId)); + return R.ok(result); + } + + /** + * 系统topo编辑 + * + * @param params + * @return + */ + @PutMapping("/project/topo") + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.TOPO) + public R updateProjectTopo(@RequestBody Map<String, Object> params) { + Integer projectId = (Integer) params.get("projectId"); + String topoConfig = (String) params.get("topo"); + + ValidateUtils.is(projectId).notNull(RCode.PROJECT_ID_ISNULL) + .and(topoConfig).notNull(RCode.PROJECT_TOPOCONFIG_ISNULL); + + topoService.updateProjectTopo(projectId, topoConfig); + return R.ok(); + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/project/dao/MonitorProjectDao.java b/nz-admin/src/main/java/com/nis/modules/project/dao/MonitorProjectDao.java new file mode 100644 index 00000000..aa274230 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/project/dao/MonitorProjectDao.java @@ -0,0 +1,10 @@ +package com.nis.modules.project.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.nis.modules.project.entity.MonitorProject; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MonitorProjectDao extends BaseMapper<MonitorProject> { + +} diff --git a/nz-admin/src/main/java/com/nis/modules/project/entity/MonitorProject.java b/nz-admin/src/main/java/com/nis/modules/project/entity/MonitorProject.java new file mode 100644 index 00000000..0bfd5d67 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/project/entity/MonitorProject.java @@ -0,0 +1,51 @@ +package com.nis.modules.project.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.nis.modules.module.entity.MonitorModule; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Data +@TableName("monitor_project") +public class MonitorProject implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 应用名称 + */ + private String name; + + /** + * 描述 + */ + private String remark; + + /** + * 是否内置 1:内置,0:非内置,默认:0 内置数据不允许删除 + */ + private Integer buildIn; + + private String seq; + + @TableField(exist = false) + private List<Integer> alertStat = new ArrayList<Integer>(); + + /** + * module 列表 + */ + @TableField(exist = false) + private List<MonitorModule> children; + +} diff --git a/nz-admin/src/main/java/com/nis/modules/project/service/MonitorProjectService.java b/nz-admin/src/main/java/com/nis/modules/project/service/MonitorProjectService.java new file mode 100644 index 00000000..5ca7aa3f --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/project/service/MonitorProjectService.java @@ -0,0 +1,22 @@ +package com.nis.modules.project.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nis.common.utils.PageUtils; +import com.nis.modules.project.entity.MonitorProject; + +import java.util.Map; + +public interface MonitorProjectService extends IService<MonitorProject> { + + MonitorProject queryProjectEntity(Integer id); + + PageUtils queryPage(Map<String, Object> params); + + Integer saveProject(MonitorProject project); + + Integer updateProject(MonitorProject project); + + void delete(Integer... ids); + + Map<String, Object> queryProjectInfo(Integer id); +} diff --git a/nz-admin/src/main/java/com/nis/modules/project/service/TopoIconService.java b/nz-admin/src/main/java/com/nis/modules/project/service/TopoIconService.java index ac7524b5..ba41c83f 100644 --- a/nz-admin/src/main/java/com/nis/modules/project/service/TopoIconService.java +++ b/nz-admin/src/main/java/com/nis/modules/project/service/TopoIconService.java @@ -20,4 +20,6 @@ public interface TopoIconService extends IService<TopoIcon> { void downloadIconFileById(Integer id, HttpServletResponse response); List<String> queryTopoIconUnitName(String name); + + void deleteTopoIconByUnit(String unit); } diff --git a/nz-admin/src/main/java/com/nis/modules/project/service/TopoService.java b/nz-admin/src/main/java/com/nis/modules/project/service/TopoService.java index 88b0a0ec..db494649 100644 --- a/nz-admin/src/main/java/com/nis/modules/project/service/TopoService.java +++ b/nz-admin/src/main/java/com/nis/modules/project/service/TopoService.java @@ -2,6 +2,7 @@ package com.nis.modules.project.service; import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.module.entity.Module; +import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.project.entity.Topo; import java.util.List; @@ -14,4 +15,6 @@ public interface TopoService extends IService<Topo> { void updateProjectTopo(Integer projectId, String topoConfig); void removeNodeAndLineByModules(List<Module> modules); -}
\ No newline at end of file + + void removeTopoConfigNodeAndLineByModules(List<MonitorModule> modules); +} diff --git a/nz-admin/src/main/java/com/nis/modules/project/service/impl/MonitorProjectServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/project/service/impl/MonitorProjectServiceImpl.java new file mode 100644 index 00000000..daff6fec --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/project/service/impl/MonitorProjectServiceImpl.java @@ -0,0 +1,206 @@ +package com.nis.modules.project.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nis.common.exception.NZException; +import com.nis.common.utils.*; +import com.nis.modules.alert.entity.AlertMessageEntity; +import com.nis.modules.alert.service.AlertMessageService; +import com.nis.modules.endpoint.dao.EndpointDao; +import com.nis.modules.endpoint.entity.Endpoint; +import com.nis.modules.endpoint.service.EndpointService; +import com.nis.modules.module.entity.Module; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.module.service.ModuleService; +import com.nis.modules.module.service.MonitorModuleService; +import com.nis.modules.overview.service.OverviewService; +import com.nis.modules.project.dao.MonitorProjectDao; +import com.nis.modules.project.dao.ProjectDao; +import com.nis.modules.project.entity.MonitorProject; +import com.nis.modules.project.entity.Project; +import com.nis.modules.project.service.MonitorProjectService; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +public class MonitorProjectServiceImpl extends ServiceImpl<MonitorProjectDao, MonitorProject> implements MonitorProjectService { + + @Autowired + private AlertMessageService alertMessageService; + + @Autowired + private MonitorModuleService monitorModuleService; + + @Autowired + private ProjectDao projectDao; + + @Autowired + private ModuleService moduleService; + + @Autowired + private OverviewService overviewService; + + @Autowired + private EndpointService endpointService; + + @Autowired + private EndpointDao endpointDao; + + @Override + public MonitorProject queryProjectEntity(Integer id) { + MonitorProject project = this.getById(id); + if (ToolUtil.isEmpty(project)) { + throw new NZException(RCode.PROJECT_NOTFOUND); + } + return project; + } + + @Override + public PageUtils queryPage(Map<String, Object> params) { + LambdaQueryWrapper<MonitorProject> queryWrapper = new LambdaQueryWrapper<MonitorProject>() + .eq(ToolUtil.isNotEmpty(params.get("id")), MonitorProject::getId, params.get("id")) + .like(ToolUtil.isNotEmpty(params.get("name")), MonitorProject::getName, params.get("name")) + .like(ToolUtil.isNotEmpty(params.get("remark")), MonitorProject::getRemark, params.get("remark")); + + IPage<MonitorProject> page = this.page(new Query<MonitorProject>().getPage(params), queryWrapper); + return new PageUtils(page); + } + + private void validateProjectInfo(MonitorProject project) { + // 1. 名称重复 + List<MonitorProject> list = this.list(new LambdaQueryWrapper<MonitorProject>().eq(MonitorProject::getName, project.getName())); + boolean flag = false; + // 当只有一个结果并且这个结果是自身时,或没有结果时,说明名称不重复 + if ((list == null || list.size() == 0) || (list != null && list.size() == 1 && list.get(0).getId().equals(project.getId()))) { + flag = true; + } + + if (!flag) { + throw new NZException(RCode.PROJECT_NAME_DUPLICATE); + } + } + + @Override + public Integer saveProject(MonitorProject project) { + // 1. 校验 + this.validateProjectInfo(project); + + // 保存 + this.save(project); + return project.getId(); + } + + @Override + public Integer updateProject(MonitorProject project) { + // 内置 project 不能编辑 + MonitorProject monitorProject = this.getById(project.getId()); + if(monitorProject.getBuildIn().equals(1)){ + throw new NZException(RCode.PROJECT_BUILDIN_CAN_NOT_EDIT); + } + + // 参数校验 + this.validateProjectInfo(project); + + // 保存 + this.updateById(project); + return project.getId(); + } + + @Override + public void delete(Integer... ids) { + List<MonitorProject> list = this.list(); + + // 1. 内置的 配置不允许删除 + List<Integer> buildInIdList = list.stream().filter(assetTypeConf -> assetTypeConf.getBuildIn().equals(1)).map(MonitorProject::getId).collect(Collectors.toList()); + buildInIdList.retainAll(Arrays.asList(ids)); + if (CollectionUtils.isNotEmpty(buildInIdList)) { + throw new NZException("These projects are built-in and cannot be deleted. Details: " + buildInIdList.toString(), RCode.PROJECT_BUILDIN_CAN_NOT_REMOVE.getCode()); + } + + // 2. 包含 module 不允许删除 + List<MonitorModule> moduleList = monitorModuleService.list(); + List<Integer> usedProjectIdList = moduleList.stream().map(MonitorModule::getProjectId).distinct().collect(Collectors.toList()); + usedProjectIdList.retainAll(Arrays.asList(ids)); + if (CollectionUtils.isNotEmpty(usedProjectIdList)) { + throw new NZException("These projects have been used by modules and cannot be deleted. Details: " + usedProjectIdList.toString(), RCode.PROJECT_REMOVE_ERROR.getCode()); + } + + // 删除 + this.removeByIds(Arrays.asList(ids)); + } + + @Override + public Map<String,Object> queryProjectInfo(Integer id) { + Map<String,Object> result = new HashMap<String,Object>(); + Project project = projectDao.selectById(id); + if(ObjectUtils.isNotEmpty(project)) { + + // project高中低alert message数据 + List<Map<String, Object>> maps = alertMessageService.listMaps(new QueryWrapper<AlertMessageEntity>().eq("project_id", id).eq("state",1).groupBy("severity").select("severity","count(*) as count")); + Map projectAlertMessageInfos =new HashMap(); + List<Integer> alertStat = project.getAlertStat(); + for(Map<String,Object> map:maps) { + projectAlertMessageInfos.put(map.get("severity"),((Long)map.get("count")).intValue()); + } + + alertStat.add(ObjectUtils.isEmpty(projectAlertMessageInfos.get(Constant.ALERT_SEVERITY_HIGH))?0:(int) projectAlertMessageInfos.get(Constant.ALERT_SEVERITY_HIGH)); + alertStat.add(ObjectUtils.isEmpty(projectAlertMessageInfos.get(Constant.ALERT_SEVERITY_MEDIUM))?0:(int) projectAlertMessageInfos.get(Constant.ALERT_SEVERITY_MEDIUM)); + alertStat.add(ObjectUtils.isEmpty(projectAlertMessageInfos.get(Constant.ALERT_SEVERITY_LOW))?0:(int) projectAlertMessageInfos.get(Constant.ALERT_SEVERITY_LOW)); + + List<Module> modules = moduleService.list(new LambdaQueryWrapper<Module>().eq(Module::getProjectId, id)); + if(ObjectUtils.isEmpty(modules)) { + modules=new ArrayList<Module>(); + } + // 根据 asset 停用状态 获取对应 endpoint ids + List<Integer> suspendedEndpointIds = endpointDao.getSuspendedEndpointIdsByAssetState(); + // 停用的 endpoint ids + List<Integer> disabledEndpointIds = endpointDao.getDisabledEndpointIds(); + suspendedEndpointIds.addAll(disabledEndpointIds); + suspendedEndpointIds = suspendedEndpointIds.stream().distinct().collect(Collectors.toList()); + + Set<Integer> endpointUpIds = overviewService.getUpStatusEndpointIds(suspendedEndpointIds); + + for(Module module : modules) { + //module高中低alert message数据 + List<Map<String, Object>> moduleMaps = alertMessageService.listMaps(new QueryWrapper<AlertMessageEntity>().eq("module_id", module.getId()).eq("state",1).groupBy("severity").select("severity","count(*) as count")); + Map moduleAlertMessageInfos = new HashMap(); + for(Map<String,Object> moduleMap : moduleMaps) { + moduleAlertMessageInfos.put(moduleMap.get("severity"),((Long)moduleMap.get("count")).intValue()); + } + List<Integer> moduleAlertStat = module.getAlertStat(); + moduleAlertStat.add(ObjectUtils.isEmpty(moduleAlertMessageInfos.get(Constant.ALERT_SEVERITY_HIGH))?0:(int) moduleAlertMessageInfos.get(Constant.ALERT_SEVERITY_HIGH)); + moduleAlertStat.add(ObjectUtils.isEmpty(moduleAlertMessageInfos.get(Constant.ALERT_SEVERITY_MEDIUM))?0:(int) moduleAlertMessageInfos.get(Constant.ALERT_SEVERITY_MEDIUM)); + moduleAlertStat.add(ObjectUtils.isEmpty(moduleAlertMessageInfos.get(Constant.ALERT_SEVERITY_LOW))?0:(int) moduleAlertMessageInfos.get(Constant.ALERT_SEVERITY_LOW)); + //组件endpoint up down统计 + if(ObjectUtils.isNotEmpty(endpointUpIds)) { + List<Integer> endpointStat = module.getEndpointStat(); + // 初始化endpoint up down suspended 状态 + endpointStat.add(0); + endpointStat.add(0); + endpointStat.add(0); + List<Endpoint> endpoints = endpointService.list(new QueryWrapper<Endpoint>().eq("module_id", module.getId())); + for(Endpoint endpoint : endpoints) { + if (endpointUpIds.contains(endpoint.getId())) { + endpointStat.set(0, (endpointStat.get(0) + 1)); + } else if (suspendedEndpointIds.contains(endpoint.getId())) { + endpointStat.set(2, (endpointStat.get(2) + 1)); + } else { + endpointStat.set(1, (endpointStat.get(1) + 1)); + } + } + } + } + result.put("basic", project); + result.put("module", modules); + } + return result; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java index 8e87312a..8da02450 100644 --- a/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java @@ -1,5 +1,6 @@ package com.nis.modules.project.service.impl; +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; @@ -8,7 +9,6 @@ import com.nis.common.utils.ToolUtil; import com.nis.modules.project.dao.TopoIconDao; import com.nis.modules.project.entity.TopoIcon; import com.nis.modules.project.service.TopoIconService; -import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -23,11 +23,11 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; - -@Slf4j @Service("topoIconService") public class TopoIconServiceImpl extends ServiceImpl<TopoIconDao, TopoIcon> implements TopoIconService { + private static Log log = Log.get(); + @Autowired private TopoIconDao topoIconDao; @@ -104,4 +104,9 @@ public class TopoIconServiceImpl extends ServiceImpl<TopoIconDao, TopoIcon> impl List<String> result = topoIcons.stream().map(TopoIcon::getUnit).collect(Collectors.toList()); return result; } -}
\ No newline at end of file + + @Override + public void deleteTopoIconByUnit(String unit) { + this.remove(new LambdaQueryWrapper<TopoIcon>().eq(TopoIcon::getUnit, unit)); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoServiceImpl.java index 35350442..1f379786 100644 --- a/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoServiceImpl.java @@ -9,6 +9,7 @@ import com.nis.common.utils.DateUtil; import com.nis.common.utils.RCode; import com.nis.common.utils.ToolUtil; import com.nis.modules.module.entity.Module; +import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.project.dao.TopoDao; import com.nis.modules.project.entity.Project; import com.nis.modules.project.entity.Topo; @@ -94,6 +95,44 @@ public class TopoServiceImpl extends ServiceImpl<TopoDao, Topo> implements TopoS this.saveOrUpdateBatch(topos); } + @Override + public void removeTopoConfigNodeAndLineByModules(List<MonitorModule> modules) { + Set<Integer> projectIds = modules.stream().map(MonitorModule::getProjectId).collect(Collectors.toSet()); + List<Topo> topos = this.list(new QueryWrapper<Topo>().lambda().in(Topo::getProjectId, projectIds)); + if (CollectionUtils.isEmpty(topos)) { + return; + } + Map<Integer, Object> topoProjectIdAndConfigMap = topos.stream().collect(Collectors.toMap(Topo::getProjectId, Topo::getTopo)); + + // module 是批量删除,删除的或许不属于同一个 project + Map<Integer, List<MonitorModule>> projectIdAndMoudles = modules.stream().collect(Collectors.groupingBy(MonitorModule::getProjectId)); + + Object topoConfig; + Map<String, JSONArray> configMap; + List<Integer> moduleIds; + for (Map.Entry<Integer, List<MonitorModule>> entry : projectIdAndMoudles.entrySet()) { + topoConfig = topoProjectIdAndConfigMap.get(entry.getKey()); + if (ToolUtil.isEmpty(topoConfig)) { + continue; + } + + moduleIds = entry.getValue().stream().map(MonitorModule::getId).collect(Collectors.toList()); + configMap = JSONObject.parseObject(topoConfig.toString(), Map.class); + configMap.put("pens", this.removeModuleEntity(configMap.get("pens"), moduleIds)); + topoProjectIdAndConfigMap.put(entry.getKey(), JSONObject.toJSONString(configMap)); + } + + Date now = DateUtil.getUTCTimeByConfigTimeZone(); + Integer userId = ShiroUtils.getUserId().intValue(); + for (Topo topo : topos) { + topo.setTopo(topoProjectIdAndConfigMap.get(topo.getProjectId()).toString()); + topo.setUpdateBy(userId); + topo.setUpdateAt(now); + } + this.saveOrUpdateBatch(topos); + } + + private JSONArray removeModuleEntity(JSONArray pens, List<Integer> moduleIds) { Map<String, Object> node, nodeData; Integer moduleId, type; diff --git a/nz-admin/src/main/resources/db/V2021.03.19__Insert monitor_project, monitor_module and monitor_endpoint table.sql b/nz-admin/src/main/resources/db/V2021.03.19__Insert monitor_project, monitor_module and monitor_endpoint table.sql new file mode 100644 index 00000000..c6c441da --- /dev/null +++ b/nz-admin/src/main/resources/db/V2021.03.19__Insert monitor_project, monitor_module and monitor_endpoint table.sql @@ -0,0 +1,65 @@ + +/** + * 1. insert monitor_project monitor_module monitor_endpoint tables + * 2. update common role remark content + * 3. sys_config 表新增 monitor_exdpoint 导入导出表头 + */ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for monitor_project +-- ---------------------------- +DROP TABLE IF EXISTS `monitor_project`; +CREATE TABLE `monitor_project` ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '应用名称', + `remark` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述信息', + `build_in` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '是否内置 1:内置,0:非内置,默认:0', + `seq` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for monitor_module +-- ---------------------------- +DROP TABLE IF EXISTS `monitor_module`; +CREATE TABLE `monitor_module` ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组件名称 唯一索引,表内不重复', + `project_id` int(10) NOT NULL, + `type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '可选值http snmp', + `endpoint_name_tmpl` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'endpoint name模板 支持 {{}} 变量替换,asset,module\r\n\r\n例:{{asset.name}}-{{module.name}}\r\n\r\n最终endpoint的name为: 192.168.40.1-mysql', + `port` int(10) NOT NULL COMMENT '默认端口 type=snmp时,默认 161', + `remark` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `configs` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '配置参数 ', + `snmp_yml` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'snmp_exporter需要的配置部分', + `build_in` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0', + `seq` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for monitor_endpoint +-- ---------------------------- +DROP TABLE IF EXISTS `monitor_endpoint`; +CREATE TABLE `monitor_endpoint` ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称', + `module_id` int(10) NOT NULL, + `asset_id` int(10) NOT NULL, + `host` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'exporter地址,默认:asset.host', + `port` int(10) NULL DEFAULT NULL COMMENT 'export端口,默认为 module.port', + `configs` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `hash` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '计算 moduleId + assetId + host + port + configs 的hash值,用于确保相同配置不重复', + `enabled` int(4) NOT NULL COMMENT '是否启用 可选值\r\n\r\n0:停用\r\n\r\n1:启用', + `seq` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1; + + +update sys_role set remark = 'The system built-in common user role' where name = 'common'; + +INSERT INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (NULL, 'monitor_endpoint_export_header', '{\r\n \"cn\": {\r\n \"*系统\": \"系统名称(必填) \\n示例: Nezha\",\r\n \"*组件\": \"组件名称(必填) \\n示例: node_exporter\",\r\n \"名称\": \"实例名称 \\n示例: node_exporter\",\r\n \"资产名称\": \"资产名称(非必填) 与 主机地址 不能同时为空 \\n示例: A0420200101\",\r\n \"端口号\": \"端口号 范围0-65535 \\n示例: 9100\",\r\n \"配置\": \"实例配置,JSON格式, \\n示例: {\\\"key\\\":\\\"value\\\"}\",\r\n \"主机地址\": \"主机地址(非必填) 与 资产名称 不能同时为空 \\n示例: 127.0.0.1\",\r\n \"启用\": \"启用状态(非必填) 可选 0:停用 1:启用,为空时默认为1 \\n示例: 1\"\r\n },\r\n \"en\": {\r\n \"*Project Name\": \"Project Name(Required) \\nExample: Nezha\",\r\n \"*Module Name\": \"Module Name(Required) \\nExample: node_exporter\",\r\n \"Name\": \"Endpoint name \\nExample: node_exporter\",\r\n \"Asset Name\": \"Asset name(Not required) And host address cannot be empty at the same time \\n示例: A0420200101\",\r\n \"Port\": \"Port number range 0-65535 \\nExample: 9100\",\r\n \"Configs\": \"Endpoint Configs,JSON format, \\nExample: {\\\"key\\\":\\\"value\\\"}\",\r\n \"Host\": \"Host address (not required) and asset name cannot be empty at the same time \\nExample: 127.0.0.1\",\r\n \"Enabled\": \"Enable state (not required) Optional values 0: Disable 1: Enable, when empty, the default is 1 \\nExample: 1\"\r\n }\r\n}', 1, 'monitor endpoint 导入表头'); diff --git a/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointDao.xml b/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointDao.xml new file mode 100644 index 00000000..87df65f1 --- /dev/null +++ b/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointDao.xml @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.nis.modules.endpoint.dao.MonitorEndpointDao"> + + <resultMap type="com.nis.modules.endpoint.entity.MonitorEndpoint" id="endpoint"> + <result property="id" column="id"/> + <result property="name" column="name"/> + <result property="moduleId" column="module_id"/> + <result property="assetId" column="asset_id"/> + <result property="host" column="host"/> + <result property="port" column="port"/> + <result property="hash" column="hash"/> + <result property="enabled" column="enabled"/> + <result property="configs" column="configs"/> + + <association columnPrefix="es_" property="endpointState" javaType="com.nis.modules.endpoint.entity.EndpointState"> + <id column="endpoint_id" property="endpointId"/> + <result column="create_time" property="createTime"/> + <result column="state" property="state"/> + </association> + + <association columnPrefix="m_" property="module" javaType="com.nis.modules.module.entity.MonitorModule"> + <id column="id" property="id"/> + <result column="name" property="name"/> + </association> + + <association columnPrefix="p_" property="project" javaType="com.nis.modules.project.entity.MonitorProject"> + <id column="id" property="id"/> + <result column="name" property="name"/> + </association> + + <association columnPrefix="a_" property="asset" javaType="com.nis.modules.asset.entity.Asset"> + <id column="id" property="id"/> + <result column="host" property="host"/> + <result column="sn" property="sn"/> + <result column="cabinet_id" property="cabinetId"/> + <result column="state" property="state"/> + <result column="purchase_date" property="purchaseDate"/> + <result column="idc_id" property="idcId"/> + <result column="model_id" property="modelId"/> + <result column="name" property="name"/> + </association> + </resultMap> + + <select id="queryPage" resultMap="endpoint"> + SELECT e.*, + m.id AS m_id, + m.name AS m_name, + + a.id AS a_id, + a.host AS a_host, + a.sn AS a_sn, + a.state AS a_state, + a.purchase_date AS a_purchase_date, + a.idc_id AS a_idc_id, + a.model_id AS a_model_id, + a.cabinet_id AS a_cabinet_id, + a.name AS a_name, + + p.id AS p_id, + p.name AS p_name, + + es.state AS es_state, + es.create_time AS es_create_time, + es.endpoint_id AS es_endpoint_id + FROM monitor_endpoint e + left join monitor_module m on e.module_id=m.id + left join monitor_project p on m.project_id=p.id + left join asset a on e.asset_id=a.id + left join endpoint_state es on e.id = es.endpoint_id + <where> + <if test="params.id != null and params.id != ''"> + e.id = #{params.id} + </if> + + <if test="params.name != null and params.name != ''"> + AND e.name like CONCAT('%', #{params.name}, '%') + </if> + + <if test="params.host != null and params.host != ''"> + AND e.host like CONCAT('%', #{params.host}, '%') + </if> + + <if test="params.projectId != null and params.projectId != ''"> + AND p.id = #{params.projectId} + </if> + + <if test="params.assetId != null and params.assetId != ''"> + AND e.asset_id = #{params.assetId} + </if> + + <if test="params.moduleId != null and params.moduleId != ''"> + AND e.module_id = #{params.moduleId} + </if> + + <if test="params.state != null and params.state != ''"> + AND es.state = #{params.state} + </if> + </where> + </select> +</mapper> diff --git a/nz-admin/src/main/resources/mapper/module/MonitorModuleDao.xml b/nz-admin/src/main/resources/mapper/module/MonitorModuleDao.xml new file mode 100644 index 00000000..590b335c --- /dev/null +++ b/nz-admin/src/main/resources/mapper/module/MonitorModuleDao.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.nis.modules.module.dao.MonitorModuleDao"> + + <resultMap type="com.nis.modules.module.entity.MonitorModule" id="module"> + <result property="id" column="id"/> + <result property="projectId" column="project_id"/> + <result property="name" column="name"/> + <result property="endpointNameTmpl" column="endpoint_name_tmpl"/> + <result property="port" column="port"/> + <result property="type" column="type"/> + <result property="remark" column="remark"/> + <result property="buildIn" column="build_in"/> + <result property="configs" column="configs"/> + + <association property="project" columnPrefix="p_" javaType="com.nis.modules.project.entity.MonitorProject"> + <id column="id" property="id"/> + <result column="name" property="name"/> + <result column="remark" property="remark"/> + </association> + </resultMap> + + <select id="queryPage" resultMap="module"> + SELECT + m.*, + p.id AS p_id, + p.name AS p_name, + p.remark AS p_remark + FROM + monitor_module m + LEFT JOIN monitor_project p ON m.project_id = p.id + <where> + <if test="params.id != null and params.id != ''"> + m.id = #{params.id} + </if> + + <if test="params.projectId != null and params.projectId != ''"> + AND m.project_id = #{params.projectId} + </if> + + <if test="params.name != null and params.name != ''"> + AND m.name LIKE CONCAT('%', #{params.name}, '%') + </if> + + <if test="params.type != null and params.type != ''"> + AND m.type = #{params.type} + </if> + + <if test="params.port != null and params.port != ''"> + AND m.port = #{params.port} + </if> + </where> + </select> + + +</mapper> diff --git a/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml b/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml index 3cf7c2f3..19de2fae 100644 --- a/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml +++ b/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml @@ -39,4 +39,4 @@ ORDER BY ts.status ASC,ts.id DESC </if> </select> -</mapper>
\ No newline at end of file +</mapper> diff --git a/nz-common/src/main/java/com/nis/common/utils/RCode.java b/nz-common/src/main/java/com/nis/common/utils/RCode.java index 8a47e072..7bac5e23 100644 --- a/nz-common/src/main/java/com/nis/common/utils/RCode.java +++ b/nz-common/src/main/java/com/nis/common/utils/RCode.java @@ -134,13 +134,14 @@ public enum RCode { PROJECT_TOPOCONFIG_ISNULL(211012, "Project topo is null"), PROJECT_NOTFOUND(216013, "Project not found"), PROJECT_TOPOICON_UNIT_ISNULL(211014,"Topo icon unit is null"), - + PROJECT_BUILDIN_CAN_NOT_EDIT(217015, "The built-in project does not allow editing"), + MODULE_ID_ISNULL(221000, "Module id can not be empty"), MODULE_PROJECTID_ISNULL(221001, "Project id can not be empty"), MODULE_NAME_ISNULL(221002, "Module name info can not be empty"), MODULE_PORT_ISNULL(221003, "Module port info can not be empty"), MODULE_PATH_ISNULL(221004, "Module path info can not be empty"), - MODULE_PORT_ERROR(221005, "Module port is incorrect"), + MODULE_PORT_ERROR(221005, "Module port is incorrect"), MODULE_BUILDIN_CAN_NOT_REMOVE(227006, "This module is built-in and cannot be deleted"), MODULE_NAME_TOO_LONG(223007, "Module name too long"), MODULE_REMARK_TOO_LONG(223008, "Module remark too long"), @@ -162,6 +163,9 @@ public enum RCode { MODULE_SNMP_NOTEXIST(226024, "SNMP type module must exist"), MODULE_LABELS_FORMAT(223025,"Module labels must be JSON format"), MODULE_LABELS_KEY_FORMAT(223026,"Module labels key format is incorrect"), + MODULE_ENDPOINTNAMETMPL_ISNULL(221027, "Module endpoint name template can not be empty"), + MODULE_CONFIGS_ISNULL(221028, "Module configs can not be empty"), + MODULE_CONFIGS_FORMAT(223029,"Module configs must be JSON format"), ENDPOINT_ID_ISNULL(231000, "Endpoint id can not be empty"), ENDPOINT_MODULEID_ISNULL(231001, "Module Id can not be empty"), @@ -187,6 +191,14 @@ public enum RCode { ENDPOINT_LABELS_KEY_FORMAT(233021,"Endpoint labels key format is incorrect"), ENDPOINT_TIMEOUT_UPDATE(233022,"Data has not been updated for more than multiple cycles"), ENDPOINT_ENABLED_INVALIDE(234023, "Endpoint enabled must be 0 or 1"), + ENDPOINT_NOTFOUND(236024, "Endpoint not found"), + ENDPOINT_NAME_ISNULL(231025, "Endpoint name can not be empty"), + ENDPOINT_NAME_DUPLICATE(232026, "Endpoint name duplicate"), + ENDPOINT_PORT_ERROR(231027, "Endpoint port is incorrect"), + ENDPOINT_ASSET_NAME_HOST_ISNULL(231028, "Asset name and host cannot be empty at the same time"), + ENDPOINT_IMPORT_ERROR(233029, "Endpoint template import error"), + ENDPOINT_CONFIGS_FORMAT(233030,"Endpoint configs must be JSON format"), + /** * assets菜单项相关 */ @@ -653,7 +665,15 @@ public enum RCode { TERMINAL_ISNULL(611004, "Error,Terminal is null"), TERMINAL_TELNET_TRANSFER(610005,"Telnet does not allow upload and download"), TERMINAL_QUERYSIZE_INVALIDED(613006, "Terminal query size cannot be less than 1"), - + + + /** + * 导入相关 + */ + IMPORT_EXCELFILE_TYPE(900, "Only support import XLS or XLSX file"), + IMPORT_EXCELFILE_PARSE_ERROR(901, "Import file resolution failed"), + IMPORT_EXCELFILE_HEADER_TEMPLATE_ERROR(902,"The header row of the excel import template is inconsistent with the system template"), + NOT_NULL_ERROR(990, "not null error"), //not null错误 NOT_NUMBER_ERROR(991, "not number error"), //not number错误 /** |
