mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-23 08:48:32 +02:00
docs: add per package README for implementation details (AI generated with human review)
This commit is contained in:
322
internal/proxmox/README.md
Normal file
322
internal/proxmox/README.md
Normal file
@@ -0,0 +1,322 @@
|
||||
# Proxmox
|
||||
|
||||
The proxmox package provides Proxmox VE integration for GoDoxy, enabling management of Proxmox LXC containers.
|
||||
|
||||
## Overview
|
||||
|
||||
The proxmox package implements Proxmox API client management, node discovery, and LXC container operations including power management and IP address retrieval.
|
||||
|
||||
### Key Features
|
||||
|
||||
- Proxmox API client management
|
||||
- Node discovery and pool management
|
||||
- LXC container operations (start, stop, status)
|
||||
- IP address retrieval for containers
|
||||
- TLS configuration options
|
||||
- Token-based authentication
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Proxmox Config] --> B[Create Client]
|
||||
B --> C[Connect to API]
|
||||
C --> D[Fetch Cluster Info]
|
||||
D --> E[Discover Nodes]
|
||||
E --> F[Add to Node Pool]
|
||||
|
||||
G[LXC Operations] --> H[Get IPs]
|
||||
G --> I[Start Container]
|
||||
G --> J[Stop Container]
|
||||
G --> K[Check Status]
|
||||
|
||||
subgraph Node Pool
|
||||
F --> L[Nodes Map]
|
||||
L --> M[Node 1]
|
||||
L --> N[Node 2]
|
||||
L --> O[Node 3]
|
||||
end
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
### Config
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
URL string `json:"url" validate:"required,url"`
|
||||
TokenID string `json:"token_id" validate:"required"`
|
||||
Secret strutils.Redacted `json:"secret" validate:"required"`
|
||||
NoTLSVerify bool `json:"no_tls_verify"`
|
||||
|
||||
client *Client
|
||||
}
|
||||
```
|
||||
|
||||
### Client
|
||||
|
||||
```go
|
||||
type Client struct {
|
||||
*proxmox.Client
|
||||
proxmox.Cluster
|
||||
Version *proxmox.Version
|
||||
}
|
||||
```
|
||||
|
||||
### Node
|
||||
|
||||
```go
|
||||
type Node struct {
|
||||
name string
|
||||
id string
|
||||
client *proxmox.Client
|
||||
}
|
||||
|
||||
var Nodes = pool.New[*Node]("proxmox_nodes")
|
||||
```
|
||||
|
||||
## Public API
|
||||
|
||||
### Configuration
|
||||
|
||||
```go
|
||||
// Init initializes the Proxmox client.
|
||||
func (c *Config) Init(ctx context.Context) gperr.Error
|
||||
|
||||
// Client returns the Proxmox client.
|
||||
func (c *Config) Client() *Client
|
||||
```
|
||||
|
||||
### Node Operations
|
||||
|
||||
```go
|
||||
// AvailableNodeNames returns all available node names.
|
||||
func AvailableNodeNames() string
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Setup
|
||||
|
||||
```go
|
||||
proxmoxCfg := &proxmox.Config{
|
||||
URL: "https://proxmox.example.com:8006",
|
||||
TokenID: "user@pam!token-name",
|
||||
Secret: "your-api-token-secret",
|
||||
NoTLSVerify: false,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err := proxmoxCfg.Init(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
client := proxmoxCfg.Client()
|
||||
```
|
||||
|
||||
### Node Access
|
||||
|
||||
```go
|
||||
// Get a specific node
|
||||
node, ok := proxmox.Nodes.Get("pve")
|
||||
if !ok {
|
||||
log.Fatal("Node not found")
|
||||
}
|
||||
|
||||
fmt.Printf("Node: %s (%s)\n", node.Name(), node.Key())
|
||||
```
|
||||
|
||||
### Available Nodes
|
||||
|
||||
```go
|
||||
names := proxmox.AvailableNodeNames()
|
||||
fmt.Printf("Available nodes: %s\n", names)
|
||||
```
|
||||
|
||||
## LXC Operations
|
||||
|
||||
### Get Container IPs
|
||||
|
||||
```go
|
||||
func getContainerIPs(ctx context.Context, node *proxmox.Node, vmid int) ([]net.IP, error) {
|
||||
var ips []net.IP
|
||||
|
||||
err := node.Get(ctx, "/lxc/"+strconv.Itoa(vmid)+"/config", &config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Parse IP addresses from config
|
||||
for _, ip := range config {
|
||||
if ipNet := net.ParseCIDR(ip); ipNet != nil {
|
||||
ips = append(ips, ipNet.IP)
|
||||
}
|
||||
}
|
||||
|
||||
return ips, nil
|
||||
}
|
||||
```
|
||||
|
||||
### Check Container Status
|
||||
|
||||
```go
|
||||
func (node *Node) LXCIsRunning(ctx context.Context, vmid int) (bool, error) {
|
||||
var status struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
err := node.Get(ctx, "/lxc/"+strconv.Itoa(vmid)+"/status/current", &status)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return status.Status == "running", nil
|
||||
}
|
||||
```
|
||||
|
||||
### Start Container
|
||||
|
||||
```go
|
||||
func (node *Node) LXCAction(ctx context.Context, vmid int, action string) error {
|
||||
return node.Post(ctx,
|
||||
"/lxc/"+strconv.Itoa(vmid)+"/status/"+action,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
const LXCStart = "start"
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Config
|
||||
participant Client
|
||||
participant NodePool
|
||||
participant LXC
|
||||
|
||||
Config->>Client: NewClient(url, options)
|
||||
Client->>ProxmoxAPI: GET /cluster/status
|
||||
ProxmoxAPI-->>Client: Cluster Info
|
||||
|
||||
Client->>NodePool: Add Nodes
|
||||
NodePool->>NodePool: Store in Pool
|
||||
|
||||
participant User
|
||||
User->>NodePool: Get Node
|
||||
NodePool-->>User: Node
|
||||
|
||||
User->>Node: LXCGetIPs(vmid)
|
||||
Node->>ProxmoxAPI: GET /lxc/{vmid}/config
|
||||
ProxmoxAPI-->>Node: Config with IPs
|
||||
Node-->>User: IP addresses
|
||||
|
||||
User->>Node: LXCAction(vmid, "start")
|
||||
Node->>ProxmoxAPI: POST /lxc/{vmid}/status/start
|
||||
ProxmoxAPI-->>Node: Success
|
||||
Node-->>User: Done
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### YAML Configuration
|
||||
|
||||
```yaml
|
||||
providers:
|
||||
proxmox:
|
||||
- url: https://proxmox.example.com:8006
|
||||
token_id: user@pam!token-name
|
||||
secret: your-api-token-secret
|
||||
no_tls_verify: false
|
||||
```
|
||||
|
||||
### TLS Configuration
|
||||
|
||||
```go
|
||||
// With TLS verification (default)
|
||||
tr := gphttp.NewTransport()
|
||||
|
||||
// Without TLS verification (insecure)
|
||||
tr := gphttp.NewTransportWithTLSConfig(&tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
```
|
||||
|
||||
## Node Pool
|
||||
|
||||
The package maintains a global node pool:
|
||||
|
||||
```go
|
||||
var Nodes = pool.New[*Node]("proxmox_nodes")
|
||||
```
|
||||
|
||||
### Pool Operations
|
||||
|
||||
```go
|
||||
// Add a node
|
||||
Nodes.Add(&Node{name: "pve1", id: "node/pve1", client: client})
|
||||
|
||||
// Get a node
|
||||
node, ok := Nodes.Get("pve1")
|
||||
|
||||
// Iterate nodes
|
||||
for _, node := range Nodes.Iter {
|
||||
fmt.Printf("Node: %s\n", node.Name())
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Route
|
||||
|
||||
The proxmox package integrates with the route package for idlewatcher:
|
||||
|
||||
```go
|
||||
// In route validation
|
||||
if r.Idlewatcher != nil && r.Idlewatcher.Proxmox != nil {
|
||||
node := r.Idlewatcher.Proxmox.Node
|
||||
vmid := r.Idlewatcher.Proxmox.VMID
|
||||
|
||||
node, ok := proxmox.Nodes.Get(node)
|
||||
if !ok {
|
||||
return gperr.Errorf("proxmox node %s not found", node)
|
||||
}
|
||||
|
||||
// Get container IPs
|
||||
ips, err := node.LXCGetIPs(ctx, vmid)
|
||||
// ... check reachability
|
||||
}
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
The package uses API tokens for authentication:
|
||||
|
||||
```go
|
||||
opts := []proxmox.Option{
|
||||
proxmox.WithAPIToken(c.TokenID, c.Secret.String()),
|
||||
proxmox.WithHTTPClient(&http.Client{
|
||||
Transport: tr,
|
||||
}),
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
```go
|
||||
// Timeout handling
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
return gperr.New("timeout fetching proxmox cluster info")
|
||||
}
|
||||
|
||||
// Connection errors
|
||||
return gperr.New("failed to fetch proxmox cluster info").With(err)
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Cluster info fetched once on init
|
||||
- Nodes cached in pool
|
||||
- Per-operation API calls
|
||||
- 3-second timeout for initial connection
|
||||
Reference in New Issue
Block a user