diff --git a/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java b/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java index 221066f..e85dced 100644 --- a/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java +++ b/src/main/java/com/kamco/cd/training/filemanager/FileManagerApiController.java @@ -233,4 +233,27 @@ public class FileManagerApiController { fileManagerService.getModelsExecutionStatus(); return ApiResponseDto.ok(response); } + + @Operation( + summary = "저장공간 정보 조회", + description = + "/home/kcomu/data 경로의 사용 중인 용량, 전체 디스크 용량, 남은 저장공간을 조회합니다. " + + "파라미터 없이 호출하면 자동으로 /home/kcomu/data 경로 정보를 반환합니다.") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + schema = @Schema(implementation = FileManagerDto.StorageSpaceRes.class))), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/storage-space") + public ApiResponseDto getStorageSpaceInfo() { + + FileManagerDto.StorageSpaceRes response = fileManagerService.getStorageSpaceInfo(); + return ApiResponseDto.ok(response); + } } diff --git a/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java b/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java index ee21b9d..607b171 100644 --- a/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java +++ b/src/main/java/com/kamco/cd/training/filemanager/dto/FileManagerDto.java @@ -232,4 +232,47 @@ public class FileManagerDto { @Schema(description = "현재 실행 중인 모델 개수", example = "2") private Integer runningCount; } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Schema(description = "저장공간 정보 응답 (남은 공간 포함)") + public static class StorageSpaceRes { + @Schema(description = "디렉토리 경로", example = "/home/kcomu/data") + private String directoryPath; + + @Schema(description = "파일 개수", example = "1234") + private Integer fileCount; + + @Schema(description = "디렉토리 개수", example = "56") + private Integer directoryCount; + + @Schema(description = "사용 중인 용량 (bytes)", example = "10485760000") + private Long usedSize; + + @Schema(description = "사용 중인 용량 (읽기 쉬운 형식)", example = "9.77 GB") + private String usedSizeFormatted; + + @Schema(description = "전체 디스크 용량 (bytes)", example = "1000000000000") + private Long totalDiskSpace; + + @Schema(description = "전체 디스크 용량 (읽기 쉬운 형식)", example = "931.32 GB") + private String totalDiskSpaceFormatted; + + @Schema(description = "남은 저장공간 (bytes)", example = "500000000000") + private Long freeSpace; + + @Schema(description = "남은 저장공간 (읽기 쉬운 형식)", example = "465.66 GB") + private String freeSpaceFormatted; + + @Schema(description = "사용 가능한 공간 (bytes)", example = "480000000000") + private Long usableSpace; + + @Schema(description = "사용 가능한 공간 (읽기 쉬운 형식)", example = "447.03 GB") + private String usableSpaceFormatted; + + @Schema(description = "디스크 사용률 (%)", example = "50.5") + private Double usagePercentage; + } } diff --git a/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java b/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java index d799174..708933b 100644 --- a/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java +++ b/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java @@ -258,15 +258,25 @@ public class FileManagerService { * @return 모델 파일 경로 및 파일 목록 */ public FileManagerDto.ModelFilePathRes getModelFilePath(UUID modelUuid) { - // tb_model_master 테이블에서 모델 존재 여부 확인 - modelMngRepository - .findByUuid(modelUuid) - .orElseThrow(() -> new IllegalArgumentException("모델을 찾을 수 없습니다: " + modelUuid)); + // tb_model_master 테이블에서 모델 조회 + ModelMasterEntity model = + modelMngRepository + .findByUuid(modelUuid) + .orElseThrow(() -> new IllegalArgumentException("모델을 찾을 수 없습니다: " + modelUuid)); - // request_path: symbolic_link_dir + model_uuid - String requestPath = symbolicLinkDir + "/" + modelUuid; + // request_path: tb_model_master.request_path 컬럼 값 사용 + // request_path 컬럼에는 'AE366F3076504FACBF12106986202AB5' 형태의 값이 저장되어 있음 + String requestPathFromDb = model.getRequestPath(); + String requestPath; + if (requestPathFromDb != null && !requestPathFromDb.isEmpty()) { + // DB에 저장된 값이 있으면 symbolic_link_dir + request_path 조합 + requestPath = symbolicLinkDir + "/" + requestPathFromDb; + } else { + // 없으면 기본값: symbolic_link_dir + model_uuid + requestPath = symbolicLinkDir + "/" + modelUuid; + } - // response_path: response_dir + model_uuid + // response_path: response_dir + model_uuid (UUID 사용) String responsePath = responseDir + "/" + modelUuid; // 파일 목록 조회 @@ -474,4 +484,89 @@ public class FileManagerService { return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0)); } } + + /** + * 저장공간 정보 조회 (남은 공간 포함) 고정 경로: /home/kcomu/data + * + * @return 저장공간 정보 (사용량, 남은 공간, 디스크 용량) + */ + public FileManagerDto.StorageSpaceRes getStorageSpaceInfo() { + // 고정 경로: /home/kcomu/data + String directoryPath = "/home/kcomu/data"; + + Path directory = Paths.get(directoryPath); + if (!Files.exists(directory)) { + throw new IllegalArgumentException("디렉토리가 존재하지 않습니다: " + directoryPath); + } + + if (!Files.isDirectory(directory)) { + throw new IllegalArgumentException("디렉토리 경로가 아닙니다: " + directoryPath); + } + + // 디렉토리 사용량 계산 (재귀적으로 모든 파일 크기 합산) + final long[] usedSize = {0}; + final int[] fileCount = {0}; + final int[] directoryCount = {0}; + + try { + Files.walkFileTree( + directory, + new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + usedSize[0] += attrs.size(); + fileCount[0]++; + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (!dir.equals(directory)) { + directoryCount[0]++; + } + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + log.error("디렉토리 용량 계산 중 오류 발생: {}", directoryPath, e); + throw new RuntimeException("디렉토리 용량 계산에 실패했습니다: " + e.getMessage()); + } + + // 디스크 공간 정보 조회 (FileStore 사용) + long totalDiskSpace = 0; + long freeSpace = 0; + long usableSpace = 0; + double usagePercentage = 0.0; + + try { + java.nio.file.FileStore fileStore = Files.getFileStore(directory); + totalDiskSpace = fileStore.getTotalSpace(); // 전체 디스크 용량 + freeSpace = fileStore.getUnallocatedSpace(); // 남은 저장공간 (할당되지 않은 공간) + usableSpace = fileStore.getUsableSpace(); // 사용 가능한 공간 (실제 사용 가능) + + // 디스크 사용률 계산 + if (totalDiskSpace > 0) { + long usedDiskSpace = totalDiskSpace - freeSpace; + usagePercentage = (usedDiskSpace * 100.0) / totalDiskSpace; + } + } catch (IOException e) { + log.error("디스크 공간 정보 조회 중 오류 발생: {}", directoryPath, e); + // 디스크 정보 조회 실패 시에도 디렉토리 용량은 반환 + } + + return FileManagerDto.StorageSpaceRes.builder() + .directoryPath(directoryPath) + .fileCount(fileCount[0]) + .directoryCount(directoryCount[0]) + .usedSize(usedSize[0]) + .usedSizeFormatted(formatFileSize(usedSize[0])) + .totalDiskSpace(totalDiskSpace) + .totalDiskSpaceFormatted(formatFileSize(totalDiskSpace)) + .freeSpace(freeSpace) + .freeSpaceFormatted(formatFileSize(freeSpace)) + .usableSpace(usableSpace) + .usableSpaceFormatted(formatFileSize(usableSpace)) + .usagePercentage(Math.round(usagePercentage * 100.0) / 100.0) + .build(); + } }