mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-20 00:03:53 +01:00
feat(proxmox): support node-level routes and journalctl access
This change enables Proxmox node-level operations without requiring a specific
LXC container VMID.
**Features added:**
- New `/proxmox/journalctl/{node}` API endpoint for streaming node journalctl
- Route configuration support for Proxmox nodes (VMID = 0)
- `ReverseLookupNode` function for node discovery by hostname/IP/alias
- `NodeJournalctl` method for executing journalctl on nodes
**Behavior changes:**
- VMID parameter in journalctl endpoints is now optional
- Routes targeting nodes (without specific containers) are now valid
**Bug fixes:**
- Fixed error message variable reference in route validation
This commit is contained in:
@@ -146,6 +146,7 @@ func NewHandler(requireAuth bool) *gin.Engine {
|
||||
|
||||
proxmox := v1.Group("/proxmox")
|
||||
{
|
||||
proxmox.GET("/journalctl/:node", proxmoxApi.Journalctl)
|
||||
proxmox.GET("/journalctl/:node/:vmid", proxmoxApi.Journalctl)
|
||||
proxmox.GET("/journalctl/:node/:vmid/:service", proxmoxApi.Journalctl)
|
||||
proxmox.GET("/stats/:node/:vmid", proxmoxApi.Stats)
|
||||
|
||||
@@ -2077,9 +2077,9 @@
|
||||
"operationId": "uptime"
|
||||
}
|
||||
},
|
||||
"/proxmox/journalctl/{node}/{vmid}": {
|
||||
"/proxmox/journalctl/{node}": {
|
||||
"get": {
|
||||
"description": "Get journalctl output",
|
||||
"description": "Get journalctl output for node or LXC container. If vmid is not provided, streams node journalctl.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -2094,19 +2094,85 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Node name",
|
||||
"name": "node",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "vmid",
|
||||
"description": "Limit output lines (1-1000)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Journalctl output",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ErrorResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ErrorResponse"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Node not found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ErrorResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-id": "journalctl",
|
||||
"operationId": "journalctl"
|
||||
}
|
||||
},
|
||||
"/proxmox/journalctl/{node}/{vmid}": {
|
||||
"get": {
|
||||
"description": "Get journalctl output for node or LXC container. If vmid is not provided, streams node journalctl.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"proxmox",
|
||||
"websocket"
|
||||
],
|
||||
"summary": "Get journalctl output",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Node name",
|
||||
"name": "node",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "limit",
|
||||
"description": "Container VMID (optional - if not provided, streams node journalctl)",
|
||||
"name": "vmid",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Limit output lines (1-1000)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
@@ -2149,7 +2215,7 @@
|
||||
},
|
||||
"/proxmox/journalctl/{node}/{vmid}/{service}": {
|
||||
"get": {
|
||||
"description": "Get journalctl output",
|
||||
"description": "Get journalctl output for node or LXC container. If vmid is not provided, streams node journalctl.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -2164,24 +2230,26 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Node name",
|
||||
"name": "node",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Container VMID (optional - if not provided, streams node journalctl)",
|
||||
"name": "vmid",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Service name (e.g., 'pveproxy' for node, 'container@.service' format for LXC)",
|
||||
"name": "service",
|
||||
"in": "path"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "vmid",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "limit",
|
||||
"description": "Limit output lines (1-1000)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
|
||||
@@ -3361,21 +3361,67 @@ paths:
|
||||
- metrics
|
||||
- websocket
|
||||
x-id: uptime
|
||||
/proxmox/journalctl/{node}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get journalctl output for node or LXC container. If vmid is not
|
||||
provided, streams node journalctl.
|
||||
parameters:
|
||||
- description: Node name
|
||||
in: path
|
||||
name: node
|
||||
required: true
|
||||
type: string
|
||||
- description: Limit output lines (1-1000)
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Journalctl output
|
||||
schema:
|
||||
type: string
|
||||
"400":
|
||||
description: Invalid request
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
"403":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
"404":
|
||||
description: Node not found
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
summary: Get journalctl output
|
||||
tags:
|
||||
- proxmox
|
||||
- websocket
|
||||
x-id: journalctl
|
||||
/proxmox/journalctl/{node}/{vmid}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get journalctl output
|
||||
description: Get journalctl output for node or LXC container. If vmid is not
|
||||
provided, streams node journalctl.
|
||||
parameters:
|
||||
- in: path
|
||||
- description: Node name
|
||||
in: path
|
||||
name: node
|
||||
required: true
|
||||
type: string
|
||||
- in: path
|
||||
- description: Container VMID (optional - if not provided, streams node journalctl)
|
||||
in: path
|
||||
name: vmid
|
||||
required: true
|
||||
type: integer
|
||||
- description: limit
|
||||
- description: Limit output lines (1-1000)
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
@@ -3411,20 +3457,24 @@ paths:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get journalctl output
|
||||
description: Get journalctl output for node or LXC container. If vmid is not
|
||||
provided, streams node journalctl.
|
||||
parameters:
|
||||
- in: path
|
||||
- description: Node name
|
||||
in: path
|
||||
name: node
|
||||
required: true
|
||||
type: string
|
||||
- in: path
|
||||
- description: Container VMID (optional - if not provided, streams node journalctl)
|
||||
in: path
|
||||
name: vmid
|
||||
type: integer
|
||||
- description: Service name (e.g., 'pveproxy' for node, 'container@.service'
|
||||
format for LXC)
|
||||
in: path
|
||||
name: service
|
||||
type: string
|
||||
- in: path
|
||||
name: vmid
|
||||
required: true
|
||||
type: integer
|
||||
- description: limit
|
||||
- description: Limit output lines (1-1000)
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
type JournalctlRequest struct {
|
||||
Node string `uri:"node" binding:"required"`
|
||||
VMID int `uri:"vmid" binding:"required"`
|
||||
VMID *int `uri:"vmid"` // optional - if not provided, streams node journalctl
|
||||
Service string `uri:"service"`
|
||||
Limit int `query:"limit" binding:"omitempty,min=1,max=1000"`
|
||||
}
|
||||
@@ -20,17 +20,20 @@ type JournalctlRequest struct {
|
||||
// @x-id "journalctl"
|
||||
// @BasePath /api/v1
|
||||
// @Summary Get journalctl output
|
||||
// @Description Get journalctl output
|
||||
// @Description Get journalctl output for node or LXC container. If vmid is not provided, streams node journalctl.
|
||||
// @Tags proxmox,websocket
|
||||
// @Accept json
|
||||
// @Produce application/json
|
||||
// @Param path path JournalctlRequest true "Request"
|
||||
// @Param limit query int false "limit"
|
||||
// @Success 200 string plain "Journalctl output"
|
||||
// @Param node path string true "Node name"
|
||||
// @Param vmid path int false "Container VMID (optional - if not provided, streams node journalctl)"
|
||||
// @Param service path string false "Service name (e.g., 'pveproxy' for node, 'container@.service' format for LXC)"
|
||||
// @Param limit query int false "Limit output lines (1-1000)"
|
||||
// @Success 200 string plain "Journalctl output"
|
||||
// @Failure 400 {object} apitypes.ErrorResponse "Invalid request"
|
||||
// @Failure 403 {object} apitypes.ErrorResponse "Unauthorized"
|
||||
// @Failure 404 {object} apitypes.ErrorResponse "Node not found"
|
||||
// @Failure 500 {object} apitypes.ErrorResponse "Internal server error"
|
||||
// @Router /proxmox/journalctl/{node} [get]
|
||||
// @Router /proxmox/journalctl/{node}/{vmid} [get]
|
||||
// @Router /proxmox/journalctl/{node}/{vmid}/{service} [get]
|
||||
func Journalctl(c *gin.Context) {
|
||||
@@ -53,7 +56,12 @@ func Journalctl(c *gin.Context) {
|
||||
}
|
||||
defer manager.Close()
|
||||
|
||||
reader, err := node.LXCJournalctl(c.Request.Context(), request.VMID, request.Service, request.Limit)
|
||||
var reader io.ReadCloser
|
||||
if request.VMID == nil {
|
||||
reader, err = node.NodeJournalctl(c.Request.Context(), request.Service, request.Limit)
|
||||
} else {
|
||||
reader, err = node.LXCJournalctl(c.Request.Context(), *request.VMID, request.Service, request.Limit)
|
||||
}
|
||||
if err != nil {
|
||||
c.Error(apitypes.InternalServerError(err, "failed to get journalctl output"))
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user