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