feat(vm): 添加虚拟机快照功能
- 新增快照列表、创建快照、删除快照和还原快照的接口和实现 - 增加与外部 API 的交互,实现快照相关操作 - 新增快照操作相关的请求和响应模型master
parent
8856817b64
commit
5511401e40
|
|
@ -3,8 +3,9 @@ package com.unisinsight.project.controller;
|
||||||
|
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.unisinsight.project.entity.req.DeleteIdReq;
|
import com.unisinsight.project.entity.req.DeleteIdReq;
|
||||||
import com.unisinsight.project.entity.req.ImageDesktopReq;
|
|
||||||
import com.unisinsight.project.entity.req.ImageVirtualMachinesReq;
|
import com.unisinsight.project.entity.req.ImageVirtualMachinesReq;
|
||||||
|
import com.unisinsight.project.entity.req.SnapShotCreateReq;
|
||||||
|
import com.unisinsight.project.entity.req.SnapShotReq;
|
||||||
import com.unisinsight.project.entity.res.ImageVirtualMachinesRes;
|
import com.unisinsight.project.entity.res.ImageVirtualMachinesRes;
|
||||||
import com.unisinsight.project.entity.res.PageResult;
|
import com.unisinsight.project.entity.res.PageResult;
|
||||||
import com.unisinsight.project.exception.BaseErrorCode;
|
import com.unisinsight.project.exception.BaseErrorCode;
|
||||||
|
|
@ -158,6 +159,34 @@ public class ImageVirtualMachinesController {
|
||||||
log.info("获取VNC信息请求参数为:{}", vmName);
|
log.info("获取VNC信息请求参数为:{}", vmName);
|
||||||
return service.getVncData(vmName);
|
return service.getVncData(vmName);
|
||||||
}
|
}
|
||||||
|
@ApiOperation(value = "获取快照列表")
|
||||||
|
@GetMapping("/snapshot/list/{vmName}")
|
||||||
|
public Result<?> snapshotList(@PathVariable("vmName") String vmName) {
|
||||||
|
|
||||||
|
log.info("获取快照列表请求参数为:{}", vmName);
|
||||||
|
return service.snapshotList(vmName);
|
||||||
|
}
|
||||||
|
@ApiOperation(value = "创建快照")
|
||||||
|
@PostMapping("/snapshot/create")
|
||||||
|
public Result<?> createSnapshot(@RequestBody SnapShotCreateReq snapShotCreateReq) {
|
||||||
|
|
||||||
|
log.info("创建快照请求参数为:{}", snapShotCreateReq);
|
||||||
|
return service.createSnapshot(snapShotCreateReq);
|
||||||
|
}
|
||||||
|
@ApiOperation(value = "删除快照")
|
||||||
|
@PostMapping("/snapshot/delete")
|
||||||
|
public Result<?> deleteSnapshot(@RequestBody SnapShotReq snapShotCreateReq) {
|
||||||
|
|
||||||
|
log.info("删除快照请求参数为:{}", snapShotCreateReq);
|
||||||
|
return service.deleteSnapshot(snapShotCreateReq);
|
||||||
|
}
|
||||||
|
@ApiOperation(value = "还原快照")
|
||||||
|
@GetMapping("/snapshot/revert")
|
||||||
|
public Result<?> revertSnapshot(@RequestBody SnapShotReq snapShotCreateReq) {
|
||||||
|
|
||||||
|
log.info("还原快照请求参数为:{}", snapShotCreateReq);
|
||||||
|
return service.revertSnapshot(snapShotCreateReq);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.unisinsight.project.entity.req;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : ch
|
||||||
|
* @version : 1.0
|
||||||
|
* @ClassName : SnapShotCreateReq
|
||||||
|
* @Description :
|
||||||
|
* @DATE : Created in 16:48 2025/9/9
|
||||||
|
* <pre> Copyright: Copyright(c) 2025 </pre>
|
||||||
|
* <pre> Company : 紫光汇智信息技术有限公司 </pre>
|
||||||
|
* Modification History:
|
||||||
|
* Date Author Version Discription
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* 2025/09/09 ch 1.0 Why & What is modified: <修改原因描述> *
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SnapShotCreateReq {
|
||||||
|
@JsonProperty("vm_name")
|
||||||
|
private String vmName;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.unisinsight.project.entity.req;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : ch
|
||||||
|
* @version : 1.0
|
||||||
|
* @ClassName : SnapShotCreateReq
|
||||||
|
* @Description :
|
||||||
|
* @DATE : Created in 16:48 2025/9/9
|
||||||
|
* <pre> Copyright: Copyright(c) 2025 </pre>
|
||||||
|
* <pre> Company : 紫光汇智信息技术有限公司 </pre>
|
||||||
|
* Modification History:
|
||||||
|
* Date Author Version Discription
|
||||||
|
* --------------------------------------------------------------------------
|
||||||
|
* 2025/09/09 ch 1.0 Why & What is modified: <修改原因描述> *
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SnapShotReq {
|
||||||
|
@JsonProperty("vm_name")
|
||||||
|
private String vmName;
|
||||||
|
@JsonProperty("snapshot_name")
|
||||||
|
private String snapshotName;
|
||||||
|
}
|
||||||
|
|
@ -93,5 +93,17 @@ public interface ExternalApiClient {
|
||||||
ApiResponse<List<BridgeInterfaceDTO>> getBridgeInterfaces();
|
ApiResponse<List<BridgeInterfaceDTO>> getBridgeInterfaces();
|
||||||
@GetMapping("/api/v1/vm/{vmName}/vnc")
|
@GetMapping("/api/v1/vm/{vmName}/vnc")
|
||||||
ApiResponse<VncData> getVncData(@PathVariable("vmName") String vmName);
|
ApiResponse<VncData> getVncData(@PathVariable("vmName") String vmName);
|
||||||
|
@GetMapping("/api/v1/snapshot/list/{vm_name}")
|
||||||
|
ApiResponse<SnapshotsResponseDTO> snapshotList(@PathVariable("vm_name") String vmName);
|
||||||
|
@PostMapping("/api/v1/snapshot/create/{vm_name}")
|
||||||
|
ApiResponse createSnapshot(@PathVariable("vm_name") String vmName,@RequestBody SnapShotCreateReq snapshotCreateReq);
|
||||||
|
@PostMapping("/api/v1/snapshot/revert/{vm_name}/{snapshot_name}")
|
||||||
|
ApiResponse revertSnapshot(@PathVariable("vm_name") String vmName,@PathVariable("snapshot_name") String snapshotName);
|
||||||
|
@DeleteMapping("/api/v1/snapshot/delete/{vm_name}/{snapshot_name}")
|
||||||
|
ApiResponse deleteSnapshot(@PathVariable("vm_name") String vmName,@PathVariable("snapshot_name") String snapshotName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ package com.unisinsight.project.service;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.unisinsight.project.entity.dao.ImageVirtualMachines;
|
import com.unisinsight.project.entity.dao.ImageVirtualMachines;
|
||||||
import com.unisinsight.project.entity.req.DeleteIdReq;
|
import com.unisinsight.project.entity.req.DeleteIdReq;
|
||||||
import com.unisinsight.project.entity.req.ImageDesktopReq;
|
|
||||||
import com.unisinsight.project.entity.req.ImageVirtualMachinesReq;
|
import com.unisinsight.project.entity.req.ImageVirtualMachinesReq;
|
||||||
|
import com.unisinsight.project.entity.req.SnapShotCreateReq;
|
||||||
|
import com.unisinsight.project.entity.req.SnapShotReq;
|
||||||
import com.unisinsight.project.entity.res.ImageVirtualMachinesRes;
|
import com.unisinsight.project.entity.res.ImageVirtualMachinesRes;
|
||||||
import com.unisinsight.project.entity.res.PageResult;
|
import com.unisinsight.project.entity.res.PageResult;
|
||||||
import com.unisinsight.project.exception.Result;
|
import com.unisinsight.project.exception.Result;
|
||||||
|
|
@ -63,5 +64,13 @@ public interface ImageVirtualMachinesService extends IService<ImageVirtualMachin
|
||||||
Result<?> attachIso(ImageVirtualMachinesReq req);
|
Result<?> attachIso(ImageVirtualMachinesReq req);
|
||||||
|
|
||||||
Result<?> getVncData(String vmName);
|
Result<?> getVncData(String vmName);
|
||||||
|
|
||||||
|
Result<?> snapshotList(String vmName);
|
||||||
|
|
||||||
|
Result<?> createSnapshot(SnapShotCreateReq snapShotCreateReq);
|
||||||
|
|
||||||
|
Result<?> deleteSnapshot(SnapShotReq snapShotCreateReq);
|
||||||
|
|
||||||
|
Result<?> revertSnapshot(SnapShotReq snapShotCreateReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,9 @@ public class ClientServiceImpl implements ClientService {
|
||||||
if (StringUtils.isNotBlank(e.getDesktopName())) {
|
if (StringUtils.isNotBlank(e.getDesktopName())) {
|
||||||
map.put("name", e.getDesktopName()+"."+e.getDesktopType());
|
map.put("name", e.getDesktopName()+"."+e.getDesktopType());
|
||||||
}
|
}
|
||||||
|
if (StringUtils.isNotBlank(e.getCloneName())) {
|
||||||
|
map.put("clone_name", e.getCloneName());
|
||||||
|
}
|
||||||
if (StringUtils.isNotBlank(e.getFileSize())) {
|
if (StringUtils.isNotBlank(e.getFileSize())) {
|
||||||
map.put("file_size", StringUtils.isNotEmpty(e.getFileSize()) ? Long.parseLong(e.getFileSize()) : 0L);
|
map.put("file_size", StringUtils.isNotEmpty(e.getFileSize()) ? Long.parseLong(e.getFileSize()) : 0L);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.unisinsight.project.entity.dao.*;
|
import com.unisinsight.project.entity.dao.*;
|
||||||
import com.unisinsight.project.entity.dto.ApiResponse;
|
import com.unisinsight.project.entity.dto.ApiResponse;
|
||||||
|
import com.unisinsight.project.entity.dto.SnapshotsResponseDTO;
|
||||||
import com.unisinsight.project.entity.dto.VmInfoDTO;
|
import com.unisinsight.project.entity.dto.VmInfoDTO;
|
||||||
import com.unisinsight.project.entity.req.*;
|
import com.unisinsight.project.entity.req.*;
|
||||||
import com.unisinsight.project.entity.res.ImageStatusRes;
|
import com.unisinsight.project.entity.res.ImageStatusRes;
|
||||||
|
|
@ -435,7 +436,7 @@ public class ImageVirtualMachinesServiceImpl extends ServiceImpl<ImageVirtualMac
|
||||||
updateWrapper.set(ImageDesktop::getPublishTime, DateUtil.date());
|
updateWrapper.set(ImageDesktop::getPublishTime, DateUtil.date());
|
||||||
//转化bt
|
//转化bt
|
||||||
String fileNamewithSuffixes = detFilePath.substring(detFilePath.lastIndexOf(fileName));
|
String fileNamewithSuffixes = detFilePath.substring(detFilePath.lastIndexOf(fileName));
|
||||||
externalTorrentClient.startBt(detFilePath, "/var/lib/vdi/test/" + fileNamewithSuffixes + ".torrent");
|
externalTorrentClient.startBt(detFilePath, "/vms/iso/" + fileNamewithSuffixes + ".torrent");
|
||||||
updateWrapper.set(ImageDesktop::getBtPath, torrentUrl + "/api/vdi/file/down/" + fileNamewithSuffixes + ".torrent");
|
updateWrapper.set(ImageDesktop::getBtPath, torrentUrl + "/api/vdi/file/down/" + fileNamewithSuffixes + ".torrent");
|
||||||
imageDesktopService.update(updateWrapper);
|
imageDesktopService.update(updateWrapper);
|
||||||
System.out.println("任务已完成,执行特有操作...");
|
System.out.println("任务已完成,执行特有操作...");
|
||||||
|
|
@ -589,5 +590,44 @@ public class ImageVirtualMachinesServiceImpl extends ServiceImpl<ImageVirtualMac
|
||||||
return Result.errorResultMessage(BaseErrorCode.HTTP_ERROR_CODE_500, vncData.getMessage());
|
return Result.errorResultMessage(BaseErrorCode.HTTP_ERROR_CODE_500, vncData.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<?> snapshotList(String vmName) {
|
||||||
|
ApiResponse<SnapshotsResponseDTO> response = externalApiClient.snapshotList(vmName);
|
||||||
|
if ( !"200".equals(response.getCode()) ||response.getData() == null) {
|
||||||
|
return Result.errorResult(BaseErrorCode.HTTP_ERROR_CODE_500, response.getMessage());
|
||||||
|
}
|
||||||
|
PageResult<SnapshotsResponseDTO.SnapshotItem> pageResult = new PageResult<>();
|
||||||
|
SnapshotsResponseDTO data = response.getData();
|
||||||
|
pageResult.setPageNum(data.getPage());
|
||||||
|
pageResult.setTotal(data.getTotal());
|
||||||
|
pageResult.setPageSize(data.getPage_size());
|
||||||
|
pageResult.setData(data.getItems());
|
||||||
|
pageResult.setTotal(data.getTotal());
|
||||||
|
return Result.successResult(pageResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<?> createSnapshot(SnapShotCreateReq snapShotCreateReq) {
|
||||||
|
externalApiClient.createSnapshot(snapShotCreateReq.getVmName(), snapShotCreateReq);
|
||||||
|
return Result.successResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<?> deleteSnapshot(SnapShotReq snapShotCreateReq) {
|
||||||
|
if (StringUtils.isEmpty(snapShotCreateReq.getVmName())|| StringUtils.isEmpty(snapShotCreateReq.getSnapshotName())){
|
||||||
|
return Result.errorResult(BaseErrorCode.HTTP_ERROR_CODE_500, "参数错误");
|
||||||
|
}
|
||||||
|
ApiResponse apiResponse = externalApiClient.deleteSnapshot(snapShotCreateReq.getVmName(), snapShotCreateReq.getSnapshotName());
|
||||||
|
return Result.successResult(apiResponse.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<?> revertSnapshot(SnapShotReq snapShotCreateReq) {
|
||||||
|
if (StringUtils.isEmpty(snapShotCreateReq.getVmName())|| StringUtils.isEmpty(snapShotCreateReq.getSnapshotName())){
|
||||||
|
return Result.errorResult(BaseErrorCode.HTTP_ERROR_CODE_500, "参数错误");
|
||||||
|
}
|
||||||
|
ApiResponse apiResponse = externalApiClient.revertSnapshot(snapShotCreateReq.getVmName(), snapShotCreateReq.getSnapshotName());
|
||||||
|
return Result.successResult(apiResponse.getData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue