1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package firecracker
import (
"context"
"errors"
"slices"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/johnandersen777/socialweb-computer-kcp/api/v1alpha1"
"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/compute"
commonv1 "github.com/johnandersen777/socialweb-computer-kcp/api/common/v1alpha1"
)
var _ compute.Provider = (*Provider)(nil)
func SpecFor(handle string, vm v1alpha1.ComputeVMSpec) v1alpha1.FirecrackerVMSpec {
return v1alpha1.FirecrackerVMSpec{Owner: v1alpha1.ComputeVMOwner{Handle: handle}, Vcpu: vm.VM.Cpus, Mem: vm.VM.Mem, Disk: vm.VM.Disk,
Image: vm.Image, UserData: vm.UserData, StopGraceSeconds: vm.StopGraceSeconds, HostPorts: slices.Clone(vm.HostPorts),
GuestNetwork: v1alpha1.GuestNetworkWith(vm.GuestNetwork.LANUDPAllowed(), vm.GuestNetwork.HostUDPAllowed(), vm.GuestNetwork.WebRTCUDPPortOf())}
}
func (p *Provider) ref(name string) commonv1.ObjectRef {
return commonv1.ObjectRef{Group: v1alpha1.GroupName, Kind: v1alpha1.BackendKindFirecrackerVM, Name: name}
}
func instanceOf(ref commonv1.ObjectRef, st v1alpha1.FirecrackerVMStatus) compute.Instance {
in := compute.Instance{Ref: ref, Phase: string(st.Phase), Message: st.Message}
if n := st.Network; n != nil {
for _, a := range []string{n.GuestIP, n.HostAddress} {
if a != "" {
in.Addresses = append(in.Addresses, a)
}
}
}
return in
}
func (p *Provider) Provision(ctx context.Context, req compute.ProvisionRequest) (compute.Instance, error) {
if req.Name == "" {
return compute.Instance{}, errors.New("firecracker: the provision request names no VM")
}
vm := &v1alpha1.FirecrackerVM{ObjectMeta: metav1.ObjectMeta{Name: req.Name},
Spec: v1alpha1.FirecrackerVMSpec{Owner: v1alpha1.ComputeVMOwner{Handle: p.handle}, Vcpu: req.Shape.CPUs, Mem: req.Shape.Mem,
Disk: req.Shape.Disk, UserData: v1alpha1.ComputeVMUserData{Vault: req.UserData}}}
st, err := p.Boot(ctx, vm, func(v1alpha1.FirecrackerVMStatus) error { return nil })
return instanceOf(p.ref(req.Name), st), err
}
func (p *Provider) Instance(ctx context.Context, ref commonv1.ObjectRef) (compute.Instance, error) {
rec, err := p.rt.Load(p.handle, ref.Name)
if err != nil {
return compute.Instance{Ref: ref, Phase: string(v1alpha1.ComputeVMPhasePending)}, nil
}
vm := &v1alpha1.FirecrackerVM{ObjectMeta: metav1.ObjectMeta{Name: ref.Name}, Spec: v1alpha1.FirecrackerVMSpec{Owner: v1alpha1.ComputeVMOwner{Handle: p.handle}},
Status: runningStatus(v1alpha1.FirecrackerVMStatus{}, 0, rec)}
return instanceOf(ref, p.Observe(ctx, vm)), nil
}
func (p *Provider) Release(ctx context.Context, ref commonv1.ObjectRef) error {
vm := &v1alpha1.FirecrackerVM{ObjectMeta: metav1.ObjectMeta{Name: ref.Name}, Spec: v1alpha1.FirecrackerVMSpec{Owner: v1alpha1.ComputeVMOwner{Handle: p.handle}}}
if rec, err := p.rt.Load(p.handle, ref.Name); err == nil {
vm.Status = runningStatus(vm.Status, 0, rec)
}
return p.Teardown(ctx, vm)
}