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 b568494..d0fd630 100644 --- a/nex-be/src/main/java/com/unisinsight/project/Application.java +++ b/nex-be/src/main/java/com/unisinsight/project/Application.java @@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; +import org.springframework.scheduling.annotation.EnableScheduling; import java.net.InetAddress; import java.net.UnknownHostException; @@ -19,6 +20,7 @@ import java.net.UnknownHostException; @SpringBootApplication @MapperScan(basePackages = "com.unisinsight.project.mapper") @EnableFeignClients(basePackages = "com.unisinsight.project.feign") +@EnableScheduling public class Application { private static final Logger logger = LoggerFactory.getLogger(Application.class); diff --git a/nex-be/src/main/java/com/unisinsight/project/config/ThreadConfig.java b/nex-be/src/main/java/com/unisinsight/project/config/ThreadConfig.java index dcbc27b..7f2471c 100644 --- a/nex-be/src/main/java/com/unisinsight/project/config/ThreadConfig.java +++ b/nex-be/src/main/java/com/unisinsight/project/config/ThreadConfig.java @@ -3,6 +3,8 @@ package com.unisinsight.project.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; @@ -64,4 +66,17 @@ public class ThreadConfig { new ThreadPoolExecutor.CallerRunsPolicy() ); } + + /** + * 配置TaskScheduler用于定时任务 + */ + @Bean + public TaskScheduler taskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setPoolSize(10); // 线程池大小 + taskScheduler.setThreadNamePrefix("scheduled-task-"); // 线程名称前缀 + taskScheduler.setWaitForTasksToCompleteOnShutdown(true); // 关闭时等待任务完成 + taskScheduler.setAwaitTerminationSeconds(30); // 等待终止时间 + return taskScheduler; + } } diff --git a/nex-be/src/main/java/com/unisinsight/project/entity/dao/ImageDesktop.java b/nex-be/src/main/java/com/unisinsight/project/entity/dao/ImageDesktop.java index 10f1134..eb38de7 100644 --- a/nex-be/src/main/java/com/unisinsight/project/entity/dao/ImageDesktop.java +++ b/nex-be/src/main/java/com/unisinsight/project/entity/dao/ImageDesktop.java @@ -40,8 +40,8 @@ public class ImageDesktop extends Model { @TableField(value = "desktop_type") - @ApiModelProperty("桌面类型:1:VHD 2:VHDX 3:QCOW2") - private Integer desktopType; + @ApiModelProperty("桌面类型") + private String desktopType; /** * 父镜像id **/ @@ -130,6 +130,9 @@ public class ImageDesktop extends Model { @TableField(value = "description") @ApiModelProperty("描述") private String description; + @TableField(value = "file_size") + @ApiModelProperty("文件大小") + private String fileSize; /** * 发布时间 **/ diff --git a/nex-be/src/main/java/com/unisinsight/project/entity/req/ImageDesktopReq.java b/nex-be/src/main/java/com/unisinsight/project/entity/req/ImageDesktopReq.java index 7d0819b..34d6a38 100644 --- a/nex-be/src/main/java/com/unisinsight/project/entity/req/ImageDesktopReq.java +++ b/nex-be/src/main/java/com/unisinsight/project/entity/req/ImageDesktopReq.java @@ -32,7 +32,7 @@ public class ImageDesktopReq { **/ @JsonProperty("desktop_type") @ApiModelProperty("桌面类型:1:VHD 2:VHDX 3:QCOW2") - private Integer desktopType; + private String desktopType; /** * 父镜像id **/ diff --git a/nex-be/src/main/java/com/unisinsight/project/entity/res/ImageDesktopRes.java b/nex-be/src/main/java/com/unisinsight/project/entity/res/ImageDesktopRes.java index 49ed8e1..330431d 100644 --- a/nex-be/src/main/java/com/unisinsight/project/entity/res/ImageDesktopRes.java +++ b/nex-be/src/main/java/com/unisinsight/project/entity/res/ImageDesktopRes.java @@ -34,7 +34,7 @@ public class ImageDesktopRes implements Serializable { **/ @JsonProperty("desktop_type") @ApiModelProperty("桌面类型:1:VHD 2:VHDX 3:QCOW2") - private Integer desktopType; + private String desktopType; /** * 父镜像id **/ @@ -108,5 +108,7 @@ public class ImageDesktopRes implements Serializable { @ApiModelProperty("发布时间") private String publishTime; + private ImageVirtualMachinesRes imageVirtualMachines; + } diff --git a/nex-be/src/main/java/com/unisinsight/project/feign/ExternalTorrentClient.java b/nex-be/src/main/java/com/unisinsight/project/feign/ExternalTorrentClient.java index da289c6..44b5a35 100644 --- a/nex-be/src/main/java/com/unisinsight/project/feign/ExternalTorrentClient.java +++ b/nex-be/src/main/java/com/unisinsight/project/feign/ExternalTorrentClient.java @@ -16,6 +16,7 @@ package com.unisinsight.project.feign; */ import com.unisinsight.project.config.FeignConfig; +import io.swagger.annotations.ApiOperation; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -39,4 +40,12 @@ public interface ExternalTorrentClient { @GetMapping("/vdi/progress") Double progress(@RequestParam("name") String name); + @GetMapping("/vdi/start") + boolean startBt(@RequestParam("sourceFile") String sourceFile, + @RequestParam("torrentFile") String torrentFile); + + @GetMapping("/start") + @ApiOperation(value = "终端开机") + boolean deviceStart(@RequestParam("macAddr") String macAddr); + } diff --git a/nex-be/src/main/java/com/unisinsight/project/service/impl/ClientOperateServiceImpl.java b/nex-be/src/main/java/com/unisinsight/project/service/impl/ClientOperateServiceImpl.java index 8cfc048..3a26cba 100644 --- a/nex-be/src/main/java/com/unisinsight/project/service/impl/ClientOperateServiceImpl.java +++ b/nex-be/src/main/java/com/unisinsight/project/service/impl/ClientOperateServiceImpl.java @@ -3,13 +3,19 @@ package com.unisinsight.project.service.impl; import com.unisinsight.project.entity.enums.GrpcTypeEnum; import com.unisinsight.project.entity.req.DeviceReq; +import com.unisinsight.project.exception.BaseErrorCode; import com.unisinsight.project.exception.Result; +import com.unisinsight.project.feign.ExternalTorrentClient; import com.unisinsight.project.grpc.generate.NotificationMessage; import com.unisinsight.project.grpc.service.SendNotificationService; import com.unisinsight.project.service.ClientOperateService; +import com.unisinsight.project.util.StringUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.io.IOException; + /** * @author : ch * @version : 1.0 @@ -24,14 +30,20 @@ import org.springframework.stereotype.Service; * 2025/08/21 ch 1.0 Why & What is modified: <修改原因描述> * */ @Service +@Slf4j public class ClientOperateServiceImpl implements ClientOperateService { @Autowired private SendNotificationService notificationService; + @Autowired + private ExternalTorrentClient externalTorrentClient; @Override public Result terminalStart(DeviceReq deviceReq) { - //todo 待客户端确认消息内容后完善 - return notificationService.sendNotification(deviceReq.getDeviceId(), NotificationMessage.newBuilder().setContent("终端开机").build()); + if (StringUtil.isNotEmpty(deviceReq.getMacAddr())) { + return Result.errorResultMessage(BaseErrorCode.PARAMS_CHK_ERROR, "请输入正确的终端MAC地址"); + } + boolean start = externalTorrentClient.deviceStart(deviceReq.getMacAddr()); + return start ? Result.successResult() : Result.errorResultMessage(BaseErrorCode.INTERNAL_EXCEPTION, "终端启动失败"); } @Override diff --git a/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageDesktopServiceImpl.java b/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageDesktopServiceImpl.java index ed014d1..f295f90 100644 --- a/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageDesktopServiceImpl.java +++ b/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageDesktopServiceImpl.java @@ -1,5 +1,9 @@ package com.unisinsight.project.service.impl; +import cn.hutool.core.lang.func.Func; +import com.unisinsight.project.entity.dao.ImageVirtualMachines; +import com.unisinsight.project.entity.res.ImageVirtualMachinesRes; +import com.unisinsight.project.mapper.ImageVirtualMachinesMapper; import org.springframework.stereotype.Service; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; @@ -24,6 +28,10 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; @Slf4j /** @@ -36,6 +44,8 @@ import java.util.List; public class ImageDesktopServiceImpl extends ServiceImpl implements ImageDesktopService { @Resource private ImageDesktopMapper mapper; + @Resource + private ImageVirtualMachinesMapper imageVirtualMachinesMapper; @Override public Result> selectPage(ImageDesktopReq imageDesktopReq) { @@ -50,6 +60,15 @@ public class ImageDesktopServiceImpl extends ServiceImpl convert = PageResult.convertIPage(imageDesktopPage, ImageDesktopRes.class); List data = convert.getData(); + List imageVirtualIdList = data.stream().map(ImageDesktopRes::getImageVirtualId).filter(Objects::nonNull).collect(Collectors.toList()); + LambdaQueryWrapper imageVirtualMachinesLambdaQueryWrapper = new LambdaQueryWrapper<>(); + imageVirtualMachinesLambdaQueryWrapper.in(ImageVirtualMachines::getId, imageVirtualIdList); + List imageVirtualMachines = imageVirtualMachinesMapper.selectList(imageVirtualMachinesLambdaQueryWrapper); + Map machinesMap = imageVirtualMachines.stream().collect(Collectors.toMap(ImageVirtualMachines::getId, Function.identity(), (k1, k2) -> k1)); + for (ImageDesktopRes datum : data) { + datum.setImageVirtualMachines(BeanUtil.copyProperties(machinesMap.get(Long.valueOf(datum.getImageVirtualId())), ImageVirtualMachinesRes.class)); + } + convert.setData(data); return Result.successResult(convert); } diff --git a/torrent-be/src/main/java/com/unisinsight/torrent/controller/DeviceController.java b/torrent-be/src/main/java/com/unisinsight/torrent/controller/DeviceController.java new file mode 100644 index 0000000..725f869 --- /dev/null +++ b/torrent-be/src/main/java/com/unisinsight/torrent/controller/DeviceController.java @@ -0,0 +1,37 @@ +package com.unisinsight.torrent.controller; + +import com.unisinsight.torrent.util.ImageVirtualUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@RestController +@Slf4j +@RequestMapping("/vdi/device") +@Api("终端") +public class DeviceController { + + @GetMapping("/start") + @ApiOperation(value = "终端开机") + public boolean start(@RequestParam("macAddr") String macAddr) { + try { + Process exec = Runtime.getRuntime().exec(" wakeonlan " + macAddr); + boolean b = exec.waitFor(2000, TimeUnit.MILLISECONDS); + return exec.exitValue() == 0; + + } catch (IOException | InterruptedException e) { + log.error("调用开机命令失败,错误详情为:", e); + } + return false; + } + + +}