035 Project 35: Proxmox Multi-Node Scheduler

035 Build a Proxmox Multi-Node Scheduler

Schedule VM placement across nodes by free memory and CPU load.

fetch node stats -> score nodes -> choose best node -> create/migrate plan

Full main.go

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "sort"
)

type NodeStat struct {
    Node  string  `json:"node"`
    CPU   float64 `json:"cpu"`
    Mem   float64 `json:"mem"`
    MaxMem float64 `json:"maxmem"`
}

type apiResp struct {
    Data []NodeStat `json:"data"`
}

func score(n NodeStat) float64 {
    freeMemRatio := 1 - (n.Mem / n.MaxMem)
    cpuHeadroom := 1 - n.CPU
    return freeMemRatio*0.7 + cpuHeadroom*0.3
}

func main() {
    base := os.Getenv("PVE_BASE_URL")
    token := os.Getenv("PVE_TOKEN")
    if base == "" || token == "" {
        fmt.Println("set PVE_BASE_URL and PVE_TOKEN")
        os.Exit(2)
    }

    req, _ := http.NewRequest(http.MethodGet, base+"/api2/json/nodes", nil)
    req.Header.Set("Authorization", "PVEAPIToken="+token)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    var out apiResp
    if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
        panic(err)
    }

    sort.Slice(out.Data, func(i, j int) bool { return score(out.Data[i]) > score(out.Data[j]) })
    fmt.Println("placement order:")
    for _, n := range out.Data {
        fmt.Printf("node=%s score=%.3f cpu=%.2f mem=%.0f/%.0f\n", n.Node, score(n), n.CPU, n.Mem, n.MaxMem)
    }
}

Step-by-Step Explanation

  1. Collect node/resource metrics from API sources.
  2. Compute deterministic scores per target.
  3. Rank candidates by score and policy constraints.
  4. Produce dry-run placement/migration decisions.
  5. Apply gradually with canary and rollback plan.

Code Anatomy

  • Data collection stage fetches capacity and load.
  • Scoring stage turns metrics into comparable values.
  • Decision stage emits ranked scheduling actions.

Learning Goals

  • Build scheduling logic that is explainable and auditable.
  • Balance utilization, reliability, and operational safety.
  • Prepare for production-grade orchestration workflows.