mirror of
https://github.com/cirruslabs/orchard.git
synced 2026-09-30 03:51:43 +02:00
Better state syncing and other improvements (#24)
This commit is contained in:
@@ -4,12 +4,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/cirruslabs/orchard/pkg/resource/v1"
|
||||
"go.uber.org/zap"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type VM struct {
|
||||
id string
|
||||
vmResource *v1.VM
|
||||
id string
|
||||
Resource v1.VM
|
||||
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
@@ -17,12 +19,12 @@ type VM struct {
|
||||
wg *sync.WaitGroup
|
||||
}
|
||||
|
||||
func NewVM(vmResource *v1.VM) *VM {
|
||||
func NewVM(vmResource v1.VM, logger *zap.SugaredLogger) *VM {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
vm := &VM{
|
||||
id: fmt.Sprintf("orchard-%s-%s", vmResource.Name, vmResource.UID),
|
||||
vmResource: vmResource,
|
||||
id: fmt.Sprintf("orchard-%s-%s", vmResource.Name, vmResource.UID),
|
||||
Resource: vmResource,
|
||||
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
@@ -35,8 +37,13 @@ func NewVM(vmResource *v1.VM) *VM {
|
||||
go func() {
|
||||
defer vm.wg.Done()
|
||||
|
||||
// Optimistic set the status to running. Will be synced later by the worker loop.
|
||||
vm.Resource.Status = v1.VMStatusRunning
|
||||
if err := vm.run(vm.ctx); err != nil {
|
||||
vmResource.Status = v1.VMStatusFailed
|
||||
logger.Errorf("VM %s failed: %v", vm.id, err)
|
||||
vm.Resource.Status = v1.VMStatusFailed
|
||||
} else {
|
||||
vm.Resource.Status = v1.VMStatusStopped
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -44,12 +51,37 @@ func NewVM(vmResource *v1.VM) *VM {
|
||||
}
|
||||
|
||||
func (vm *VM) run(ctx context.Context) error {
|
||||
_, _, err := Tart(ctx, "clone", vm.vmResource.Image, vm.id)
|
||||
_, _, err := Tart(ctx, "clone", vm.Resource.Image, vm.id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = Tart(ctx, "run", vm.id)
|
||||
if vm.Resource.Memory != 0 {
|
||||
_, _, err = Tart(ctx, "set", "--memory", strconv.FormatUint(vm.Resource.Memory, 10), vm.id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if vm.Resource.CPU != 0 {
|
||||
_, _, err = Tart(ctx, "set", "--cpu", strconv.FormatUint(vm.Resource.CPU, 10), vm.id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var runArgs = []string{"run"}
|
||||
|
||||
if vm.Resource.Softnet {
|
||||
runArgs = append(runArgs, "--net-softnet")
|
||||
}
|
||||
|
||||
if vm.Resource.Headless {
|
||||
runArgs = append(runArgs, "--no-graphics")
|
||||
}
|
||||
|
||||
runArgs = append(runArgs, vm.id)
|
||||
_, _, err = Tart(ctx, runArgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -57,13 +89,17 @@ func (vm *VM) run(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VM) Close() error {
|
||||
_, _, _ = Tart(context.Background(), "stop", "--timeout", "5", vm.id)
|
||||
func (vm *VM) Stop() error {
|
||||
_, _, _ = Tart(context.Background(), "stop", vm.id)
|
||||
|
||||
vm.cancel()
|
||||
|
||||
vm.wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VM) Delete() error {
|
||||
_, _, err := Tart(context.Background(), "delete", vm.id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: failed to delete VM %s: %v", ErrFailed, vm.id, err)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
v1 "github.com/cirruslabs/orchard/pkg/resource/v1"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var ErrFailed = errors.New("VM manager failed")
|
||||
@@ -18,13 +19,13 @@ func New() *VMManager {
|
||||
}
|
||||
}
|
||||
|
||||
func (vmm *VMManager) Exists(vmResource *v1.VM) bool {
|
||||
func (vmm *VMManager) Exists(vmResource v1.VM) bool {
|
||||
_, ok := vmm.vms[vmResource.UID]
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func (vmm *VMManager) Get(vmResource *v1.VM) (*VM, error) {
|
||||
func (vmm *VMManager) Get(vmResource v1.VM) (*VM, error) {
|
||||
managedVM, ok := vmm.vms[vmResource.UID]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w: VM does not exist", ErrFailed)
|
||||
@@ -33,25 +34,34 @@ func (vmm *VMManager) Get(vmResource *v1.VM) (*VM, error) {
|
||||
return managedVM, nil
|
||||
}
|
||||
|
||||
func (vmm *VMManager) Create(vmResource *v1.VM) (*VM, error) {
|
||||
func (vmm *VMManager) Create(vmResource v1.VM, logger *zap.SugaredLogger) (*VM, error) {
|
||||
if _, ok := vmm.vms[vmResource.UID]; ok {
|
||||
return nil, fmt.Errorf("%w: VM already exists", ErrFailed)
|
||||
}
|
||||
|
||||
managedVM := NewVM(vmResource)
|
||||
managedVM := NewVM(vmResource, logger)
|
||||
|
||||
vmm.vms[vmResource.UID] = managedVM
|
||||
|
||||
return managedVM, nil
|
||||
}
|
||||
|
||||
func (vmm *VMManager) Delete(vmResource *v1.VM) error {
|
||||
func (vmm *VMManager) Stop(vmResource v1.VM) error {
|
||||
managedVM, ok := vmm.vms[vmResource.UID]
|
||||
if !ok {
|
||||
return fmt.Errorf("%w: VM does not exist", ErrFailed)
|
||||
}
|
||||
|
||||
if err := managedVM.Close(); err != nil {
|
||||
return managedVM.Stop()
|
||||
}
|
||||
|
||||
func (vmm *VMManager) Delete(vmResource v1.VM) error {
|
||||
managedVM, ok := vmm.vms[vmResource.UID]
|
||||
if !ok {
|
||||
return fmt.Errorf("%w: VM does not exist", ErrFailed)
|
||||
}
|
||||
|
||||
if err := managedVM.Delete(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -59,3 +69,13 @@ func (vmm *VMManager) Delete(vmResource *v1.VM) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vmm *VMManager) List() []*VM {
|
||||
var vms []*VM
|
||||
|
||||
for _, vm := range vmm.vms {
|
||||
vms = append(vms, vm)
|
||||
}
|
||||
|
||||
return vms
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user