small fix, don't worry about it

This commit is contained in:
Tomas Dvorak
2026-04-10 12:02:36 +02:00
parent 08bd0c6e5c
commit 08cb5754f3
638 changed files with 57332 additions and 34706 deletions
-480
View File
@@ -1,480 +0,0 @@
package api
import (
"net/http"
"strconv"
"containr/internal/proxmox"
"github.com/gin-gonic/gin"
)
// ProxmoxHandler handles Proxmox-related API endpoints
type ProxmoxHandler struct {
service *proxmox.Service
}
// NewProxmoxHandler creates a new Proxmox handler
func NewProxmoxHandler(service *proxmox.Service) *ProxmoxHandler {
return &ProxmoxHandler{
service: service,
}
}
// RegisterProxmoxRoutes registers Proxmox API routes
func RegisterProxmoxRoutes(router *gin.Engine, service *proxmox.Service) {
handler := NewProxmoxHandler(service)
proxmox := router.Group("/api/proxmox")
{
// Cluster and node management
proxmox.GET("/cluster/status", handler.getClusterStatus)
proxmox.GET("/nodes", handler.getNodes)
proxmox.GET("/nodes/:nodeName/stats", handler.getNodeStats)
proxmox.GET("/nodes/:nodeName/templates", handler.getTemplates)
// VM management
proxmox.GET("/vms", handler.getAllVMs)
proxmox.GET("/vms/:vmid/status", handler.getVMStatus)
proxmox.POST("/vms", handler.createVM)
proxmox.POST("/vms/:vmid/start", handler.startVM)
proxmox.POST("/vms/:vmid/stop", handler.stopVM)
proxmox.DELETE("/vms/:vmid", handler.deleteVM)
// Container management
proxmox.GET("/containers", handler.getAllContainers)
proxmox.POST("/containers", handler.createContainer)
proxmox.POST("/containers/:vmid/start", handler.startContainer)
proxmox.POST("/containers/:vmid/stop", handler.stopContainer)
proxmox.DELETE("/containers/:vmid", handler.deleteContainer)
// Resource management
proxmox.GET("/resources/usage", handler.getResourceUsage)
proxmox.GET("/health", handler.healthCheck)
}
}
// getClusterStatus returns the overall cluster status
func (h *ProxmoxHandler) getClusterStatus(c *gin.Context) {
status, err := h.service.GetClusterStatus()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": status})
}
// getNodes returns all nodes in the cluster
func (h *ProxmoxHandler) getNodes(c *gin.Context) {
nodes, err := h.service.GetAllNodes()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": nodes})
}
// getNodeStats returns detailed statistics for a specific node
func (h *ProxmoxHandler) getNodeStats(c *gin.Context) {
nodeName := c.Param("nodeName")
stats, err := h.service.GetNodeStats(nodeName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": stats})
}
// getTemplates returns available VM and container templates
func (h *ProxmoxHandler) getTemplates(c *gin.Context) {
nodeName := c.Param("nodeName")
templates, err := h.service.GetAvailableTemplates(nodeName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": templates})
}
// getAllVMs returns all VMs across all nodes
func (h *ProxmoxHandler) getAllVMs(c *gin.Context) {
vms, err := h.service.GetAllVMs()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": vms})
}
// getVMStatus returns the status of a specific VM
func (h *ProxmoxHandler) getVMStatus(c *gin.Context) {
vmidStr := c.Param("vmid")
vmid, err := strconv.Atoi(vmidStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid VM ID"})
return
}
// For now, we'll need to determine the node - this could be improved
// by maintaining a VM-to-node mapping
nodes, err := h.service.GetAllNodes()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Try each node until we find the VM
for _, node := range nodes {
if node.Status == "online" {
status, err := h.service.GetInstanceStatus(node.Node, vmid, "qemu")
if err == nil {
c.JSON(http.StatusOK, gin.H{"data": status})
return
}
}
}
c.JSON(http.StatusNotFound, gin.H{"error": "VM not found"})
}
// createVM creates a new VM
func (h *ProxmoxHandler) createVM(c *gin.Context) {
var config proxmox.ServiceVMConfig
if err := c.ShouldBindJSON(&config); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// For now, use the first available online node
// In a production system, you'd want smarter node selection
nodes, err := h.service.GetAllNodes()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var targetNode string
for _, node := range nodes {
if node.Status == "online" {
targetNode = node.Node
break
}
}
if targetNode == "" {
c.JSON(http.StatusInternalServerError, gin.H{"error": "No online nodes available"})
return
}
vm, err := h.service.CreateServiceVM(targetNode, config)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"data": vm})
}
// startVM starts a VM
func (h *ProxmoxHandler) startVM(c *gin.Context) {
vmidStr := c.Param("vmid")
vmid, err := strconv.Atoi(vmidStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid VM ID"})
return
}
// Find which node the VM is on
vms, err := h.service.GetAllVMs()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var nodeName string
for _, vm := range vms {
if vm.VMID == vmid {
nodeName = vm.Node
break
}
}
if nodeName == "" {
c.JSON(http.StatusNotFound, gin.H{"error": "VM not found"})
return
}
err = h.service.StartInstance(nodeName, vmid, "qemu")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "VM started successfully"})
}
// stopVM stops a VM
func (h *ProxmoxHandler) stopVM(c *gin.Context) {
vmidStr := c.Param("vmid")
vmid, err := strconv.Atoi(vmidStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid VM ID"})
return
}
// Find which node the VM is on
vms, err := h.service.GetAllVMs()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var nodeName string
for _, vm := range vms {
if vm.VMID == vmid {
nodeName = vm.Node
break
}
}
if nodeName == "" {
c.JSON(http.StatusNotFound, gin.H{"error": "VM not found"})
return
}
err = h.service.StopInstance(nodeName, vmid, "qemu")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "VM stopped successfully"})
}
// deleteVM deletes a VM
func (h *ProxmoxHandler) deleteVM(c *gin.Context) {
vmidStr := c.Param("vmid")
vmid, err := strconv.Atoi(vmidStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid VM ID"})
return
}
// Find which node the VM is on
vms, err := h.service.GetAllVMs()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var nodeName string
for _, vm := range vms {
if vm.VMID == vmid {
nodeName = vm.Node
break
}
}
if nodeName == "" {
c.JSON(http.StatusNotFound, gin.H{"error": "VM not found"})
return
}
err = h.service.DeleteInstance(nodeName, vmid, "qemu")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "VM deleted successfully"})
}
// getAllContainers returns all containers across all nodes
func (h *ProxmoxHandler) getAllContainers(c *gin.Context) {
containers, err := h.service.GetAllContainers()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": containers})
}
// createContainer creates a new container
func (h *ProxmoxHandler) createContainer(c *gin.Context) {
var config proxmox.ServiceContainerConfig
if err := c.ShouldBindJSON(&config); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// For now, use the first available online node
nodes, err := h.service.GetAllNodes()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var targetNode string
for _, node := range nodes {
if node.Status == "online" {
targetNode = node.Node
break
}
}
if targetNode == "" {
c.JSON(http.StatusInternalServerError, gin.H{"error": "No online nodes available"})
return
}
container, err := h.service.CreateServiceContainer(targetNode, config)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"data": container})
}
// startContainer starts a container
func (h *ProxmoxHandler) startContainer(c *gin.Context) {
vmidStr := c.Param("vmid")
vmid, err := strconv.Atoi(vmidStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid container ID"})
return
}
// Find which node the container is on
containers, err := h.service.GetAllContainers()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var nodeName string
for _, container := range containers {
if container.VMID == vmid {
nodeName = container.Node
break
}
}
if nodeName == "" {
c.JSON(http.StatusNotFound, gin.H{"error": "Container not found"})
return
}
err = h.service.StartInstance(nodeName, vmid, "lxc")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Container started successfully"})
}
// stopContainer stops a container
func (h *ProxmoxHandler) stopContainer(c *gin.Context) {
vmidStr := c.Param("vmid")
vmid, err := strconv.Atoi(vmidStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid container ID"})
return
}
// Find which node the container is on
containers, err := h.service.GetAllContainers()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var nodeName string
for _, container := range containers {
if container.VMID == vmid {
nodeName = container.Node
break
}
}
if nodeName == "" {
c.JSON(http.StatusNotFound, gin.H{"error": "Container not found"})
return
}
err = h.service.StopInstance(nodeName, vmid, "lxc")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Container stopped successfully"})
}
// deleteContainer deletes a container
func (h *ProxmoxHandler) deleteContainer(c *gin.Context) {
vmidStr := c.Param("vmid")
vmid, err := strconv.Atoi(vmidStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid container ID"})
return
}
// Find which node the container is on
containers, err := h.service.GetAllContainers()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var nodeName string
for _, container := range containers {
if container.VMID == vmid {
nodeName = container.Node
break
}
}
if nodeName == "" {
c.JSON(http.StatusNotFound, gin.H{"error": "Container not found"})
return
}
err = h.service.DeleteInstance(nodeName, vmid, "lxc")
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Container deleted successfully"})
}
// getResourceUsage returns resource usage across the cluster
func (h *ProxmoxHandler) getResourceUsage(c *gin.Context) {
usage, err := h.service.GetResourceUsage()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": usage})
}
// healthCheck validates the connection to Proxmox
func (h *ProxmoxHandler) healthCheck(c *gin.Context) {
err := h.service.ValidateConnection()
if err != nil {
c.JSON(http.StatusServiceUnavailable, gin.H{
"status": "unhealthy",
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"status": "healthy",
"message": "Proxmox connection is working",
})
}