diff --git a/nex-be/pom.xml b/nex-be/pom.xml index a712c52..41a08e1 100644 --- a/nex-be/pom.xml +++ b/nex-be/pom.xml @@ -23,6 +23,7 @@ 1.8 3.23.4 + 2021.0.5 @@ -32,6 +33,11 @@ spring-boot-starter-web + + org.springframework.cloud + spring-cloud-starter-openfeign + + org.springframework.boot @@ -124,7 +130,19 @@ spring-boot-starter-test test + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + diff --git a/nex-be/src/main/java/com/unisinsight/project/Application.java b/nex-be/src/main/java/com/unisinsight/project/Application.java index b1fdf4d..96f6660 100644 --- a/nex-be/src/main/java/com/unisinsight/project/Application.java +++ b/nex-be/src/main/java/com/unisinsight/project/Application.java @@ -3,12 +3,14 @@ package com.unisinsight.project; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; /** * 分片上传应用启动类 */ @SpringBootApplication @MapperScan(basePackages = "com.unisinsight.project.mapper") +@EnableFeignClients(basePackages = "com.unisinsight.project.feign") public class Application { public static void main(String[] args) { diff --git a/nex-be/src/main/java/com/unisinsight/project/config/FeignConfig.java b/nex-be/src/main/java/com/unisinsight/project/config/FeignConfig.java new file mode 100644 index 0000000..2154752 --- /dev/null +++ b/nex-be/src/main/java/com/unisinsight/project/config/FeignConfig.java @@ -0,0 +1,35 @@ +package com.unisinsight.project.config; + +import feign.Logger; +import feign.Request; +import feign.Retryer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FeignConfig { + + /** + * 配置请求日志级别 + */ + @Bean + public Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } + + /** + * 配置超时时间 + */ + @Bean + public Request.Options options() { + return new Request.Options(5000, 10000); // 连接超时5秒,读取超时10秒 + } + + /** + * 配置重试机制 + */ + @Bean + public Retryer retryer() { + return new Retryer.Default(1000, 2000, 3); // 初始间隔1秒,最大间隔2秒,最多重试3次 + } +} diff --git a/nex-be/src/main/java/com/unisinsight/project/entity/dto/ApiResponse.java b/nex-be/src/main/java/com/unisinsight/project/entity/dto/ApiResponse.java new file mode 100644 index 0000000..34a1839 --- /dev/null +++ b/nex-be/src/main/java/com/unisinsight/project/entity/dto/ApiResponse.java @@ -0,0 +1,91 @@ + +package com.unisinsight.project.entity.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 通用API响应结果类 + */ +@Data +@ApiModel(description = "API响应结果") +public class ApiResponse implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "响应码") + private String code; + + @ApiModelProperty(value = "响应消息") + private String message; + + @ApiModelProperty(value = "响应数据") + private T data; + + public ApiResponse() {} + + public ApiResponse(String code, String message) { + this.code = code; + this.message = message; + } + + public ApiResponse(String code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + /** + * 成功响应 + */ + public static ApiResponse success() { + return new ApiResponse<>("200", "操作成功"); + } + + public static ApiResponse success(T data) { + return new ApiResponse<>("200", "操作成功", data); + } + + public static ApiResponse success(String message, T data) { + return new ApiResponse<>("200", message, data); + } + + /** + * 失败响应 + */ + public static ApiResponse error(String message) { + return new ApiResponse<>("500", message); + } + + public static ApiResponse error(String code, String message) { + return new ApiResponse<>(code, message); + } + + public static ApiResponse error(String code, String message, T data) { + return new ApiResponse<>(code, message, data); + } + + /** + * 参数校验错误 + */ + public static ApiResponse badRequest(String message) { + return new ApiResponse<>("400", message); + } + + /** + * 权限错误 + */ + public static ApiResponse forbidden(String message) { + return new ApiResponse<>("403", message); + } + + /** + * 未找到 + */ + public static ApiResponse notFound(String message) { + return new ApiResponse<>("404", message); + } +} \ No newline at end of file diff --git a/nex-be/src/main/java/com/unisinsight/project/entity/req/StoragePoolReq.java b/nex-be/src/main/java/com/unisinsight/project/entity/req/StoragePoolReq.java index 3f505c3..3261428 100644 --- a/nex-be/src/main/java/com/unisinsight/project/entity/req/StoragePoolReq.java +++ b/nex-be/src/main/java/com/unisinsight/project/entity/req/StoragePoolReq.java @@ -20,6 +20,9 @@ public class StoragePoolReq { @ApiModelProperty(value = "id") private Integer id; + @ApiModelProperty("自动启动,默认是") + private boolean autostart = true; + @ApiModelProperty("名称") @NotBlank(message = "名称不能为空") @Size(max = 64, message = "名称长度不能超过64个字符") diff --git a/nex-be/src/main/java/com/unisinsight/project/feign/ExternalApiClient.java b/nex-be/src/main/java/com/unisinsight/project/feign/ExternalApiClient.java new file mode 100644 index 0000000..0a9b615 --- /dev/null +++ b/nex-be/src/main/java/com/unisinsight/project/feign/ExternalApiClient.java @@ -0,0 +1,50 @@ +package com.unisinsight.project.feign; + +import com.unisinsight.project.config.FeignConfig; +import com.unisinsight.project.entity.dto.ApiResponse; +import com.unisinsight.project.entity.req.NetworkManageReq; +import com.unisinsight.project.entity.req.StoragePoolReq; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * 第三方API客户端 + */ +@FeignClient( + name = "external-api-client", + url = "${external.api.url:http://10.100.51.118:8000}", + configuration = FeignConfig.class +) +public interface ExternalApiClient { + + @PostMapping("/api/v1/network/create") + ApiResponse createNetwork(@RequestBody NetworkManageReq networkManageReq); + + @DeleteMapping("/api/v1/network/{network_name}") + ApiResponse deleteNetwork(@PathVariable("network_name") String networkName); + + @PostMapping("/api/v1/network/update") + ApiResponse updateNetwork(@RequestBody NetworkManageReq networkManageReq); + + @PostMapping("/api/v1/network/start") + ApiResponse startNetwork(@RequestBody NetworkManageReq networkManageReq); + + @PostMapping("/api/v1/network/stop") + ApiResponse stopNetwork(@RequestBody NetworkManageReq networkManageReq); + + @PostMapping("/api/v1/storage/pools") + ApiResponse createStorage(@RequestBody StoragePoolReq storagePoolReq); + + @PostMapping("/api/v1/storage/pools/start") + ApiResponse startStorage(@RequestBody StoragePoolReq storagePoolReq); + + @PostMapping("/api/v1/storage/pools/stop") + ApiResponse stopStorage(@RequestBody StoragePoolReq storagePoolReq); + + @DeleteMapping("/api/v1/storage/pools/{pool_name}") + ApiResponse deleteStorage(@PathVariable("pool_name") String poolName); + +} diff --git a/nex-be/src/main/java/com/unisinsight/project/service/StoragePoolService.java b/nex-be/src/main/java/com/unisinsight/project/service/StoragePoolService.java index 50eea1f..c767e2a 100644 --- a/nex-be/src/main/java/com/unisinsight/project/service/StoragePoolService.java +++ b/nex-be/src/main/java/com/unisinsight/project/service/StoragePoolService.java @@ -14,7 +14,7 @@ public interface StoragePoolService { /** * 新增存储池 * - * @param storagePool 存储池对象 + * @param storagePoolReq * @return StoragePool 返回新增的存储池对象 */ StoragePool addStoragePool(StoragePoolReq storagePoolReq); @@ -22,7 +22,7 @@ public interface StoragePoolService { /** * 根据ID更新存储池信息 * - * @param storagePool 存储池对象 + * @param storagePoolReq * @return boolean 是否更新成功 */ boolean updateStoragePool(StoragePoolReq storagePoolReq); @@ -46,11 +46,7 @@ public interface StoragePoolService { /** * 分页查询存储池列表 * - * @param currentPage 当前页码 - * @param pageSize 每页大小 - * @param name 存储池名称(可选查询条件) - * @param type 存储池类型(可选查询条件) - * @param status 存储池状态(可选查询条件) + * @param storagePoolReq * @return Page 分页结果 */ PageResult pageStoragePools(StoragePoolReq storagePoolReq); diff --git a/nex-be/src/main/java/com/unisinsight/project/service/impl/NetworkManageServiceImpl.java b/nex-be/src/main/java/com/unisinsight/project/service/impl/NetworkManageServiceImpl.java index cfe34f1..d5658ef 100644 --- a/nex-be/src/main/java/com/unisinsight/project/service/impl/NetworkManageServiceImpl.java +++ b/nex-be/src/main/java/com/unisinsight/project/service/impl/NetworkManageServiceImpl.java @@ -5,16 +5,19 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.unisinsight.project.entity.dao.NetworkManage; +import com.unisinsight.project.entity.dto.ApiResponse; import com.unisinsight.project.entity.req.NetworkManagePageReq; import com.unisinsight.project.entity.req.NetworkManageReq; import com.unisinsight.project.entity.res.PageResult; import com.unisinsight.project.exception.BusinessException; +import com.unisinsight.project.feign.ExternalApiClient; import com.unisinsight.project.mapper.NetworkManageMapper; import com.unisinsight.project.service.NetworkManageService; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; import java.util.Date; import java.util.List; @@ -24,6 +27,8 @@ import java.util.List; @Service public class NetworkManageServiceImpl extends ServiceImpl implements NetworkManageService { + @Resource + private ExternalApiClient client; /** * 新增网络管理信息 * @@ -38,6 +43,16 @@ public class NetworkManageServiceImpl extends ServiceImpl 0) { throw new BusinessException("网络名称'" + networkManageReq.getName() + "'已存在,请使用其他名称"); } + + // 调用虚拟机创建存储池 + try { + ApiResponse response = client.createNetwork(networkManageReq); + if (!"200".equals(response.getCode())) { + throw new BusinessException("调用外部接口失败: " + response.getMessage()); + } + } catch (Exception e) { + throw new BusinessException("调用外部接口失败: " + e.getMessage()); + } // 设置创建时间和更新时间 NetworkManage networkManage = new NetworkManage(); BeanUtils.copyProperties(networkManageReq, networkManage); @@ -76,8 +91,33 @@ public class NetworkManageServiceImpl extends ServiceImpl implements StoragePoolService { + @Resource + private ExternalApiClient client; + /** * 新增存储池 * @@ -37,6 +43,17 @@ public class StoragePoolServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("name", storagePoolReq.getName()); - if (this.count(queryWrapper) > 0) { - throw new BusinessException("存储池名称'" + storagePoolReq.getName() + "'已存在,请使用其他名称"); - } - existing.setName(storagePoolReq.getName()); - } +// if (storagePoolReq.getName() != null && !storagePoolReq.getName().isEmpty() +// && !storagePoolReq.getName().equals(existing.getName())) { +// // 检查新名称是否重复 +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// queryWrapper.eq("name", storagePoolReq.getName()); +// if (this.count(queryWrapper) > 0) { +// throw new BusinessException("存储池名称'" + storagePoolReq.getName() + "'已存在,请使用其他名称"); +// } +// existing.setName(storagePoolReq.getName()); +// } + // 调用虚拟机创建存储池 // 修改状态 - if (storagePoolReq.getStatus() != null - && !storagePoolReq.getStatus().equals(existing.getStatus())) { + if (storagePoolReq.getStatus() != null) { + try { + storagePoolReq.setName(existing.getName()); + ApiResponse response; + if(1==storagePoolReq.getStatus()){ + response = client.startStorage(storagePoolReq); + } else { + response =client.stopStorage(storagePoolReq); + } + if (!"200".equals(response.getCode())) { + throw new BusinessException("调用外部接口失败: " + response.getMessage()); + } + } catch (Exception e) { + throw new BusinessException("调用外部接口失败: " + e.getMessage()); + } existing.setStatus(storagePoolReq.getStatus()); } @@ -90,6 +122,19 @@ public class StoragePoolServiceImpl extends ServiceImpl 分页结果 */ @Override diff --git a/nex-be/src/main/resources/application.yml b/nex-be/src/main/resources/application.yml index 842287a..e65a9dc 100644 --- a/nex-be/src/main/resources/application.yml +++ b/nex-be/src/main/resources/application.yml @@ -55,4 +55,19 @@ mybatis-plus: grpc: server: # 指定Grpc暴露的端口,后续客户端通过这个端口访问 - port: 51051 \ No newline at end of file + port: 51051 + +# Feign 配置 +feign: + client: + config: + external-api-client: # 对应 FeignClient 的 name + logger-level: full # 完整日志级别 + default: # 全局默认配置 + logger-level: basic + +# 日志配置 +logging: + level: + com.unisinsight.project.feign: debug # Feign 客户端包路径 + com.unisinsight.project.feign.ExternalApiClient: debug \ No newline at end of file