This repository has no description
1//go:build linux
2
3package microvm
4
5import (
6 "fmt"
7 "os/exec"
8 "runtime"
9
10 "tangled.org/core/spindle/engines/microvm/placement"
11 "tangled.org/core/spindle/models"
12)
13
14func (e *Engine) ValidateWorkflowPlacement(wf *models.Workflow) error {
15 state, ok := wf.Data.(*workflowState)
16 if !ok || state == nil {
17 return fmt.Errorf("microVM workflow state is not initialized")
18 }
19 return e.validateImagePlacement(state.ImageSpec)
20}
21
22func (e *Engine) validateImagePlacement(spec ImageSpec) error {
23 if err := spec.Validate(); err != nil {
24 return err
25 }
26 if !placement.IsNativeArchitecture(spec.Arch, runtime.GOARCH) {
27 return fmt.Errorf("microVM image architecture %q is not native to executor architecture %q", spec.Arch, runtime.GOARCH)
28 }
29 if err := spec.validateImageFiles(); err != nil {
30 return err
31 }
32 runner, err := runnerFor(spec.RunnerType)
33 if err != nil {
34 return err
35 }
36 if err := runner.Validate(spec, e.cfg.MicroVMPipelines.EnableKVM); err != nil {
37 return err
38 }
39 if len(spec.Volumes) > 0 {
40 if _, err := exec.LookPath("mkfs.ext4"); err != nil {
41 return fmt.Errorf("required host command %q not found in PATH: %w", "mkfs.ext4", err)
42 }
43 for _, volume := range spec.Volumes {
44 if volume.ReadOnly {
45 return fmt.Errorf("read-only microvm volume %q is not supported yet", volume.Image)
46 }
47 if volume.FSType != "ext4" {
48 return fmt.Errorf("microvm volume %q uses unsupported fsType %q", volume.Image, volume.FSType)
49 }
50 if volume.ImageType != "" && volume.ImageType != "raw" {
51 return fmt.Errorf("microvm volume %q uses unsupported imageType %q", volume.Image, volume.ImageType)
52 }
53 }
54 }
55
56 request := resourcesForImage(spec)
57 if !request.Fits(e.budget) || !request.Fits(e.maxWorkflow) {
58 return fmt.Errorf("microVM image resources exceed executor limits: request=%v budget=%v max=%v", request, e.budget, e.maxWorkflow)
59 }
60 return nil
61}