docs(milestone): complete scheduling-streaming (v0.3)
---ci--- project: orca phase: 3 milestone: v0.3 status: complete requirements: covered: [REQ-022, REQ-030, REQ-032] partial: [] ---/ci--- v0.3 milestone merged to main. Includes all v0.2 work (P08-P10) that was previously on the milestone branch but not yet merged to main, plus the v0.3 completion work (iter.Seq streaming + doctor network/db). v0.2 phases included: P08 (mTLS), P09 (scheduling), P10 (security scan). v0.3 phases: P0 (pre-execution), P1 (iter.Seq streaming), P2 (doctor), P3 (final review+ship). Total: 40 requirements, all complete. No new go.mod dependencies. Full test suite passes under -race. gofmt + go vet clean.
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
// node_capacity.go implements `orca node capacity` for v0.2 P02.
|
||||
// The capacity declaration is per-node (cpu_millicores, memory_mib,
|
||||
// disk_mib) and feeds the bin-packing scheduler.
|
||||
//
|
||||
// REQ-028: HCL/YAML schema for NodeCapacity — the CLI accepts the
|
||||
// three numeric flags and writes a row to the `node_capacity` table.
|
||||
// A future enhancement can read `~/.orca/node.hcl` at join time
|
||||
// (out of scope for P02).
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"git.cloudinit.dev/coreci/orca/internal/store"
|
||||
)
|
||||
|
||||
var (
|
||||
capSetCPU int64
|
||||
capSetMem int64
|
||||
capSetDisk int64
|
||||
capNodeID string
|
||||
)
|
||||
|
||||
var nodeCapacityCmd = &cobra.Command{
|
||||
Use: "capacity",
|
||||
Short: "Manage node capacity declarations (P02 bin-packing input)",
|
||||
Long: "Read or write the per-node capacity used by the multi-node scheduler.",
|
||||
}
|
||||
|
||||
var nodeCapacityShowCmd = &cobra.Command{
|
||||
Use: "show [node-id]",
|
||||
Short: "Show capacity for a node (defaults to 'self')",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
id := capNodeID
|
||||
if id == "" && len(args) > 0 {
|
||||
id = args[0]
|
||||
}
|
||||
if id == "" {
|
||||
id = "self"
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
db, closer, err := openDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
repo := store.NewCapacityRepo(db)
|
||||
c, err := repo.Get(ctx, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("node %s: %w (use `orca node capacity --set` to declare)", id, err)
|
||||
}
|
||||
if jsonOutput {
|
||||
return printJSON(c)
|
||||
}
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "Node: %s\n", c.NodeID)
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "CPU: %d millicores\n", c.CPUMillicores)
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "Memory: %d MiB\n", c.MemoryMiB)
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "Disk: %d MiB\n", c.DiskMiB)
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "Updated: %s\n", c.UpdatedAt.UTC().Format(time.RFC3339))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var nodeCapacitySetCmd = &cobra.Command{
|
||||
Use: "set",
|
||||
Short: "Declare capacity for a node (used by bin-packing)",
|
||||
Long: "Write cpu_millicores, memory_mib, and disk_mib for the named node. Idempotent: subsequent calls overwrite.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if capSetCPU <= 0 || capSetMem <= 0 || capSetDisk <= 0 {
|
||||
return fmt.Errorf("--cpu, --memory, and --disk must all be positive")
|
||||
}
|
||||
id := capNodeID
|
||||
if id == "" {
|
||||
id = "self"
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
db, closer, err := openDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
repo := store.NewCapacityRepo(db)
|
||||
c := &store.NodeCapacity{
|
||||
NodeID: id,
|
||||
CPUMillicores: capSetCPU,
|
||||
MemoryMiB: capSetMem,
|
||||
DiskMiB: capSetDisk,
|
||||
}
|
||||
if err := repo.Upsert(ctx, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if jsonOutput {
|
||||
return printJSON(c)
|
||||
}
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "✓ Capacity set for %s: cpu=%d mem=%d disk=%d\n",
|
||||
c.NodeID, c.CPUMillicores, c.MemoryMiB, c.DiskMiB)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var nodeCapacityListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all node capacity declarations",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
db, closer, err := openDB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
repo := store.NewCapacityRepo(db)
|
||||
rows, err := repo.List(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if jsonOutput {
|
||||
return printJSON(rows)
|
||||
}
|
||||
if len(rows) == 0 {
|
||||
fmt.Fprintln(cmd.OutOrStdout(), "No capacity declarations. Use `orca node capacity --set` to add one.")
|
||||
return nil
|
||||
}
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%-20s %12s %12s %12s %s\n", "NODE", "CPU(mc)", "MEM(MiB)", "DISK(MiB)", "UPDATED")
|
||||
for _, c := range rows {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%-20s %12d %12d %12d %s\n",
|
||||
c.NodeID, c.CPUMillicores, c.MemoryMiB, c.DiskMiB, c.UpdatedAt.UTC().Format(time.RFC3339))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
nodeCapacitySetCmd.Flags().Int64Var(&capSetCPU, "cpu", 0, "CPU capacity in millicores (1000 = 1 vCPU)")
|
||||
nodeCapacitySetCmd.Flags().Int64Var(&capSetMem, "memory", 0, "Memory capacity in MiB")
|
||||
nodeCapacitySetCmd.Flags().Int64Var(&capSetDisk, "disk", 0, "Disk capacity in MiB")
|
||||
nodeCapacitySetCmd.Flags().StringVar(&capNodeID, "node", "", "node id (defaults to 'self')")
|
||||
nodeCapacityShowCmd.Flags().StringVar(&capNodeID, "node", "", "node id (defaults to 'self')")
|
||||
|
||||
nodeCapacityCmd.AddCommand(nodeCapacityShowCmd, nodeCapacitySetCmd, nodeCapacityListCmd)
|
||||
nodeCmd.AddCommand(nodeCapacityCmd)
|
||||
}
|
||||
Reference in New Issue
Block a user