Monorepo for Tangled tangled.org
4

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / engines / microvm / budget.go
2.4 kB 96 lines
1//go:build linux 2 3package microvm 4 5import ( 6 "context" 7 "fmt" 8 "time" 9 10 "tangled.org/core/spindle/config" 11 "tangled.org/core/spindle/engine" 12 "tangled.org/core/spindle/models" 13) 14 15// memory buffer for qemu process / slirp4netns itself 16const runnerBufferMiB = 96 17 18type Resources struct { 19 MemoryMiB int64 20 VCPUs int64 21 DiskMiB int64 22} 23 24func (r Resources) Fits(limit Resources) bool { 25 if limit.MemoryMiB > 0 && r.MemoryMiB > limit.MemoryMiB { 26 return false 27 } 28 if limit.VCPUs > 0 && r.VCPUs > limit.VCPUs { 29 return false 30 } 31 if limit.DiskMiB > 0 && r.DiskMiB > limit.DiskMiB { 32 return false 33 } 34 return true 35} 36 37func (r Resources) Add(other Resources) Resources { 38 return Resources{ 39 MemoryMiB: r.MemoryMiB + other.MemoryMiB, 40 VCPUs: r.VCPUs + other.VCPUs, 41 DiskMiB: r.DiskMiB + other.DiskMiB, 42 } 43} 44 45func (r Resources) Sub(other Resources) Resources { 46 return Resources{ 47 MemoryMiB: max(0, r.MemoryMiB-other.MemoryMiB), 48 VCPUs: max(0, r.VCPUs-other.VCPUs), 49 DiskMiB: max(0, r.DiskMiB-other.DiskMiB), 50 } 51} 52 53func (r Resources) String() string { 54 return fmt.Sprintf("memory=%dMiB vcpus=%d disk=%dMiB", r.MemoryMiB, r.VCPUs, r.DiskMiB) 55} 56 57func newVMBudgetConfig(cfg config.MicroVMPipelines) (Resources, Resources, time.Duration) { 58 budget := Resources{ 59 MemoryMiB: cfg.MaxTotalMemoryMiB, 60 VCPUs: cfg.MaxTotalVCPUs, 61 DiskMiB: cfg.MaxTotalDiskMiB, 62 } 63 maxReq := Resources{ 64 MemoryMiB: cfg.MaxWorkflowMemoryMiB, 65 VCPUs: cfg.MaxWorkflowVCPUs, 66 DiskMiB: cfg.MaxWorkflowDiskMiB, 67 } 68 return budget, maxReq, cfg.AgingThreshold 69} 70 71func (e *Engine) AcquireWorkflowSlot(ctx context.Context, wid models.WorkflowId, wf *models.Workflow) (engine.WorkflowSlot, error) { 72 state, ok := wf.Data.(*workflowState) 73 if !ok || state == nil { 74 return nil, fmt.Errorf("microVM workflow state is not initialized") 75 } 76 if e.scheduler == nil { 77 return engine.NoopSlot{}, nil 78 } 79 req := resourcesForImage(state.ImageSpec) 80 if req.MemoryMiB < 0 || req.VCPUs < 0 || req.DiskMiB < 0 { 81 return nil, fmt.Errorf("microVM resource request must not be negative: %s", req) 82 } 83 return e.scheduler.Acquire(ctx, req) 84} 85 86func resourcesForImage(spec ImageSpec) Resources { 87 var diskMiB int64 88 for _, volume := range spec.Volumes { 89 diskMiB += volume.SizeMiB 90 } 91 return Resources{ 92 MemoryMiB: int64(spec.MemoryMiB) + runnerBufferMiB, 93 VCPUs: int64(spec.VCPUs), 94 DiskMiB: diskMiB, 95 } 96}