mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-19 23:11:25 +02:00
feat(proxmox): add LXC container control endpoints
Add start, stop, and restart endpoints for LXC containers via the Proxmox API: - POST /api/v1/proxmox/lxc/:node/:vmid/start - POST /api/v1/proxmox/lxc/:node/:vmid/stop - POST /api/v1/proxmox/lxc/:node/:vmid/restart
This commit is contained in:
2
goutils
2
goutils
Submodule goutils updated: bc9e96ebf3...bcc4b498f8
@@ -149,6 +149,9 @@ func NewHandler(requireAuth bool) *gin.Engine {
|
|||||||
proxmox.GET("/journalctl/:node/:vmid", proxmoxApi.Journalctl)
|
proxmox.GET("/journalctl/:node/:vmid", proxmoxApi.Journalctl)
|
||||||
proxmox.GET("/journalctl/:node/:vmid/:service", proxmoxApi.Journalctl)
|
proxmox.GET("/journalctl/:node/:vmid/:service", proxmoxApi.Journalctl)
|
||||||
proxmox.GET("/stats/:node/:vmid", proxmoxApi.Stats)
|
proxmox.GET("/stats/:node/:vmid", proxmoxApi.Stats)
|
||||||
|
proxmox.POST("/lxc/:node/:vmid/start", proxmoxApi.Start)
|
||||||
|
proxmox.POST("/lxc/:node/:vmid/stop", proxmoxApi.Stop)
|
||||||
|
proxmox.POST("/lxc/:node/:vmid/restart", proxmoxApi.Restart)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -310,6 +310,168 @@
|
|||||||
"operationId": "journalctl"
|
"operationId": "journalctl"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/v1/proxmox/lxc/:node/:vmid/restart": {
|
||||||
|
"post": {
|
||||||
|
"description": "Restart LXC container by node and vmid",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"proxmox"
|
||||||
|
],
|
||||||
|
"summary": "Restart LXC container",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "node",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "vmid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/SuccessResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Node not found",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-id": "lxcRestart",
|
||||||
|
"operationId": "lxcRestart"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/proxmox/lxc/:node/:vmid/start": {
|
||||||
|
"post": {
|
||||||
|
"description": "Start LXC container by node and vmid",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"proxmox"
|
||||||
|
],
|
||||||
|
"summary": "Start LXC container",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "node",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "vmid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/SuccessResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Node not found",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-id": "lxcStart",
|
||||||
|
"operationId": "lxcStart"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/v1/proxmox/lxc/:node/:vmid/stop": {
|
||||||
|
"post": {
|
||||||
|
"description": "Stop LXC container by node and vmid",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"proxmox"
|
||||||
|
],
|
||||||
|
"summary": "Stop LXC container",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"name": "node",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"name": "vmid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/SuccessResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Invalid request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Node not found",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/ErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-id": "lxcStop",
|
||||||
|
"operationId": "lxcStop"
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/proxmox/stats/{node}/{vmid}": {
|
"/api/v1/proxmox/stats/{node}/{vmid}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Get proxmox stats in format of \"STATUS|CPU%%|MEM USAGE/LIMIT|MEM%%|NET I/O|BLOCK I/O\"",
|
"description": "Get proxmox stats in format of \"STATUS|CPU%%|MEM USAGE/LIMIT|MEM%%|NET I/O|BLOCK I/O\"",
|
||||||
|
|||||||
@@ -2183,6 +2183,111 @@ paths:
|
|||||||
- proxmox
|
- proxmox
|
||||||
- websocket
|
- websocket
|
||||||
x-id: journalctl
|
x-id: journalctl
|
||||||
|
/api/v1/proxmox/lxc/:node/:vmid/restart:
|
||||||
|
post:
|
||||||
|
description: Restart LXC container by node and vmid
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: node
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: path
|
||||||
|
name: vmid
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/SuccessResponse'
|
||||||
|
"400":
|
||||||
|
description: Invalid request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
"404":
|
||||||
|
description: Node not found
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
summary: Restart LXC container
|
||||||
|
tags:
|
||||||
|
- proxmox
|
||||||
|
x-id: lxcRestart
|
||||||
|
/api/v1/proxmox/lxc/:node/:vmid/start:
|
||||||
|
post:
|
||||||
|
description: Start LXC container by node and vmid
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: node
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: path
|
||||||
|
name: vmid
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/SuccessResponse'
|
||||||
|
"400":
|
||||||
|
description: Invalid request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
"404":
|
||||||
|
description: Node not found
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
summary: Start LXC container
|
||||||
|
tags:
|
||||||
|
- proxmox
|
||||||
|
x-id: lxcStart
|
||||||
|
/api/v1/proxmox/lxc/:node/:vmid/stop:
|
||||||
|
post:
|
||||||
|
description: Stop LXC container by node and vmid
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: node
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: path
|
||||||
|
name: vmid
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/SuccessResponse'
|
||||||
|
"400":
|
||||||
|
description: Invalid request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
"404":
|
||||||
|
description: Node not found
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ErrorResponse'
|
||||||
|
summary: Stop LXC container
|
||||||
|
tags:
|
||||||
|
- proxmox
|
||||||
|
x-id: lxcStop
|
||||||
/api/v1/proxmox/stats/{node}/{vmid}:
|
/api/v1/proxmox/stats/{node}/{vmid}:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|||||||
6
internal/api/v1/proxmox/common.go
Normal file
6
internal/api/v1/proxmox/common.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package proxmoxapi
|
||||||
|
|
||||||
|
type ActionRequest struct {
|
||||||
|
Node string `uri:"node" binding:"required"`
|
||||||
|
VMID int `uri:"vmid" binding:"required"`
|
||||||
|
}
|
||||||
42
internal/api/v1/proxmox/restart.go
Normal file
42
internal/api/v1/proxmox/restart.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package proxmoxapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/yusing/godoxy/internal/proxmox"
|
||||||
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @x-id "lxcRestart"
|
||||||
|
// @BasePath /api/v1
|
||||||
|
// @Summary Restart LXC container
|
||||||
|
// @Description Restart LXC container by node and vmid
|
||||||
|
// @Tags proxmox
|
||||||
|
// @Produce json
|
||||||
|
// @Param path path ActionRequest true "Request"
|
||||||
|
// @Success 200 {object} apitypes.SuccessResponse
|
||||||
|
// @Failure 400 {object} apitypes.ErrorResponse "Invalid request"
|
||||||
|
// @Failure 404 {object} apitypes.ErrorResponse "Node not found"
|
||||||
|
// @Failure 500 {object} apitypes.ErrorResponse
|
||||||
|
// @Router /api/v1/proxmox/lxc/:node/:vmid/restart [post]
|
||||||
|
func Restart(c *gin.Context) {
|
||||||
|
var req ActionRequest
|
||||||
|
if err := c.ShouldBindUri(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, apitypes.Error("invalid request", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
node, ok := proxmox.Nodes.Get(req.Node)
|
||||||
|
if !ok {
|
||||||
|
c.JSON(http.StatusNotFound, apitypes.Error("node not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.LXCAction(c.Request.Context(), req.VMID, proxmox.LXCReboot); err != nil {
|
||||||
|
c.Error(apitypes.InternalServerError(err, "failed to restart container"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, apitypes.Success("container restarted"))
|
||||||
|
}
|
||||||
42
internal/api/v1/proxmox/start.go
Normal file
42
internal/api/v1/proxmox/start.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package proxmoxapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/yusing/godoxy/internal/proxmox"
|
||||||
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @x-id "lxcStart"
|
||||||
|
// @BasePath /api/v1
|
||||||
|
// @Summary Start LXC container
|
||||||
|
// @Description Start LXC container by node and vmid
|
||||||
|
// @Tags proxmox
|
||||||
|
// @Produce json
|
||||||
|
// @Param path path ActionRequest true "Request"
|
||||||
|
// @Success 200 {object} apitypes.SuccessResponse
|
||||||
|
// @Failure 400 {object} apitypes.ErrorResponse "Invalid request"
|
||||||
|
// @Failure 404 {object} apitypes.ErrorResponse "Node not found"
|
||||||
|
// @Failure 500 {object} apitypes.ErrorResponse
|
||||||
|
// @Router /api/v1/proxmox/lxc/:node/:vmid/start [post]
|
||||||
|
func Start(c *gin.Context) {
|
||||||
|
var req ActionRequest
|
||||||
|
if err := c.ShouldBindUri(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, apitypes.Error("invalid request", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
node, ok := proxmox.Nodes.Get(req.Node)
|
||||||
|
if !ok {
|
||||||
|
c.JSON(http.StatusNotFound, apitypes.Error("node not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.LXCAction(c.Request.Context(), req.VMID, proxmox.LXCStart); err != nil {
|
||||||
|
c.Error(apitypes.InternalServerError(err, "failed to start container"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, apitypes.Success("container started"))
|
||||||
|
}
|
||||||
42
internal/api/v1/proxmox/stop.go
Normal file
42
internal/api/v1/proxmox/stop.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package proxmoxapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/yusing/godoxy/internal/proxmox"
|
||||||
|
apitypes "github.com/yusing/goutils/apitypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @x-id "lxcStop"
|
||||||
|
// @BasePath /api/v1
|
||||||
|
// @Summary Stop LXC container
|
||||||
|
// @Description Stop LXC container by node and vmid
|
||||||
|
// @Tags proxmox
|
||||||
|
// @Produce json
|
||||||
|
// @Param path path ActionRequest true "Request"
|
||||||
|
// @Success 200 {object} apitypes.SuccessResponse
|
||||||
|
// @Failure 400 {object} apitypes.ErrorResponse "Invalid request"
|
||||||
|
// @Failure 404 {object} apitypes.ErrorResponse "Node not found"
|
||||||
|
// @Failure 500 {object} apitypes.ErrorResponse
|
||||||
|
// @Router /api/v1/proxmox/lxc/:node/:vmid/stop [post]
|
||||||
|
func Stop(c *gin.Context) {
|
||||||
|
var req ActionRequest
|
||||||
|
if err := c.ShouldBindUri(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, apitypes.Error("invalid request", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
node, ok := proxmox.Nodes.Get(req.Node)
|
||||||
|
if !ok {
|
||||||
|
c.JSON(http.StatusNotFound, apitypes.Error("node not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := node.LXCAction(c.Request.Context(), req.VMID, proxmox.LXCShutdown); err != nil {
|
||||||
|
c.Error(apitypes.InternalServerError(err, "failed to stop container"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, apitypes.Success("container stopped"))
|
||||||
|
}
|
||||||
Submodule internal/go-proxmox updated: 38d75007b2...8560d07538
Reference in New Issue
Block a user