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