Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ddcd09e
Quarantine wedged vGPU VFs convicted by the guest sentinel
yummybomb Aug 20, 2026
8d3c427
Report GPU init failure from the guest agent and harden quarantine
yummybomb Aug 20, 2026
7cee402
Close sentinel replay, fail-open, and persist-retry holes
yummybomb Aug 20, 2026
f592039
Match only kernel-facility kmsg records in the GPU init watch
yummybomb Aug 21, 2026
d0fb5bc
Bound vGPU sentinel scans to the line cap
yummybomb Aug 21, 2026
296aad0
Signal an unavailable VF health store
yummybomb Aug 21, 2026
fc725dd
Repeat the GPU init-failure marker so printk splits cannot lose a report
yummybomb Aug 21, 2026
c29c9b5
Remove the conviction brake
yummybomb Aug 21, 2026
b65ab4b
Read /dev/kmsg with a record-sized buffer
yummybomb Aug 21, 2026
22bae7c
Fsync VF health state writes
yummybomb Aug 21, 2026
7f6a105
Persist only the matched sentinel marker
yummybomb Aug 21, 2026
b3b0fdd
Trim unused VF health and sentinel surface
yummybomb Aug 21, 2026
f81d91b
Re-probe framework discovery while the sentinel gate is unknown
yummybomb Aug 21, 2026
c27276e
Revalidate the assignment before conviction and list targets strictly
yummybomb Aug 21, 2026
8144c9b
Document draining the parent GPU before an SR-IOV cycle
yummybomb Aug 21, 2026
b9dd20a
Deduplicate the wedge remediation docs
yummybomb Aug 21, 2026
a719965
Convict on a released assignment instead of skipping
yummybomb Aug 21, 2026
d5291b4
Harden vGPU quarantine accounting
yummybomb Aug 24, 2026
b79af89
Validate persisted VF health state
yummybomb Aug 24, 2026
1fc0dff
Require full vGPU sentinel log lines
yummybomb Aug 24, 2026
559cfcf
Reject incompatible vGPU sentinel managers
yummybomb Aug 24, 2026
0b34da1
Initialize VF health during provider wiring
yummybomb Aug 24, 2026
734a300
Centralize allocatable VF quarantine policy
yummybomb Aug 24, 2026
300d9d7
Distinguish partial metadata listing failures
yummybomb Aug 24, 2026
5eed4a3
Share the vGPU placement lock across platforms
yummybomb Aug 24, 2026
b8ea93e
Test guest GPU reports against host matcher
yummybomb Aug 24, 2026
1f91863
Log vGPU sentinel start after vendor detection
yummybomb Aug 24, 2026
e90c1f1
Tighten vGPU sentinel comments
yummybomb Aug 24, 2026
070dd54
Tidy VF health store boundaries and admission errors
yummybomb Aug 24, 2026
44158d3
Reprobe for late vendor VFIO devices
yummybomb Aug 25, 2026
5ec6dfb
Merge remote-tracking branch 'origin/hypeship/vendor-vfio-vgpu' into …
yummybomb Aug 25, 2026
c971d0d
Trim vGPU sentinel comments and tests
yummybomb Aug 25, 2026
be50050
Quarantine VFs on a failure threshold with success reset
yummybomb Aug 25, 2026
7b24855
Expose allocatable and quarantined GPU slots in resources API
yummybomb Aug 25, 2026
15541f0
Remove comment for VFQuarantineThreshold in GPUConfig
yummybomb Aug 25, 2026
9d2f3fc
Keep scanning below threshold and retry failed tally clears
yummybomb Aug 25, 2026
4306d8b
Format GPU config fields
yummybomb Aug 25, 2026
1ae633a
Harden VF tally clearing, probe timeout, and threshold validation
yummybomb Aug 25, 2026
c5df41c
Merge remote-tracking branch 'origin/hypeship/vendor-vfio-vgpu' into …
yummybomb Aug 26, 2026
83a9e50
Preserve vGPU success ordering
yummybomb Aug 26, 2026
2ed1461
Harden vGPU assignment reconciliation
yummybomb Aug 26, 2026
8f419d9
Merge remote-tracking branch 'origin/hypeship/vgpu-wedge-quarantine' …
yummybomb Aug 26, 2026
a0d2849
Simplify vGPU quarantine implementation
yummybomb Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions cmd/api/api/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ func convertResourceStatus(rs resources.ResourceStatus) oapi.ResourceStatus {

func convertGPUResourceStatus(gs *resources.GPUResourceStatus) oapi.GPUResourceStatus {
result := oapi.GPUResourceStatus{
Mode: oapi.GPUResourceStatusMode(gs.Mode),
TotalSlots: gs.TotalSlots,
UsedSlots: gs.UsedSlots,
Mode: oapi.GPUResourceStatusMode(gs.Mode),
TotalSlots: gs.TotalSlots,
UsedSlots: gs.UsedSlots,
AllocatableSlots: gs.AllocatableSlots,
QuarantinedSlots: gs.QuarantinedSlots,
}

// Convert profiles (vGPU mode)
Expand Down
9 changes: 7 additions & 2 deletions cmd/api/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ type SnapshotConfig struct {

// GPUConfig holds GPU-related settings.
type GPUConfig struct {
ProfileCacheTTL string `koanf:"profile_cache_ttl"`
ProfileCacheTTL string `koanf:"profile_cache_ttl"`
VFQuarantineThreshold int `koanf:"vf_quarantine_threshold"`
}

// Config is the top-level Hypeman server configuration.
Expand Down Expand Up @@ -494,7 +495,8 @@ func defaultConfig() *Config {
},

GPU: GPUConfig{
ProfileCacheTTL: "30m",
ProfileCacheTTL: "30m",
VFQuarantineThreshold: 2,
},
}
}
Expand Down Expand Up @@ -647,6 +649,9 @@ func (c *Config) Validate() error {
if c.Build.MaxConcurrentSourceBuilds <= 0 {
return fmt.Errorf("build.max_concurrent_source_builds must be positive, got %d", c.Build.MaxConcurrentSourceBuilds)
}
if c.GPU.VFQuarantineThreshold < 1 {
return fmt.Errorf("gpu.vf_quarantine_threshold must be >= 1, got %d", c.GPU.VFQuarantineThreshold)
}
if c.Limits.MaxConcurrentPushes <= 0 {
return fmt.Errorf("limits.max_concurrent_pushes must be positive, got %d", c.Limits.MaxConcurrentPushes)
}
Expand Down
12 changes: 12 additions & 0 deletions cmd/api/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,18 @@ func TestValidateRejectsInvalidMetricsPort(t *testing.T) {
}
}

func TestValidateRejectsInvalidVFQuarantineThreshold(t *testing.T) {
for _, threshold := range []int{0, -1} {
cfg := defaultConfig()
cfg.GPU.VFQuarantineThreshold = threshold

err := cfg.Validate()
if err == nil {
t.Fatalf("expected validation error for vf_quarantine_threshold %d", threshold)
}
}
}

func TestValidateRejectsInvalidMetricExportInterval(t *testing.T) {
cfg := defaultConfig()
cfg.Otel.MetricExportInterval = "not-a-duration"
Expand Down
7 changes: 7 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func run() error {

// Configure GPU profile cache TTL
devices.SetGPUProfileCacheTTL(cfg.GPU.ProfileCacheTTL)
devices.SetVFQuarantineThreshold(cfg.GPU.VFQuarantineThreshold)

// Initialize OpenTelemetry (before wire initialization)
otelCfg := otel.Config{
Expand Down Expand Up @@ -653,6 +654,12 @@ func run() error {
return app.HealthCheckController.Run(gctx)
})
}
if app.VGPUSentinelController != nil {
grp.Go(func() error {
logger.Info("starting vGPU sentinel controller")
return app.VGPUSentinelController.Run(gctx)
})
}
if restartController, ok := app.InstanceManager.(interface {
StartRestartPolicyController(context.Context) error
}); ok {
Expand Down
42 changes: 22 additions & 20 deletions cmd/api/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,27 @@ import (

// application struct to hold initialized components
type application struct {
Ctx context.Context
Logger *slog.Logger
Config *config.Config
ImageManager images.Manager
SystemManager system.Manager
NetworkManager network.Manager
DeviceManager devices.Manager
InstanceManager instances.Manager
VolumeManager volumes.Manager
BuilderManager builders.Manager
IngressManager ingress.Manager
BuildManager builds.Manager
PushManager imagepush.Manager
ResourceManager *resources.Manager
GuestMemoryController guestmemory.Controller
AutoStandbyController *autostandby.Controller
HealthCheckController *instances.HealthCheckController
VMMetricsManager *vm_metrics.Manager
Registry *registry.Registry
ApiService *api.ApiService
Ctx context.Context
Logger *slog.Logger
Config *config.Config
ImageManager images.Manager
SystemManager system.Manager
NetworkManager network.Manager
DeviceManager devices.Manager
InstanceManager instances.Manager
VolumeManager volumes.Manager
BuilderManager builders.Manager
IngressManager ingress.Manager
BuildManager builds.Manager
PushManager imagepush.Manager
ResourceManager *resources.Manager
GuestMemoryController guestmemory.Controller
AutoStandbyController *autostandby.Controller
HealthCheckController *instances.HealthCheckController
VGPUSentinelController *instances.VGPUSentinelController
VMMetricsManager *vm_metrics.Manager
Registry *registry.Registry
ApiService *api.ApiService
}

// initializeApp is the injector function
Expand All @@ -72,6 +73,7 @@ func initializeApp() (*application, func(), error) {
providers.ProvideGuestMemoryController,
providers.ProvideAutoStandbyController,
providers.ProvideHealthCheckController,
providers.ProvideVGPUSentinelController,
providers.ProvideVMMetricsManager,
providers.ProvideRegistry,
api.New,
Expand Down
86 changes: 46 additions & 40 deletions cmd/api/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ data_dir: /var/lib/hypeman
# idle_ttl: "" # delete builders idle this long (e.g. "24h");
# # destructive, empty = disabled

# gpu:
# profile_cache_ttl: 30m # vGPU profile metadata cache TTL
# vf_quarantine_threshold: 2 # distinct instance assignments that must report
# # a guest driver init failure before the VF is
# # quarantined (must be >= 1)

# =============================================================================
# Resource Limits
# =============================================================================
Expand Down
Loading