From 9ea834dc6928f31bc1b5a48dc1615318c1ca061f Mon Sep 17 00:00:00 2001 From: j553liu <1007388420@qq.com> Date: Sat, 16 Mar 2024 15:42:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=91=E6=B5=8B=E5=B7=A5=E5=85=B7=E5=88=86?= =?UTF-8?q?=E6=9E=90=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/CloudTest/pom.xml | 260 ++++++ .../cloudtest/CompatibleTestApplication.java | 33 + .../common/config/TaskPoolConfig.java | 59 ++ .../common/exception/BaseException.java | 24 + .../exception/ClamAvSizeLimitException.java | 24 + .../common/exception/SshErrorException.java | 24 + .../typehandler/AbstractListTypeHandler.java | 82 ++ .../common/typehandler/CryptoTypeHandler.java | 69 ++ .../typehandler/JacksonTypeHandler.java | 100 +++ .../controller/LabEnvController.java | 72 ++ .../cloudtest/dao/CloudDevUseRecordDao.java | 40 + .../cloudtest/dao/CloudLabTestTaskDao.java | 116 +++ .../cloudtest/dao/PerformanceServiceDao.java | 52 ++ .../cloudtest/entity/CloudLabTestTask.java | 282 +++++++ .../openlab/cloudtest/entity/LabTestReq.java | 47 ++ .../openlab/cloudtest/entity/MqsMessage.java | 184 ++++ .../cloudtest/entity/PerformanceService.java | 24 + .../cloudtest/entity/ScriptResultConfig.java | 21 + .../cloudtest/entity/SystemParams.java | 82 ++ .../openlab/cloudtest/entity/TaskDelay.java | 56 ++ .../cloudtest/entity/TestCaseResult.java | 67 ++ .../cloudtest/entity/TestCaseResultCount.java | 41 + .../CompatibilityFilesParser.java | 31 + .../CompatibilityTestResult.java | 40 + .../ParseFunctionTestLog.java | 231 +++++ .../ParseInfoLog.java | 219 +++++ .../ParseSafetyFiles.java | 141 ++++ .../impl/AbsParseCompatibilityFiles.java | 103 +++ .../impl/AbsParsePerformanceFiles.java | 92 ++ .../impl/ParseClamLog.java | 152 ++++ .../impl/ParseCpuComFiles.java | 155 ++++ .../impl/ParseCpuPerFiles.java | 179 ++++ .../impl/ParseCveCheckFiles.java | 113 +++ .../impl/ParseDiskComFiles.java | 213 +++++ .../impl/ParseDiskPerFiles.java | 213 +++++ .../impl/ParseMemComFiles.java | 168 ++++ .../impl/ParseMemPerFiles.java | 171 ++++ .../impl/ParseNetComFiles.java | 251 ++++++ .../impl/ParseNetPerFiles.java | 262 ++++++ .../impl/ParseSoftwareLog.java | 181 ++++ .../cloudtest/service/DevkitService.java | 147 ++++ .../cloudtest/service/LabEnvService.java | 642 ++++++++++++++ .../cloudtest/service/TarFileService.java | 387 +++++++++ .../service/TaskDelayMapService.java | 174 ++++ .../ic/openlab/cloudtest/util/AESUtil.java | 245 ++++++ .../openlab/cloudtest/util/ApiCenterUtil.java | 117 +++ .../ic/openlab/cloudtest/util/Constants.java | 789 ++++++++++++++++++ .../cloudtest/util/DgCodeServerClient.java | 36 + .../ic/openlab/cloudtest/util/FileUtil.java | 54 ++ .../ic/openlab/cloudtest/util/MQSUtil.java | 43 + .../ic/openlab/cloudtest/util/NormalResp.java | 63 ++ .../ic/openlab/cloudtest/util/PBKDF2Util.java | 67 ++ .../cloudtest/util/PerformanceApiClient.java | 53 ++ .../ic/openlab/cloudtest/util/RandomUtil.java | 31 + .../cloudtest/util/TeeCodeServerClient.java | 36 + .../ic/openlab/cloudtest/util/ToolUtil.java | 88 ++ .../cloudtest/util/fastdfs/FastDfsClient.java | 47 ++ .../cloudtest/util/sshclient/SFTPUtil.java | 103 +++ .../cloudtest/util/sshclient/SSHUtil.java | 123 +++ .../src/main/resources/application.yml | 30 + .../src/main/resources/fastjson.properties | 1 + .../src/main/resources/key/EXTRUBjR/NmsaKOHM | 1 + .../src/main/resources/key/STZQZzfs/PIeavG3r | 1 + .../src/main/resources/key/SW7HH3Up/59X8ARQZ | 1 + .../src/main/resources/logback-spring.xml | 53 ++ .../mapper/CloudDevUseRecordMapper.xml | 26 + .../mapper/CloudLabTestTaskMapper.xml | 266 ++++++ .../mapper/PerformanceServiceMapper.xml | 37 + 68 files changed, 8335 insertions(+) create mode 100644 component/CloudTest/pom.xml create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/CompatibleTestApplication.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/config/TaskPoolConfig.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/BaseException.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/ClamAvSizeLimitException.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/SshErrorException.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/AbstractListTypeHandler.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/CryptoTypeHandler.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/JacksonTypeHandler.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/controller/LabEnvController.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudDevUseRecordDao.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudLabTestTaskDao.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/PerformanceServiceDao.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/CloudLabTestTask.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/LabTestReq.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/MqsMessage.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/PerformanceService.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/ScriptResultConfig.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/SystemParams.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TaskDelay.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResult.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResultCount.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityFilesParser.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityTestResult.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseFunctionTestLog.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseInfoLog.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseSafetyFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParseCompatibilityFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParsePerformanceFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseClamLog.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuComFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuPerFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCveCheckFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskComFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskPerFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemComFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemPerFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetComFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetPerFiles.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseSoftwareLog.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/DevkitService.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/LabEnvService.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TarFileService.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TaskDelayMapService.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/AESUtil.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ApiCenterUtil.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/Constants.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/DgCodeServerClient.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/FileUtil.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/MQSUtil.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/NormalResp.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PBKDF2Util.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PerformanceApiClient.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/RandomUtil.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/TeeCodeServerClient.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ToolUtil.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/fastdfs/FastDfsClient.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SFTPUtil.java create mode 100644 component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SSHUtil.java create mode 100644 component/CloudTest/src/main/resources/application.yml create mode 100644 component/CloudTest/src/main/resources/fastjson.properties create mode 100644 component/CloudTest/src/main/resources/key/EXTRUBjR/NmsaKOHM create mode 100644 component/CloudTest/src/main/resources/key/STZQZzfs/PIeavG3r create mode 100644 component/CloudTest/src/main/resources/key/SW7HH3Up/59X8ARQZ create mode 100644 component/CloudTest/src/main/resources/logback-spring.xml create mode 100644 component/CloudTest/src/main/resources/mapper/CloudDevUseRecordMapper.xml create mode 100644 component/CloudTest/src/main/resources/mapper/CloudLabTestTaskMapper.xml create mode 100644 component/CloudTest/src/main/resources/mapper/PerformanceServiceMapper.xml diff --git a/component/CloudTest/pom.xml b/component/CloudTest/pom.xml new file mode 100644 index 0000000..f9929bf --- /dev/null +++ b/component/CloudTest/pom.xml @@ -0,0 +1,260 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.15 + + + com.huawei + cloudTest + 1.0.0 + cloudTest + Demo project for Spring Boot + + 1.8 + 2021.0.3 + 4.1.100.Final + + + + com.mikesamuel + json-sanitizer + 1.2.3 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + org.apache.commons + commons-compress + 1.23.0 + + + commons-io + commons-io + 2.11.0 + + + commons-fileupload + commons-fileupload + 1.5 + + + org.apache.httpcomponents + httpclient + 4.5.13 + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.2.2 + + + + org.mariadb.jdbc + mariadb-java-client + + + org.springframework.boot + spring-boot-starter-test + test + + + junit + junit + test + + + com.alibaba + fastjson + 1.2.83 + + + org.projectlombok + lombok + + + org.springframework.boot + spring-boot-starter-data-redis + + + io.netty + netty-buffer + + + io.netty + netty-codec + + + io.netty + netty-common + + + io.netty + netty-handler + + + io.netty + netty-resolver + + + io.netty + netty-transport + + + io.netty + netty-transport-native-unix-common + + + + + io.netty + netty-buffer + ${netty.version} + + + io.netty + netty-codec + ${netty.version} + + + io.netty + netty-common + ${netty.version} + + + io.netty + netty-handler + ${netty.version} + + + io.netty + netty-resolver + ${netty.version} + + + io.netty + netty-transport + ${netty.version} + + + io.netty + netty-transport-native-unix-common + ${netty.version} + + + + + org.apache.sshd + sshd-core + 2.10.0 + + + com.jcraft + jsch + 0.1.54 + + + org.springframework.cloud + spring-cloud-starter-openfeign + 4.0.3 + + + org.bouncycastle + bcpkix-jdk15on + + + org.springframework.security + spring-security-crypto + + + + + com.github.tobato + fastdfs-client + 1.27.2 + + + commons-beanutils + commons-beanutils + + + + + commons-beanutils + commons-beanutils + 1.9.4 + + + + + + org.yaml + snakeyaml + 1.32 + + + + xyz.capybara + clamav-client + 2.1.2 + + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + cloudTest + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.2 + + + copy-dependencies + compile + + copy-dependencies + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/lib + + system + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.7.15 + + + + + diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/CompatibleTestApplication.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/CompatibleTestApplication.java new file mode 100644 index 0000000..331e92c --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/CompatibleTestApplication.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * CompatibleTestApplication + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +@EnableAsync +@EnableScheduling +@EnableFeignClients +public class CompatibleTestApplication { + /** + * main + * + * @param args params + */ + public static void main(String[] args) { + SpringApplication.run(CompatibleTestApplication.class, args); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/config/TaskPoolConfig.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/config/TaskPoolConfig.java new file mode 100644 index 0000000..45eb966 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/config/TaskPoolConfig.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.common.config; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +/** + * TaskPoolConfig + * + * @author kongcaizhi + * @since 2022-10-19 + */ +@Configuration +@EnableAsync +@Slf4j +public class TaskPoolConfig implements AsyncConfigurer { + @Override + @Bean(name = "asyncExecutor", destroyMethod = "shutdown") + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + // 核心线程数 + executor.setCorePoolSize(100); + + // 最大线程数,默认 40000 + executor.setMaxPoolSize(300); + + // 线程池队列最大线程数,默认80000 + executor.setQueueCapacity(1000); + + // 线程池线程最大空闲时间(秒) + executor.setKeepAliveSeconds(300); + executor.setThreadNamePrefix("async-task-"); + executor.initialize(); + return executor; + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return (throwable, method, objects) -> + log.error( + "An exception occurred during asynchronous task execution, message {}, method {}, params {}", + throwable.getLocalizedMessage(), + method, + objects + ); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/BaseException.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/BaseException.java new file mode 100644 index 0000000..755b5ff --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/BaseException.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.common.exception; + +/** + * BaseException + * + * @author kongcaizhi + * @since 2021-10-19 + */ +public class BaseException extends RuntimeException { + private static final long serialVersionUID = 120492404095565805L; + + /** + * BaseException + * + * @param message message + */ + public BaseException(String message) { + super(message); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/ClamAvSizeLimitException.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/ClamAvSizeLimitException.java new file mode 100644 index 0000000..c0f310f --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/ClamAvSizeLimitException.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.common.exception; + +/** + * ClamAVSizeLimitException + * + * @author kongcaizhi + * @since 2021-10-19 + */ +public class ClamAvSizeLimitException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** + * Construction function + * + * @param msg message + */ + public ClamAvSizeLimitException(String msg) { + super(msg); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/SshErrorException.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/SshErrorException.java new file mode 100644 index 0000000..b011a75 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/exception/SshErrorException.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.common.exception; + +/** + * ClamAVSizeLimitException + * + * @author kongcaizhi + * @since 2021-10-19 + */ +public class SshErrorException extends Exception { + private static final long serialVersionUID = 116717817166294456L; + + /** + * SshErrorException + * + * @param message message + */ + public SshErrorException(String message) { + super(message); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/AbstractListTypeHandler.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/AbstractListTypeHandler.java new file mode 100644 index 0000000..4ad6d09 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/AbstractListTypeHandler.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.common.typehandler; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.CollectionType; +import com.google.json.JsonSanitizer; + +import lombok.SneakyThrows; + +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; +import org.springframework.util.StringUtils; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +/** + * AbstractListTypeHandler + * + * @author kongcaizhi + * @since 2021-11-19 + */ +@MappedTypes(List.class) +@MappedJdbcTypes(JdbcType.VARCHAR) +public abstract class AbstractListTypeHandler extends BaseTypeHandler { + /** + * objectMapper + */ + protected ObjectMapper objectMapper = new ObjectMapper(); + + /** + * javaType + */ + protected CollectionType javaType; + + @SneakyThrows + @Override + public void setNonNullParameter(PreparedStatement ps, int i, List list, JdbcType jdbcType) throws SQLException { + ps.setString(i, objectMapper.writeValueAsString(list)); + } + + @SneakyThrows + @Override + public List getNullableResult(ResultSet rs, String columnName) throws SQLException { + String json = rs.getString(columnName); + List list = null; + if (!StringUtils.hasLength(json)) { + list = objectMapper.readValue(JsonSanitizer.sanitize(json), javaType); + } + return list; + } + + @SneakyThrows + @Override + public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + String json = rs.getString(rs.getString(columnIndex)); + List list = null; + if (!StringUtils.hasLength(json)) { + list = objectMapper.readValue(JsonSanitizer.sanitize(json), javaType); + } + return list; + } + + @SneakyThrows + @Override + public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + String json = cs.getString(columnIndex); + List list = null; + if (!StringUtils.hasLength(json)) { + list = objectMapper.readValue(JsonSanitizer.sanitize(json), javaType); + } + return list; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/CryptoTypeHandler.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/CryptoTypeHandler.java new file mode 100644 index 0000000..fb2b2b6 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/CryptoTypeHandler.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.common.typehandler; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.util.AESUtil; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * CryptoTypeHandler + * + * @author kongcaizhi + * @since 2021-11-19 + */ +@Slf4j +@MappedJdbcTypes(JdbcType.VARCHAR) +public class CryptoTypeHandler extends BaseTypeHandler { + private static final Integer PASSWORD_LENGTH_WITHOUT_ENCRYPT = 50; + + @Override + public void setNonNullParameter(PreparedStatement preparedStatement, int i, String s, JdbcType jdbcType) + throws SQLException { + preparedStatement.setString(i, doEncrypt(s)); + } + + @Override + public String getNullableResult(ResultSet resultSet, String s) throws SQLException { + return doDecruypt(resultSet.getString(s)); + } + + @Override + public String getNullableResult(ResultSet resultSet, int i) throws SQLException { + return doDecruypt(resultSet.getString(i)); + } + + @Override + public String getNullableResult(CallableStatement callableStatement, int i) throws SQLException { + return doDecruypt(callableStatement.getString(i)); + } + + private String doEncrypt(String password) { + return AESUtil.gcmEncrypt(password, AESUtil.CRYPTO.getAesDefaultKey(), AESUtil.CRYPTO.getAesDefaultAad()); + } + + private String doDecruypt(String password) { + if (!isEncrypt(password)) { + throw new BaseException("password decruypt failed"); + } + return AESUtil.gcmDecrypt(password, AESUtil.CRYPTO.getAesDefaultKey()); + } + + private boolean isEncrypt(String password) { + return (StringUtils.isNotEmpty(password) && password.length() > PASSWORD_LENGTH_WITHOUT_ENCRYPT) + ? true : false; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/JacksonTypeHandler.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/JacksonTypeHandler.java new file mode 100644 index 0000000..5fe1e0e --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/common/typehandler/JacksonTypeHandler.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.common.typehandler; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.ibatis.exceptions.PersistenceException; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; + +import java.io.IOException; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * JacksonTypeHandler + * + * @author kongcaizhi + * @since 2021-11-19 + */ +@Slf4j +@MappedJdbcTypes(JdbcType.VARCHAR) +public class JacksonTypeHandler extends BaseTypeHandler { + private static final ObjectMapper OBJECT_MAPPER; + + static { + OBJECT_MAPPER = new ObjectMapper(); + OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + private final Class type; + + /** + * JacksonTypeHandler + * + * @param type Class + */ + public JacksonTypeHandler(Class type) { + if (log.isTraceEnabled()) { + log.trace("JacksonTypeHandler ({})", type); + } + if (type == null) { + throw new PersistenceException("Type argument cannot be null"); + } + this.type = type; + } + + private T parse(String json) { + T object = null; + try { + if (!(json == null || json.length() == 0)) { + object = OBJECT_MAPPER.readValue(json, type); + } + return object; + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new BaseException(e.getMessage()); + } + } + + private String toJsonString(T obj) { + try { + return OBJECT_MAPPER.writeValueAsString(obj); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + throw new BaseException(e.getMessage()); + } + } + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, toJsonString(parameter)); + } + + @Override + public T getNullableResult(ResultSet rs, String columnName) throws SQLException { + return parse(rs.getString(columnName)); + } + + @Override + public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return parse(rs.getString(columnIndex)); + } + + @Override + public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return parse(cs.getString(columnIndex)); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/controller/LabEnvController.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/controller/LabEnvController.java new file mode 100644 index 0000000..5991761 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/controller/LabEnvController.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.controller; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.service.LabEnvService; +import com.huawei.ic.openlab.cloudtest.service.TarFileService; +import com.huawei.ic.openlab.cloudtest.util.Constants; +import com.huawei.ic.openlab.cloudtest.util.NormalResp; + +import lombok.extern.slf4j.Slf4j; + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.List; +import java.util.Objects; + +/** + * 实验室环境测试控制器类 + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +@RestController +@RequestMapping(value = "/api/v1", produces = MediaType.APPLICATION_JSON_VALUE) +public class LabEnvController { + private final TarFileService tarFileService; + private final LabEnvService labEnvService; + + + /** + * LabEnvController + * @param tarFileService labEnvService + * @param service LabEnvService + */ + @Autowired + public LabEnvController(TarFileService tarFileService, LabEnvService labEnvService) { + this.tarFileService = tarFileService; + this.labEnvService = labEnvService; + } + + /** + * 测试远程实验室连接是否正常 + * + * @param ip ip + * @param port port + * @param userName username + * @param passWord password + * @return response string + */ + @GetMapping(value = "/report") + public String setTestFile(@RequestParam(value = "file") String file, @RequestParam(value = "savePath") String savePath) throws IOException { + if (!Objects.requireNonNull(file).matches("^.*\\.tar.gz$")) { + throw new BaseException("文件后缀错误"); + } + labEnvService.resultJson(file, savePath); + return "success"; + } +} \ No newline at end of file diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudDevUseRecordDao.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudDevUseRecordDao.java new file mode 100644 index 0000000..e44bd19 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudDevUseRecordDao.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +/** + * 云开发平台访问记录 + * + * @since 2023-01-16 + * @author kongcaizhi + */ + +public interface CloudDevUseRecordDao { + /** + * Get record by taskId + * + * @param taskDeviceId task id + * @param kpToken kp token + * @return response string + */ + String getRecordById(@Param("taskDeviceId") String taskDeviceId, + @Param("kpToken") String kpToken); + + /** + * insert record + * + * @param requestTime requestTime + * @param taskDeviceId taskDeviceId + * @param kpToken KP TOKEN + * @return RESPONSE STRING + */ + int insertRecord(@Param("requestTime") String requestTime, + @Param("taskDeviceId") String taskDeviceId, + @Param("kpToken") String kpToken); +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudLabTestTaskDao.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudLabTestTaskDao.java new file mode 100644 index 0000000..a398515 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/CloudLabTestTaskDao.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.dao; + +import com.huawei.ic.openlab.cloudtest.entity.CloudLabTestTask; +import com.huawei.ic.openlab.cloudtest.entity.LabTestReq; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * CloudLabTestTaskDao + * + * @author kongcaizhi + * @since 2021-12-15 + */ + +public interface CloudLabTestTaskDao { + /** + * get Test Task + * + * @param projectId projectId + * @return CloudLabTestTask + */ + CloudLabTestTask getTestTask(@Param("projectId") String projectId); + + /** + * get Ongoing Task + * + * @param data LabTestReq + * @return Task + */ + List getOngoingTask(@Param("data") LabTestReq data); + + /** + * set Test Task + * + * @param projectId projectId + * @param data data + */ + void setTestTask(@Param("projectId") String projectId, + @Param("data") CloudLabTestTask data); + + /** + * update Project Status + * + * @param projectId projectId + * @param status status + * @param startTime start Time + * @param finishTime finish Time + * @param statusDesc status Desc + * @return update num + */ + int updateProjectStatus(@Param("projectId") String projectId, + @Param("status") Integer status, + @Param("startTime") String startTime, + @Param("finishTime") String finishTime, + @Param("statusDesc") String statusDesc); + + /** + * update Upload File + * + * @param projectId projectId + * @param userId userId + * @param column column + * @param data data + * @param ip ip + * @return update num + */ + int updateUploadFile(@Param("projectId") String projectId, + @Param("userId") String userId, + @Param("column") String column, + @Param("data") CloudLabTestTask.UploadFile data, + @Param("ip") String ip); + + /** + * update Step Status + * + * @param data data + * @param testBeginTime test Begin Time + * @param projectId projectId + * @return update num + */ + int updateStepStatus(@Param("data") CloudLabTestTask.StepStatus data, + @Param("testBeginTime") CloudLabTestTask.TestBeginTime testBeginTime, + @Param("projectId") String projectId); + + /** + * update With Exception File + * + * @param data CloudLabTestTask + * @return update num + */ + int updateWithExceptionFile(@Param("data") CloudLabTestTask data); + + /** + * update Compatibility Result + * + * @param data CloudLabTestTask + * @return update num + */ + int updateCompatibilityResult(@Param("data") CloudLabTestTask data); + + /** + * update Performance Result + * + * @param data CloudLabTestTask + * @return update num + */ + int updatePerformanceResult(@Param("data") CloudLabTestTask data); +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/PerformanceServiceDao.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/PerformanceServiceDao.java new file mode 100644 index 0000000..a54979c --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/dao/PerformanceServiceDao.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.dao; + +import com.huawei.ic.openlab.cloudtest.entity.PerformanceService; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * PerformanceServiceDao + * + * @author kongcaizhi + * @since 2021-12-15 + */ + +public interface PerformanceServiceDao { + /** + * Get Performance service + * + * @return get record + */ + List getPerformanceService(); + + /** + * Get Idle Service + * + * @return get record + */ + PerformanceService getIdleService(); + + /** + * add task + * + * @param serviceIp service ip + * @return add record + */ + int addTask(@Param("serviceIp") String serviceIp); + + /** + * Subtract task + * + * @param serviceIp service IP + * @return record + */ + int subtractTask(@Param("serviceIp") String serviceIp); +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/CloudLabTestTask.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/CloudLabTestTask.java new file mode 100644 index 0000000..351a793 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/CloudLabTestTask.java @@ -0,0 +1,282 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * 远程实验室测试实体类 + * + * @author kongcaizhi + * @since 2021-11-11 + */ +@Data +public class CloudLabTestTask { + private String projectId; + private String userId; + private String serverIp; + private int serverPort; + private String serverUser; + private String serverPassword; + + private int projectStatus = 0; + private String statusDesc; + + private String requestTime; + private String startTime; + private String finishTime; + + @JsonProperty(value = "compatibilityTest") + private boolean isCompatibilityTest; + @JsonProperty(value = "reliabilityTest") + private boolean isReliabilityTest; + @JsonProperty(value = "securityTest") + private boolean isSecurityTest; + @JsonProperty(value = "functionTest") + private boolean isFunctionTest; + @JsonProperty(value = "performanceTest") + private boolean isPerformanceTest; + + private StepStatus stepStatus; + private String currentStatus; + private UploadFile functionFile; + private UploadFile performanceFile; + private UploadFile resultFile; + private TestCaseSummary testSummary; + private List testDetail; + private ScriptResultConfig scriptResultConfig; + private String performanceService; + private TestBeginTime testBeginTime; + private String taskLanguage; + + /** + * StepStatus + * + * @author kongcaizhi + * @since 2021-11-11 + */ + @AllArgsConstructor + @NoArgsConstructor + @Data + public static class StepStatus { + private String step1Code; + private String step1Time; + private UploadFile step1File; + private String step2Code; + private String step2Time; + private UploadFile step2File; + private String step3Code; + private String step3Time; + private UploadFile step3File; + private String step4Code; + private String step4Time; + private UploadFile step4File; + private String step5Code; + private String step5Time; + private UploadFile step5File; + private String step6Code; + private String step6Time; + private UploadFile step6File; + private String step7Code; + private String step7Time; + private UploadFile step7File; + private String step8Code; + private String step8Time; + private UploadFile step8File; + private String step9Code; + private String step9Time; + private UploadFile step9File; + private String step10Code; + private String step10Time; + private UploadFile step10File; + private String functionCode; + private String functionTime; + private UploadFile functionFile; + private String performanceCode; + private String performanceTime; + private UploadFile performanceFile; + + /** + * set Step1 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep1(String resultCode, String timeString) { + this.setStep1Code(resultCode); + this.setStep1Time(timeString); + } + + /** + * set Step2 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep2(String resultCode, String timeString) { + this.setStep2Code(resultCode); + this.setStep2Time(timeString); + } + + /** + * set Step3 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep3(String resultCode, String timeString) { + if (StringUtils.isNoneEmpty(this.getStep3Code())) { + this.setStep3Code(this.getStep3Code() + ";" + resultCode); + } else { + this.setStep3Code(resultCode); + } + this.setStep3Time(timeString); + } + + /** + * set Step4 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep4(String resultCode, String timeString) { + this.setStep4Code(resultCode); + this.setStep4Time(timeString); + } + + /** + * set Step5 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep5(String resultCode, String timeString) { + this.setStep5Code(resultCode); + this.setStep5Time(timeString); + } + + /** + * set Step6 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep6(String resultCode, String timeString) { + this.setStep6Code(resultCode); + this.setStep6Time(timeString); + } + + /** + * set Step7 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep7(String resultCode, String timeString) { + this.setStep7Code(resultCode); + this.setStep7Time(timeString); + } + + /** + * set Step8 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep8(String resultCode, String timeString) { + this.setStep8Code(resultCode); + this.setStep8Time(timeString); + } + + /** + * set Step9 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep9(String resultCode, String timeString) { + this.setStep9Code(resultCode); + this.setStep9Time(timeString); + } + + /** + * set Step10 + * + * @param resultCode resultCode + * @param timeString timeString + */ + public void setStep10(String resultCode, String timeString) { + this.setStep10Code(resultCode); + this.setStep10Time(timeString); + } + } + + /** + * UploadFile + * + * @author kongcaizhi + * @since 2021-11-11 + */ + @AllArgsConstructor + @NoArgsConstructor + @Data + public static class UploadFile { + private String fileDesc; + private String fileStatus; + private String fileId; + private String fileName; + private String filePath; + } + + /** + * TestBeginTime + * + * @author kongcaizhi + * @since 2021-11-11 + */ + @AllArgsConstructor + @NoArgsConstructor + @Data + public static class TestBeginTime { + private String compatibilityTime; + private String reliabilityTime; + private String securityTime; + private String functionTime; + private String performanceTime; + } + + /** + * TestCaseSummary + * + * @author kongcaizhi + * @since 2021-11-11 + */ + @AllArgsConstructor + @NoArgsConstructor + @Data + public static class TestCaseSummary { + private TestCaseResultCount function; + private TestCaseResultCount performance; + private TestCaseResultCount security; + private TestCaseResultCount compatibility; + private TestCaseResultCount reliability; + + public TestCaseSummary(TestCaseResultCount function, TestCaseResultCount security, + TestCaseResultCount compatibility, TestCaseResultCount reliability) { + this.function = function; + this.security = security; + this.compatibility = compatibility; + this.reliability = reliability; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/LabTestReq.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/LabTestReq.java new file mode 100644 index 0000000..a149413 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/LabTestReq.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +/** + * 网站请求蓝区兼容性测试实体类 + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@Data +public class LabTestReq { + private String projectId; + private String userId; + + private String serverIp; + private int serverPort; + private String serverUser; + private String serverPassword; + + @JsonProperty(value = "compatibilityTest") + private boolean isCompatibilityTest; + @JsonProperty(value = "reliabilityTest") + private boolean isReliabilityTest; + @JsonProperty(value = "securityTest") + private boolean isSecurityTest; + @JsonProperty(value = "functionTest") + private boolean isFunctionTest; + @JsonProperty(value = "performance") + private boolean isPerformanceTest; + + private String deployDir; + private String applicationNames; + private String startAppCommands; + private String stopAppCommands; + + private int webPort; + + @JsonProperty(value = "language", defaultValue = "CN") + private String taskLanguage; +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/MqsMessage.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/MqsMessage.java new file mode 100644 index 0000000..35020a7 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/MqsMessage.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * MQSMessage + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@Data +public class MqsMessage { + private String projectId; + private String userId; + private String serverIp; + private String status; + private String statusDesc; + private String statusTime; + private MessageDetail detail; + private MessageResult testResult; + + /** + * MessageDetail + * + * @author kongcaizhi + * @since 2021-10-30 + */ + @AllArgsConstructor + @NoArgsConstructor + @Data + public static class MessageDetail { + private String step; + private String stepStatus; + private String exceptionType; + private String exceptionDesc; + private String exceptionFileName; + private String resultFileName; + private String fileStatus; + + /** + * DEPENDENCY_INSTALL_SUCCESS + */ + public void setDependencyInstallSuccess() { + this.setStep(Constants.DEPENDENCY_INSTALL_DESC); + this.setStepStatus(Constants.TEST_FINISHED_CN); + } + + /** + * APP_START_SUCCESS + */ + public void setAppStartSuccess() { + this.setStep(Constants.DEPENDENCY_INSTALL_DESC); + this.setStepStatus(Constants.TEST_FINISHED_CN); + } + + /** + * APP_STOP_SUCCESS + * + * @param isCompatibilityTest isCompatibilityTest + * @param isReliabilityTest isReliabilityTest + * @param isSecurityTest isSecurityTest + */ + public void setAppStopSuccess(boolean isCompatibilityTest, boolean isReliabilityTest, boolean isSecurityTest) { + this.setStep(Constants.APP_STOP_DESC); + this.setStepStatus(Constants.TEST_FINISHED_CN); + if (isCompatibilityTest) { + this.setStep(Constants.COMPATIBILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + if (isReliabilityTest) { + this.setStep(Constants.RELIABILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + if (isSecurityTest) { + this.setStep(Constants.SECURITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + } + + /** + * COM_START_SUCCESS + * + * @param isReliabilityTest isReliabilityTest + * @param isSecurityTest isSecurityTest + */ + public void setComStartSuccess(boolean isReliabilityTest, boolean isSecurityTest) { + this.setStep(Constants.COMPATIBILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + if (isReliabilityTest) { + this.setStep(Constants.RELIABILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + if (isSecurityTest) { + this.setStep(Constants.SECURITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + } + + /** + * PORT_TEST_SUCCESS + */ + public void setPortTestSuccess() { + this.setStep(Constants.DEPENDENCY_INSTALL_DESC); + this.setStepStatus(Constants.TEST_FINISHED_CN); + } + + /** + * VIRUS_SCAN_SUCCESS + * + * @param isCompatibilityTest isCompatibilityTest + * @param isReliabilityTest isReliabilityTest + */ + public void setVirusScanSuccess(boolean isCompatibilityTest, boolean isReliabilityTest) { + this.setStep(Constants.SECURITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + if (isCompatibilityTest) { + this.setStep(Constants.COMPATIBILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + if (isReliabilityTest) { + this.setStep(Constants.RELIABILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + } + + /** + * VULNERABLE_SCAN_SUCCESS + * + * @param isCompatibilityTest isCompatibilityTest + * @param isReliabilityTest isReliabilityTest + */ + public void setVulnerableScanSuccess(boolean isCompatibilityTest, boolean isReliabilityTest) { + this.setStep(Constants.SECURITY_TEST_DESC); + this.setStepStatus(Constants.TEST_FINISHED_CN); + if (isCompatibilityTest) { + this.setStep(Constants.COMPATIBILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + if (isReliabilityTest) { + this.setStep(Constants.RELIABILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + } + + /** + * EXCEPTION_TEST_FINISH + * + * @param isCompatibilityTest isCompatibilityTest + */ + public void setExceptionTestFinish(boolean isCompatibilityTest) { + this.setStep(Constants.RELIABILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_FINISHED_CN); + if (isCompatibilityTest) { + this.setStep(Constants.COMPATIBILITY_TEST_DESC); + this.setStepStatus(Constants.TEST_PROCESSING); + } + } + } + + /** + * MessageResult + * + * @author kongcaizhi + * @since 2021-10-30 + */ + @AllArgsConstructor + @NoArgsConstructor + @Data + public static class MessageResult { + private CloudLabTestTask.TestCaseSummary testSummary; + private List testDetail; + private ScriptResultConfig scriptResultConfig; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/PerformanceService.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/PerformanceService.java new file mode 100644 index 0000000..c5d1602 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/PerformanceService.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import lombok.Data; + +/** + * PerformanceService + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@Data +public class PerformanceService { + private String id; + private String deviceId; + private String serviceIp; + private String loginAccount; + private String loginPassword; + private String status; + private int taskNum; +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/ScriptResultConfig.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/ScriptResultConfig.java new file mode 100644 index 0000000..7ff6688 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/ScriptResultConfig.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import lombok.Data; + +/** + * ScriptResultConfig + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@Data +public class ScriptResultConfig { + private String applicationNames; + private String startAppCommands; + private String stopAppCommands; + private String osVersion; +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/SystemParams.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/SystemParams.java new file mode 100644 index 0000000..51f8b82 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/SystemParams.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import lombok.Data; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * SystemParams + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@Component +@Data +public class SystemParams { + @Value("${scriptConfigCn}") + private String scriptConfigCn; + + @Value("${scriptConfigEn}") + private String scriptConfigEn; + + @Value("${tempDir}") + private String tempDir; + + @Value("${deployIp}") + private String deployIP; + + @Value("${uploadFileDir}") + private String uploadFileDir; + + @Value("${appId}") + private String appId; + + @Value("${appKey}") + private String appKey; + + @Value("${mqsTopic}") + private String mqsTopic; + + @Value("${mqsUrl}") + private String mqsUrl; + + @Value("${clamdIp}") + private String clamdIp; + + @Value("${clamdPort}") + private int clamdPort; + + @Value("${performanceTestUrl}") + private String performanceTestUrl; + + + @Value("${appIdUat}") + private String appIdUat; + + @Value("${appKeyUat}") + private String appKeyUat; + + @Value("${mqsTopicUat}") + private String mqsTopicUat; + + @Value("${mqsUrlUat}") + private String mqsUrlUat; + + @Value("${kunpengServiceUrl}") + private String kunpengServiceUrl; + + /** + * get Script Config + * + * @param language language + * @return Config + */ + public String getScriptConfig(String language) { + return "CN".equals(language) ? scriptConfigCn : scriptConfigEn; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TaskDelay.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TaskDelay.java new file mode 100644 index 0000000..8ed1261 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TaskDelay.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import com.huawei.ic.openlab.cloudtest.util.Constants; +import com.huawei.ic.openlab.cloudtest.util.ToolUtil; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * TaskDelay + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@Data +@Slf4j +@AllArgsConstructor +@NoArgsConstructor +public class TaskDelay { + private static final long PERFORMANCE_DELAY = 60 * 60 * 1000L; + private static final long DELAY = 60 * 60 * 1000L; + + private String projectId; + private Long startTime; + private Long updateTime; + private String currentStatus; + + /** + * 更新任务状态 + * + * @param currentStatus currentStatus + */ + public void updateCurrentStatus(String currentStatus) { + this.updateTime = ToolUtil.getMillionSeconds(); + this.currentStatus = currentStatus; + } + + /** + * 判断任务是否过期 + * + * @return isExpired + */ + public boolean isExpired() { + if (Constants.PERFORMANCE_TESTING.equals(currentStatus)) { + return (ToolUtil.getMillionSeconds() - this.updateTime) > PERFORMANCE_DELAY; + } else { + return (ToolUtil.getMillionSeconds() - this.updateTime) > DELAY; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResult.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResult.java new file mode 100644 index 0000000..e488989 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResult.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; + +import lombok.Data; + +import org.springframework.util.StringUtils; + +import java.util.List; + +/** + * TaskDelay + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@Data +public class TestCaseResult { + private String id; + private String result; + private String evidence; + private String reason; + + /** + * transferResult + * + * @return String + */ + public String transferResult() { + if (Constants.TEST_PASSED.equals(result)) { + return "通过"; + } else { + return "不通过"; + } + } + + /** + * transferEvidence + * + * @return String + */ + public String transferEvidence() { + JSONArray array = JSON.parseArray(evidence); + List list = array.toJavaList(String.class); + return String.join("", list); + } + + /** + * transferReason + * + * @return String + */ + public String transferReason() { + if (StringUtils.hasLength(reason)) { + return ",原因为:" + reason; + } else { + return ""; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResultCount.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResultCount.java new file mode 100644 index 0000000..1f3a984 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/TestCaseResultCount.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity; + +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * TestCaseResultCount + * + * @author kongcaizhi + * @since 2021-10-30 + */ +@AllArgsConstructor +@NoArgsConstructor +@Data +public class TestCaseResultCount { + private int total = 0; + private int passed = 0; + private int failed = 0; + private String startTime; + + /** + * add result + * + * @param result result + */ + public void add(String result) { + if (Constants.TEST_PASSED.equals(result)) { + passed += 1; + } else { + failed += 1; + } + total += 1; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityFilesParser.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityFilesParser.java new file mode 100644 index 0000000..d4884e1 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityFilesParser.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis; + +import java.io.IOException; + +/** + * CompatibilityFilesParser + * + * @author kongcaizhi + * @since 2021-12-15 + */ +public interface CompatibilityFilesParser { + /** + * Get result + * + * @return CompatibilityTestResult + * @throws IOException exception + */ + CompatibilityTestResult getResult() throws IOException; + + /** + * parseFiles + * + * @return CompatibilityTestResult + * @throws IOException exception + */ + CompatibilityTestResult parseFiles() throws IOException; +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityTestResult.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityTestResult.java new file mode 100644 index 0000000..56776b8 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/CompatibilityTestResult.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * CompatibilityTestResult + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Data +public class CompatibilityTestResult { + private String id; + private String result; + private List evidence = new ArrayList<>(); + private List evidenceEn = new ArrayList<>(); + private String reason; + private String reasonEn; + private String osVersion; + private List applicationNames; + private List startAppCommands; + private List stopAppCommands; + private List deployDir; + + /** + * CompatibilityTestResult + * + * @param testName test Name + */ + public CompatibilityTestResult(String testName) { + this.id = testName; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseFunctionTestLog.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseFunctionTestLog.java new file mode 100644 index 0000000..715878d --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseFunctionTestLog.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import com.alibaba.fastjson.JSONObject; + +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * ParseFunctionTestLog + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseFunctionTestLog { + private static final Pattern RUN_PATTERN = Pattern.compile(Constants.PYTEST_RUN_PATTERN); + private static final Pattern SUCCESS_PATTERN = Pattern.compile(Constants.PYTEST_SUCCESS_PATTERN); + private static final Pattern FAIL_PATTERN = Pattern.compile(Constants.PYTEST_FAILED_PATTERN); + private static final Pattern SHELL_TEST_PATTERN = Pattern.compile(Constants.SHELL_UNIT_TEST_PATTERN); + private static final Pattern SHELL_RUN_PATTERN = Pattern.compile(Constants.SHELL_UNIT_RUN_PATTERN); + private static final Pattern SHELL_FAIL_PATTERN = Pattern.compile(Constants.SHELL_UNIT_FAILED_PATTERN); + + private final byte[] shellBytes; + private final byte[] pytestBytes; + + /** + * constructin function + * + * @param shellBytes shellBytes + * @param pytestBytes pytestBytes + */ + public ParseFunctionTestLog(byte[] shellBytes, byte[] pytestBytes) { + this.shellBytes = shellBytes; + this.pytestBytes = pytestBytes; + } + + /** + * get Shell Result + * + * @return CompatibilityTestResult + * @throws IOException IOException + */ + public CompatibilityTestResult getShellResult() { + Map resultMap = new HashMap<>(); + resultMap.put(Constants.TEST_FAILED, 0); + resultMap.put(Constants.TEST_PASSED, 0); + + List evidenceList = matches(resultMap); + CompatibilityTestResult testResult = new CompatibilityTestResult("Function_Test"); + testResult.setEvidence(evidenceList); + testResult.setReason(JSONObject.toJSONString(resultMap)); + return testResult; + } + + private List matches(Map resultMap) { + List evidenceList = new ArrayList<>(); + try (InputStream inputStream = new ByteArrayInputStream(shellBytes); + BufferedReader reader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String line; + int totalTest = 0; + while ((line = reader.readLine()) != null) { + match(line, evidenceList, resultMap, totalTest); + } + } catch (IOException e) { + throw new BaseException(e.getMessage()); + } + return evidenceList; + } + + private void match(String line, List evidenceList, Map resultMap, + int totalTest) { + int failTest; + int total = totalTest; + Matcher testMatch = SHELL_TEST_PATTERN.matcher(line); + if (testMatch.find()) { + evidenceList.add(line.replace(System.lineSeparator(), "")); + } + Matcher matcher = SHELL_RUN_PATTERN.matcher(line); + if (matcher.find()) { + evidenceList.add(line.replace(System.lineSeparator(), "")); + try { + total = Integer.parseInt(matcher.group(1).trim()); + } catch (NumberFormatException ex) { + total = 0; + } + } + if (line.matches("^\\\u001B\\[1;32mOK\\\u001B\\[0m")) { + evidenceList.add(line.replace(System.lineSeparator(), "")); + resultMap.put(Constants.TEST_PASSED, total + resultMap.get(Constants.TEST_PASSED)); + total = 0; + } + Matcher failedMatcher = SHELL_FAIL_PATTERN.matcher(line); + if (failedMatcher.find()) { + evidenceList.add(line.replace(System.lineSeparator(), "")); + try { + failTest = Integer.parseInt(failedMatcher.group(1).trim()); + } catch (NumberFormatException ex) { + failTest = 0; + } + if (failTest > total) { + failTest = total; + } + resultMap.put(Constants.TEST_FAILED, failTest + resultMap.get(Constants.TEST_FAILED)); + if (total != 0) { + resultMap.put(Constants.TEST_PASSED, + total - failTest + resultMap.get(Constants.TEST_PASSED)); + } + } + } + + private CompatibilityTestResult getPytestResult() { + List evidenceList = new ArrayList<>(); + Map resultMap = new HashMap<>(); + resultMap.put(Constants.TEST_FAILED, 0); + resultMap.put(Constants.TEST_PASSED, 0); + + try (InputStream inputStream = new ByteArrayInputStream(pytestBytes); + BufferedReader reader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + matcher(line, evidenceList, resultMap); + } + } catch (IOException e) { + throw new BaseException(e.getMessage()); + } + CompatibilityTestResult testResult = new CompatibilityTestResult("Function_Test"); + testResult.setReason(JSONObject.toJSONString(resultMap)); + testResult.setEvidence(evidenceList); + return testResult; + } + + private void matcher(String line, List evidenceList, Map resultMap) { + Matcher runMatcher = RUN_PATTERN.matcher(line); + if (runMatcher.find()) { + evidenceList.add(line.replace(System.lineSeparator(), "")); + } + Matcher matcher = SUCCESS_PATTERN.matcher(line); + if (matcher.find()) { + evidenceList.add(line.replace(System.lineSeparator(), "")); + try { + resultMap.put(Constants.TEST_PASSED, + Integer.parseInt(matcher.group(1).trim()) + resultMap.get(Constants.TEST_PASSED)); + } catch (NumberFormatException ex) { + log.error("Error in parsing Python test results {}", line); + } + } + Matcher failedMatcher = FAIL_PATTERN.matcher(line); + if (failedMatcher.find()) { + evidenceList.add(line.replace(System.lineSeparator(), "")); + try { + resultMap.put(Constants.TEST_PASSED, + Integer.parseInt(failedMatcher.group(2).trim()) + + resultMap.get(Constants.TEST_PASSED)); + resultMap.put(Constants.TEST_FAILED, + Integer.parseInt(failedMatcher.group(1).trim()) + + resultMap.get(Constants.TEST_FAILED)); + } catch (NumberFormatException ex) { + log.error("Error in parsing Python test results {}", line); + } + } + } + + /** + * parseFunctionTestLog + * + * @return CompatibilityTestResult + */ + public CompatibilityTestResult parseFunctionTestLog() { + Map resultMap = new HashMap<>(); + List evidenceList = new ArrayList<>(); + CompatibilityTestResult testResult = new CompatibilityTestResult("Function_Test"); + try { + if (shellBytes.length != 0) { + CompatibilityTestResult shellResult = getShellResult(); + if (shellResult.getEvidence() != null && shellResult.getEvidence().size() > 0) { + evidenceList.addAll(shellResult.getEvidence()); + } + if (shellResult.getReason() != null) { + JSONObject jsonObject = JSONObject.parseObject(shellResult.getReason()); + resultMap.put(Constants.TEST_FAILED, jsonObject.getIntValue(Constants.TEST_FAILED)); + resultMap.put(Constants.TEST_PASSED, jsonObject.getIntValue(Constants.TEST_PASSED)); + } + } + if (pytestBytes.length != 0) { + CompatibilityTestResult pytestResult = getPytestResult(); + if (pytestResult.getEvidence() != null && pytestResult.getEvidence().size() > 0) { + evidenceList.addAll(pytestResult.getEvidence()); + } + if (pytestResult.getReason() != null) { + JSONObject jsonObject = JSONObject.parseObject(pytestResult.getReason()); + resultMap.put(Constants.TEST_FAILED, resultMap.getOrDefault(Constants.TEST_FAILED, 0) + + jsonObject.getIntValue(Constants.TEST_FAILED)); + resultMap.put(Constants.TEST_PASSED, resultMap.getOrDefault(Constants.TEST_PASSED, 0) + + jsonObject.getIntValue(Constants.TEST_PASSED)); + } + } + testResult.setResult(Constants.TEST_PASSED); + testResult.setReason(JSONObject.toJSONString(resultMap)); + testResult.setEvidence(evidenceList); + if (pytestBytes.length == 0 & shellBytes.length == 0) { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason("没有功能测试文件"); + } + } catch (BaseException e) { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason("功能测试文件解析出错"); + } + return testResult; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseInfoLog.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseInfoLog.java new file mode 100644 index 0000000..6a3e6a7 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseInfoLog.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis; + +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * ParseInfoLog + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseInfoLog { + private final byte[] infoLogBytes; + private String osVersion; + + /** + * construction function + * + * @param infoLogBytes info log bytes + * @param osVersion os version + */ + public ParseInfoLog(byte[] infoLogBytes, String osVersion) { + this.infoLogBytes = infoLogBytes; + this.osVersion = osVersion; + } + + private Map initMap() { + Map resultMap = new HashMap<>(); + resultMap.put(Constants.CompatibilityTestName.APPLICATION_START.getTestName(), + new CompatibilityTestResult(Constants.CompatibilityTestName.APPLICATION_START.getTestName())); + resultMap.put(Constants.CompatibilityTestName.APPLICATION_STOP.getTestName(), + new CompatibilityTestResult(Constants.CompatibilityTestName.APPLICATION_STOP.getTestName())); + resultMap.put(Constants.CompatibilityTestName.EXCEPTION_KILL.getTestName(), + new CompatibilityTestResult(Constants.CompatibilityTestName.EXCEPTION_KILL.getTestName())); + return resultMap; + } + + /** + * parse info log + * + * @return Map + */ + public Map parseInfoLog() { + Map resultMap = initMap(); + if (infoLogBytes.length == 0) { + for (Map.Entry entry : resultMap.entrySet()) { + CompatibilityTestResult testResult = entry.getValue(); + testResult.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get("FILE_NOT_EXIT").getTestResult()); + testResult.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get("FILE_NOT_EXIT").getTestReason()); + testResult.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get("FILE_NOT_EXIT").getTestReasonEn()); + entry.setValue(testResult); + } + return resultMap; + } + try { + resultMap = readInfoLog(); + } catch (IllegalStateException | IOException ex) { + log.error("Exception in parsing info.log ", ex); + for (Map.Entry entry : resultMap.entrySet()) { + CompatibilityTestResult testResult = entry.getValue(); + testResult.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get("READ_ERROR").getTestResult()); + testResult.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get("READ_ERROR").getTestReason()); + testResult.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get("READ_ERROR").getTestReasonEn()); + entry.setValue(testResult); + } + } catch (Exception ex) { + log.error("Exception in uncompressing info.log ", ex); + for (Map.Entry entry : resultMap.entrySet()) { + CompatibilityTestResult testResult = entry.getValue(); + testResult.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get("UNZIP_ERROR").getTestResult()); + testResult.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get("UNZIP_ERROR").getTestReason()); + testResult.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get("UNZIP_ERROR").getTestReasonEn()); + entry.setValue(testResult); + } + } + return resultMap; + } + + /** + * get os version + * + * @return os version + */ + public String getOsVersion() { + return osVersion; + } + + /** + * 读取Info日志 + * + * @return map + * @throws IOException exception + */ + private Map readInfoLog() throws IOException { + Map> evidenceMap = new HashMap<>(); + + try (InputStream inputStream = new ByteArrayInputStream(infoLogBytes); + BufferedReader reader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + List beginTestIndex = new ArrayList<>(); + String line; + int count = 0; + reader.mark(infoLogBytes.length + 1); + while ((line = reader.readLine()) != null) { + count++; + if (StringUtils.contains(line, Constants.START_TEST_STRING) || StringUtils.contains(line, + Constants.START_TEST_STRING_EN)) { + beginTestIndex.add(count); + } + } + int lastBeginTest = Collections.max(beginTestIndex); + reader.reset(); + + for (int i = 0; i <= lastBeginTest; i++) { + reader.readLine(); + } + + StringBuilder stringBuilder = new StringBuilder(16); + while ((line = reader.readLine()) != null) { + stringBuilder.append(line).append(System.lineSeparator()); + } + + Matcher osMatcher = Pattern.compile(Constants.OS_PATTERN_CN).matcher(stringBuilder.toString()); + if (osMatcher.find()) { + osVersion = osMatcher.group(3); + } + for (Map.Entry entry : Constants.LOG_WHITE_RULES.entrySet()) { + Pattern pattern = entry.getValue(); + Matcher matcher = pattern.matcher(stringBuilder.toString()); + if (matcher.find()) { + List evidenceList = evidenceMap.getOrDefault(entry.getKey(), new ArrayList<>()); + evidenceList.add(matcher.group(0).replace(System.lineSeparator(), "")); + evidenceMap.put(entry.getKey(), evidenceList); + } + } + } + return getResultMap(evidenceMap); + } + + /** + * 根据日志解析内容,返回用例结果. + * + * @param evidenceMap map + * @return map + */ + private Map getResultMap(Map> evidenceMap) { + CompatibilityTestResult startTest = + new CompatibilityTestResult(Constants.CompatibilityTestName.APPLICATION_START.getTestName()); + CompatibilityTestResult stopTest = + new CompatibilityTestResult(Constants.CompatibilityTestName.APPLICATION_STOP.getTestName()); + CompatibilityTestResult exceptionTest = + new CompatibilityTestResult(Constants.CompatibilityTestName.EXCEPTION_KILL.getTestName()); + startTest.setOsVersion(getOsVersion()); + + if (evidenceMap.size() > 0) { + for (Map.Entry> entry : evidenceMap.entrySet()) { + if (entry.getKey().contains("START_APP")) { + startTest.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestResult()); + startTest.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestReason()); + startTest.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestReasonEn()); + startTest.setEvidence(entry.getValue()); + startTest.setEvidenceEn(entry.getValue()); + } + if (entry.getKey().contains("RELIABLE_TEST")) { + exceptionTest.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestResult()); + exceptionTest.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestReason()); + exceptionTest.setReasonEn( + Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestReasonEn()); + exceptionTest.setEvidence(entry.getValue()); + exceptionTest.setEvidenceEn(entry.getValue()); + } + if (entry.getKey().contains("STOP_APP")) { + stopTest.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestResult()); + stopTest.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestReason()); + stopTest.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get(entry.getKey()).getTestReasonEn()); + stopTest.setEvidence(entry.getValue()); + stopTest.setEvidenceEn(entry.getValue()); + } + } + } else { + startTest.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_START_APP").getTestResult()); + startTest.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_START_APP").getTestReason()); + startTest.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_START_APP").getTestReasonEn()); + stopTest.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_STOP_APP").getTestResult()); + stopTest.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_STOP_APP").getTestReason()); + stopTest.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_STOP_APP").getTestReasonEn()); + exceptionTest.setResult(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_RELIABLE_TEST").getTestResult()); + exceptionTest.setReason(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_RELIABLE_TEST").getTestReason()); + exceptionTest.setReasonEn(Constants.INFO_TEST_CASE_RESULT_MAP.get("NO_RELIABLE_TEST").getTestReasonEn()); + } + Map resultMap = new HashMap<>(); + resultMap.put(Constants.CompatibilityTestName.APPLICATION_START.getTestName(), startTest); + resultMap.put(Constants.CompatibilityTestName.APPLICATION_STOP.getTestName(), stopTest); + resultMap.put(Constants.CompatibilityTestName.EXCEPTION_KILL.getTestName(), exceptionTest); + return resultMap; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseSafetyFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseSafetyFiles.java new file mode 100644 index 0000000..74f7f62 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/ParseSafetyFiles.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * ParseSafetyFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseSafetyFiles { + private final byte[] protocolBytes; + private final byte[] udpBytes; + private final byte[] tcpBytes; + + /** + * construction function + * + * @param protocolBytes bytes + * @param udpBytes udp bytes + * @param tcpBytes tcp bytes + */ + public ParseSafetyFiles(byte[] protocolBytes, byte[] udpBytes, byte[] tcpBytes) { + this.protocolBytes = protocolBytes; + this.udpBytes = udpBytes; + this.tcpBytes = tcpBytes; + } + + /** + * get average + * + * @param fileBytes file bytes + * @return average list + * @throws IOException exception + */ + public List getAverage(byte[] fileBytes) throws IOException { + List averageList = new ArrayList<>(); + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader beginReader = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + String line; + while ((line = beginReader.readLine()) != null) { + if (!StringUtils.startsWith(line, "#") + || StringUtils.containsIgnoreCase(line, "# Ports scanned")) { + averageList.add(line.trim()); + } + } + } + return averageList; + } + + /** + * read safety file + * + * @return CompatibilityTestResult + * @throws IOException exception + */ + public CompatibilityTestResult readSafetyFile() throws IOException { + if (protocolBytes.length == 0 || udpBytes.length == 0 || tcpBytes.length == 0) { + throw new BaseException("端口扫描文件缺失"); + } + List protocolList = getAverage(protocolBytes); + List tcpList = getAverage(tcpBytes); + List udpList = getAverage(udpBytes); + + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.SECURITY_PORT.getTestName()); + if (protocolList.size() > 0 && tcpList.size() > 0 && udpList.size() > 0) { + testResult.setResult(Constants.TEST_PASSED); + List evidenceList = new ArrayList<>(); + List evidenceEnList = new ArrayList<>(); + evidenceList.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(5), "PROTOCOL")); + evidenceList.addAll(protocolList); + evidenceList.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(5), "UDP")); + evidenceList.addAll(udpList); + evidenceList.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(5), "TCP")); + evidenceList.addAll(tcpList); + testResult.setEvidence(evidenceList); + evidenceEnList.add(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_EN_LIST.get(5), "PROTOCOL")); + evidenceEnList.addAll(protocolList); + evidenceEnList.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(5), "UDP")); + evidenceEnList.addAll(udpList); + evidenceEnList.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(5), "TCP")); + evidenceEnList.addAll(tcpList); + testResult.setEvidenceEn(evidenceEnList); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SAFETY_FILE_LOSS); + testResult.setReasonEn(Constants.SAFETY_FILE_LOSS_EN); + } + return testResult; + } + + /** + * parseSafetyFile + * + * @return CompatibilityTestResult + */ + public CompatibilityTestResult parseSafetyFile() { + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.SECURITY_PORT.getTestName()); + try { + testResult = readSafetyFile(); + } catch (BaseException ex) { + log.error("Missing security file", ex.getMessage()); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SAFETY_FILE_LOSS); + testResult.setReasonEn(Constants.SAFETY_FILE_LOSS_EN); + } catch (NumberFormatException | IOException ex) { + log.error("Security file parsing error", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_LIST.get(2), "安全测试")); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_EN_LIST.get(2), "security " + + "test")); + } + return testResult; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParseCompatibilityFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParseCompatibilityFiles.java new file mode 100644 index 0000000..2b4aaf3 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParseCompatibilityFiles.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * AbsParseCompatibilityFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +abstract class AbsParseCompatibilityFiles { + private final Map beginByteMap; + private final Map endByteMap; + + /** + * AbsParseCompatibilityFiles init + * + * @param beginByteMap beginByteMap + * @param endByteMap endByteMap + */ + protected AbsParseCompatibilityFiles(Map beginByteMap, Map endByteMap) { + this.beginByteMap = beginByteMap; + this.endByteMap = endByteMap; + } + + /** + * read File + * + * @param beginBytes beginBytes + * @param endBytes endBytes + * @return CompatibilityTestResult + * @throws IOException Exception + */ + abstract CompatibilityTestResult readFile(byte[] beginBytes, byte[] endBytes) throws IOException; + + /** + * Get average rate + * + * @param fileBytes file bytes + * @return average list + * @throws IOException exception + */ + abstract List getAverage(byte[] fileBytes) throws IOException; + + /** + * Get Result + * + * @param testName Test name + * @param fileType file type + * @param fileTypeEn file type in English + * @param descIndex description index + * @return CompatibilityTestResult + * @throws IOException exception + */ + public CompatibilityTestResult getResult(String testName, String fileType, String fileTypeEn, int descIndex) + throws IOException { + if (beginByteMap == null || beginByteMap.size() == 0) { + throw new BaseException(String.format(Locale.ROOT, "解析空载测试%s文件缺失", fileType)); + } + if (endByteMap == null || endByteMap.size() == 0) { + throw new BaseException(String.format(Locale.ROOT, "解析空载测试%s文件缺失", fileType)); + } + List clusterResult = new ArrayList<>(); + List beginFileNames = beginByteMap.keySet().stream().filter(s -> StringUtils.endsWith(s, ".log")) + .collect(Collectors.toList()); + List endFileNames = endByteMap.keySet().stream().filter(s -> StringUtils.endsWith(s, ".log")) + .collect(Collectors.toList()); + + if (beginFileNames.size() > 0 && endFileNames.size() > 0) { + clusterResult.add(readFile(beginByteMap.get(beginFileNames.get(0)), endByteMap.get(endFileNames.get(0)))); + } + + if (clusterResult.size() > 0) { + if (clusterResult.stream().anyMatch(s -> StringUtils.contains(s.getResult(), Constants.TEST_FAILED))) { + return clusterResult.stream().filter(s -> StringUtils.contains(s.getResult(), Constants.TEST_FAILED)) + .collect(Collectors.toList()).get(0); + } else { + return clusterResult.get(0); + } + } + CompatibilityTestResult testResult = new CompatibilityTestResult(testName); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(descIndex), fileType)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(descIndex), + fileTypeEn)); + return testResult; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParsePerformanceFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParsePerformanceFiles.java new file mode 100644 index 0000000..35be92e --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/AbsParsePerformanceFiles.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * AbsParsePerformanceFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +abstract class AbsParsePerformanceFiles { + private final Map inputByteMap; + + /** + * Construction function + * + * @param inputByteMap map + */ + public AbsParsePerformanceFiles(Map inputByteMap) { + this.inputByteMap = inputByteMap; + } + + /** + * Get result + * + * @param testName testName + * @param fileType file Type + * @param fileTypeEn file type in English + * @param descIndex description index + * @return CompatibilityTestResult object + * @throws IOException IOException + */ + public CompatibilityTestResult getResult(String testName, String fileType, String fileTypeEn, int descIndex) + throws IOException { + CompatibilityTestResult testResult = new CompatibilityTestResult(testName); + if (inputByteMap == null || inputByteMap.size() == 0) { + throw new BaseException(String.format(Locale.ROOT, "解析压力测试%s文件缺失", fileType)); + } + List beginFileNames = inputByteMap.keySet().stream().filter(s -> StringUtils.endsWith(s, ".log")) + .collect(Collectors.toList()); + if (beginFileNames.size() > 0) { + return readFile(inputByteMap.get(beginFileNames.get(0))); + } + + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(descIndex), fileType)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(descIndex), + fileTypeEn)); + return testResult; + } + + /** + * read file + * + * @param fileBytes file bytes + * @return CompatibilityTestResult + * @throws IOException Exception + */ + abstract CompatibilityTestResult readFile(byte[] fileBytes) throws IOException; + + /** + * Get Idle list + * + * @param fileBytes FILE BYTES + * @return IDLE List + * @throws IOException exception + */ + abstract List getIdleList(byte[] fileBytes) throws IOException; + + /** + * GET idle map + * + * @param fileBytes fileBytes + * @return idle map + * @throws IOException exception + */ + abstract Map>> getIdleMap(byte[] fileBytes) throws IOException; +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseClamLog.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseClamLog.java new file mode 100644 index 0000000..f823c8b --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseClamLog.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * AbsParsePerformanceFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseClamLog implements CompatibilityFilesParser { + private static final String RESULT_DESC = "result"; + private static final String EVIDENCE_DESC = "evidence"; + + private final Map inputByteMap; + + /** + * Construction function + * + * @param inputByteMap map + */ + public ParseClamLog(Map inputByteMap) { + this.inputByteMap = inputByteMap; + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.SECURITY_VIRUS.getTestName()); + if (inputByteMap == null || inputByteMap.size() == 0) { + throw new BaseException("病毒扫描文件缺失"); + } + List beginFileNames = inputByteMap.keySet().stream().filter(s -> StringUtils.contains(s, + "clam.log")) + .collect(Collectors.toList()); + if (beginFileNames.size() > 0) { + return readVirusScanFile(inputByteMap.get(beginFileNames.get(0))); + } + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SAFETY_FILE_LOSS); + testResult.setReasonEn(Constants.SAFETY_FILE_LOSS_EN); + return testResult; + } + + private Map> getScanResult(BufferedReader reader) throws IOException { + String result = null; + List evidenceList = new ArrayList<>(); + String line; + while ((line = reader.readLine()) != null) { + String lineTrim = line.trim(); + evidenceList.add(lineTrim); + if (lineTrim.isEmpty()) { + break; + } + Pattern pattern = Pattern.compile(Constants.CLAM_RESULT_PATTERN); + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { + result = matcher.group(1).trim(); + } + } + Map> resultMap = new HashMap<>(); + resultMap.put(RESULT_DESC, Collections.singletonList(result)); + resultMap.put(EVIDENCE_DESC, evidenceList); + return resultMap; + } + + /** + * Read virus scan file + * + * @param clamFileBytes clam file bytes + * @return CompatibilityTestResult + * @throws IOException exception + */ + public CompatibilityTestResult readVirusScanFile(byte[] clamFileBytes) throws IOException { + if (clamFileBytes.length == 0) { + throw new BaseException("病毒扫描文件的内容为空"); + } + + Map> resultMap = new HashMap<>(); + try (InputStream inputStream = new ByteArrayInputStream(clamFileBytes); + BufferedReader bufferedReader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + if (StringUtils.containsIgnoreCase(line, "SCAN SUMMARY")) { + resultMap = getScanResult(bufferedReader); + } + } + } + + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.SECURITY_VIRUS.getTestName()); + if (resultMap.containsKey(RESULT_DESC) && !CollectionUtils.isEmpty(resultMap.get(RESULT_DESC))) { + if (StringUtils.equals(resultMap.get(RESULT_DESC).get(0), "0")) { + testResult.setResult(Constants.TEST_PASSED); + } else { + testResult.setResult(Constants.TEST_FAILED); + } + if (resultMap.containsKey(EVIDENCE_DESC) && resultMap.get(EVIDENCE_DESC) != null) { + testResult.setEvidence(resultMap.get(EVIDENCE_DESC)); + testResult.setEvidenceEn(resultMap.get(EVIDENCE_DESC)); + } + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SAFETY_FILE_LOSS); + testResult.setReasonEn(Constants.SAFETY_FILE_LOSS_EN); + } + return testResult; + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.SECURITY_VIRUS.getTestName()); + try { + testResult = getResult(); + } catch (IOException ex) { + log.error("Exception occur in parsing virus file", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SAFETY_FILE_LOSS); + } + return testResult; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuComFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuComFiles.java new file mode 100644 index 0000000..129b1f0 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuComFiles.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * ParseCpuComFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseCpuComFiles implements CompatibilityFilesParser { + private static final String CPU_DESC = "CPU"; + + private final ParseCompatibilityFilesImpl parseCompatibilityFiles; + + /** + * ParseCpuComFiles + * + * @param beginCpuByteMap beginCpuByteMap + * @param endCpuByteMap endCpuByteMap + */ + public ParseCpuComFiles(Map beginCpuByteMap, Map endCpuByteMap) { + this.parseCompatibilityFiles = new ParseCompatibilityFilesImpl(beginCpuByteMap, endCpuByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parseCompatibilityFiles.getResult(Constants.CompatibilityTestName.IDLE_CPU.getTestName(), + CPU_DESC, CPU_DESC, 2); + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.IDLE_CPU.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing idle test cpu file ", ex.getMessage()); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(3), CPU_DESC)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(3), CPU_DESC)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception in parsing idle test cpu file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(2), CPU_DESC)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(2), CPU_DESC)); + } + return testResult; + } + + private static class ParseCompatibilityFilesImpl extends AbsParseCompatibilityFiles { + /** + * ParseCompatibilityFilesImpl + * + * @param beginByteMap beginByteMap + * @param endByteMap endByteMap + */ + protected ParseCompatibilityFilesImpl(Map beginByteMap, Map endByteMap) { + super(beginByteMap, endByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] beginBytes, byte[] endBytes) throws IOException { + if (beginBytes.length == 0 || endBytes.length == 0) { + throw new BaseException("解析空载测试CPU文件缺失"); + } + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.IDLE_CPU.getTestName()); + List beginAverageList = getAverage(beginBytes); + List endAverageList = getAverage(endBytes); + double cpuMaxUsedIdle; + if (beginAverageList.size() > 0 && endAverageList.size() > 0) { + cpuMaxUsedIdle = + new BigDecimal(beginAverageList.get(0)) + .subtract(new BigDecimal(endAverageList.get(0))).abs().doubleValue(); + if (cpuMaxUsedIdle <= 1.0) { + testResult.setResult(Constants.TEST_PASSED); + List evidence = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), CPU_DESC, + cpuMaxUsedIdle, "小于")); + List evidenceEn = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), + CPU_DESC, cpuMaxUsedIdle, "less")); + testResult.setEvidence(evidence); + testResult.setEvidenceEn(evidenceEn); + } else { + testResult.setResult(Constants.TEST_FAILED); + List evidence = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), CPU_DESC, + cpuMaxUsedIdle, "大于")); + testResult.setEvidence(evidence); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), + CPU_DESC, cpuMaxUsedIdle, "大于")); + List evidenceEn = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), + CPU_DESC, cpuMaxUsedIdle, "greater")); + testResult.setEvidenceEn(evidenceEn); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), + CPU_DESC, cpuMaxUsedIdle, "greater")); + } + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(2), CPU_DESC)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(2), + CPU_DESC)); + } + return testResult; + } + + @Override + List getAverage(byte[] fileBytes) throws IOException { + List averageList = new ArrayList<>(); + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader beginReader = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + String line; + + while ((line = beginReader.readLine()) != null) { + if (StringUtils.containsIgnoreCase(line, "平均时间") + || StringUtils.startsWithIgnoreCase(line, "Average")) { + averageList.add(line.substring(line.length() - 8).trim()); + averageList.add(line.replace(System.lineSeparator(), "")); + } + } + } + return averageList; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuPerFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuPerFiles.java new file mode 100644 index 0000000..3ceb5cf --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCpuPerFiles.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * ParseCpuPerFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseCpuPerFiles implements CompatibilityFilesParser { + private static final String CPU_DESC = "CPU"; + + private final ParsePerformanceFilesImpl parsePerformanceFiles; + + /** + * construction function + * + * @param inputByteMap map + */ + public ParseCpuPerFiles(Map inputByteMap) { + this.parsePerformanceFiles = new ParsePerformanceFilesImpl(inputByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parsePerformanceFiles.getResult(Constants.CompatibilityTestName.PRESSURE_CPU.getTestName(), + CPU_DESC, CPU_DESC, 2); + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.PRESSURE_CPU.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing pressure test CPU file ", ex); + testResult.setResult(Constants.TEST_SKIPPED); + testResult.setReason(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(3), CPU_DESC)); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(3), CPU_DESC)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception in parsing pressure test CPU file ", ex); + + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(2), CPU_DESC)); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(2), CPU_DESC)); + } + return testResult; + } + + private static class ParsePerformanceFilesImpl extends AbsParsePerformanceFiles { + private final Pattern idlePattern = Pattern.compile( + "\\d{2}(:|时)\\d{2}(:|分)\\d{2}(秒|\\s(PM|AM|HKT|))\\s+all\\s+"); + + /** + * ParsePerformanceFilesImpl + * + * @param inputByteMap inputByteMap + */ + public ParsePerformanceFilesImpl(Map inputByteMap) { + super(inputByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] fileBytes) throws IOException { + if (fileBytes.length == 0) { + throw new BaseException("解析压力测试CPU文件缺失"); + } + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.PRESSURE_CPU.getTestName()); + List idleList = getIdleList(fileBytes); + if (idleList.size() > 0) { + List evidence = new ArrayList<>(idleList.subList(1, idleList.size())); + List evidenceEn = new ArrayList<>(idleList.subList(1, idleList.size())); + if (Double.parseDouble(idleList.get(0)) <= 5.0d) { + testResult.setResult(Constants.TEST_PASSED); + evidence.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(0), CPU_DESC, + Double.parseDouble(idleList.get(0)), "小于")); + evidenceEn.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(0), CPU_DESC, + Double.parseDouble(idleList.get(0)), "less")); + } else { + testResult.setResult(Constants.TEST_FAILED); + evidence.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(0), CPU_DESC, + Double.parseDouble(idleList.get(0)), "大于")); + evidenceEn.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(0), CPU_DESC, + Double.parseDouble(idleList.get(0)), "greater")); + testResult.setReason(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(0), CPU_DESC, + Double.parseDouble(idleList.get(0)), "大于") + + Constants.PERFORMANCE_DESC_LIST.get(1)); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(0), + CPU_DESC, + Double.parseDouble(idleList.get(0)), "greater") + + Constants.PERFORMANCE_DESC_EN_LIST.get(1)); + } + testResult.setEvidence(evidence); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(2), CPU_DESC)); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(2), CPU_DESC)); + } + return testResult; + } + + @Override + List getIdleList(byte[] fileBytes) throws IOException { + Double maxIdle = 0.0d; + String maxEvidence = null; + Double minIdle = 100.0d; + String minEvidence = null; + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader beginReader = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + String line; + while ((line = beginReader.readLine()) != null && idlePattern.matcher(line).find()) { + String idle = line.substring(line.length() - 8).trim(); + if (maxIdle <= Double.parseDouble(idle)) { + maxIdle = Double.parseDouble(idle); + maxEvidence = line; + } + if (minIdle >= Double.parseDouble(idle)) { + minIdle = Double.parseDouble(idle); + minEvidence = line; + } + } + } + + List idleList = new ArrayList<>(); + if (maxEvidence != null) { + idleList.add(String.format(Locale.ROOT, "%.2f", new BigDecimal(maxIdle.toString()) + .subtract(new BigDecimal(minIdle.toString())).abs().doubleValue())); + idleList.add(maxEvidence); + idleList.add(minEvidence); + } + return idleList; + } + + @Override + Map>> getIdleMap(byte[] fileBytes) { + return new HashMap<>(); + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCveCheckFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCveCheckFiles.java new file mode 100644 index 0000000..5cff564 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseCveCheckFiles.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * ParseCveCheckFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseCveCheckFiles implements CompatibilityFilesParser { + private final Map inputByteMap; + + /** + * construction function + * + * @param inputByteMap map + */ + public ParseCveCheckFiles(Map inputByteMap) { + this.inputByteMap = inputByteMap; + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.SECURITY_VULNERABLE.getTestName()); + if (inputByteMap == null || inputByteMap.size() == 0) { + throw new BaseException("漏洞扫描文件缺失"); + } + List beginFileNames = inputByteMap.keySet().stream().filter(s -> StringUtils.contains(s, + "cvecheck-result.json")) + .collect(Collectors.toList()); + if (beginFileNames.size() > 0) { + return readVirusScanFile(inputByteMap.get(beginFileNames.get(0))); + } + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SAFETY_FILE_LOSS); + testResult.setReasonEn(Constants.SAFETY_FILE_LOSS_EN); + return testResult; + } + + /** + * readVirusScanFile + * + * @param cveFileBytes cveFileBytes + * @return CompatibilityTestResult + * @throws IOException IOException + */ + public CompatibilityTestResult readVirusScanFile(byte[] cveFileBytes) throws IOException { + if (cveFileBytes.length == 0) { + throw new BaseException("漏洞扫描文件缺失"); + } + String line; + StringBuilder stringBuilder = new StringBuilder(16); + try (InputStream inputStream = new ByteArrayInputStream(cveFileBytes); + BufferedReader reader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + } + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.SECURITY_VULNERABLE.getTestName()); + if (stringBuilder.toString().matches("(\\[\\])+")) { + testResult.setResult(Constants.TEST_PASSED); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setEvidence(Collections.singletonList(stringBuilder.toString())); + testResult.setEvidenceEn(Collections.singletonList(stringBuilder.toString())); + testResult.setReason(stringBuilder.toString()); + testResult.setReasonEn(stringBuilder.toString()); + } + return testResult; + } + + @Override + public CompatibilityTestResult parseFiles() throws IOException { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.SECURITY_VULNERABLE.getTestName()); + try { + testResult = getResult(); + } catch (NumberFormatException | IOException ex) { + log.error("Exception in parsing cve check file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SAFETY_FILE_LOSS); + testResult.setReasonEn(Constants.SAFETY_FILE_LOSS_EN); + } + return testResult; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskComFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskComFiles.java new file mode 100644 index 0000000..2aa2d92 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskComFiles.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +/** + * ParseDiskComFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseDiskComFiles implements CompatibilityFilesParser { + private static final String DRIVE_CN = "硬盘"; + private static final String DRIVE_EN = "drive"; + + private final ParseCompatibilityFilesImpl parseCompatibilityFiles; + + /** + * ParseDiskComFiles + * + * @param beginDiskByteMap beginDiskByteMap + * @param endDiskByteMap endDiskByteMap + */ + public ParseDiskComFiles(Map beginDiskByteMap, Map endDiskByteMap) { + this.parseCompatibilityFiles = new ParseCompatibilityFilesImpl(beginDiskByteMap, endDiskByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parseCompatibilityFiles.getResult(Constants.CompatibilityTestName.IDLE_DISK.getTestName(), + DRIVE_CN, DRIVE_EN, 2); + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.IDLE_DISK.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing idle test disk file ", ex.getMessage()); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(3), DRIVE_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(3), DRIVE_EN)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception in parsing idle test disk file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(2), DRIVE_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(2), DRIVE_EN)); + } + return testResult; + } + + private static class ParseCompatibilityFilesImpl extends AbsParseCompatibilityFiles { + private final Pattern averagePattern = Pattern.compile("(平均时间|Average):"); + + /** + * ParseCompatibilityFilesImpl + * + * @param beginByteMap beginByteMap + * @param endByteMap endByteMap + */ + protected ParseCompatibilityFilesImpl(Map beginByteMap, Map endByteMap) { + super(beginByteMap, endByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] beginBytes, byte[] endBytes) throws IOException { + if (beginBytes.length == 0 || endBytes.length == 0) { + throw new BaseException("解析空载测试硬盘文件缺失"); + } + + Map> beginAverageMap = getAverageMap(beginBytes); + Map> endAverageMap = getAverageMap(endBytes); + + double diskMaxUsedIdle = 0.0d; + String maxDiskName = null; + double diskIdle = 0.0d; + if (beginAverageMap.size() > 0 && endAverageMap.size() > 0) { + for (Map.Entry> entry : beginAverageMap.entrySet()) { + if (!endAverageMap.containsKey(entry.getKey())) { + continue; + } + diskIdle = new BigDecimal(beginAverageMap.get(entry.getKey()).get(0)) + .subtract(new BigDecimal(endAverageMap.get(entry.getKey()).get(0))) + .abs().doubleValue(); + if (diskMaxUsedIdle <= diskIdle) { + maxDiskName = entry.getKey(); + diskMaxUsedIdle = diskIdle; + } + } + } + return getTestResult(maxDiskName, diskMaxUsedIdle, beginAverageMap, endAverageMap); + } + + private CompatibilityTestResult getTestResult(String maxDiskName, double diskMaxUsedIdle, + Map> beginAverageMap, Map> endAverageMap) { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.IDLE_DISK.getTestName()); + List evidence; + List evidenceEn; + if (maxDiskName != null) { + if (diskMaxUsedIdle <= 1.0) { + testResult.setResult(Constants.TEST_PASSED); + evidence = Arrays.asList(beginAverageMap.get(maxDiskName).get(1), + endAverageMap.get(maxDiskName).get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), DRIVE_CN, + diskMaxUsedIdle, "小于")); + evidenceEn = Arrays.asList(beginAverageMap.get(maxDiskName).get(1), + endAverageMap.get(maxDiskName).get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), + DRIVE_EN, diskMaxUsedIdle, "less")); + } else { + testResult.setResult(Constants.TEST_FAILED); + evidence = Arrays.asList(beginAverageMap.get(maxDiskName).get(1), + endAverageMap.get(maxDiskName).get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), + DRIVE_CN, diskMaxUsedIdle, "大于")); + evidenceEn = Arrays.asList(beginAverageMap.get(maxDiskName).get(1), + endAverageMap.get(maxDiskName).get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), + DRIVE_EN, diskMaxUsedIdle, "greater")); + } + testResult.setEvidence(evidence); + testResult.setEvidenceEn(evidenceEn); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(2), DRIVE_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(2), + DRIVE_EN)); + } + return testResult; + } + + @Override + List getAverage(byte[] fileBytes) { + return new ArrayList<>(); + } + + /** + * Get average map + * + * @param cpuBytes cpu bytes + * @return average map + * @throws IOException exception + */ + public Map> getAverageMap(byte[] cpuBytes) throws IOException { + String line = null; + Map> averageMap = new HashMap<>(); + Map indexMap = new HashMap<>(); + try (InputStream beginInput = new ByteArrayInputStream(cpuBytes); + BufferedReader beginReader = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + boolean flag = true; + while ((line = beginReader.readLine()) != null) { + if (!StringUtils.containsIgnoreCase(line, "DEV") && averagePattern.matcher(line).find()) { + String[] split = line.split("\\s+"); + String idle = split[indexMap.get("%util")]; + String diskName = split[indexMap.get("DEV")]; + List averageList = new ArrayList<>(); + averageList.add(idle); + averageList.add(line.replace("\n", "")); + averageMap.put(diskName, averageList); + } else if (flag && StringUtils.containsIgnoreCase(line, "DEV") + && averagePattern.matcher(line).find() ){ + indexMap = getIndexMap(line); + flag = false; + } + } + } + return averageMap; + } + + private static Map getIndexMap(String line) { + Map indexMap = new HashMap<>(); + String[] split =line.split("\\s+"); + for (int i = 0; i < split.length; i++) { + if (split[i].equals("DEV")) { + indexMap.put("DEV", i); + } else if (split[i].equals("%util")) { + indexMap.put("%util", i); + } + } + return indexMap; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskPerFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskPerFiles.java new file mode 100644 index 0000000..2049a77 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseDiskPerFiles.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * ParseDiskPerFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseDiskPerFiles implements CompatibilityFilesParser { + private static final String DRIVE_CN = "硬盘"; + private static final String DRIVE_EN = "drive"; + + private final ParsePerformanceFilesImpl parsePerformanceFiles; + + /** + * construction function + * + * @param inputByteMap MAP + */ + public ParseDiskPerFiles(Map inputByteMap) { + this.parsePerformanceFiles = new ParsePerformanceFilesImpl(inputByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parsePerformanceFiles.getResult(Constants.CompatibilityTestName.PRESSURE_DISK.getTestName(), + DRIVE_CN, DRIVE_EN, 2); + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.PRESSURE_DISK.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing pressure test disk file ", ex.getMessage()); + testResult.setResult(Constants.TEST_SKIPPED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(3), DRIVE_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(3), DRIVE_EN)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception occur in parsing pressure test disk file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(2), DRIVE_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(2), DRIVE_EN)); + } + return testResult; + } + + private static class ParsePerformanceFilesImpl extends AbsParsePerformanceFiles { + private final Pattern idlePattern = Pattern.compile( + "\\d{2}(:|时)\\d{2}(:|分)\\d{2}(秒|\\s(PM|AM|HKT|))\\s+"); + + /** + * ParsePerformanceFilesImpl + * + * @param inputByteMap inputByteMap + */ + public ParsePerformanceFilesImpl(Map inputByteMap) { + super(inputByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] fileBytes) throws IOException { + if (fileBytes.length == 0) { + throw new BaseException("解析压力测试硬盘文件缺失"); + } + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.PRESSURE_DISK.getTestName()); + Map>> idleMap = getIdleMap(fileBytes); + if (idleMap.size() > 0) { + Double maxGap = 0.00d; + String maxDiskName = null; + String diskMax = null; + String diskMin = null; + for (Map.Entry>> entry : idleMap.entrySet()) { + List idleList = entry.getValue().get("idle"); + double diskMaxGap = idleList.stream().mapToDouble(Double::parseDouble).max().orElse(0.00d); + double diskMinGap = idleList.stream().mapToDouble(Double::parseDouble).min().orElse(0.00d); + Double gap = new BigDecimal(String.valueOf(diskMaxGap)) + .subtract(new BigDecimal(String.valueOf(diskMinGap))).abs().doubleValue(); + if (maxGap <= gap) { + maxGap = gap; + maxDiskName = entry.getKey(); + diskMax = String.format(Locale.ROOT, "%.2f", diskMaxGap); + diskMin = String.format(Locale.ROOT, "%.2f", diskMinGap); + } + } + testResult = getTestResult(maxDiskName, maxGap, idleMap, diskMax, diskMin); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_LIST.get(2), DRIVE_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(2), DRIVE_EN)); + } + return testResult; + } + + private CompatibilityTestResult getTestResult(String maxDiskName, Double maxGap, + Map>> idleMap, + String diskMax, String diskMin) { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.PRESSURE_DISK.getTestName()); + List evidenceList = idleMap.get(maxDiskName).get("evidence"); + List evidence = new ArrayList<>(); + evidence.add(evidenceList.stream().filter( + s -> StringUtils.containsIgnoreCase(s, diskMax)).limit(1) + .collect(Collectors.joining())); + evidence.add(evidenceList.stream().filter( + s -> StringUtils.containsIgnoreCase(s, diskMin)).limit(1) + .collect(Collectors.joining())); + List evidenceEn = new ArrayList<>(evidence); + if (maxGap <= 5.0) { + testResult.setResult(Constants.TEST_PASSED); + evidence.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(0), DRIVE_CN, maxGap, + "小于")); + evidenceEn.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(0), DRIVE_EN, maxGap, "less")); + } else { + testResult.setResult(Constants.TEST_FAILED); + evidence.add(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(0), + DRIVE_CN, maxGap, "大于")); + evidenceEn.add(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(0), + DRIVE_EN, maxGap, "greater")); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(0), + DRIVE_CN, maxGap, "大于")); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(0), + DRIVE_EN, maxGap, "greater")); + } + testResult.setEvidence(evidence); + testResult.setEvidenceEn(evidenceEn); + return testResult; + } + + @Override + List getIdleList(byte[] fileBytes) { + return new ArrayList<>(); + } + + @Override + Map>> getIdleMap(byte[] fileBytes) throws IOException { + String line = null; + Map>> averageMap = new HashMap<>(); + Map indexMap = new HashMap<>(); + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader beginReader = new BufferedReader(new InputStreamReader(beginInput, + StandardCharsets.UTF_8))) { + boolean flag = true; + + while ((line = beginReader.readLine()) != null) { + if (!StringUtils.containsIgnoreCase(line, "DEV") && idlePattern.matcher(line).find()) { + String[] split = line.split("\\s+"); + + String idle = split[indexMap.get("%util")]; + + String diskName = split[indexMap.get("DEV")]; + Map> diskMap = averageMap.computeIfAbsent(diskName, e -> new HashMap<>()); + diskMap.computeIfAbsent("idle", e -> new ArrayList<>()).add(idle); + diskMap.computeIfAbsent("evidence", e -> new ArrayList<>()).add(line); + } else if (flag && StringUtils.containsIgnoreCase(line, "DEV")) { + indexMap = getIndexMap(line); + flag = false; + } + } + } + return averageMap; + } + + private Map getIndexMap(String line) { + Map indexMap = new HashMap<>(); + String[] split = line.split("\\s+"); + for (int i =0; i < split.length; i++) { + if (split[i].equals("DEV")) { + indexMap.put("DEV", i); + } else if (split[i].equals("%util")) { + indexMap.put("%util", i); + } + } + return indexMap; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemComFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemComFiles.java new file mode 100644 index 0000000..aa500d3 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemComFiles.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * ParseMemComFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseMemComFiles implements CompatibilityFilesParser { + private static final String MEMORY_CN = "内存"; + private static final String MEMORY_EN = "memory"; + private static final Pattern PATTERN = Pattern.compile("\\d+\\.\\d+"); + + private final ParseCompatibilityFilesImpl parseCompatibilityFiles; + + /** + * ParseMemComFiles + * + * @param beginMemByteMap beginMemByteMap + * @param endMemByteMap endMemByteMap + */ + public ParseMemComFiles(Map beginMemByteMap, Map endMemByteMap) { + this.parseCompatibilityFiles = new ParseCompatibilityFilesImpl(beginMemByteMap, endMemByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parseCompatibilityFiles.getResult(Constants.CompatibilityTestName.IDLE_MEM.getTestName(), MEMORY_CN, + MEMORY_EN, 3); + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.IDLE_MEM.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing idle test memory file ", ex.getMessage()); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(3), MEMORY_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(3), MEMORY_EN)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception occur in parsing idle test memory file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(2), MEMORY_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(2), MEMORY_EN)); + } + return testResult; + } + + private static class ParseCompatibilityFilesImpl extends AbsParseCompatibilityFiles { + /** + * ParseCompatibilityFilesImpl + * + * @param beginByteMap beginByteMap + * @param endByteMap endByteMap + */ + protected ParseCompatibilityFilesImpl(Map beginByteMap, Map endByteMap) { + super(beginByteMap, endByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] beginBytes, byte[] endBytes) throws IOException { + if (beginBytes.length == 0 || endBytes.length == 0) { + throw new BaseException("解析空载测试内存文件缺失"); + } + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.IDLE_MEM.getTestName()); + List beginAverageList = getAverage(beginBytes); + List endAverageList = getAverage(endBytes); + double memMaxUsedIdle = 0.0d; + List evidence; + List evidenceEn; + if (beginAverageList.size() > 0 && endAverageList.size() > 0) { + memMaxUsedIdle = new BigDecimal(beginAverageList.get(0)) + .subtract(new BigDecimal(endAverageList.get(0))) + .abs().doubleValue(); + if (memMaxUsedIdle <= 1.0) { + testResult.setResult(Constants.TEST_PASSED); + evidence = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), MEMORY_CN, + memMaxUsedIdle, "小于")); + evidenceEn = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), MEMORY_EN, + memMaxUsedIdle, "less")); + } else { + testResult.setResult(Constants.TEST_FAILED); + evidence = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), MEMORY_CN, + memMaxUsedIdle, "大于")); + evidenceEn = Arrays.asList(beginAverageList.get(1), endAverageList.get(1), + String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), MEMORY_EN, + memMaxUsedIdle, "greater")); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(1), + MEMORY_CN, memMaxUsedIdle, "大于")); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(1), + MEMORY_EN, memMaxUsedIdle, "greater")); + } + testResult.setEvidence(evidence); + testResult.setEvidenceEn(evidenceEn); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(2), MEMORY_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(2), + MEMORY_EN)); + } + return testResult; + } + + @Override + List getAverage(byte[] fileBytes) { + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader br = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + String line; + List averageList = new ArrayList<>(); + while ((line = br.readLine()) != null) { + average(line, averageList); + } + return averageList; + } catch (IOException e) { + throw new BaseException(e.getMessage()); + } + } + + private void average(String line, List averageList) { + if (StringUtils.containsIgnoreCase(line, "平均时间") + || StringUtils.startsWithIgnoreCase(line, + "Average")) { + Matcher matcher = PATTERN.matcher(line); + if (matcher.find()) { + averageList.add(matcher.group()); + averageList.add(line.replace(System.lineSeparator(), "")); + } + } + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemPerFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemPerFiles.java new file mode 100644 index 0000000..d377d4e --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseMemPerFiles.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * ParseMemPerFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseMemPerFiles implements CompatibilityFilesParser { + private static final String MEMORY_CN = "内存"; + private static final String MEMORY_EN = "memory"; + + private final ParsePerformanceFilesImpl parsePerformanceFiles; + + /** + * construction file + * + * @param inputByteMap map + */ + public ParseMemPerFiles(Map inputByteMap) { + this.parsePerformanceFiles = new ParsePerformanceFilesImpl(inputByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parsePerformanceFiles.getResult(Constants.CompatibilityTestName.PRESSURE_MEM.getTestName(), MEMORY_CN, + MEMORY_EN, 2); + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.PRESSURE_MEM.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing pressure test memory file ", ex.getMessage()); + testResult.setResult(Constants.TEST_SKIPPED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(3), MEMORY_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(3), MEMORY_EN)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception in parsing pressure test memory file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(2), MEMORY_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(2), MEMORY_EN)); + } + return testResult; + } + + private static class ParsePerformanceFilesImpl extends AbsParsePerformanceFiles { + private final Pattern idlePattern = Pattern.compile("\\d{2}(:|时)\\d{2}(:|分)\\d{2}(秒|\\s(PM|AM|HKT|))\\s+"); + private final Pattern pattern = Pattern.compile("\\d+\\.\\d+"); + + /** + * inputByteMap + * + * @param inputByteMap inputByteMap + */ + public ParsePerformanceFilesImpl(Map inputByteMap) { + super(inputByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] fileBytes) throws IOException { + if (fileBytes.length == 0) { + throw new BaseException("解析压力测试硬盘文件缺失"); + } + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.PRESSURE_MEM.getTestName()); + List idleList = getIdleList(fileBytes); + if (idleList.size() > 0) { + List evidence = new ArrayList<>(idleList.subList(1, idleList.size())); + List evidenceEn = new ArrayList<>(idleList.subList(1, idleList.size())); + if (Double.parseDouble(idleList.get(0)) <= 5.0d) { + testResult.setResult(Constants.TEST_PASSED); + evidence.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(0), MEMORY_CN, + Double.parseDouble(idleList.get(0)), "小于")); + evidenceEn.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(0), MEMORY_EN, + Double.parseDouble(idleList.get(0)), "less")); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(0), MEMORY_CN, + Double.parseDouble(idleList.get(0)), "大于")); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(0), + MEMORY_EN, + Double.parseDouble(idleList.get(0)), "greater")); + evidence.add(testResult.getReason()); + evidenceEn.add(testResult.getReasonEn()); + } + testResult.setEvidence(evidence); + testResult.setEvidenceEn(evidenceEn); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(2), MEMORY_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(2), + MEMORY_EN)); + } + return testResult; + } + + @Override + List getIdleList(byte[] fileBytes) throws IOException { + Double maxIdle = 0.0d; + String maxEvidence = null; + Double minIdle = 100.0d; + String minEvidence = null; + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader beginReader = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + String line; + while ((line = beginReader.readLine()) != null) { + Matcher matcher = pattern.matcher(line); + if (!StringUtils.containsAnyIgnoreCase(line, "kbmemfree") + && idlePattern.matcher(line).find() && matcher.find()) { + Double idleDouble = Double.parseDouble(matcher.group().trim()); + maxEvidence = maxIdle <= idleDouble ? line : maxEvidence; + maxIdle = Math.max(idleDouble, maxIdle); + minIdle = Math.min(idleDouble, minIdle); + minEvidence = minIdle >= idleDouble ? line : minEvidence; + } + } + } + + List idleList = new ArrayList<>(); + if (maxEvidence != null) { + idleList.add(String.format(Locale.ROOT, "%.2f", new BigDecimal(String.valueOf(maxIdle)) + .subtract(new BigDecimal(String.valueOf(maxIdle))).abs().doubleValue())); + idleList.add(maxEvidence); + idleList.add(minEvidence); + } + return idleList; + } + + @Override + Map>> getIdleMap(byte[] fileBytes) { + return new HashMap<>(); + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetComFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetComFiles.java new file mode 100644 index 0000000..cb09b8f --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetComFiles.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * ParseNetComFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseNetComFiles implements CompatibilityFilesParser { + private static final String NIC_CN = "网卡"; + private static final String NIC_EN = "NIC"; + + private final ParseCompatibilityFilesImpl parseCompatibilityFiles; + + /** + * construction function + * + * @param beginNetByteMap beginNetByteMap + * @param endNetByteMap endNetByteMap + */ + public ParseNetComFiles(Map beginNetByteMap, Map endNetByteMap) { + this.parseCompatibilityFiles = new ParseCompatibilityFilesImpl(beginNetByteMap, endNetByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parseCompatibilityFiles.getResult(Constants.CompatibilityTestName.IDLE_NET.getTestName(), + NIC_CN, NIC_EN, 2); + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.IDLE_NET.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing idle test net file ", ex.getMessage()); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(3), NIC_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(3), NIC_EN)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception in parsing idle test net file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(2), NIC_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(2), NIC_EN)); + } + return testResult; + } + + private static class ParseCompatibilityFilesImpl extends AbsParseCompatibilityFiles { + private final Pattern averagePattern = Pattern.compile("(平均时间|Average):\\s*(?!IFACE|lo)\\w.*"); + private final Pattern pattern = Pattern.compile("\\d+\\.\\d+"); + + /** + * ParseCompatibilityFilesImpl + * + * @param beginByteMap beginByteMap + * @param endByteMap endByteMap + */ + protected ParseCompatibilityFilesImpl(Map beginByteMap, Map endByteMap) { + super(beginByteMap, endByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] beginBytes, byte[] endBytes) throws IOException { + if (beginBytes.length == 0 || endBytes.length == 0) { + throw new BaseException("解析空载测试网卡文件缺失"); + } + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.IDLE_NET.getTestName()); + Map> beginAverageMap = getAverageMap(beginBytes); + Map> endAverageMap = getAverageMap(endBytes); + + if (beginAverageMap.size() > 0 && endAverageMap.size() > 0) { + createTestResult(testResult, beginAverageMap, endAverageMap); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_LIST.get(2), NIC_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_EN_LIST.get(2), NIC_EN)); + } + return testResult; + } + + private void createTestResult(CompatibilityTestResult testResult, Map> beginAverageMap, + Map> endAverageMap) { + Double rxkbIdle; + Double txkbIdle; + Double maxRxkbIdle = 0.0d; + Double maxTxkbIdle = 0.0d; + String rxkbNetName = null; + String txkbNetName = null; + BigDecimal num = new BigDecimal(8).divide(new BigDecimal(1000 * 1024)); + for (Map.Entry> entry : beginAverageMap.entrySet()) { + if (!endAverageMap.containsKey(entry.getKey())) { + continue; + } + rxkbIdle = new BigDecimal(beginAverageMap.get(entry.getKey()).get(0)) + .subtract(new BigDecimal(endAverageMap.get(entry.getKey()).get(0))) + .abs().multiply(num).doubleValue(); + txkbIdle = new BigDecimal(beginAverageMap.get(entry.getKey()).get(1)) + .subtract(new BigDecimal(endAverageMap.get(entry.getKey()).get(1))) + .abs().multiply(num).doubleValue(); + if (rxkbIdle >= maxRxkbIdle) { + maxRxkbIdle = rxkbIdle; + rxkbNetName = entry.getKey(); + } + if (txkbIdle >= maxTxkbIdle) { + maxTxkbIdle = txkbIdle; + txkbNetName = entry.getKey(); + } + } + List evidence = new ArrayList<>(); + evidence.add(beginAverageMap.get(rxkbNetName).get(2)); + evidence.add(endAverageMap.get(rxkbNetName).get(2)); + List evidenceEn = new ArrayList<>(evidence); + + int[] kbpass = {0, 0}; + checkMaxRxkbIdle(maxRxkbIdle, kbpass, evidence, evidenceEn); + evidence.add(beginAverageMap.get(txkbNetName).get(2)); + evidence.add(endAverageMap.get(txkbNetName).get(2)); + evidenceEn.add(beginAverageMap.get(txkbNetName).get(2)); + evidenceEn.add(endAverageMap.get(txkbNetName).get(2)); + checkMaxTxkbIdle(maxTxkbIdle, kbpass, evidence, evidenceEn); + + testResult.setEvidence(evidence); + testResult.setEvidenceEn(evidenceEn); + setTestResult(maxRxkbIdle, maxTxkbIdle, kbpass, testResult); + } + + private void checkMaxRxkbIdle(Double maxRxkbIdle, int[] kbpass, List evidence, + List evidenceEn) { + Double maxRxkb = new BigDecimal(maxRxkbIdle.toString()).multiply(new BigDecimal(100)).doubleValue(); + if (maxRxkbIdle <= 0.01) { + kbpass[0] = 1; + evidence.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(6), + "接收", maxRxkb, "小于")); + evidenceEn.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(6), + "received", maxRxkb, "less")); + } else { + evidence.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(6), + "接收", maxRxkb, "大于")); + evidenceEn.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(6), + "received", maxRxkb, "greater")); + } + } + + private void checkMaxTxkbIdle(Double maxTxkbIdle, int[] kbpass, List evidence, + List evidenceEn) { + Double maxTxkb = new BigDecimal(maxTxkbIdle.toString()).multiply(new BigDecimal(100)).doubleValue(); + if (maxTxkbIdle < 0.01) { + kbpass[1] = 1; + evidence.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(6), "发送", + maxTxkb, "小于")); + evidenceEn.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(6), "sent", + maxTxkb, "less")); + } else { + evidence.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_LIST.get(6), "发送", + maxTxkb, "大于")); + evidenceEn.add(String.format(Locale.ROOT, Constants.COMPATIBILITY_DESC_EN_LIST.get(6), "sent", + maxTxkb, "greater")); + } + } + + private void setTestResult(Double maxRxkbIdle, Double maxTxkbIdle, int[] kbpass, + CompatibilityTestResult testResult) { + if (kbpass[0] == 1 && kbpass[1] == 1) { + testResult.setResult(Constants.TEST_PASSED); + } else { + double maxRxkb = new BigDecimal(maxRxkbIdle.toString()).multiply(new BigDecimal(100)).doubleValue(); + double maxTxkb = new BigDecimal(maxTxkbIdle.toString()).multiply(new BigDecimal(100)).doubleValue(); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_LIST.get(7), "发送", + maxTxkb) + String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_LIST.get(7), "接收", + maxRxkb)); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_EN_LIST.get(7), + "sent", maxTxkb) + String.format(Locale.ROOT, + Constants.COMPATIBILITY_DESC_LIST.get(7), "received", + maxRxkb)); + } + } + + @Override + List getAverage(byte[] fileBytes) { + return new ArrayList<>(); + } + + /** + * get Average Map + * + * @param fileBytes fileBytes + * @return Map + * @throws IOException IOException + */ + public Map> getAverageMap(byte[] fileBytes) throws IOException { + Map> averageMap = new HashMap<>(); + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader beginReader = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + String line; + + while ((line = beginReader.readLine()) != null) { + if (!averagePattern.matcher(line).find()) { + continue; + } + Matcher matcher = pattern.matcher(line); + String netName = line.substring(13).trim().split(" ")[0]; + List matchList = new ArrayList<>(); + while (matcher.find()) { + matchList.add(matcher.group().trim()); + } + averageMap.put(netName, Arrays.asList(matchList.get(2), matchList.get(3), line)); + } + } + return averageMap; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetPerFiles.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetPerFiles.java new file mode 100644 index 0000000..6120491 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseNetPerFiles.java @@ -0,0 +1,262 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * ParseNetPerFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseNetPerFiles implements CompatibilityFilesParser { + private static final String NIC_CN = "网卡"; + private static final String NIC_EN = "NIC"; + + private final ParsePerformanceFilesImpl parsePerformanceFiles; + + /** + * construction function + * + * @param inputByteMap map + */ + public ParseNetPerFiles(Map inputByteMap) { + this.parsePerformanceFiles = new ParsePerformanceFilesImpl(inputByteMap); + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + return parsePerformanceFiles.getResult(Constants.CompatibilityTestName.PRESSURE_NET.getTestName(), NIC_CN, + NIC_EN, 2); + } + + @Override + public CompatibilityTestResult parseFiles() throws IOException { + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.PRESSURE_NET.getTestName()); + try { + testResult = getResult(); + } catch (BaseException ex) { + log.error("Missing pressure test net file ", ex.getMessage()); + testResult.setResult(Constants.TEST_SKIPPED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(3), NIC_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(3), NIC_EN)); + } catch (NumberFormatException | IOException ex) { + log.error("Exception in parsing idle test net file ", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(2), NIC_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(2), NIC_EN)); + } + return testResult; + } + + @Data + private static class XxkbRate { + double maxXxkbRate = 0.00d; + String maxXxkbDiskName = null; + String netXxkbMax = null; + String netXxkbMin = null; + double netXxkbRate = 0.0d; + } + + private static class ParsePerformanceFilesImpl extends AbsParsePerformanceFiles { + private final Pattern idlePattern = Pattern.compile("\\d{2}(:|时)\\d{2}(:|分)\\d{2}(秒|\\s(PM|AM|HKT|))\\s+"); + private final Pattern pattern = Pattern.compile("\\d+\\.\\d+"); + + public ParsePerformanceFilesImpl(Map inputByteMap) { + super(inputByteMap); + } + + @Override + CompatibilityTestResult readFile(byte[] fileBytes) throws IOException { + if (fileBytes.length == 0) { + throw new BaseException("解析压力测试硬盘文件缺失"); + } + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.PRESSURE_NET.getTestName()); + Map>> netIdleMap = getIdleMap(fileBytes); + if (netIdleMap.size() > 0) { + XxkbRate rxkbRate = new XxkbRate(); + XxkbRate txkbRate = new XxkbRate(); + for (Map.Entry>> entry : netIdleMap.entrySet()) { + if (entry.getValue().get("rxkb").size() < 4 || entry.getValue().get("txkb").size() < 4) { + continue; + } + + List rxkbDoubleList = entry.getValue().get("rxkb").stream() + .map(Double::parseDouble).collect(Collectors.toList()); + calculateXxkbRate(rxkbDoubleList, entry.getKey(), rxkbRate); + + List txkbDoubleList = entry.getValue().get("txkb") + .stream().map(Double::parseDouble).collect(Collectors.toList()); + + calculateXxkbRate(txkbDoubleList, entry.getKey(), txkbRate); + } + testResult = getTestCaseResult(rxkbRate, txkbRate, netIdleMap); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(2), NIC_CN)); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(2), NIC_EN)); + } + return testResult; + } + + private void calculateXxkbRate(List rxkbDoubleList, String key, XxkbRate rate) { + Double maxRxkb = Collections.max(rxkbDoubleList); + rxkbDoubleList.remove(maxRxkb); + Double minRxkb = Collections.min(rxkbDoubleList); + rxkbDoubleList.remove(minRxkb); + double rxkbAvg = rxkbDoubleList.stream().mapToDouble(Double::valueOf).average().orElse(0.00); + if (Math.round(rxkbAvg) > 0) { + BigDecimal num = new BigDecimal(8).divide(new BigDecimal(1000 * 1024)); + rate.setNetXxkbRate(BigDecimal.valueOf(Collections.max(rxkbDoubleList)) + .subtract(new BigDecimal(String.valueOf(rxkbAvg))).abs().multiply(num).doubleValue()); + } else { + rate.setNetXxkbRate(0.0); + } + if (rate.getMaxXxkbRate() <= rate.getNetXxkbRate()) { + rate.setMaxXxkbDiskName(key); + rate.setMaxXxkbRate(rate.getNetXxkbRate()); + rate.setNetXxkbMax(String.format(Locale.ROOT, "%.2f", Collections.max(rxkbDoubleList))); + rate.setNetXxkbMin(String.format(Locale.ROOT, "%.2f", Collections.min(rxkbDoubleList))); + } + } + + private CompatibilityTestResult getTestCaseResult(XxkbRate rxkb, XxkbRate txkb, + Map>> netIdleMap) { + int[] kbPass = {0, 0}; + if (rxkb.getMaxXxkbRate() <= 0.05) { + kbPass[0] = 1; + } + if (txkb.getMaxXxkbRate() <= 0.05) { + kbPass[1] = 1; + } + + List evidence = evidenceInit(rxkb, txkb, netIdleMap); + List evidenceEn = new ArrayList<>(evidence); + Double maxRxkb = new BigDecimal(String.valueOf(rxkb.getMaxXxkbRate())) + .multiply(new BigDecimal(100)).doubleValue(); + Double maxTxkb = new BigDecimal(String.valueOf(txkb.getMaxXxkbRate())) + .multiply(new BigDecimal(100)).doubleValue(); + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.PRESSURE_NET.getTestName()); + if (kbPass[0] == 1 && kbPass[1] == 1) { + testResult.setResult(Constants.TEST_PASSED); + evidence.add(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_LIST.get(4), "接收", + maxRxkb) + String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(5), "发送", + maxTxkb, "小于")); + evidenceEn.add(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(4), "received", + maxRxkb) + String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(5), "sent", + maxTxkb, "less")); + } else { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(4), "接收", + maxRxkb) + String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_LIST.get(5), "发送", + maxTxkb, "大于")); + testResult.setReasonEn(String.format(Locale.ROOT, Constants.PERFORMANCE_DESC_EN_LIST.get(4), + "received", maxRxkb) + String.format(Locale.ROOT, + Constants.PERFORMANCE_DESC_EN_LIST.get(5), "sent", + maxTxkb, "greater")); + evidence.add(testResult.getResult()); + evidenceEn.add(testResult.getReasonEn()); + } + testResult.setEvidence(evidence); + testResult.setEvidenceEn(evidenceEn); + return testResult; + } + + private List evidenceInit(XxkbRate rxkb, XxkbRate txkb, + Map>> netIdleMap) { + List rxkbEvidenceList = netIdleMap.get(rxkb.getMaxXxkbDiskName()).get("evidence"); + List txkbEvidenceList = netIdleMap.get(txkb.getMaxXxkbDiskName()).get("evidence"); + + List evidence = new ArrayList<>(); + String finalNetRxkbMax = rxkb.getNetXxkbMax(); + evidence.add(rxkbEvidenceList.stream().filter(s -> StringUtils.containsIgnoreCase(s, finalNetRxkbMax)) + .limit(1).collect(Collectors.joining())); + String finalNetRxkbMin = rxkb.getNetXxkbMin(); + evidence.add(rxkbEvidenceList.stream().filter(s -> StringUtils.containsIgnoreCase(s, finalNetRxkbMin)) + .limit(1).collect(Collectors.joining())); + String finalNetTxkbMax = txkb.getNetXxkbMax(); + evidence.add(txkbEvidenceList.stream().filter(s -> StringUtils.containsIgnoreCase(s, finalNetTxkbMax)) + .limit(1).collect(Collectors.joining())); + String finalNetTxkbMin = txkb.getNetXxkbMin(); + evidence.add(txkbEvidenceList.stream().filter(s -> StringUtils.containsIgnoreCase(s, finalNetTxkbMin)) + .limit(1).collect(Collectors.joining())); + return evidence; + } + + @Override + List getIdleList(byte[] fileBytes) throws IOException { + return new ArrayList<>(); + } + + @Override + Map>> getIdleMap(byte[] fileBytes) throws IOException { + Map>> averageMap = new HashMap<>(); + try (InputStream beginInput = new ByteArrayInputStream(fileBytes); + BufferedReader beginReader = new BufferedReader( + new InputStreamReader(beginInput, StandardCharsets.UTF_8))) { + String line; + + while ((line = beginReader.readLine()) != null + && !StringUtils.containsIgnoreCase(line, "IFACE") + && !StringUtils.containsIgnoreCase(line, "lo") + && idlePattern.matcher(line).find()) { + Matcher matcher = pattern.matcher(line); + String netName = line.substring(13).trim().split(" ")[0]; + List matchList = new ArrayList<>(); + while (matcher.find()) { + matchList.add(matcher.group().trim()); + } + Map> netMap = averageMap.getOrDefault(netName, new HashMap<>()); + List rxkbList = netMap.getOrDefault("rxkb", new ArrayList<>()); + rxkbList.add(matchList.get(2)); + List txkbList = netMap.getOrDefault("txkb", new ArrayList<>()); + txkbList.add(matchList.get(3)); + List evidenceList = netMap.getOrDefault("evidence", new ArrayList<>()); + evidenceList.add(line); + netMap.put("rxkb", rxkbList); + netMap.put("txkb", txkbList); + netMap.put("evidence", evidenceList); + averageMap.put(netName, netMap); + } + } + return averageMap; + } + } +} \ No newline at end of file diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseSoftwareLog.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseSoftwareLog.java new file mode 100644 index 0000000..75c35cb --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/entity/compatibilityfileanalysis/impl/ParseSoftwareLog.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityFilesParser; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * ParseNetPerFiles + * + * @author kongcaizhi + * @since 2021-12-15 + */ +@Slf4j +public class ParseSoftwareLog implements CompatibilityFilesParser { + private final byte[] configBytes; + private final byte[] productNameBytes; + + /** + * construction function + * + * @param configBytes config bytes + * @param productNameBytes product name bytes + */ + public ParseSoftwareLog(byte[] configBytes, byte[] productNameBytes) { + this.configBytes = configBytes; + this.productNameBytes = productNameBytes; + } + + private Map> parseConfig() { + Map> configMap = new HashMap<>(); + if (configBytes.length == 0) { + return configMap; + } + + String line; + Pattern appPattern = Pattern.compile(Constants.APPLICATION_NAMES); + Pattern startPattern = Pattern.compile(Constants.START_APP_COMMANDS); + Pattern stopPattern = Pattern.compile(Constants.STOP_APP_COMMANDS); + try (InputStream input = new ByteArrayInputStream(configBytes); + BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { + while ((line = reader.readLine()) != null) { + Matcher appMatcher = appPattern.matcher(line); + if (appMatcher.find()) { + List applicationNamesList = Arrays.asList(appMatcher.group(1).split(",")); + configMap.put("applicationNames", applicationNamesList); + } + + Matcher startMatcher = startPattern.matcher(line); + if (startMatcher.find()) { + List startAppCommandsList = Arrays.asList(startMatcher.group(1).split(",")); + configMap.put("startAppCommands", startAppCommandsList); + } + + Matcher stopMatcher = stopPattern.matcher(line); + if (stopMatcher.find()) { + List stopAppCommandsList = Arrays.asList(stopMatcher.group(1).split(",")); + configMap.put("stopAppCommands", stopAppCommandsList); + } + } + } catch (IllegalStateException | IOException ex) { + log.error("Error reading configuration file for compatibility testing tool", ex); + } + return configMap; + } + + @Override + public CompatibilityTestResult getResult() throws IOException { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.SOFTWARE_NAME.getTestName()); + if (this.productNameBytes.length == 0) { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SOFTWARE_COMPARE_DESC_LIST.get(3)); + return testResult; + } + Map> configMap = parseConfig(); + if (configMap.size() == 0 || configMap.get("applicationNames").size() == 0) { + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SOFTWARE_COMPARE_DESC_LIST.get(2)); + } else { + testResult.setApplicationNames(configMap.get("applicationNames")); + testResult.setStartAppCommands(configMap.get("startAppCommands")); + testResult.setStopAppCommands(configMap.get("stopAppCommands")); + } + + getApplicationNames(configMap, testResult, this.productNameBytes); + return testResult; + } + + private void getApplicationNames(Map> configMap, CompatibilityTestResult testResult, + byte[] productNameBytes) { + try (InputStream inputStream = new ByteArrayInputStream(productNameBytes); + BufferedReader reader = new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + String line; + Map appCountMap = new HashMap<>(); + while ((line = reader.readLine()) != null) { + getApplicationName(line, configMap, testResult, appCountMap); + } + for (Map.Entry entry : appCountMap.entrySet()) { + if (appCountMap.get(entry.getKey()) == 0) { + testResult.setResult(Constants.TEST_FAILED); + List evidenceList = testResult.getEvidence(); + evidenceList.add(String.format(Locale.ROOT, + Constants.SOFTWARE_COMPARE_DESC_LIST.get(0), entry.getKey())); + testResult.setEvidence(evidenceList); + evidenceList = testResult.getEvidenceEn(); + evidenceList.add(String.format(Locale.ROOT, + Constants.SOFTWARE_COMPARE_DESC_EN_LIST.get(0), entry.getKey())); + testResult.setEvidenceEn(evidenceList); + } + } + if (Constants.TEST_FAILED.equals(testResult.getResult())) { + testResult.setReason(String.format(Locale.ROOT, + Constants.SOFTWARE_COMPARE_DESC_LIST.get(1), configMap.get("applicationNames").toString())); + testResult.setReasonEn(String.format(Locale.ROOT, + Constants.SOFTWARE_COMPARE_DESC_EN_LIST.get(1), configMap.get("applicationNames").toString())); + } else { + testResult.setResult(Constants.TEST_PASSED); + } + } catch (IOException e) { + throw new BaseException(e.getMessage()); + } + } + + private void getApplicationName(String line, Map> configMap, + CompatibilityTestResult testResult, Map appCountMap) { + int userLength = line.split(" ")[0].length(); + String lineSplit = line.substring(userLength); + + for (String app : configMap.get("applicationNames")) { + if (StringUtils.startsWithIgnoreCase(lineSplit, app)) { + appCountMap.put(app, appCountMap.getOrDefault(app, 0) + 1); + List evidenceList = testResult.getEvidence() == null ? new ArrayList<>() + : testResult.getEvidence(); + evidenceList.add(line.replace(System.lineSeparator(), "")); + testResult.setEvidence(evidenceList); + testResult.setEvidenceEn(evidenceList); + } + } + } + + @Override + public CompatibilityTestResult parseFiles() { + CompatibilityTestResult testResult = new CompatibilityTestResult( + Constants.CompatibilityTestName.SOFTWARE_NAME.getTestName()); + try { + testResult = getResult(); + } catch (IllegalStateException | IOException ex) { + log.error("Error parsing configuration file and software process stack information of compatibility " + + "testing tool", ex); + testResult.setResult(Constants.TEST_FAILED); + testResult.setReason(Constants.SOFTWARE_COMPARE_DESC_LIST.get(4)); + testResult.setReasonEn(Constants.SOFTWARE_COMPARE_DESC_EN_LIST.get(4)); + } + return testResult; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/DevkitService.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/DevkitService.java new file mode 100644 index 0000000..51ef42d --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/DevkitService.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.service; + +import com.huawei.ic.openlab.cloudtest.entity.SystemParams; +import com.huawei.ic.openlab.cloudtest.util.ApiCenterUtil; +import com.huawei.ic.openlab.cloudtest.util.DgCodeServerClient; +import com.huawei.ic.openlab.cloudtest.util.TeeCodeServerClient; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.concurrent.TimeUnit; + +import javax.servlet.http.HttpServletRequest; + +/** + * devkit环境申请service + * + * @author kongcaizhi + * @since 2022-10-19 + */ +@Slf4j +public class DevkitService { + private final TeeCodeServerClient client; + private final DgCodeServerClient dgCodeServerClient; + private final SystemParams systemParams; + + @Autowired + private RedisTemplate redisTemplate; + + /** + * construction function + * + * @param client client + * @param dgCodeServerClient dgCodeServer client + * @param systemParams system parameter + */ + public DevkitService(TeeCodeServerClient client, DgCodeServerClient dgCodeServerClient, + SystemParams systemParams) { + this.client = client; + this.dgCodeServerClient = dgCodeServerClient; + this.systemParams = systemParams; + } + + /** + * 往redis 增加 device-id + * + * @param server 服务器信息 + */ + public void addTaskDeviceId(DevkitServer server) { + client.addTaskDeviceId(server.getTaskDeviceId(), server.getInternalIp()); + dgCodeServerClient.addTaskDeviceId(server.getTaskDeviceId(), server.getInternalIp()); + if (Boolean.TRUE.equals(redisTemplate.hasKey(server.getTaskDeviceId()))) { + redisTemplate.opsForValue().setIfAbsent(server.getTaskDeviceId(), server.getInternalIp()); + } else { + redisTemplate.opsForValue().append(server.getTaskDeviceId(), server.getInternalIp()); + } + } + + /** + * 往redis 删除device-id + * + * @param taskDeviceId device-id + * @return boolean + */ + public boolean deleteTaskDeviceId(String taskDeviceId) { + client.deleteTaskDeviceId(taskDeviceId); + dgCodeServerClient.deleteTaskDeviceId(taskDeviceId); + return Boolean.TRUE.equals(redisTemplate.delete(taskDeviceId)); + } + + /** + * 向API网关验证token是否有效 + * + * @return validate + */ + public boolean validateToken() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = requestAttributes instanceof ServletRequestAttributes + ? ((ServletRequestAttributes) requestAttributes).getRequest() : null; + + if (request == null) { + return false; + } + + String token = request.getHeader("KP-TOKEN"); + String taskDeviceId = request.getHeader("TASK-DEVICE-ID"); + + if (StringUtils.isEmpty(token)) { + log.error("token is empty"); + return false; + } + + if (StringUtils.isEmpty(taskDeviceId)) { + log.error("taskDeviceId is empty"); + return false; + } + return validateToken(token, taskDeviceId); + } + + /** + * 检查redis是否有token, 如果有,返回为真,如果没有请求apigw判断.如果apigw返回为真,则保存在redis中,设置超时时间为1分钟. + * + * @param token token + * @param taskDeviceId taskDeviceId + * @return true|false + */ + private boolean validateToken(String token, String taskDeviceId) { + String key = token + "-" + taskDeviceId; + + if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) { + return true; + } else { + boolean isValidated = ApiCenterUtil.validateToken(systemParams, token, taskDeviceId); + if (isValidated) { + redisTemplate.opsForValue().set(key, "token", 5, TimeUnit.MINUTES); + log.info("Add token to redis return{}", + redisTemplate.expire(key, 5, TimeUnit.MINUTES)); + } + return isValidated; + } + } + + /** + * DevkitServer + * + * @author kongcaizhi + * @since 2022-10-19 + */ + @Data + public static class DevkitServer { + private String taskDeviceId; + private String agentId; + private String internalIp; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/LabEnvService.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/LabEnvService.java new file mode 100644 index 0000000..1eba0aa --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/LabEnvService.java @@ -0,0 +1,642 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.service; + +import com.alibaba.fastjson.JSONArray; +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; +import com.huawei.ic.openlab.cloudtest.common.exception.SshErrorException; +import com.huawei.ic.openlab.cloudtest.entity.CloudLabTestTask; +import com.huawei.ic.openlab.cloudtest.entity.LabTestReq; +import com.huawei.ic.openlab.cloudtest.entity.MqsMessage; +import com.huawei.ic.openlab.cloudtest.entity.ScriptResultConfig; +import com.huawei.ic.openlab.cloudtest.entity.SystemParams; +import com.huawei.ic.openlab.cloudtest.entity.TestCaseResult; +import com.huawei.ic.openlab.cloudtest.entity.TestCaseResultCount; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.util.Constants; +import com.huawei.ic.openlab.cloudtest.util.FileUtil; +import com.huawei.ic.openlab.cloudtest.util.NormalResp; +import com.huawei.ic.openlab.cloudtest.util.PerformanceApiClient; +import com.huawei.ic.openlab.cloudtest.util.RandomUtil; +import com.huawei.ic.openlab.cloudtest.util.ToolUtil; +import com.huawei.ic.openlab.cloudtest.util.fastdfs.FastDfsClient; +import com.huawei.ic.openlab.cloudtest.util.sshclient.SFTPUtil; +import com.huawei.ic.openlab.cloudtest.util.sshclient.SSHUtil; + +import com.alibaba.fastjson.JSONObject; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.SftpException; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.DigestUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +/** + * LabEnvService + * + * @author kongcaizhi + * @since 2021-10-19 + */ +@Service +@Slf4j +public class LabEnvService { + @Autowired + private SystemParams systemParams; + @Autowired + private TarFileService fileService; + @Autowired + private PerformanceApiClient performanceApiClient; + @Autowired + private FastDfsClient fastDfsClient; + + /** + * getLabConnectTest + * + * @param ip ip + * @param port port + * @param userName userName + * @param passWord password + * @return boolean + */ + public boolean getLabConnectTest(String ip, int port, String userName, String passWord) { + return SSHUtil.sshConnectTest(ip, port, userName, passWord); + } + + /** + * validatedZipFileSize + * + * @param fileInputStream fileInputStream + * @param language language + * @throws IOException exception + */ + public void validatedZipFileSize(InputStream fileInputStream, String language) throws IOException { + fileService.validatedZipFileSize(fileInputStream, language); + } + + /** + * validatedTarZipFile + * + * @param fileInputStream fileInputStream + * @throws IOException exception + */ + public void validatedTarZipFile(InputStream fileInputStream) throws IOException { + fileService.validatedTarGzFileSize(fileInputStream); + } + + + /** + * testPreparation + * + * @param testReq testReq + * @throws SshErrorException SshErrorException + * @throws FileNotFoundException FileNotFoundException + */ + public void testPreparation(LabTestReq testReq) throws SshErrorException, FileNotFoundException { + List commandList = new ArrayList<>(); + commandList.add("mkdir -p /home/compatibility_testing; mkdir -p /home/function_testing"); + String wgetCom = "cd /home/compatibility_testing; wget http://%s:8080/download/compatibility_testing.tar.gz"; + commandList.add(String.format(Locale.ROOT, wgetCom, systemParams.getDeployIP())); + commandList.add("cd /home/compatibility_testing; tar -xvzf compatibility_testing.tar.gz"); + String wgetFun = "cd /home/function_testing; wget http://%s:8080/download/shunit2-master.zip"; + commandList.add(String.format(Locale.ROOT, wgetFun, systemParams.getDeployIP())); + commandList.add("cd /home/function_testing; unzip -o -q shunit2-master.zip"); + SSHUtil.sshExecCmd(testReq.getServerIp(), testReq.getServerPort(), testReq.getServerUser(), + testReq.getServerPassword(), commandList); + } + + /** + * 修改配置文件,并上传到实验室环境 + * + * @param testReq testReq + * @throws IOException IOException + * @throws JSchException JSchException + * @throws SftpException SftpException + */ + private void setConfigFile(LabTestReq testReq) throws IOException, JSchException, SftpException { + String configContent = readConfigFile(testReq); + String configFileName = writeConfigFile(configContent); + ToolUtil.validPath(configFileName); + File configFile = new File(configFileName); + try (InputStream in = Files.newInputStream(configFile.toPath())) { + String targetPath = String.format(Locale.ROOT, "/home/compatibility_testing/compatibility_testing/%s" + + "/compatibility_testing.conf", "CN".equals(testReq.getTaskLanguage()) ? "Chinese" : "English"); + SFTPUtil.uploadFile(testReq, targetPath, in); + } + log.info("Delete configure file {},result {}", configFileName, configFile.delete()); + } + + private String readConfigFile(LabTestReq testReq) { + StringBuilder res = new StringBuilder(16); + try (BufferedReader reader = new BufferedReader( + new FileReader(systemParams.getScriptConfig(testReq.getTaskLanguage())))) { + String line; + while ((line = reader.readLine()) != null) { + if (StringUtils.startsWithIgnoreCase(line, "application_names=")) { + line = line + testReq.getApplicationNames(); + } + if (StringUtils.startsWithIgnoreCase(line, "start_app_commands=")) { + line = line + testReq.getStartAppCommands(); + } + if (StringUtils.startsWithIgnoreCase(line, "stop_app_commands=")) { + line = line + testReq.getStopAppCommands(); + } + if (StringUtils.startsWithIgnoreCase(line, "application_install_dir=")) { + line = line + testReq.getDeployDir(); + } + res.append(line).append(System.lineSeparator()); + } + } catch (FileNotFoundException ex) { + log.error(ex.getLocalizedMessage()); + throw new BaseException("配置文件不存在"); + } catch (IOException e) { + log.error(e.getLocalizedMessage(), e); + } + return res.toString(); + } + + private String writeConfigFile(String content) { + SecureRandom random = RandomUtil.getRandom(); + int ends = random.nextInt(99); + String fileName = ToolUtil.getTimeStr() + String.format(Locale.ROOT, "%02d", ends); + fileName = systemParams.getTempDir() + File.separator + fileName; + try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { + writer.write(content); + writer.flush(); + } catch (IOException e) { + log.error(e.getLocalizedMessage(), e); + } + return fileName; + } + + private void setStep(String step, String resultCode, String timeString, CloudLabTestTask.StepStatus stepStatus) { + switch (step) { + case "01": + stepStatus.setStep1(resultCode, timeString); + break; + case "02": + stepStatus.setStep2(resultCode, timeString); + break; + case "03": + stepStatus.setStep3(resultCode, timeString); + break; + case "04": + stepStatus.setStep4(resultCode, timeString); + break; + case "05": + stepStatus.setStep5(resultCode, timeString); + break; + case "06": + stepStatus.setStep6(resultCode, timeString); + break; + case "07": + stepStatus.setStep7(resultCode, timeString); + break; + case "08": + stepStatus.setStep8(resultCode, timeString); + break; + case "09": + stepStatus.setStep9(resultCode, timeString); + break; + default: + stepStatus.setStep10(resultCode, timeString); + break; + } + } + + private void setTestTime(String step, String timeString, CloudLabTestTask.TestBeginTime testBeginTime, + boolean isFunctionTest) { + if ("05".equals(step)) { + testBeginTime.setCompatibilityTime(timeString); + testBeginTime.setSecurityTime(timeString); + testBeginTime.setReliabilityTime(timeString); + testBeginTime.setFunctionTime(timeString); + } else if ("06".equals(step)) { + testBeginTime.setCompatibilityTime(timeString); + testBeginTime.setReliabilityTime(timeString); + } else if ("08".equals(step)) { + testBeginTime.setCompatibilityTime(timeString); + } else if ("09".equals(step) && isFunctionTest) { + testBeginTime.setFunctionTime(timeString); + } else { + log.info("not contrast"); + } + } + + /** + * 组装测试进度推送MQS 消息 + * + * @param task task + * @param resultCode resultCode + * @param timeString timeString + * @return MqsMessage object + */ + private MqsMessage getProgressMessage(CloudLabTestTask task, String resultCode, String timeString) { + MqsMessage message = new MqsMessage(); + message.setProjectId(task.getProjectId()); + message.setUserId(task.getUserId()); + message.setServerIp(task.getServerIp()); + message.setStatusTime(timeString); + message.setStatus(Constants.MQS_STATUS_ONGOING); + message.setStatusDesc(""); + + MqsMessage.MessageDetail detail = setDetail(task, resultCode); + message.setDetail(detail); + return message; + } + + private MqsMessage.MessageDetail setDetail(CloudLabTestTask task, String resultCode) { + MqsMessage.MessageDetail detail = new MqsMessage.MessageDetail(); + switch (Objects.requireNonNull(Constants.CompatibilityTestStep.fromStepIndex(resultCode))) { + case DEPENDENCY_INSTALL_SUCCESS: + detail.setDependencyInstallSuccess(); + break; + case APP_START_SUCCESS: + detail.setAppStartSuccess(); + break; + case APP_STOP_SUCCESS: + detail.setAppStopSuccess(task.isCompatibilityTest(), + task.isReliabilityTest(), task.isSecurityTest()); + break; + case COMPATIBILITY_TEST_SUCCESS: + case COM_START_SUCCESS: + detail.setComStartSuccess(task.isReliabilityTest(), task.isSecurityTest()); + if ((task.isCompatibilityTest() || task.isReliabilityTest()) + && !task.isSecurityTest() && task.getPerformanceFile() != null) { + setPerformanceTest(task, true); + } + break; + case PORT_TEST_SUCCESS: + detail.setPortTestSuccess(); + break; + case VIRUS_SCAN_SUCCESS: + detail.setVirusScanSuccess(task.isCompatibilityTest(), task.isReliabilityTest()); + if ((task.isCompatibilityTest() || task.isReliabilityTest()) && task.getPerformanceFile() != null) { + setPerformanceTest(task, true); + } + break; + case VULNERABLE_SCAN_SUCCESS: + detail.setVulnerableScanSuccess(task.isCompatibilityTest(), task.isReliabilityTest()); + break; + case EXCEPTION_TEST_FINISH: + detail.setExceptionTestFinish(task.isCompatibilityTest()); + break; + case COMPATIBILITY_TEST_FINISH: + detail.setStep(Constants.COMPATIBILITY_TEST_DESC); + detail.setStepStatus(Constants.TEST_FINISHED_CN); + break; + case FUN_TEST_FILE_EXIST_ERROR: + case FUN_TEST_FILE_DIR_ERROR: + case FUN_TEST_PYTEST_ERROR: + detail.setStep(Constants.FUNCTION_TEST_DESC); + detail.setStepStatus(Constants.TEST_FAILURE_CN); + break; + default: + break; + } + return detail; + } + + private void sendExceptionMessage(CloudLabTestTask task, String timeString, MqsMessage.MessageDetail detail) { + MqsMessage message = new MqsMessage(); + message.setProjectId(task.getProjectId()); + message.setUserId(task.getUserId()); + message.setServerIp(task.getServerIp()); + message.setStatusTime(timeString); + message.setStatus(Constants.MQS_STATUS_EXCEPTION); + message.setStatusDesc(detail.getExceptionType()); + message.setDetail(detail); + } + + private void ransfer2json(List input_info, String path) { + String jsonArray = JSONArray.toJSONString(input_info); + byte[] temp_result = jsonArray.getBytes(StandardCharsets.UTF_8); + try(FileOutputStream fos=new FileOutputStream(new File(path)); + ByteArrayInputStream bais = new ByteArrayInputStream(temp_result)){ + IOUtils.copy(bais, fos); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void resultJson(String multipartFile, String savePath) { + List testCaseResultList = null; + List results = fileService.compatibilityResultAnalysis(multipartFile); + if (results.size() != 0){ + testCaseResultList = analyseCompatibilityTestResult(results, "CN"); + } else { + throw new BaseException("解析兼容性测试工具输出日志异常"); + } + ransfer2json(testCaseResultList, savePath); + } + + private String resultFileAnalysis(CloudLabTestTask task, MultipartFile multipartFile, String resultCode, + String fileStatus, String timeString) { + List temp = null; + CloudLabTestTask.StepStatus stepStatus = task.getStepStatus(); + if (stepStatus == null) { + stepStatus = new CloudLabTestTask.StepStatus(); + } + stepStatus.setStep10Code(resultCode); + stepStatus.setStep10Time(timeString); + stepStatus.setStep10File(getFileFromRequest(multipartFile, "兼容性测试工具输出日志", fileStatus)); + if (!task.isPerformanceTest() || (task.getPerformanceFile() == null + && Constants.RELIABILITY_START_APP_FAIL_CODE.equals(stepStatus.getStep9Code()))) { + task.setProjectStatus(Constants.CLOUD_LAB_TEST_FINISH); + task.setFinishTime(timeString); + + task.setProjectStatus(Constants.CLOUD_LAB_TEST_FINISH); + } else { + stepStatus.setPerformanceTime(timeString); + } + if (multipartFile != null) { + task.setResultFile(stepStatus.getStep10File()); + List results = fileService.compatibilityResultAnalysis(multipartFile.getOriginalFilename()); + if (results.size() != 0) { + temp = analyseCompatibilityTestResult(results, "CN"); + } else { + task.setStatusDesc("解析兼容性测试工具输出日志异常"); + task.setProjectStatus(Constants.CLOUD_LAB_TEST_EXCEPTION); + } + } else { + task.setStatusDesc("兼容性测试工具输出日志," + fileStatus); + task.setProjectStatus(Constants.CLOUD_LAB_TEST_EXCEPTION); + } + + task.setStepStatus(stepStatus); + + return NormalResp.ok(); + } + + private void setPerformanceTest(CloudLabTestTask task, boolean isTimeLimited) { + try { + String fileName = task.getPerformanceFile().getFilePath(); + MultipartFile multipartFile = FileUtil.fileToMultipartFile(fileName); + String result = performanceApiClient.setPerformanceTest(createURI(task.getPerformanceService()), + task.getProjectId(), task.getServerIp(), isTimeLimited, multipartFile); + log.info("Task {} request {} return from performance test {}", task.getProjectId(), + task.getPerformanceService(), result); + } catch (URISyntaxException ex) { + log.error("Failed to request performance test {}", ex.getLocalizedMessage()); + } + } + + /** + * 往MQS发送性能测试中状态 + * + * @param task task + * @param timeString timeString + */ + private void sendPerformanceMQS(CloudLabTestTask task, String timeString) { + MqsMessage message = new MqsMessage(); + message.setProjectId(task.getProjectId()); + message.setUserId(task.getUserId()); + message.setServerIp(task.getServerIp()); + message.setStatusTime(timeString); + message.setStatus(Constants.MQS_STATUS_ONGOING); + message.setStatusDesc(""); + MqsMessage.MessageDetail detail = new MqsMessage.MessageDetail(); + detail.setStep(Constants.PERFORMANCE_TEST_DESC); + detail.setStepStatus(Constants.TEST_PROCESSING); + message.setDetail(detail); + } + + /** + * 往MQS发送分析结果 + * + * @param task task + * @param timeString time string + */ + private void sentResultMQSMessage(CloudLabTestTask task, String timeString) { + MqsMessage message = new MqsMessage(); + message.setProjectId(task.getProjectId()); + message.setUserId(task.getUserId()); + message.setServerIp(task.getServerIp()); + message.setStatusTime(timeString); + message.setStatus(Constants.MQS_STATUS_FINISH); + MqsMessage.MessageDetail detail = new MqsMessage.MessageDetail(); + detail.setResultFileName(task.getResultFile().getFileName()); + detail.setFileStatus(Constants.TEST_NORMAL_CN); + message.setDetail(detail); + MqsMessage.MessageResult result = new MqsMessage.MessageResult(); + result.setScriptResultConfig(task.getScriptResultConfig()); + result.setTestDetail(task.getTestDetail()); + result.setTestSummary(task.getTestSummary()); + message.setTestResult(result); + + } + + /** + * 上传的文件,存储到服务器,返回路径 + * + * @param multipartFile multipartFile + * @param type type + * @param fileStatus fileStatus + * @return 路径 + */ + private CloudLabTestTask.UploadFile getFileFromRequest(MultipartFile multipartFile, String type, + String fileStatus) { + CloudLabTestTask.UploadFile uploadFile = new CloudLabTestTask.UploadFile(); + uploadFile.setFileDesc(type); + uploadFile.setFileStatus(fileStatus); + if (multipartFile == null) { + return uploadFile; + } + try { + SecureRandom random = RandomUtil.getRandom(); + String fileName = random.getAlgorithm() + "-" + + DigestUtils.md5DigestAsHex(multipartFile.getInputStream()) + + multipartFile.getOriginalFilename().substring( + multipartFile.getOriginalFilename().lastIndexOf(".")); + String dirName = systemParams.getUploadFileDir() + File.separator + + ToolUtil.getDateStr() + File.separator + fileName; + ToolUtil.validPath(dirName); + File file = new File(dirName); + FileUtils.copyToFile(multipartFile.getInputStream(), file); + uploadFile.setFileId(DigestUtils.md5DigestAsHex(multipartFile.getInputStream())); + uploadFile.setFileName(fileName); + uploadFile.setFilePath(dirName); + } catch (IOException ex) { + log.error(ex.getLocalizedMessage(), ex); + uploadFile.setFileStatus(Constants.UPLOAD_FILE_STATUS_EXCEPTION); + } + return uploadFile; + } + + private List analyseCompatibilityTestResult(List results, String lan) { + ScriptResultConfig config = new ScriptResultConfig(); + TestCaseResultCount functionCount = new TestCaseResultCount(); + TestCaseResultCount compatibilityCount = new TestCaseResultCount(); + TestCaseResultCount reliabilityCount = new TestCaseResultCount(); + TestCaseResultCount securityCount = new TestCaseResultCount(); + List testCaseResults = new ArrayList<>(); + + for (CompatibilityTestResult item : results) { + ready(item, config); + if (StringUtils.isNoneEmpty(item.getId()) && item.getId().startsWith( + "Compatibility")) { + compatibilityCount.add(item.getResult()); + testCaseResults.add(getTestCaseResult(item, lan)); + } else if (StringUtils.isNoneEmpty(item.getId()) && item.getId().startsWith( + "Reliability")) { + reliabilityCount.add(item.getResult()); + testCaseResults.add(getTestCaseResult(item, lan)); + } else if (StringUtils.isNoneEmpty(item.getId()) && item.getId().startsWith( + "Security")) { + securityCount.add(item.getResult()); + testCaseResults.add(getTestCaseResult(item, lan)); + } else { + log.info("not contrast"); + } + } + CloudLabTestTask.TestCaseSummary testCaseSummary = new CloudLabTestTask.TestCaseSummary(compatibilityCount, + reliabilityCount, securityCount, functionCount); + + return testCaseResults; + } + + private void ready(CompatibilityTestResult item, ScriptResultConfig config) { + if (StringUtils.isNoneEmpty(item.getId()) && StringUtils.equals(item.getId(), + Constants.CompatibilityTestName.APPLICATION_START.getTestName())) { + config.setOsVersion(item.getOsVersion()); + } else if (StringUtils.isNoneEmpty(item.getId()) && StringUtils.equals(item.getId(), + Constants.CompatibilityTestName.SOFTWARE_NAME.getTestName())) { + config.setApplicationNames(item.getApplicationNames() != null ? String.join(",", + item.getApplicationNames()) : ""); + config.setStartAppCommands(item.getStartAppCommands() != null ? String.join(",", + item.getStartAppCommands()) : ""); + config.setStopAppCommands(item.getStopAppCommands() != null ? String.join(",", + item.getStopAppCommands()) : ""); + } else { + log.info("not contrast"); + } + } + + private TestCaseResult createTestCaseResult(CloudLabTestTask.UploadFile performanceFile, String taskLanguage) { + TestCaseResult testCaseResult = new TestCaseResult(); + testCaseResult.setId(Constants.PERFORMANCE_TEST_ID); + testCaseResult.setResult(Constants.TEST_FAILED); + if (performanceFile == null) { + testCaseResult.setReason(Constants.PERFORMANCE_FILE_MISSING_MAP.get(taskLanguage)); + } else { + testCaseResult.setReason(Constants.APP_START_UP_FAILURE_DESC_MAP.get(taskLanguage)); + } + return testCaseResult; + } + + private void setFunctionCount(CompatibilityTestResult item, TestCaseResultCount functionCount, + CloudLabTestTask.StepStatus status, CloudLabTestTask.TestBeginTime testBeginTime) { + if (Constants.TEST_PASSED.equals(item.getResult())) { + JSONObject jsonObject = JSONObject.parseObject(item.getReason()); + functionCount.setPassed(jsonObject.getIntValue(Constants.TEST_PASSED)); + functionCount.setFailed(jsonObject.getIntValue(Constants.TEST_FAILED)); + functionCount.setTotal(jsonObject.getIntValue(Constants.TEST_PASSED) + + jsonObject.getIntValue(Constants.TEST_FAILED)); + } + if (Constants.RELIABILITY_START_APP_FAIL_CODE.equals(status.getStep9Code())) { + functionCount.setPassed(0); + functionCount.setFailed(0); + functionCount.setTotal(0); + } + functionCount.setStartTime(testBeginTime.getFunctionTime()); + } + + private TestCaseResult getTestCaseResult(CompatibilityTestResult testResult, String language) { + TestCaseResult testCaseResult = new TestCaseResult(); + testCaseResult.setId(testResult.getId()); + testCaseResult.setResult(testResult.getResult()); + testCaseResult.setReason("CN".equals(language) ? testResult.getReason() : testResult.getReasonEn()); + testCaseResult.setEvidence(String.join(",", "CN".equals(language) + ? testResult.getEvidence() : testResult.getEvidenceEn())); + return testCaseResult; + } + + /** + * 上传功能测试文件到远程实验室 + * + * @param task task + * @param uploadFile upload file + */ + private void setRemoteFunctionFile(CloudLabTestTask task, CloudLabTestTask.UploadFile uploadFile) { + ToolUtil.validPath(uploadFile.getFilePath()); + try (InputStream in = new FileInputStream(uploadFile.getFilePath())) { + SFTPUtil.uploadFile(task, "/home/function_testing/function_testing.zip", in); + } catch (JSchException | SftpException | IOException ex) { + log.error("Failed to upload task {} function file {} to remote lab {},{}", task.getProjectId(), + uploadFile.getFilePath(), task.getServerIp(), ex.getLocalizedMessage()); + } + } + + private boolean stopCompatibilityTesting(CloudLabTestTask task) { + List commandList = new ArrayList<>(); + commandList.add("pid=$(pgrep -f sh\\ compatibility_testing.sh|head -1);sub_pids=$(pgrep -P ${pid});for " + + "subpid" + " " + "in ${sub_pids};do kill -9 \"${subpid}\" ;done;kill -9 \"${pid}\" "); + try { + SSHUtil.sshExecCmd(task.getServerIp(), task.getServerPort(), task.getServerUser(), + task.getServerPassword(), commandList); + + return true; + } catch (SshErrorException ex) { + log.error("Failed to execute task {},{}", task.getProjectId(), ex.getLocalizedMessage()); + return false; + } + } + + private boolean stopPerformanceTesting(CloudLabTestTask task) { + try { + String result = performanceApiClient.stopPerformanceTest(createURI(task.getPerformanceService()), + task.getProjectId()); + log.info("Task {} request {} stop performance test, return {}", task.getProjectId(), + task.getPerformanceService(), result); + JSONObject resultJson = JSONObject.parseObject(result); + return resultJson.containsKey("code") && "0000".equals(resultJson.getString("code")); + } catch (URISyntaxException ex) { + log.error("Failed to stop performance test {}", ex.getLocalizedMessage()); + return false; + } + } + + /** + * upload file + * + * @param file file + * @return response + */ + public String uploadFile(MultipartFile file) { + String fileId = null; + try { + fileId = fastDfsClient.uploadFile(file); + } catch (IOException ex) { + log.error(ex.getLocalizedMessage()); + } + return fileId; + } + + private URI createURI(String param) throws URISyntaxException { + ToolUtil.checkParameter(param); + return new URI(String.format(Locale.ROOT, + systemParams.getPerformanceTestUrl(), param)); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TarFileService.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TarFileService.java new file mode 100644 index 0000000..95e1d89 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TarFileService.java @@ -0,0 +1,387 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.service; + +import com.huawei.ic.openlab.cloudtest.entity.CloudLabTestTask; +import com.huawei.ic.openlab.cloudtest.entity.SystemParams; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.CompatibilityTestResult; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.ParseFunctionTestLog; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.ParseInfoLog; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.ParseSafetyFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseClamLog; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseCpuComFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseCpuPerFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseCveCheckFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseDiskComFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseDiskPerFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseMemComFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseMemPerFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseNetComFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseNetPerFiles; +import com.huawei.ic.openlab.cloudtest.entity.compatibilityfileanalysis.impl.ParseSoftwareLog; +import com.huawei.ic.openlab.cloudtest.util.Constants; +import com.huawei.ic.openlab.cloudtest.util.ToolUtil; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.zip.ZipInputStream; + +/** + * TarFileService + * + * @author kongcaizhi + * @since 2021-10-19 + */ +@Service +@Slf4j +public class TarFileService { + /** + * BUFFER + */ + public static final int BUFFER = 512; + + /** + * TOOBIG + */ + public static final int TOOBIG = 0X64000000; + + private final SystemParams systemParams; + + /** + * TarFileService + * + * @param systemParams system Params + */ + public TarFileService(SystemParams systemParams) { + this.systemParams = systemParams; + } + + /** + * validatedTarGzFileSize + * + * @param fileInputStream input stream + * @throws IOException exception + */ + public void validatedTarGzFileSize(InputStream fileInputStream) throws IOException { + long total = 0L; + try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fileInputStream))) { + while (zis.getNextEntry() != null) { + total = getTarTotalSize(total, zis); + if (total > TOOBIG) { + throw new IllegalStateException(Constants.TAR_FILE_TOO_BIG); + } + } + } + } + + private long getTarTotalSize(long total, ZipInputStream zis) throws IOException { + int count; + byte[] data = new byte[BUFFER]; + long sum = total; + while ((count = zis.read(data, 0, BUFFER)) != -1) { + sum += count; + if (sum > TOOBIG) { + break; + } + } + return sum; + } + + /** + * validatedZipFileSize + * + * @param fileInputStream input stream + * @param language language + * @throws IOException exception + */ + public void validatedZipFileSize(InputStream fileInputStream, String language) throws IOException { + long total = 0L; + try (ZipArchiveInputStream zis = new ZipArchiveInputStream(new BufferedInputStream(fileInputStream))) { + while (zis.getNextEntry() != null) { + total = getZipTotalSize(total, zis); + if (total > TOOBIG) { + throw new IllegalStateException( + Constants.TAR_FILE_TOO_BIG_MAP.getOrDefault(language, "CN")); + } + } + } + } + + private long getZipTotalSize(long total, ZipArchiveInputStream zis) throws IOException { + int count; + byte[] data = new byte[BUFFER]; + long sum = total; + while ((count = zis.read(data, 0, BUFFER)) != -1) { + sum += count; + if (sum > TOOBIG) { + break; + } + } + return sum; + } + + /** + * 应用启动、停止、异常测试用例 + * + * @param filePath file path + * @param testResultList test result list + * @throws IOException exception + */ + private void getTestCaseFromInfoLog(String filePath, List testResultList) + throws IOException { + byte[] infoLogFile = readSpecificFile(filePath, Constants.CompatibilityTarFile.INFO_LOG.getFileName()); + ParseInfoLog parseInfoLog = new ParseInfoLog(infoLogFile, ""); + Map infoResultMap = parseInfoLog.parseInfoLog(); + for (Map.Entry entry : infoResultMap.entrySet()) { + testResultList.add(entry.getValue()); + } + } + + /** + * 软件识别用例 + * + * @param filePath file path + * @param testResultList test result list + * @throws IOException exception + */ + private void getTestCaseFromProductName(String filePath, List testResultList) + throws IOException { + byte[] configFile = readSpecificFile(filePath, Constants.CompatibilityTarFile.CONFIGURE_INFO.getFileName()); + byte[] processFile = readSpecificFile(filePath, Constants.CompatibilityTarFile.PRODUCT_NAME.getFileName()); + ParseSoftwareLog softwareLog = new ParseSoftwareLog(configFile, processFile); + CompatibilityTestResult softwareResult = softwareLog.parseFiles(); + testResultList.add(softwareResult); + } + + /** + * 空载测试用例 + * + * @param filePath filePath + * @param testResultList testResultList + * @throws IOException IOException + */ + private void getTestCaseFromIdleFile(String filePath, List testResultList) + throws IOException { + // 空载测试CPU 用例 + Map beginCpuComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_CPU_0.getFileName()); + Map endCpuComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_CPU_1.getFileName()); + CompatibilityTestResult cpuComResult = new ParseCpuComFiles(beginCpuComFile, endCpuComFile).parseFiles(); + testResultList.add(cpuComResult); + + // 空载测试内存用例 + Map beginMemComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_MEM_0.getFileName()); + Map endMemComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_MEM_1.getFileName()); + CompatibilityTestResult memComResult = new ParseMemComFiles(beginMemComFile, endMemComFile).parseFiles(); + testResultList.add(memComResult); + + Map beginDiskComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_DISK_0.getFileName()); + Map endDiskComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_DISK_1.getFileName()); + CompatibilityTestResult diskComResult = new ParseDiskComFiles(beginDiskComFile, endDiskComFile).parseFiles(); + testResultList.add(diskComResult); + + Map beginNetComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_NET_0.getFileName()); + Map endNetComFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.COMPATIBILITY_NET_1.getFileName()); + CompatibilityTestResult diskNetResult = new ParseNetComFiles(beginNetComFile, endNetComFile).parseFiles(); + testResultList.add(diskNetResult); + } + + /** + * 压力测试用例 + * + * @param filePath filePath + * @param testResultList testResultList + * @throws IOException exception + */ + private void getTestCaseFromPressureFile(String filePath, List testResultList) + throws IOException { + Map cpuPerFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.PERFORMANCE_CPU.getFileName()); + CompatibilityTestResult cpuPerTestResult = new ParseCpuPerFiles(cpuPerFile).parseFiles(); + testResultList.add(cpuPerTestResult); + Map memPerFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.PERFORMANCE_MEM.getFileName()); + CompatibilityTestResult memPerTestResult = new ParseMemPerFiles(memPerFile).parseFiles(); + testResultList.add(memPerTestResult); + + Map diskPerFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.PERFORMANCE_DISK.getFileName()); + CompatibilityTestResult diskPerTestResult = new ParseDiskPerFiles(diskPerFile).parseFiles(); + testResultList.add(diskPerTestResult); + Map netPerFile = getSpecificFile(filePath, + Constants.CompatibilityTarFile.PERFORMANCE_NET.getFileName()); + CompatibilityTestResult netPerTestResult = new ParseNetPerFiles(netPerFile).parseFiles(); + testResultList.add(netPerTestResult); + } + + private void getTestCaseFromSafeFile(List fileList, String filePath, + List testResultList) throws IOException { + // 端口扫描 + byte[] protocolFile = new byte[0]; + byte[] updFile = new byte[0]; + byte[] tcpFile = new byte[0]; + + for (String tarFileName : fileList) { + if (StringUtils.endsWith(tarFileName, "gnmap") + && StringUtils.containsIgnoreCase(tarFileName, "PROTOCOL")) { + protocolFile = readSpecificFile(filePath, tarFileName); + } else if (StringUtils.endsWith(tarFileName, "gnmap") + && StringUtils.containsIgnoreCase(tarFileName, "UDP" + )) { + updFile = readSpecificFile(filePath, tarFileName); + } else if (StringUtils.endsWith(tarFileName, "gnmap") + && StringUtils.containsIgnoreCase(tarFileName, "TCP" + )) { + tcpFile = readSpecificFile(filePath, tarFileName); + } else { + log.info("not contrast"); + } + } + testResultList.add(new ParseSafetyFiles(protocolFile, updFile, tcpFile).parseSafetyFile()); + } + + /** + * compatibility Result Analysis + * + * @param task task + * @param multipartFile multipartFile + * @return CompatibilityTestResult list + */ + public List compatibilityResultAnalysis(String multipartFile) { + + String logPath = multipartFile; + File file = FileUtils.getFile(logPath); + List testResultList = new ArrayList<>(); + try { + List fileList = getTarFileList(logPath); + getTestCaseFromInfoLog(logPath, testResultList); + + // 硬件识别用例 + CompatibilityTestResult testResult = + new CompatibilityTestResult(Constants.CompatibilityTestName.HARDWARE_SERVER.getTestName()); + testResult.setResult(Constants.TEST_PASSED); + testResult.setReason(Constants.HCS_DESC); + testResultList.add(testResult); + + getTestCaseFromProductName(logPath, testResultList); + getTestCaseFromIdleFile(logPath, testResultList); + getTestCaseFromPressureFile(logPath, testResultList); + getTestCaseFromSafeFile(fileList, logPath, testResultList); + + // 功能测试 + byte[] shellBytes = readSpecificFile(logPath, + Constants.CompatibilityTarFile.FUNCTION_SHELL_UNIT.getFileName()); + byte[] pytestBytes = readSpecificFile(logPath, + Constants.CompatibilityTarFile.FUNCTION_PY_TEST.getFileName()); + testResultList.add(new ParseFunctionTestLog(shellBytes, pytestBytes).parseFunctionTestLog()); + } catch (IOException ex) { + log.error("Error parsing tar file", ex); + } + return testResultList; + } + + /** + * get tar file list + * + * @param tarGzFile tar file + * @return file list + * @throws IOException exception + */ + public List getTarFileList(String tarGzFile) throws IOException { + ToolUtil.validPath(tarGzFile); + List fileList = new ArrayList<>(); + try (FileInputStream fin = new FileInputStream(tarGzFile); + BufferedInputStream in = new BufferedInputStream(fin); + GzipCompressorInputStream gzip = new GzipCompressorInputStream(in); + TarArchiveInputStream tarIn = new TarArchiveInputStream(gzip)) { + TarArchiveEntry entry; + while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) { + fileList.add(entry.getName()); + } + } + return fileList; + } + + /** + * get specific file + * + * @param tarGzFile tar file + * @param fileName file name + * @return file map + * @throws IOException exception + */ + public Map getSpecificFile(String tarGzFile, String fileName) throws IOException { + ToolUtil.validPath(tarGzFile); + Map fileMap = new HashMap<>(); + try (FileInputStream fin = new FileInputStream(tarGzFile); + BufferedInputStream in = new BufferedInputStream(fin); + GzipCompressorInputStream gzip = new GzipCompressorInputStream(in); + TarArchiveInputStream tarIn = new TarArchiveInputStream(gzip)) { + TarArchiveEntry entry; + + while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) { + if (StringUtils.startsWithIgnoreCase(entry.getName(), fileName)) { + byte[] fileBytes = new byte[(int) entry.getSize()]; + tarIn.read(fileBytes); + fileMap.put(entry.getName(), fileBytes); + } + } + } + return fileMap; + } + + /** + * read specific file + * + * @param tarGzFile tar file + * @param fileName file name + * @return byte [] + * @throws IOException exception + */ + public byte[] readSpecificFile(String tarGzFile, String fileName) throws IOException { + ToolUtil.validPath(tarGzFile); + byte[] fileBytes = new byte[0]; + try (FileInputStream fin = new FileInputStream(tarGzFile); + BufferedInputStream in = new BufferedInputStream(fin); + GzipCompressorInputStream gzip = new GzipCompressorInputStream(in); + TarArchiveInputStream tarIn = new TarArchiveInputStream(gzip)) { + TarArchiveEntry entry; + while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) { + if (StringUtils.startsWithIgnoreCase(entry.getName(), fileName)) { + fileBytes = new byte[(int) entry.getSize()]; + tarIn.read(fileBytes); + } + } + } + return fileBytes; + } +} \ No newline at end of file diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TaskDelayMapService.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TaskDelayMapService.java new file mode 100644 index 0000000..e59911c --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/service/TaskDelayMapService.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.service; + +import com.huawei.ic.openlab.cloudtest.common.exception.SshErrorException; +import com.huawei.ic.openlab.cloudtest.dao.CloudLabTestTaskDao; +import com.huawei.ic.openlab.cloudtest.entity.CloudLabTestTask; +import com.huawei.ic.openlab.cloudtest.entity.MqsMessage; +import com.huawei.ic.openlab.cloudtest.entity.SystemParams; +import com.huawei.ic.openlab.cloudtest.entity.TaskDelay; +import com.huawei.ic.openlab.cloudtest.util.Constants; +import com.huawei.ic.openlab.cloudtest.util.ToolUtil; +import com.huawei.ic.openlab.cloudtest.util.sshclient.SSHUtil; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * TaskDelayMapService + * + * @author kongcaizhi + * @since 2021-10-19 + */ +@Slf4j +public class TaskDelayMapService { + private final Map taskMap = new HashMap<>(); + private final CloudLabTestTaskDao dao; + private final SystemParams systemParams; + + /** + * construction function + * + * @param dao dao + * @param systemParams system parameter + */ + public TaskDelayMapService(CloudLabTestTaskDao dao, SystemParams systemParams) { + this.dao = dao; + this.systemParams = systemParams; + } + + /** + * add task + * + * @param projectId project id + * @param currentStatus status + */ + public void addTask(String projectId, String currentStatus) { + TaskDelay taskDelay; + if (taskMap.containsKey(projectId)) { + taskDelay = taskMap.get(projectId); + taskDelay.updateCurrentStatus(currentStatus); + } else { + taskDelay = new TaskDelay(projectId, ToolUtil.getMillionSeconds(), ToolUtil.getMillionSeconds(), + currentStatus); + } + taskMap.put(projectId, taskDelay); + } + + /** + * update task + * + * @param projectId project id + * @param currentStatus current status + * @return boolean + */ + public boolean updateTask(String projectId, String currentStatus) { + if (taskMap.containsKey(projectId)) { + TaskDelay taskDelay = taskMap.get(projectId); + taskDelay.updateCurrentStatus(currentStatus); + taskMap.put(projectId, taskDelay); + return true; + } + return false; + } + + /** + * get task status + * + * @param projectId project id + * @return status + */ + public String getTaskStatus(String projectId) { + if (taskMap.containsKey(projectId)) { + taskMap.get(projectId); + return taskMap.get(projectId).getCurrentStatus(); + } + return StringUtils.EMPTY; + } + + /** + * remove task + * + * @param projectId project id + * @return remove task + */ + public boolean removeTask(String projectId) { + if (taskMap.containsKey(projectId)) { + taskMap.remove(projectId); + return true; + } + return false; + } + + /** + * expire task + * + */ + @Scheduled(cron = "0 0/5 * * * ?") + public void expireTask() { + TaskDelay task; + Iterator> iterator = taskMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + task = entry.getValue(); + if (task.isExpired()) { + iterator.remove(); + CloudLabTestTask testTask = dao.getTestTask(task.getProjectId()); + testTask.setProjectStatus(Constants.CLOUD_LAB_TEST_EXCEPTION); + testTask.setStatusDesc(Constants.TASK_EXPIRE_ESC_MAP.get(testTask.getTaskLanguage())); + testTask.setFinishTime(ToolUtil.getStandardTime()); + dao.updateProjectStatus(testTask.getProjectId(), testTask.getProjectStatus(), "", + testTask.getFinishTime(), testTask.getStatusDesc()); + sendExceptionMessage(testTask); + + // 删除服务器上的测试文件 + deleteTestFile(testTask); + log.error("Task {} status {}: wait for 60 minutes without any change in status, abnormal testing task", + task.getProjectId(), task.getCurrentStatus()); + } + } + } + + private void sendExceptionMessage(CloudLabTestTask task) { + MqsMessage message = new MqsMessage(); + message.setProjectId(task.getProjectId()); + message.setUserId(task.getUserId()); + message.setServerIp(task.getServerIp()); + message.setStatusTime(task.getFinishTime()); + message.setStatus(Constants.MQS_STATUS_EXCEPTION); + message.setStatusDesc(task.getStatusDesc()); + } + + /** + * delete test file + * + * @param task task + */ + public void deleteTestFile(CloudLabTestTask task) { + try { + List commandList = new ArrayList<>(); + commandList.add("cd /home/compatibility_testing;find . -name \"*.sh\"| xargs rm -rf ; " + + "rm -rf compatibility_testing.tar.gz;"); + commandList.add("cd /home/function_testing; rm -rf shunit2-master.zip shunit2-master;"); + + SSHUtil.sshExecCmd(task.getServerIp(), task.getServerPort(), task.getServerUser(), + task.getServerPassword(), commandList); + } catch (SshErrorException ex) { + log.error("task {} in server {} failed in delete {}", task.getProjectId(), task.getServerIp(), + ex.getLocalizedMessage()); + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/AESUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/AESUtil.java new file mode 100644 index 0000000..a8ffc08 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/AESUtil.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Locale; +import java.util.Optional; + +import javax.annotation.PostConstruct; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * AESUtil + * + * @author liuchunwang + * @since 2023-07-21 + */ +@Slf4j +@Component +public class AESUtil { + /** + * CRYPTO + */ + public static final Crypto CRYPTO = new Crypto(); + + private static final int PRIVATE_KEY_LENGTH = 256; + private static final int GCM_IV_LENGTH = 12; + private static final int GCM_TAG_LENGTH = 16; + + private final Environment environment; + + /** + * AESUtil + * + * @param environment env + */ + public AESUtil(Environment environment) { + this.environment = environment; + } + + /** + * Crypto + * + * @author liuchunwang + * @since 2023-07-21 + */ + @Data + public static class Crypto { + private String aesCipherMode; + private String aesDefaultKey; + private String aesDefaultAad; + } + + @PostConstruct + private void initCrypto() { + CRYPTO.aesCipherMode = environment.getRequiredProperty("crypto.aes-cipher-mode"); + CRYPTO.aesDefaultKey = environment.getRequiredProperty("crypto.aes-default-key"); + CRYPTO.aesDefaultAad = environment.getRequiredProperty("crypto.aes-default-aad"); + } + + /** + * get PrivateKey + * + * @return PrivateKey + */ + public static byte[] getPrivateKey() { + KeyGenerator keygen = null; + try { + keygen = KeyGenerator.getInstance("AES"); + } catch (NoSuchAlgorithmException e) { + log.error(e.getMessage(), e); + } + + if (keygen != null) { + keygen.init(AESUtil.PRIVATE_KEY_LENGTH); + return keygen.generateKey().getEncoded(); + } + return new byte[0]; + } + + /** + * gcmEncrypt + * + * @param input input + * @param key key + * @param aadStr aadStr + * @return String + */ + public static String gcmEncrypt(String input, String key, String aadStr) { + byte[] data = input.getBytes(StandardCharsets.UTF_8); + byte[] privateKey = hex2byte(key); + byte[] iv = genRandomBytes(); + int tagLength = GCM_TAG_LENGTH; + byte[] aad = StringUtils.isBlank(aadStr) ? null : aadStr.getBytes(StandardCharsets.UTF_8); + byte[] cipherData = Optional.ofNullable(gcmEncrypt(data, privateKey, iv, tagLength, aad)) + .orElseThrow(() -> new BaseException("Parsing exceptions")); + + byte[] ivLengthByteArray = int2ByteArray(iv.length); + byte[] tagLengthByteArray = int2ByteArray(tagLength); + int aadLength = aad == null ? 0 : aad.length; + byte[] addLengthByteArray = int2ByteArray(aadLength); + + byte[] result = new byte[12 + iv.length + aadLength + cipherData.length]; + System.arraycopy(ivLengthByteArray, 0, result, 0, 4); + System.arraycopy(tagLengthByteArray, 0, result, 4, 4); + System.arraycopy(addLengthByteArray, 0, result, 8, 4); + System.arraycopy(iv, 0, result, 12, iv.length); + if (aad != null) { + System.arraycopy(aad, 0, result, 12 + iv.length, aadLength); + } + System.arraycopy(cipherData, 0, result, 12 + iv.length + aadLength, cipherData.length); + return byte2Hex(result); + } + + /** + * gcmDecrypt + * + * @param input input + * @param key key + * @return String + */ + public static String gcmDecrypt(String input, String key) { + byte[] data = hex2byte(input); + byte[] paramLength = new byte[4]; + + System.arraycopy(data, 0, paramLength, 0, 4); + int ivLength = byteArray2Int(paramLength); + byte[] iv = new byte[ivLength]; + System.arraycopy(data, 12, iv, 0, ivLength); + System.arraycopy(data, 4, paramLength, 0, 4); + int tagLength = byteArray2Int(paramLength); + System.arraycopy(data, 8, paramLength, 0, 4); + + int aadLength = byteArray2Int(paramLength); + byte[] aad = aadLength == 0 ? null : new byte[aadLength]; + if (aad != null) { + System.arraycopy(data, 12 + ivLength, aad, 0, aadLength); + } + + byte[] cipherData = new byte[data.length - ivLength - aadLength - 12]; + System.arraycopy(data, 12 + ivLength + aadLength, cipherData, 0, cipherData.length); + + byte[] privateKey = hex2byte(key); + return new String(gcmDecrypt(cipherData, privateKey, iv, tagLength, aad)); + } + + private static byte[] gcmEncrypt(byte[] data, byte[] privateKey, byte[] iv, int tagLength, byte[] aad) { + try { + Cipher cipher = cipher(privateKey, iv, tagLength, Cipher.ENCRYPT_MODE); + return handle(data, cipher, aad); + } catch (GeneralSecurityException e) { + throw new BaseException("Parsing exceptions"); + } + } + + private static byte[] gcmDecrypt(byte[] data, byte[] privateKey, byte[] iv, int tagLength, byte[] aad) { + try { + Cipher cipher = cipher(privateKey, iv, tagLength, Cipher.DECRYPT_MODE); + return handle(data, cipher, aad); + } catch (GeneralSecurityException e) { + throw new BaseException("Parsing exceptions"); + } + } + + private static Cipher cipher(byte[] privateKey, byte[] iv, int tagLength, int mode) + throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance(CRYPTO.aesCipherMode); + SecretKey secretKey = new SecretKeySpec(privateKey, "AES"); + GCMParameterSpec parameterSpec = new GCMParameterSpec(tagLength * Byte.SIZE, iv); + cipher.init(mode, secretKey, parameterSpec); + return cipher; + } + + private static byte[] handle(byte[] data, Cipher cipher, byte[] aad) throws GeneralSecurityException { + if (aad != null) { + cipher.updateAAD(aad); + } + return cipher.doFinal(data); + } + + private static byte[] genRandomBytes() { + byte[] result = new byte[AESUtil.GCM_IV_LENGTH]; + SecureRandom rand = RandomUtil.getRandom(); + rand.nextBytes(result); + return result; + } + + private static byte[] int2ByteArray(int i) { + byte[] result = new byte[4]; + result[0] = (byte) ((i >> 24) & 0xFF); + result[1] = (byte) ((i >> 16) & 0xFF); + result[2] = (byte) ((i >> 8) & 0xFF); + result[3] = (byte) (i & 0xFF); + return result; + } + + private static int byteArray2Int(byte[] bytes) { + int result = 0; + for (int i = 0; i < 4; i++) { + int shift = (3 - i) * 8; + result += (bytes[i] & 0xFF) << shift; + } + return result; + } + + private static String byte2Hex(byte[] bytes) { + StringBuilder sb = new StringBuilder(16); + for (byte b : bytes) { + String hex = Integer.toHexString(b & 0xFF); + if (hex.length() < 2) { + sb.append(0); + } + sb.append(hex.toUpperCase(Locale.US)); + } + return sb.toString(); + } + + private static byte[] hex2byte(String hexString) { + byte[] bytes = new byte[hexString.length() / 2]; + for (int i = 0; i < hexString.length(); i += 2) { + bytes[i / 2] = + (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + + Character.digit(hexString.charAt(i + 1), 16)); + } + return bytes; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ApiCenterUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ApiCenterUtil.java new file mode 100644 index 0000000..637885b --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ApiCenterUtil.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import com.huawei.ic.openlab.cloudtest.entity.SystemParams; + +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Objects; + +import javax.net.ssl.SSLContext; + +/** + * API网关的接口工具类 + * + * @author kongcaizhi + * @since 2022-10-24 + */ +@Slf4j +public class ApiCenterUtil { + private static final String VALIDATED_TOKEN_SUCCESS_CODE = "200"; + + private static HttpHeaders getBasicHttpHeaders(SystemParams systemParams) { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + headers.add("X-HW-ID", systemParams.getAppId()); + headers.add("X-HW-APPKEY", systemParams.getAppKey()); + return headers; + } + + private static RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, + KeyManagementException { + TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; + SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() + .loadTrustMaterial(null, acceptingTrustStrategy) + .build(); + SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); + CloseableHttpClient httpClient = HttpClients.custom() + .setSSLSocketFactory(csf) + .build(); + + HttpComponentsClientHttpRequestFactory requestFactory = + new HttpComponentsClientHttpRequestFactory(); + requestFactory.setHttpClient(httpClient); + + return new RestTemplate(requestFactory); + } + + /** + * 向API网关验证token是否有效 + * + * @param systemParams 系统参数 + * @param token token + * @param taskDeviceId taskDeviceId + * @return boolean 是否有效 + */ + public static boolean validateToken(SystemParams systemParams, String token, String taskDeviceId) { + // 添加请求头 + HttpEntity request = new HttpEntity<>(null, getBasicHttpHeaders(systemParams)); + + // 发送GET请求 + try { + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(systemParams.getKunpengServiceUrl()) + .queryParam("sessionId", token) + .queryParam("token", taskDeviceId) + .queryParam("tag", 1); + String requestUrl = builder.build().encode().toUriString(); + ResponseEntity response = restTemplate().exchange(requestUrl, HttpMethod.GET, request, + ValidatedResp.class); + + log.info("request apiwg check token return{}", JSONObject.toJSONString(response.getBody())); + if (response.getStatusCode().is2xxSuccessful() && response.hasBody() + && VALIDATED_TOKEN_SUCCESS_CODE.equals(Objects.requireNonNull(response.getBody()).getCode())) { + return true; + } else { + return false; + } + } catch (KeyStoreException | NoSuchAlgorithmException | KeyManagementException | RestClientException ex) { + log.error("request apiwg check taskDeviceId {} exception {}", taskDeviceId, + ex.getLocalizedMessage()); + return false; + } + } + + @Data + private static class ValidatedResp { + private String code; + private String msg; + private String data; + @JsonProperty("success") + private Boolean isSuccess; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/Constants.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/Constants.java new file mode 100644 index 0000000..5ca52e6 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/Constants.java @@ -0,0 +1,789 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * Constants + * + * @author kongcaizhi + * @since 2022-10-24 + */ +public final class Constants { + /** + * TEST_PASSED + */ + public static final String TEST_PASSED = "passed"; + + /** + * TEST_FAILED + */ + public static final String TEST_FAILED = "failed"; + + /** + * TEST_SKIPPED + */ + public static final String TEST_SKIPPED = "skipped"; + + /** + * CLOUD_LAB_TEST_SUBMIT + */ + public static final Integer CLOUD_LAB_TEST_SUBMIT = 0; + + /** + * CLOUD_LAB_TEST_START + */ + public static final Integer CLOUD_LAB_TEST_START = 1; + + /** + * CLOUD_LAB_TEST_FINISH + */ + public static final Integer CLOUD_LAB_TEST_FINISH = 2; + + /** + * CLOUD_LAB_TEST_EXCEPTION + */ + public static final Integer CLOUD_LAB_TEST_EXCEPTION = 3; + + /** + * CLOUD_LAB_TEST_HALT + */ + public static final Integer CLOUD_LAB_TEST_HALT = 4; + + /** + * TAR_FILE_TOO_BIG + */ + public static final String TAR_FILE_TOO_BIG = "上传的文件解压后不能超过100M,请重新上传."; + + /** + * FILE_TOO_BIG + */ + public static final String FILE_TOO_BIG = "上传的文件不能超过100M,请重新上传."; + + /** + * CONNECT_EXCEPTION_DESC + */ + public static final String CONNECT_EXCEPTION_DESC = "连接异常,请检查登录密码."; + + /** + * TASK_DUPLICATE + */ + public static final String TASK_DUPLICATE = "%s服务器正在测试中,请勿重复提交."; + + /** + * TEMPLATE_DECOMPRESSION_ERROR + */ + public static final String TEMPLATE_DECOMPRESSION_ERROR = "请下载模板,根据模板修改,上传修改后的压缩文件"; + + /** + * FILE_FAILED_VIRUS_SCAN + */ + public static final String FILE_FAILED_VIRUS_SCAN = "文件没有通过病毒扫描,请重新上传"; + + /** + * 正常 + */ + public static final String UPLOAD_FILE_STATUS_NORMAL = "00"; + + /** + * 已删除 + */ + public static final String UPLOAD_FILE_STATUS_DELETE = "01"; + + /** + * 安全检查不通过 + */ + public static final String UPLOAD_FILE_STATUS_SCAN_FAIL = "02"; + + /** + * 文件太大 + */ + public static final String UPLOAD_FILE_STATUS_TOO_BIG = "03"; + + /** + * 文件异常 + */ + public static final String UPLOAD_FILE_STATUS_EXCEPTION = "04"; + + /** + * 安全测试文件缺失或者读取失败 + */ + public static final String SAFETY_FILE_LOSS = "安全测试文件缺失或者读取失败"; + + /** + * SAFETY_FILE_LOSS_EN + */ + public static final String SAFETY_FILE_LOSS_EN = "The security test file is missing or cannot be read"; + + /** + * HCS_DESC + */ + public static final String HCS_DESC = "硬件包含鲲鹏芯片,符合要求"; + + /** + * PERFORMANCE_TEST_ID + */ + public static final String PERFORMANCE_TEST_ID = "Performance_Test_1"; + + /** + * TASK_DOES_NOT_EXIST + */ + public static final String TASK_DOES_NOT_EXIST = "任务不存在"; + + /** + * TASK_HAS_FINISHED + */ + public static final String TASK_HAS_FINISHED = "测试已结束"; + + /** + * FAILED_TO_STOP_TASK + */ + public static final String FAILED_TO_STOP_TASK = "停止测试任务失败"; + + /** + * PERFORMANCE_TESTING + */ + public static final String PERFORMANCE_TESTING = "性能测试中"; + + /** + * START_TEST_STRING + */ + public static final String START_TEST_STRING = "自动化测试采集工具开始执行"; + + /** + * START_TEST_STRING_EN + */ + public static final String START_TEST_STRING_EN = "The automatic test tool starts to run."; + + /** + * DEPENDENCY_INSTALL_FAILURE_DESC + */ + public static final String DEPENDENCY_INSTALL_FAILURE_DESC = "依赖软件安装失败"; + + /** + * MQS_STATUS_ONGOING + */ + public static final String MQS_STATUS_ONGOING = "ongoing"; + + /** + * MQS_STATUS_FINISH + */ + public static final String MQS_STATUS_FINISH = "finished"; + + /** + * MQS_STATUS_EXCEPTION + */ + public static final String MQS_STATUS_EXCEPTION = "exception"; + + /** + * 依赖软件安装 + */ + public static final String DEPENDENCY_INSTALL_DESC = "0-1"; + + /** + * 应用软件启动 + */ + public static final String APP_START_DESC = "0-2"; + + /** + * 应用软件停止 + */ + public static final String APP_STOP_DESC = "0-3"; + + /** + * 安全测试 + */ + public static final String SECURITY_TEST_DESC = "1"; + + /** + * 可靠性测试 + */ + public static final String RELIABILITY_TEST_DESC = "2"; + + /** + * 兼容性测试 + */ + public static final String COMPATIBILITY_TEST_DESC = "3"; + + /** + * 功能测试 + */ + public static final String FUNCTION_TEST_DESC = "4"; + + /** + * 性能测试 + */ + public static final String PERFORMANCE_TEST_DESC = "5"; + + /** + * 测试状态-中 + */ + public static final String TEST_PROCESSING = "0"; + + /** + * 测试状态-完成 + */ + public static final String TEST_FINISHED_CN = "1"; + + /** + * 测试状态-失败 + */ + public static final String TEST_FAILURE_CN = "2"; + + /** + * 测试状态-异常 + */ + public static final String TEST_EXCEPTION_CN = "异常"; + + /** + * T测试状态-正常 + */ + public static final String TEST_NORMAL_CN = "正常"; + + /** + * RELIABILITY_START_APP_FAIL_CODE + */ + public static final String RELIABILITY_START_APP_FAIL_CODE = "0911"; + + /** + * OS_PATTERN_CN + */ + public static final String OS_PATTERN_CN = "#\\d{4}-\\d{2}-\\d{2}\\s+(20|21|22|23|[0-1]\\d)" + + ":[0-5]\\d:[0-5]\\d#info#1#(当前的操作系统版本是|The current OS version is)(.*)(.|.)"; + + /** + * APPLICATION_NAMES + */ + public static final String APPLICATION_NAMES = "^application_names=(.+)"; + + /** + * START_APP_COMMANDS + */ + public static final String START_APP_COMMANDS = "^start_app_commands=(.+)"; + + /** + * STOP_APP_COMMANDS + */ + public static final String STOP_APP_COMMANDS = "^stop_app_commands=(.+)"; + + /** + * CLAM_RESULT_PATTERN + */ + public static final String CLAM_RESULT_PATTERN = "Infected files: (.+)"; + + /** + * 功能测试内存 SHELL_UNIT_RUN_PATTERN + */ + public static final String SHELL_UNIT_RUN_PATTERN = "^Ran \\\u001B\\[1;36m(.*)\\\u001B\\[0m test"; + + /** + * 功能测试内存 SHELL_UNIT_TEST_PATTERN + */ + public static final String SHELL_UNIT_TEST_PATTERN = "^-+ Test file name : (.*).sh -+"; + + /** + * 功能测试内存 SHELL_UNIT_FAILED_PATTERN + */ + public static final String SHELL_UNIT_FAILED_PATTERN = "^\\\u001B\\[1;31mFAILED\\\u001B\\[0m \\(\\\u001B\\[1;" + + "31mfailures=(.*)\\\u001B\\[0m\\)"; + + /** + * PYTEST_SUCCESS_PATTERN + */ + public static final String PYTEST_SUCCESS_PATTERN = "^=+ (.*) passed in .* =+"; + + /** + * PYTEST_RUN_PATTERN + */ + public static final String PYTEST_RUN_PATTERN = "^-+ Test file name : (.*).py -+"; + + /** + * PYTEST_FAILED_PATTERN + */ + public static final String PYTEST_FAILED_PATTERN = "^=+ (.*) failed, (.*) passed in .*=+"; + + /** + * APP_PACKAGE_TEST_TOPIC + */ + public static final String APP_PACKAGE_TEST_TOPIC = "App_Package_Test"; + + /** + * SECURITY_SCAN_TAG + */ + public static final String SECURITY_SCAN_TAG = "Security_Scan"; + + /** + * INFO_TEST_CASE_RESULT_MAP + */ + public static final Map INFO_TEST_CASE_RESULT_MAP = + Collections.unmodifiableMap(new HashMap() { + { + put("FAILED_TO_START_APP", new InfoTestCaseResult( + TEST_FAILED, "软件启动失败.", "Failed to start the software.")); + put("SUCCESS_TO_START_APP", new InfoTestCaseResult( + TEST_PASSED, "", "")); + put("FAILED_TO_RELIABLE_TEST", new InfoTestCaseResult( + TEST_FAILED, "强制杀死进程,启动失败,异常测试失败.", + "After the process was forcibly killed," + + " the process failed to be restarted, and exception test failed.")); + put("SUCCESS_TO_RELIABLE_TEST", new InfoTestCaseResult( + TEST_PASSED, "", "")); + put("FAILED_TO_STOP_APP", new InfoTestCaseResult( + TEST_FAILED, "软件停止失败.", "Failed to stop the software.")); + put("SUCCESS_TO_STOP_APP", new InfoTestCaseResult( + TEST_PASSED, "", "")); + put("FILE_NOT_EXIT", new InfoTestCaseResult( + TEST_FAILED, "测试结果中没有兼容性测试工具的日志文件.", + "The compressed file package does not contain" + + " the log file of the compatibility test tool.")); + put("NO_START_APP", new InfoTestCaseResult(TEST_FAILED, "没有执行软件启动.", + "You have no started the software.")); + put("NO_STOP_APP", new InfoTestCaseResult(TEST_FAILED, "没有执行软件停止.", + "You have no stop the software.")); + put("NO_RELIABLE_TEST", new InfoTestCaseResult(TEST_FAILED, "没有执行可靠性测试.", + "You have no conducted the reliability test.")); + put("UNZIP_ERROR", new InfoTestCaseResult(TEST_FAILED, "测试结果解压错误.", + "An error occurred when decompressing the log file " + + "of the test tool from the uploaded file package.")); + put("READ_ERROR", new InfoTestCaseResult(TEST_FAILED, "测试结果读取错误.", + "An error occurred when reading the log file" + + " of the test tool from the uploaded file package.")); + } + }); + + /** + * SOFTWARE_COMPARE_DESC_LIST + */ + public static final List SOFTWARE_COMPARE_DESC_LIST = Collections.unmodifiableList( + Arrays.asList("未匹配到相应软件:%s", "兼容性测试配置文件填写的应用软件为:%s", + "兼容性测试配置文件应用软件名称为空", "没有找到进程快照文件", "解析配置文件和软件进程栈信息出错")); + + /** + * SOFTWARE_COMPARE_DESC_EN_LIST + */ + public static final List SOFTWARE_COMPARE_DESC_EN_LIST = Collections.unmodifiableList( + Arrays.asList( + "No matching software %s found.", "The application software recorded in the compatibility test " + + "configuration file is %s", + "The name of the application software in the compatibility test configuration file is %s.", + "Cannot find the process snapshot file in the uploaded file package.", + "An error occurred when reading the process snapshot file in the uploaded file package.")); + + /** + * COMPATIBILITY_DESC_LIST + */ + public static final List COMPATIBILITY_DESC_LIST = Collections.unmodifiableList( + Arrays.asList( + "被测试软件启动前采集%1$s资源利用率与被测试软件停止后%1$s利用率之间的波动为%2$,.2f %%.", + "被测试软件启动前采集%1$s资源利用率与被测试软件停止后%1$s利用率之间的波动为%2$,.2f %%,%3$s 1.00 %% .", + "被测试软件启动前采集%1$s资源利用率与被测试软件停止后%1$s资源利用率文件解析出错.", + "被测试软件启动前采集%1$s资源利用率与被测试软件停止后%1$s资源利用率文件缺失.", + "根据端口扫描的结果,结合软件端口矩阵,合适是否存在未知端口,并澄清原因.", "%s协议扫描结果如下:", + "被测试软件启动前采集的网卡资源%1$s数据与被测软件停止后采集网卡资源%1$s数据之间的波动为%2$," + + ".2f %%,%s测试前波动的1.00%%.", + "被测试软件启动前采集的网卡资源%1$s数据与被测软件停止后采集网卡资源%1$s数据之间的波动为%2$,.2f %%.")); + + /** + * COMPATIBILITY_DESC_EN_LIST + */ + public static final List COMPATIBILITY_DESC_EN_LIST = Collections.unmodifiableList( + Arrays.asList( + "The change rate of the %s usage collected before the tested software was started " + + "and after the target software was stopped is %.2f %%.", + "The change rate of the %s usage collected before the tested software was started " + + "and after the target software was stopped is %.2f %%, which is %s than 1.00%%.", + "An error occurred when parsing the resource files related to %s," + + "before the tested software was started and after the software was stopped.", + "An error occurred when reading the resource files related to %s," + + "before the tested software was started and after the software was stopped.", + "Check whether unknown ports are opened according to the port scanning " + + "result and the tested software port matrix, and locate the cause.", + "The scanning result of the %s protocols is as follows:", + "The data %s by the NIC fluctuates by %.2f %% before the tested software was " + + "started and after the tested software was stopped," + + " which is%s than 1.00%% before the test.", + "The data %s by the NIC fluctuates by %.2f %% before the tested software was " + + "started and after the software was stopped." + )); + + /** + * PERFORMANCE_DESC_LIST + */ + public static final List PERFORMANCE_DESC_LIST = Collections.unmodifiableList( + Arrays.asList( + "压力测试期间%s 资源波动值为%.2f %%,%s 5.00%%.", "后续可结合实际业务澄清波动合理性", + "压力测试期间%s 资源文件读取出错.", "压力测试期间%s 资源文件缺失.", + "压力测试期间网卡%s数据波动是%.2f %%.", "压力测试期间网卡%s数据波动是%.2f %%,%s 5.00%%." + )); + + /** + * PERFORMANCE_DESC_EN_LIST + */ + public static final List PERFORMANCE_DESC_EN_LIST = Collections.unmodifiableList( + Arrays.asList( + "During the pressure test, the fluctuation value of %s is %.2f %%, which is %s than 5.00%%.", + "The cause of the fluctuation can be clarified based on actual services.", + "An error occurred when parsing the %s resource file during the pressure test.", + "The %s resource file is missing during the pressure test.", + "During the pressure test, the fluctuation value of data %s by the NIC is %.2f %%.", + "During the pressure test, the fluctuation value of data %s" + + " by the NIC is %.2f %%, which is %s than 5.00%%." + )); + + /** + * LOG_WHITE_RULES + */ + public static final Map LOG_WHITE_RULES = Collections.unmodifiableMap( + new HashMap() { + { + put("FAILED_TO_START_APP", Pattern.compile( + "#\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}#.*(#5)?#" + + "(检查到业务应用启动不成功|" + + "Failed to start the application (.*). Check the startup script.)")); + put("SUCCESS_TO_START_APP", Pattern.compile( + "#\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}#.*(#5)?#(业务应用(" + + ".*)(启动)?完成|" + "Succeeded in starting the application (.*))")); + put("FAILED_TO_RELIABLE_TEST", Pattern.compile( + "#\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}#.*(#8)?#" + + "(可靠性测试, 业务应用(.*)启动失败,可靠性测试失败|" + + "可靠性测试, 执行强制杀死进程(.*)报错, 可靠性测试失败|" + + "可靠性测试前, 业务应用(.*)已停止, 可靠性测试失败|" + + "(.*)The reliability test failed.)")); + put("SUCCESS_TO_RELIABLE_TEST", Pattern.compile( + "#\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}#.*(#8)?#" + + "(可靠性测试, 业务应用(.*)启动完成.可靠性测试成功|" + + "(.*)The reliability test is successful.)")); + put("FAILED_TO_STOP_APP", Pattern.compile( + "#\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}#.*(#9)?#" + + "(检查到应用程序还在启动,且用户未能停止应用|" + + "Failed to stop the service application (.*). Check the stop script.)")); + put("SUCCESS_TO_STOP_APP", Pattern.compile( + "#\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}#.*(#9)?#(进程(.*)" + + "不存在|The (.*) process does not exist.)")); + } + }); + + /** + * CONNECT_EXCEPTION_DESC_MAP + */ + public static final Map CONNECT_EXCEPTION_DESC_MAP = Collections.unmodifiableMap( + new HashMap() { + { + put("CN", CONNECT_EXCEPTION_DESC); + put("EN", "Connection exception. Check whether the login account and password are correct."); + } + }); + + /** + * TASK_DUPLICATE_MAP + */ + public static final Map TASK_DUPLICATE_MAP = Collections.unmodifiableMap( + new HashMap() { + { + put("CN", TASK_DUPLICATE); + put("EN", "The test is proceeding in %s. Please do not submit repeatedly."); + } + }); + + /** + * TASK_DUPLICATE_MAP + */ + public static final Map TAR_FILE_TOO_BIG_MAP = Collections.unmodifiableMap( + new HashMap() { + { + put("CN", TAR_FILE_TOO_BIG); + put("EN", "The uploaded file cannot exceed 100MB after decompression. " + + "Modify the file and upload it again."); + } + }); + + /** + * FAILED_ENCRYPT_MAP + */ + public static final Map FAILED_ENCRYPT_MAP = Collections.unmodifiableMap( + new HashMap() { + { + put("CN", "加密参数失败."); + put("EN", "Failed to encrypt the parameter."); + } + }); + + /** + * FAILED_ENCRYPT_MAP + */ + public static final Map TEMPLATE_DECOMPRESSION_ERROR_MAP = + Collections.unmodifiableMap(new HashMap() { + { + put("CN", TEMPLATE_DECOMPRESSION_ERROR); + put("EN", "Download the template, modify the file according to the template, " + + "and upload the compressed file after modification."); + } + }); + + /** + * FILE_FAILED_VIRUS_SCAN_MAP + */ + public static final Map FILE_FAILED_VIRUS_SCAN_MAP = + Collections.unmodifiableMap(new HashMap() { + { + put("CN", FILE_FAILED_VIRUS_SCAN); + put("EN", "The file failed the antivirus scan. Modify the file and upload it again."); + } + }); + + /** + * FILE_TOO_BIG_MAP + */ + public static final Map FILE_TOO_BIG_MAP = Collections.unmodifiableMap( + new HashMap() { + { + put("CN", FILE_TOO_BIG); + put("EN", "The uploaded file cannot exceed 100MB after decompression."); + } + }); + + /** + * FILE_TYPE_ERROR_MAP + */ + public static final Map FILE_TYPE_ERROR_MAP = Collections.unmodifiableMap( + new HashMap() { + { + put("CN", "文件解析出错."); + put("EN", "An error occurred when parsing the file."); + } + }); + + /** + * UPLOAD_FILE_STATUS_NORMAL_MAP + */ + public static final Map UPLOAD_FILE_STATUS_NORMAL_MAP = Collections.unmodifiableMap( + new HashMap() { + { + put("CN", "00"); + put("EN", "00"); + } + }); + + /** + * DEPENDENCY_INSTALL_FAILURE + */ + public static final Map DEPENDENCY_INSTALL_FAILURE = + Collections.unmodifiableMap(new HashMap() { + { + put("CN", "依赖软件安装异常."); + put("EN", "Dependency installation exception."); + } + }); + + /** + * APP_START_UP_FAILURE_DESC_MAP + */ + public static final Map APP_START_UP_FAILURE_DESC_MAP = + Collections.unmodifiableMap(new HashMap() { + { + put("CN", "待测试应用软件启动失败."); + put("EN", "Failed to start the application to be tested."); + } + }); + + /** + * APP_STOP_FAILURE_DESC_MAP + */ + public static final Map APP_STOP_FAILURE_DESC_MAP = + Collections.unmodifiableMap(new HashMap() { + { + put("CN", "待测试应用软件停止失败."); + put("EN", "Failed to stop the application to be tested."); + } + }); + + /** + * PERFORMANCE_FILE_MISSING_MAP + */ + public static final Map PERFORMANCE_FILE_MISSING_MAP = + Collections.unmodifiableMap(new HashMap() { + { + put("CN", "没有上传性能测试文件"); + put("EN", "No performance test file is uploaded."); + } + }); + + /** + * TASK_EXPIRE_ESC_MAP + */ + public static final Map TASK_EXPIRE_ESC_MAP = + Collections.unmodifiableMap(new HashMap() { + { + put("CN", "测试任务超时"); + put("EN", "The test task timed out without feedback."); + } + }); + + /** + * InfoTestCaseResult + * + * @author kongcaizhi + * @since 2021-10-19 + */ + @AllArgsConstructor + @Data + public static final class InfoTestCaseResult { + private final String testResult; + private final String testReason; + private final String testReasonEn; + } + + /** + * CompatibilityTarFile + * + * @author kongcaizhi + * @since 2021-10-19 + */ + public enum CompatibilityTarFile { + HARDWARE_INFO("data/hardware/hardware_info.log", 0), + INFO_LOG("data/others/info.log", 1), + CONFIGURE_INFO("data/compatibility_testing.conf", 2), + PRODUCT_NAME("data/product/product_name.log", 3), + COMPATIBILITY_CPU_0("data/test/compatiable/test_perf_cpu_0.log", 4), + COMPATIBILITY_CPU_1("data/test/compatiable/test_perf_cpu_1.log", 5), + COMPATIBILITY_MEM_0("data/test/compatiable/test_perf_mem_0.log", 6), + COMPATIBILITY_MEM_1("data/test/compatiable/test_perf_mem_1.log", 7), + COMPATIBILITY_DISK_0("data/test/compatiable/test_perf_disk_0.log", 8), + COMPATIBILITY_DISK_1("data/test/compatiable/test_perf_disk_1.log", 9), + COMPATIBILITY_NET_0("data/test/compatiable/test_perf_net_0.log", 10), + COMPATIBILITY_NET_1("data/test/compatiable/test_perf_net_1.log", 11), + PERFORMANCE_CPU("data/test/performance/test_perf_cpu_1.log", 12), + PERFORMANCE_MEM("data/test/performance/test_perf_mem_1.log", 13), + PERFORMANCE_DISK("data/test/performance/test_perf_disk_1.log", 14), + PERFORMANCE_NET("data/test/performance/test_perf_net_1.log", 15), + CLAM_LOG("data/test/safety/clam.log", 16), + FUNCTION_SHELL_UNIT("data/test/function/bash_test.log", 17), + FUNCTION_PY_TEST("data/test/function/python_test.log", 18), + CVE_CHECK_LOG("data/test/safety/cvecheck-result.json", 19); + + private final String fileName; + + CompatibilityTarFile(String fileName, int fileIndex) { + this.fileName = fileName; + } + + /** + * get File Name + * + * @return File Name + */ + public String getFileName() { + return this.fileName; + } + } + + /** + * CompatibilityTestName + * + * @author kongcaizhi + * @since 2021-10-19 + */ + public enum CompatibilityTestName { + HARDWARE_SERVER("Compatibility_Hardware_Server", 0), + SOFTWARE_NAME("Compatibility_Software_Name", 1), + APPLICATION_START("Compatibility_Application_Start", 2), + APPLICATION_STOP("Compatibility_Application_Stop", 3), + IDLE_CPU("Compatibility_Idle_Cpu", 4), + IDLE_MEM("Compatibility_Idle_Memory", 5), + IDLE_DISK("Compatibility_Idle_Disk", 6), + IDLE_NET("Compatibility_Idle_Network", 7), + PRESSURE_CPU("Reliability_Pressure_Cpu", 8), + PRESSURE_MEM("Reliability_Pressure_Memory", 9), + PRESSURE_DISK("Reliability_Pressure_Disk", 10), + PRESSURE_NET("Reliability_Pressure_Network", 11), + EXCEPTION_KILL("Reliability_Exception_Kill", 12), + SECURITY_PORT("Security_Base_Port", 13), + SECURITY_VIRUS("Security_Base_Virus", 14), + SECURITY_VULNERABLE("Security_Base_CveCheck", 15), + FUNCTION_TEST("Function_Test", 16); + + private final String testName; + + CompatibilityTestName(String testName, int testIndex) { + this.testName = testName; + } + + /** + * get Test Name + * + * @return Test Name + */ + public String getTestName() { + return this.testName; + } + } + + /** + * CompatibilityTestStep + * + * @author kongcaizhi + * @since 2021-10-19 + */ + public enum CompatibilityTestStep { + DEPENDENCY_INSTALL_SUCCESS("0210", "依赖软件安装完成"), + DEPENDENCY_INSTALL_FAILURE("0211", "依赖软件安装失败"), + APP_START_SUCCESS("0310", "应用软件启动完成"), + APP_START_FAILURE("0311", "应用软件启动失败"), + APP_STOP_SUCCESS("0320", "应用软件停止完成"), + APP_STOP_FAILURE("0321", "应用软件停止失败"), + COMPATIBILITY_TEST_SUCCESS("0410", "兼容性测试中"), + COM_START_SUCCESS("0510", "应用软件启动完成"), + COM_START_FAILURE("0511", "应用软件启动失败"), + PORT_TEST_SUCCESS("0610", "端口扫描完成"), + VIRUS_SCAN_SUCCESS("0620", "病毒扫描完成"), + VULNERABLE_SCAN_SUCCESS("0630", "漏洞扫描完成"), + EXCEPTION_TEST_FINISH("0810", "可靠性测试完成"), + COMPATIBILITY_TEST_FINISH("0910", "兼容性测试结束"), + FUN_TEST_FILE_EXIST_ERROR("1011", "测试失败-功能测试文件不存在"), + FUN_TEST_FILE_DIR_ERROR("1012", "测试失败-功能测试文件function_testing目录不存在"), + FUN_TEST_PYTEST_ERROR("1013", "测试失败-pytest安装失败"); + + private final String stepIndex; + + CompatibilityTestStep(String stepIndex, String stepDesc) { + this.stepIndex = stepIndex; + } + + /** + * get Step Index + * + * @return stepIndex + */ + public String getStepIndex() { + return this.stepIndex; + } + + /** + * fromStepIndex + * + * @param stepIndex stepIndex + * @return CompatibilityTestStep + */ + public static CompatibilityTestStep fromStepIndex(String stepIndex) { + CompatibilityTestStep compatibilityTestStep = null; + for (CompatibilityTestStep step : CompatibilityTestStep.values()) { + if (step.getStepIndex().equals(stepIndex)) { + compatibilityTestStep = step; + break; + } + } + return compatibilityTestStep; + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/DgCodeServerClient.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/DgCodeServerClient.java new file mode 100644 index 0000000..d0a8e12 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/DgCodeServerClient.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * DGCodeServer nginx动态路由增加和删除taskDeviceId + * + * @author kongcaizhi + * @since 2023-03-23 + */ +@FeignClient(url = "${dgCodeServerUrl}", name = "dgCodeServer") +public interface DgCodeServerClient { + /** + * 路由增加taskDeviceId + * + * @param taskDeviceId 服务器信息 + * @param internalIp 服务器信息 + */ + @GetMapping("/add-task-device-id") + void addTaskDeviceId(@RequestParam("taskDeviceId") String taskDeviceId, + @RequestParam("internalIp") String internalIp); + + /** + * 路由删除taskDeviceId + * + * @param taskDeviceId taskdeviceId + */ + @GetMapping("/delete-task-device-id") + void deleteTaskDeviceId(@RequestParam("taskDeviceId") String taskDeviceId); +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/FileUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/FileUtil.java new file mode 100644 index 0000000..0fc1a91 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/FileUtil.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.commons.CommonsMultipartFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * FileUtil + * + * @author kongcaizhi + * @since 2023-03-23 + */ +@Slf4j +public class FileUtil { + /** + * fileToMultipartFile + * + * @param fileName fileName + * @return MultipartFile + */ + public static MultipartFile fileToMultipartFile(String fileName) { + FileItem fileItem = createFileItem(new File(fileName)); + return new CommonsMultipartFile(fileItem); + } + + private static FileItem createFileItem(File file) { + FileItemFactory factory = new DiskFileItemFactory(16, null); + FileItem item = factory.createItem("textField", "text/plain", true, file.getName()); + int bytesRead = 0; + byte[] buffer = new byte[8192]; + try (FileInputStream fis = new FileInputStream(file); + OutputStream os = item.getOutputStream()) { + while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) { + os.write(buffer, 0, bytesRead); + } + } catch (IOException e) { + log.error("Exception in transforming File to multipartFile {}", e.getLocalizedMessage()); + } + return item; + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/MQSUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/MQSUtil.java new file mode 100644 index 0000000..3c7930a --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/MQSUtil.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import com.huawei.ic.openlab.cloudtest.entity.MqsMessage; +import com.huawei.ic.openlab.cloudtest.entity.SystemParams; + +import com.alibaba.fastjson.JSONObject; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLContext; + +/** + * MQSUtil + * + * @author kongcaizhi + * @since 2023-03-23 + */ +@Slf4j +public class MQSUtil { + +} + diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/NormalResp.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/NormalResp.java new file mode 100644 index 0000000..8a204f3 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/NormalResp.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; + +import lombok.Builder; +import lombok.Data; + +/** + * NormalResp + * + * @author kongcaizhi + * @since 2021-03-23 + */ +@Data +@Builder +public class NormalResp { + private String code; + private String msg; + private String data; + + /** + * toJSONString + * + * @return String + */ + public String toJSONString() { + return JSON.toJSONString(this, SerializerFeature.WriteMapNullValue); + } + + /** + * ok + * + * @return String + */ + public static String ok() { + return NormalResp.builder().code("0000").msg("Success").build().toJSONString(); + } + + /** + * ok + * + * @param data data + * @return String + */ + public static String ok(String data) { + return NormalResp.builder().code("0000").data(data).msg("Success").build().toJSONString(); + } + + /** + * badRequest + * + * @param data data + * @return String + */ + public static String badRequest(String data) { + return NormalResp.builder().code("4001").data(data).msg("Bad Request").build().toJSONString(); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PBKDF2Util.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PBKDF2Util.java new file mode 100644 index 0000000..3eaeb23 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PBKDF2Util.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; + +import lombok.extern.slf4j.Slf4j; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; + +/** + * Pbkdf2Util + * + * @since 2022-11-08 + * @author kongcaizhi + */ +@Slf4j +public class PBKDF2Util { + private static final String DEFAULT_CIPHER_AND_PADDING = "PBKDF2WithHmacSHA256"; + private static final int ITERATION_COUNT = 10000000; + private static final int KEY_LENGTH = 256; + private static final int COMPONENT_LENGTH = 48; + + private static byte[] digest(char[] password, String salt) throws NoSuchAlgorithmException, + InvalidKeySpecException { + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DEFAULT_CIPHER_AND_PADDING); + PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt.getBytes(Charset.defaultCharset()), ITERATION_COUNT, + KEY_LENGTH); + SecretKey secretKey = keyFactory.generateSecret(pbeKeySpec); + return secretKey.getEncoded(); + } + + /** + * pbkdf2ForRootKey + * + * @param salt salt + * @param components components + * @return String + */ + public static String pbkdf2ForRootKey(String salt, String... components) { + char[] component = new char[COMPONENT_LENGTH]; + for (int i = 0; i < COMPONENT_LENGTH; i++) { + component[i] = 0; + for (String s : components) { + char[] temp = s.toCharArray(); + component[i] ^= temp[i]; + } + } + + try { + return new String(PBKDF2Util.digest(component, salt), StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeySpecException e) { + log.error(e.getMessage(), e); + throw new BaseException(e.getMessage()); + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PerformanceApiClient.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PerformanceApiClient.java new file mode 100644 index 0000000..c00baeb --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/PerformanceApiClient.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +import java.net.URI; + +/** + * NormalResp + * + * @author kongcaizhi + * @since 2021-03-23 + */ +@FeignClient(url = "EMPTY", name = "PerformanceTest") +public interface PerformanceApiClient { + /** + * set Performance Test + * + * @param uri uri + * @param projectId projectId + * @param serverIp serverIp + * @param isTimeLimit isTimeLimit + * @param multipartFile multipartFile + * @return result + */ + @PostMapping( + value = "/{projectId}/performance-upload", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + String setPerformanceTest(URI uri, @PathVariable("projectId") String projectId, + @RequestParam("serverIp") String serverIp, + @RequestParam("timeLimit") boolean isTimeLimit, + @RequestPart(value = "file") MultipartFile multipartFile); + + /** + * stop Performance Test + * + * @param uri uri + * @param projectId projectId + * @return result + */ + @GetMapping("/{projectId}/stop-test") + String stopPerformanceTest(URI uri, @PathVariable("projectId") String projectId); +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/RandomUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/RandomUtil.java new file mode 100644 index 0000000..491493f --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/RandomUtil.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * RandomUtil + * + * @author liuchunwang + * @since 2023-11-03 + */ +public class RandomUtil { + /** + * getRandom + * + * @return SecureRandom + */ + public static SecureRandom getRandom() { + try { + return SecureRandom.getInstanceStrong(); + } catch (NoSuchAlgorithmException e) { + throw new BaseException("make random number exception"); + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/TeeCodeServerClient.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/TeeCodeServerClient.java new file mode 100644 index 0000000..0d3ca09 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/TeeCodeServerClient.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * TeeCodeServer nginx动态路由增加和删除taskDeviceId + * + * @author kongcaizhi + * @since 2022-12-20 + */ +@FeignClient(url = "${teeCodeServerUrl}", name = "TeeCodeServer") +public interface TeeCodeServerClient { + /** + * 路由增加taskDeviceId + * + * @param taskDeviceId 服务器信息 + * @param internalIp 服务器信息 + */ + @GetMapping("/add-task-device-id") + void addTaskDeviceId(@RequestParam("taskDeviceId") String taskDeviceId, + @RequestParam("internalIp") String internalIp); + + /** + * 路由删除taskDeviceId + * + * @param taskDeviceId taskdeviceId + */ + @GetMapping("/delete-task-device-id") + void deleteTaskDeviceId(@RequestParam("taskDeviceId") String taskDeviceId); +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ToolUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ToolUtil.java new file mode 100644 index 0000000..d175240 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/ToolUtil.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util; + +import com.huawei.ic.openlab.cloudtest.common.exception.BaseException; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * ToolUtil + * + * @author kongcaizhi + * @since 2021-03-23 + */ +public class ToolUtil { + private static final DateTimeFormatter STRING_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + private static final DateTimeFormatter STANDARD_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss,SSS"); + private static final String REGEX = "\\.\\.+|\\/[.|\\\\]\\/"; + private static final String REGEX_URL = "([0-9]+\\.){3}[0-9]+"; + + /** + * get Time Str + * + * @return Time Str + */ + public static String getTimeStr() { + return LocalDateTime.now().format(STRING_FORMATTER); + } + + /** + * get Standard Time + * + * @return Standard Time + */ + public static String getStandardTime() { + return LocalDateTime.now().format(STANDARD_FORMATTER); + } + + /** + * get data Time + * + * @return data Time + */ + public static String getDateStr() { + return LocalDateTime.now().format(DATE_FORMATTER); + } + + /** + * getMillionSeconds + * + * @return MillionSeconds + */ + public static Long getMillionSeconds() { + return System.currentTimeMillis(); + } + + /** + * validPath + * + * @param path path + */ + public static void validPath(String path) { + Pattern pattern = Pattern.compile(REGEX); + Matcher matcher = pattern.matcher(path); + if (matcher.find()) { + throw new BaseException("The File's path is illegal: " + path); + } + } + + /** + * checkParameter + * + * @param param param + */ + public static void checkParameter(String param) { + Pattern pattern = Pattern.compile(REGEX_URL); + Matcher matcher = pattern.matcher(param); + if (!matcher.find()) { + throw new BaseException("The URL's param is illegal: " + param); + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/fastdfs/FastDfsClient.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/fastdfs/FastDfsClient.java new file mode 100644 index 0000000..569a9ec --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/fastdfs/FastDfsClient.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util.fastdfs; + +import com.github.tobato.fastdfs.domain.fdfs.StorePath; +import com.github.tobato.fastdfs.service.FastFileStorageClient; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.io.FilenameUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +/** + * FastDfsClient + * + * @author kongcaizhi + * @since 2021-10-19 + */ +@Slf4j +@Component +public class FastDfsClient { + @Autowired + private FastFileStorageClient storageClient; + + /** + * 上传文件 + * + * @param file 文件对象 + * @return 文件访问地址 + * @throws IOException IOException + */ + public String uploadFile(MultipartFile file) throws IOException { + StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), + FilenameUtils.getExtension(file.getOriginalFilename()), null); + return getResAccessUrl(storePath); + } + + private String getResAccessUrl(StorePath storePath) { + return storePath.getFullPath(); + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SFTPUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SFTPUtil.java new file mode 100644 index 0000000..25c2212 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SFTPUtil.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util.sshclient; + +import com.huawei.ic.openlab.cloudtest.entity.CloudLabTestTask; +import com.huawei.ic.openlab.cloudtest.entity.LabTestReq; + +import com.jcraft.jsch.Channel; +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import com.jcraft.jsch.SftpException; + +import lombok.extern.slf4j.Slf4j; + +import java.io.InputStream; +import java.util.Properties; + +/** + * FastDfsClient + * + * @author kongcaizhi + * @since 2021-10-19 + */ +@Slf4j +public class SFTPUtil { + private static final Integer DEFAULT_TIMEOUT = 1000 * 60; + + /** + * upload file + * + * @param testReq testReq + * @param targetPath target path + * @param in input stream + * @throws JSchException JSchException + * @throws SftpException SftpException + */ + public static void uploadFile(LabTestReq testReq, + String targetPath, + InputStream in) throws JSchException, SftpException { + JSch jsch = new JSch(); + Session sshSession = jsch.getSession(testReq.getServerUser(), testReq.getServerIp(), testReq.getServerPort()); + sshSession.setPassword(testReq.getServerPassword()); + Properties config = new Properties(); + config.put("StrictHostKeyChecking", "no"); + sshSession.setConfig(config); + sshSession.connect(DEFAULT_TIMEOUT); + + Channel channel = sshSession.openChannel("sftp"); + channel.connect(); + ChannelSftp sftp = null; + if (!(channel instanceof ChannelSftp)) { + return; + } + try { + sftp = (ChannelSftp) channel; + sftp.put(in, targetPath); + } finally { + if (sftp != null) { + sftp.exit(); + } + } + } + + /** + * upload file + * + * @param task testReq + * @param targetPath target path + * @param in input stream + * @throws JSchException JSchException + * @throws SftpException SftpException + */ + public static void uploadFile(CloudLabTestTask task, + String targetPath, + InputStream in) throws JSchException, SftpException { + JSch jsch = new JSch(); + Session sshSession = jsch.getSession(task.getServerUser(), task.getServerIp(), task.getServerPort()); + sshSession.setPassword(task.getServerPassword()); + Properties config = new Properties(); + config.put("StrictHostKeyChecking", "no"); + sshSession.setConfig(config); + sshSession.connect(DEFAULT_TIMEOUT); + + Channel channel = sshSession.openChannel("sftp"); + channel.connect(); + ChannelSftp sftp = null; + if (!(channel instanceof ChannelSftp)) { + return; + } + try { + sftp = (ChannelSftp) channel; + sftp.put(in, targetPath); + } finally { + if (sftp != null) { + sftp.exit(); + } + } + } +} diff --git a/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SSHUtil.java b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SSHUtil.java new file mode 100644 index 0000000..8882cb4 --- /dev/null +++ b/component/CloudTest/src/main/java/com/huawei/ic/openlab/cloudtest/util/sshclient/SSHUtil.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. + */ + +package com.huawei.ic.openlab.cloudtest.util.sshclient; + +import com.huawei.ic.openlab.cloudtest.common.exception.SshErrorException; + +import lombok.extern.slf4j.Slf4j; + +import org.apache.sshd.client.SshClient; +import org.apache.sshd.client.channel.ChannelExec; +import org.apache.sshd.client.channel.ClientChannelEvent; +import org.apache.sshd.client.session.ClientSession; +import org.apache.sshd.common.util.io.output.NoCloseOutputStream; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * SSH 远程连接服务 + * + * @author kongcaizhi + * @since 2021-10-19 + */ +@Slf4j +public class SSHUtil { + private static final Integer DEFAULT_TIMEOUT = 1000 * 30; + private static final String DEFAULT_SHELL_CHARSET_NAME = "UTF-8"; + + /** + * 测试ssh连接 + * + * @param ip ip + * @param port port + * @param userName username + * @param passWord password + * @return boolean + * @throws SshErrorException exception + */ + public static boolean sshConnectTest(String ip, int port, String userName, String passWord) { + try (SshClient client = SshClient.setUpDefaultClient()) { + client.start(); + try (ClientSession session = client.connect(userName, ip, port).verify(DEFAULT_TIMEOUT).getSession()) { + session.addPasswordIdentity(passWord); + return session.auth().verify(DEFAULT_TIMEOUT).isSuccess(); + } finally { + client.stop(); + } + } catch (IOException e) { + log.error(e.getLocalizedMessage(), e); + } + return false; + } + + /** + * sshExecCmd + * + * @param ip ip + * @param port port + * @param userName username + * @param passWord password + * @param commandList command list + * @return string + * @throws SshErrorException exception + */ + public static String sshExecCmd(String ip, int port, String userName, String passWord, List commandList) + throws SshErrorException { + try (SshClient client = SshClient.setUpDefaultClient()) { + client.start(); + try (ClientSession session = client.connect(userName, ip, port).verify(DEFAULT_TIMEOUT).getSession()) { + return execCmd(passWord, session, commandList, DEFAULT_SHELL_CHARSET_NAME); + } finally { + client.stop(); + } + } catch (IOException e) { + log.error(e.getLocalizedMessage(), e); + throw new SshErrorException("SSH出现IO异常"); + } + } + + private static String execCmd(String passWord, ClientSession session, List commandList, String charsetName) + throws IOException, SshErrorException { + session.addPasswordIdentity(passWord); + if (session.auth().verify(DEFAULT_TIMEOUT).isFailure()) { + throw new SshErrorException("SSH 连接超时"); + } + try { + String response = ""; + for (String command : commandList) { + response = exec(session, command, charsetName); + } + return response; + } finally { + session.close(false); + } + } + + private static String exec(ClientSession session, String command, String charsetName) + throws IOException, SshErrorException { + try (ChannelExec channelExec = session.createExecChannel(command); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + channelExec.setOut(new NoCloseOutputStream(out)); + channelExec.setErr(new NoCloseOutputStream(out)); + if (!channelExec.open().verify(DEFAULT_TIMEOUT).isOpened()) { + throw new SshErrorException("SSH 连接异常"); + } + List list = new ArrayList<>(); + list.add(ClientChannelEvent.CLOSED); + channelExec.waitFor(list, DEFAULT_TIMEOUT); + channelExec.close(); + + String response = out.toString(charsetName); + String[] lines = response.split(System.lineSeparator()); + for (String line : lines) { + log.debug(line); + } + return response; + } + } +} diff --git a/component/CloudTest/src/main/resources/application.yml b/component/CloudTest/src/main/resources/application.yml new file mode 100644 index 0000000..34b6de0 --- /dev/null +++ b/component/CloudTest/src/main/resources/application.yml @@ -0,0 +1,30 @@ +server: + port: 10037 + +scriptConfigCn: /data/software/cloudTest/script/compatibility_testing.conf +scriptConfigEn: /data/software/cloudTest/script/compatibility_testing_EN.conf +tempDir: /data/software/cloudTest/tmp +deployIp: 172.39.92.22 +uploadFileDir: /data/software/cloudTest/data +appId: com.huawei.icopenlab.website +appKey: ENC(avto39VXGCZudTEfU1DQjuou0INTVQpvA75GmdwZzIA=) +mqsTopic: T_OPENLAB_TEST_PROJECT_MESSAGE +mqsUrl: https://apigw-beta.huawei.com/api/mqs/message/beta +clamdIp : localhost +clamdPort : 3310 +performanceTestUrl : http://%s:8095/rest/v1/cloud-test/lab +appIdUat: com.huawei.icopenlab.website +appKeyUat: ENC(avto39VXGCZudTEfU1DQjuou0INTVQpvA75GmdwZzIA=) +mqsTopicUat: T_OPENLAB_TEST_PROJECT_MESSAGE +mqsUrlUat: https://mqs/message/beta +kunpengServiceUrl: https://kunpengcommunity/cloudbase/auth +teeCodeServerUrl : http://1111/code-server/ +dgCodeServerUrl: http://1111/code-server/ + +crypto: + aes-default-key: ENC(x2P5OjvjSqOMi9AGhKR70e1o5XLRd9XuUdfZPfFiL2VeQ5RTs498/f85N4moRzeBbr1to42juDgqnsuw8Wn9ykc9WrpdZ2AiwYdV09O9600=) + aes-default-aad: openlab + aes-cipher-mode: AES/GCM/PKCS5Padding +logging: + level: + root: debug \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/fastjson.properties b/component/CloudTest/src/main/resources/fastjson.properties new file mode 100644 index 0000000..f3c0788 --- /dev/null +++ b/component/CloudTest/src/main/resources/fastjson.properties @@ -0,0 +1 @@ +fastjson.parser.safeMode=true \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/key/EXTRUBjR/NmsaKOHM b/component/CloudTest/src/main/resources/key/EXTRUBjR/NmsaKOHM new file mode 100644 index 0000000..94e2349 --- /dev/null +++ b/component/CloudTest/src/main/resources/key/EXTRUBjR/NmsaKOHM @@ -0,0 +1 @@ +8BQTpsioA5ulNBnfY16hfL34mAsm1t98CQHd6h9EjLM0sgob \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/key/STZQZzfs/PIeavG3r b/component/CloudTest/src/main/resources/key/STZQZzfs/PIeavG3r new file mode 100644 index 0000000..9f1b0fe --- /dev/null +++ b/component/CloudTest/src/main/resources/key/STZQZzfs/PIeavG3r @@ -0,0 +1 @@ +hyDu3TZOu2EcY61T5fo2VzdHOP4pp0wU4r1csz9Fne4wVmXt \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/key/SW7HH3Up/59X8ARQZ b/component/CloudTest/src/main/resources/key/SW7HH3Up/59X8ARQZ new file mode 100644 index 0000000..52be9ac --- /dev/null +++ b/component/CloudTest/src/main/resources/key/SW7HH3Up/59X8ARQZ @@ -0,0 +1 @@ +ijRxLKur4sztVzq4Ff7xqSgafxLGcMsG7HqV1H8bModYK5Cn \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/logback-spring.xml b/component/CloudTest/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..d0aa28d --- /dev/null +++ b/component/CloudTest/src/main/resources/logback-spring.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + + + ${LOG_HOME}/cloudTest_%d{yyyy-MM-dd}.%i.log + + 10MB + + + 30 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/mapper/CloudDevUseRecordMapper.xml b/component/CloudTest/src/main/resources/mapper/CloudDevUseRecordMapper.xml new file mode 100644 index 0000000..5131544 --- /dev/null +++ b/component/CloudTest/src/main/resources/mapper/CloudDevUseRecordMapper.xml @@ -0,0 +1,26 @@ + + + + + + + INSERT INTO CLOUD_DEV_USE_RECORD( + REQUEST_TIME, + TASK_DEVICE_ID, + KP_TOKEN + )VALUE( + #{requestTime}, + #{taskDeviceId}, + #{kpToken} + ) + + \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/mapper/CloudLabTestTaskMapper.xml b/component/CloudTest/src/main/resources/mapper/CloudLabTestTaskMapper.xml new file mode 100644 index 0000000..60ddf31 --- /dev/null +++ b/component/CloudTest/src/main/resources/mapper/CloudLabTestTaskMapper.xml @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + INSERT INTO CLOUD_LAB_TEST_TASK( + PROJECT_ID, + USER_ID, + SERVER_IP, + SERVER_PORT, + SERVER_USER, + SERVER_PASSWORD, + PROJECT_STATUS, + REQUEST_TIME, + START_TIME, + FINISH_TIME, + COMPATIBILITY_TEST, + RELIABILITY_TEST, + SECURITY_TEST, + FUNCTION_TEST, + PERFORMANCE_TEST, + STEP_STATUS, + CURRENT_STATUS, + FUNCTION_FILE, + PERFORMANCE_FILE, + RESULT_FILE, + TEST_SUMMARY, + TEST_DETAIL, + TASK_LANGUAGE + ) + VALUE( + #{projectId}, + #{data.userId}, + #{data.serverIp}, + #{data.serverPort}, + #{data.serverUser}, + #{data.serverPassword, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.CryptoTypeHandler}, + #{data.projectStatus}, + #{data.requestTime}, + #{data.startTime}, + #{data.finishTime}, + #{data.compatibilityTest}, + #{data.reliabilityTest}, + #{data.securityTest}, + #{data.functionTest}, + #{data.performanceTest}, + #{data.stepStatus, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + #{data.currentStatus}, + #{data.functionFile, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + #{data.performanceFile, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + #{data.resultFile, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + #{data.testSummary, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + #{data.testDetail, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + #{data.taskLanguage} + )ON DUPLICATE KEY UPDATE + SERVER_IP = #{data.serverIp}, + SERVER_PORT = #{data.serverPort}, + SERVER_USER = #{data.serverUser}, + SERVER_PASSWORD = + #{data.serverPassword, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.CryptoTypeHandler}, + PROJECT_STATUS = #{data.projectStatus}, + REQUEST_TIME = #{data.requestTime}, + COMPATIBILITY_TEST = #{data.compatibilityTest}, + RELIABILITY_TEST = #{data.reliabilityTest}, + SECURITY_TEST = #{data.securityTest}, + FUNCTION_TEST = #{data.functionTest}, + PERFORMANCE_TEST = #{data.performanceTest}, + TASK_LANGUAGE = #{data.taskLanguage}, + STEP_STATUS = null, + CURRENT_STATUS = null, + RESULT_FILE = null, + TEST_SUMMARY = null, + TEST_DETAIL = null, + SCRIPT_RESULT_CONFIG = null + + + + UPDATE CLOUD_LAB_TEST_TASK + SET + PROJECT_STATUS = #{status}, + STATUS_DESC = #{statusDesc}, + + START_TIME = #{startTime} + + + FINISH_TIME = #{finishTime} + + WHERE PROJECT_ID = #{projectId} + + + + + SELECT COUNT(*) FROM CLOUD_LAB_TEST_TASK WHERE PROJECT_ID = #{projectId} + + + + UPDATE CLOUD_LAB_TEST_TASK + SET + PERFORMANCE_SERVICE = #{ip}, + + FUNCTION_FILE = + #{data, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler} + + + PERFORMANCE_FILE = + #{data, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler} + + WHERE PROJECT_ID = #{projectId} + + + INSERT INTO CLOUD_LAB_TEST_TASK( + PROJECT_ID, + USER_ID, + PERFORMANCE_SERVICE, + + FUNCTION_FILE + + + PERFORMANCE_FILE + + )VALUE( + #{projectId}, + #{userId}, + #{ip}, + #{data, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler} + ) + + + + + + UPDATE CLOUD_LAB_TEST_TASK + SET + STEP_STATUS = #{data, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + TEST_BEGIN_TIME = + #{testBeginTime, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler} + WHERE PROJECT_ID = #{projectId} + + + + UPDATE CLOUD_LAB_TEST_TASK + SET + STEP_STATUS = + #{data.stepStatus, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + PROJECT_STATUS = #{data.projectStatus}, + STATUS_DESC = #{data.statusDesc}, + FINISH_TIME = #{data.finishTime} + WHERE PROJECT_ID = #{data.projectId} + + + + + + UPDATE CLOUD_LAB_TEST_TASK + SET + STEP_STATUS = + #{data.stepStatus, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + PROJECT_STATUS = #{data.projectStatus}, + STATUS_DESC = #{data.statusDesc}, + FINISH_TIME = #{data.finishTime}, + RESULT_FILE = + #{data.resultFile, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + TEST_SUMMARY = + #{data.testSummary, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + TEST_DETAIL = + #{data.testDetail, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + SCRIPT_RESULT_CONFIG = + #{data.scriptResultConfig, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler} + WHERE PROJECT_ID = #{data.projectId} + + + + + UPDATE CLOUD_LAB_TEST_TASK + SET + STEP_STATUS = + #{data.stepStatus, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + PROJECT_STATUS = #{data.projectStatus}, + STATUS_DESC = #{data.statusDesc}, + FINISH_TIME = #{data.finishTime}, + TEST_SUMMARY = + #{data.testSummary, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler}, + TEST_DETAIL = + #{data.testDetail, typeHandler=com.huawei.ic.openlab.cloudtest.common.typehandler.JacksonTypeHandler} + WHERE PROJECT_ID = #{data.projectId} + + + \ No newline at end of file diff --git a/component/CloudTest/src/main/resources/mapper/PerformanceServiceMapper.xml b/component/CloudTest/src/main/resources/mapper/PerformanceServiceMapper.xml new file mode 100644 index 0000000..6ad8b70 --- /dev/null +++ b/component/CloudTest/src/main/resources/mapper/PerformanceServiceMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + UPDATE PERFORMANCE_SERVICE + SET TASK_NUM = TASK_NUM +1 + WHERE SERVICE_IP = #{serviceIp} + + + + UPDATE PERFORMANCE_SERVICE + SET TASK_NUM = TASK_NUM -1 + WHERE SERVICE_IP = #{serviceIp} + + \ No newline at end of file -- Gitee