feat(image): 添加定时任务检查虚拟机克隆进度并更新桌面镜像状态
- 在 ImageVirtualMachinesServiceImpl 中添加进度检查任务- 在 Application 中启用定时任务调度器 - 在 ClientOperateServiceImpl 中添加终端开机功能 - 新增 DeviceController 用于处理终端开机请求 - 更新 ExternalTorrentClient接口,添加新的远程调用方法master
parent
24deac28ae
commit
598acecab5
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ public class ImageDesktop extends Model<ImageDesktop> {
|
|||
|
||||
|
||||
@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<ImageDesktop> {
|
|||
@TableField(value = "description")
|
||||
@ApiModelProperty("描述")
|
||||
private String description;
|
||||
@TableField(value = "file_size")
|
||||
@ApiModelProperty("文件大小")
|
||||
private String fileSize;
|
||||
/**
|
||||
* 发布时间
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class ImageDesktopReq {
|
|||
**/
|
||||
@JsonProperty("desktop_type")
|
||||
@ApiModelProperty("桌面类型:1:VHD 2:VHDX 3:QCOW2")
|
||||
private Integer desktopType;
|
||||
private String desktopType;
|
||||
/**
|
||||
* 父镜像id
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<ImageDesktopMapper, ImageDesktop> implements ImageDesktopService {
|
||||
@Resource
|
||||
private ImageDesktopMapper mapper;
|
||||
@Resource
|
||||
private ImageVirtualMachinesMapper imageVirtualMachinesMapper;
|
||||
|
||||
@Override
|
||||
public Result<PageResult<ImageDesktopRes>> selectPage(ImageDesktopReq imageDesktopReq) {
|
||||
|
|
@ -50,6 +60,15 @@ public class ImageDesktopServiceImpl extends ServiceImpl<ImageDesktopMapper, Ima
|
|||
} else {
|
||||
PageResult<ImageDesktopRes> convert = PageResult.convertIPage(imageDesktopPage, ImageDesktopRes.class);
|
||||
List<ImageDesktopRes> data = convert.getData();
|
||||
List<Integer> imageVirtualIdList = data.stream().map(ImageDesktopRes::getImageVirtualId).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
LambdaQueryWrapper<ImageVirtualMachines> imageVirtualMachinesLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
imageVirtualMachinesLambdaQueryWrapper.in(ImageVirtualMachines::getId, imageVirtualIdList);
|
||||
List<ImageVirtualMachines> imageVirtualMachines = imageVirtualMachinesMapper.selectList(imageVirtualMachinesLambdaQueryWrapper);
|
||||
Map<Long, ImageVirtualMachines> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue