from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from typing import List from app.database import get_db from app.schemas.vm import VMInfo, VMListResponse, VMDetail, VMControlRequest, VMControlResponse from app.schemas.auth import CurrentUser from app.api.auth import get_current_user from app.services.proxmox_service import proxmox_service from app.models.vm import VMAccess from app.utils.exceptions import NotFoundError, PermissionDeniedError router = APIRouter() @router.get("/my", response_model=VMListResponse) async def get_my_vms( current_user: CurrentUser = Depends(get_current_user), db: Session = Depends(get_db) ): """ 내 VM 목록 조회 현재 사용자가 접근 가능한 VM 목록을 반환합니다. """ # Proxmox에서 모든 VM 가져오기 all_vms = await proxmox_service.get_all_vms() # 현재 사용자의 VMAccess 정보 조회 vm_accesses = db.query(VMAccess).filter( VMAccess.user_id == current_user.id, VMAccess.is_active == True ).all() # vm_id를 키로 하는 딕셔너리 생성 access_map = {access.vm_id: access for access in vm_accesses} vm_list = [] for vm in all_vms: vm_id = vm["vmid"] access = access_map.get(vm_id) # 권한이 없는 VM은 목록에서 제외 if not access: continue # VMAccess가 있으면 해당 정보 사용 vm_info = VMInfo( vm_id=vm_id, node=vm.get("node"), # cluster/resources returns 'node' type=vm.get("type", "qemu"), name=vm.get("name", "Unknown"), status=vm.get("status", "unknown"), ip_address=access.static_ip, # Static IP cpus=vm.get("maxcpu", 0), # cluster/resources uses maxcpu memory=vm.get("maxmem", 0) // (1024 * 1024), # bytes to MB memory_usage=vm.get("mem", 0) // (1024 * 1024) if vm.get("mem") else None, cpu_usage=vm.get("cpu", 0), can_start=access.can_start, can_stop=access.can_stop, can_reboot=access.can_reboot, can_connect=access.can_connect, rdp_username=access.rdp_username, rdp_password=access.rdp_password, rdp_port=access.rdp_port or 3389 ) vm_list.append(vm_info) return VMListResponse(total=len(vm_list), vms=vm_list) @router.get("/{vm_id}", response_model=VMDetail) async def get_vm_detail( vm_id: int, node: str, type: str = "qemu", current_user: CurrentUser = Depends(get_current_user) ): """ VM 상세 정보 조회 """ # VM 상태 조회 status = await proxmox_service.get_vm_status(node, vm_id, type) if not status: raise NotFoundError(f"VM {vm_id}를 찾을 수 없습니다") return VMDetail( vm_id=vm_id, node=node, type=type, name=status.get("name", "Unknown"), status=status.get("status", "unknown"), ip_address=None, # IP 조회 안 함 cpus=status.get("cpus", 0), memory=status.get("maxmem", 0) // (1024 * 1024), memory_usage=status.get("mem", 0) // (1024 * 1024) if status.get("mem") else None, cpu_usage=status.get("cpu", 0), uptime=status.get("uptime"), rdp_port=3389, has_guest_agent=False # Guest Agent 불필요 ) @router.post("/{vm_id}/start", response_model=VMControlResponse) async def start_vm( vm_id: int, node: str, type: str = "qemu", current_user: CurrentUser = Depends(get_current_user) ): """VM 시작""" success = await proxmox_service.start_vm(node, vm_id, type) return VMControlResponse( success=success, message="VM이 시작되었습니다" if success else "VM 시작에 실패했습니다", vm_id=vm_id, action="start" ) @router.post("/{vm_id}/stop", response_model=VMControlResponse) async def stop_vm( vm_id: int, node: str, type: str = "qemu", current_user: CurrentUser = Depends(get_current_user) ): """VM 종료""" success = await proxmox_service.stop_vm(node, vm_id, type) return VMControlResponse( success=success, message="VM이 종료되었습니다" if success else "VM 종료에 실패했습니다", vm_id=vm_id, action="stop" ) @router.post("/{vm_id}/reboot", response_model=VMControlResponse) async def reboot_vm( vm_id: int, node: str, type: str = "qemu", current_user: CurrentUser = Depends(get_current_user) ): """VM 재시작""" success = await proxmox_service.reboot_vm(node, vm_id, type) return VMControlResponse( success=success, message="VM이 재시작되었습니다" if success else "VM 재시작에 실패했습니다", vm_id=vm_id, action="reboot" )