~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
75 lines · 2.8 KB Raw History
package computevm

import (
	"cmp"
	"context"
	"fmt"
	"sync"
	"time"

	kruntime "k8s.io/apimachinery/pkg/runtime"

	"github.com/johnandersen777/socialweb-computer-kcp/api/v1alpha1"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/compute/firecracker"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/computevm"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/firecrackervm"
	ctlruntime "github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/runtime"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/runtime/manifests"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/hostprocess"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/hostsvc"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/kit/supervise"
)

const RestartMax = time.Minute

func Run(ctx context.Context, c computevm.Config) error {
	log := c.Log
	var wg sync.WaitGroup
	defer wg.Wait()
	wg.Go(func() { hostprocess.Supervise(ctx, computevm.Supervisor(c)) })
	supervise.Restart(ctx, "computevm", supervise.Backoff{Min: computevm.RetryAfter, Max: RestartMax, OnError: func(err error, after time.Duration) {
		if log != nil {
			log.Error("the ComputeVM and FirecrackerVM controllers stopped; starting them again", "err", fmt.Sprint(err), "after", after.String())
		}
	}}, func(ctx context.Context) error { return run(ctx, c) })
	return nil
}

func run(ctx context.Context, c computevm.Config) error {
	host, err := computevm.Open(ctx, c)
	if err != nil {
		return err
	}
	workspace := cmp.Or(c.Workspace, hostprocess.DefaultWorkspace)
	mgr, err := ctlruntime.NewManager(ctlruntime.Config{Rest: host.Rest, ExportWorkspace: manifests.Rebase(workspace, ctlruntime.DefaultExportWorkspace),
		AddToScheme: []func(*kruntime.Scheme) error{v1alpha1.AddToScheme}, Log: c.Log})
	if err != nil {
		return err
	}
	if _, err := Register(mgr, host); err != nil {
		return err
	}
	placement := firecrackervm.NewPlacement(host)
	provider, err := firecracker.New(firecracker.Config{Handle: c.Handle, Log: c.Log},
		firecracker.Deps{Runtime: c.Runtime, Units: c.Manager, UserData: host, Placement: placement, Processes: hostsvc.Processes{}})
	if err != nil {
		return err
	}
	defer provider.Close()
	fc, err := firecrackervm.Register(ctx, mgr, provider, host, placement)
	if err != nil {
		return err
	}
	caps := c.Runtime.Capabilities()
	host.Log().Info("the ComputeVM and FirecrackerVM controllers run in the core", "workspace", workspace, "backend", string(caps.Backend),
		"hypervisor", caps.Hypervisor, "enforcesLimits", caps.EnforcesLimits, "gracefulStop", caps.GracefulStop)
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	var wg sync.WaitGroup
	defer wg.Wait()
	wg.Go(func() {
		fc.Run(ctx)
		cancel()
	})
	return mgr.Start(ctx)
}