Better VM runtime logic
This commit is contained in:
parent
58039acc3c
commit
7b5391f4d8
7 changed files with 165 additions and 220 deletions
|
|
@ -13,10 +13,9 @@ var buildCmd = &cobra.Command{
|
|||
Run: func(cmd *cobra.Command, args []string) {
|
||||
store := createStoreOrExit()
|
||||
|
||||
err := store.BuildVMImageWithInterruptHandler(vmDebugFlag, buildOverwriteFlag)
|
||||
if err != nil {
|
||||
slog.Error("Failed to build VM image", "error", err.Error())
|
||||
os.Exit(1)
|
||||
exitCode := store.RunCLIImageBuild(vmDebugFlag, buildOverwriteFlag)
|
||||
if exitCode != 0 {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
slog.Info("VM image built successfully", "path", store.GetVMImagePath())
|
||||
|
|
|
|||
125
cmd/runvm/runvm.go
Normal file
125
cmd/runvm/runvm.go
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
package runvm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"log/slog"
|
||||
|
||||
"github.com/AlexSSD7/linsk/share"
|
||||
"github.com/AlexSSD7/linsk/vm"
|
||||
)
|
||||
|
||||
type RunVMFunc func(context.Context, *vm.VM, *vm.FileManager, *share.NetTapRuntimeContext) int
|
||||
|
||||
func RunVM(vi *vm.VM, initFileManager bool, tapRuntimeCtx *share.NetTapRuntimeContext, fn RunVMFunc) int {
|
||||
runErrCh := make(chan error, 1)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
ctx, ctxCancel := context.WithCancel(context.Background())
|
||||
defer ctxCancel()
|
||||
|
||||
interrupt := make(chan os.Signal, 2)
|
||||
signal.Notify(interrupt, syscall.SIGTERM, syscall.SIGINT)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
err := vi.Run()
|
||||
ctxCancel()
|
||||
runErrCh <- err
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for i := 0; ; i++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
signal.Reset()
|
||||
return
|
||||
case sig := <-interrupt:
|
||||
lg := slog.With("signal", sig)
|
||||
|
||||
switch {
|
||||
case i == 0:
|
||||
lg.Warn("Caught interrupt, safely shutting down")
|
||||
case i < 10:
|
||||
lg.Warn("Caught subsequent interrupt, please interrupt n more times to panic", "n", 10-i)
|
||||
default:
|
||||
panic("force interrupt")
|
||||
}
|
||||
|
||||
err := vi.Cancel()
|
||||
if err != nil {
|
||||
lg.Warn("Failed to cancel VM context", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
var fm *vm.FileManager
|
||||
if initFileManager {
|
||||
fm = vm.NewFileManager(slog.Default().With("caller", "file-manager"), vi)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case err := <-runErrCh:
|
||||
if err == nil {
|
||||
err = fmt.Errorf("operation canceled by user")
|
||||
}
|
||||
|
||||
slog.Error("Failed to start the VM", "error", err.Error())
|
||||
return 1
|
||||
case <-vi.SSHUpNotifyChan():
|
||||
if fm != nil {
|
||||
err := fm.Init()
|
||||
if err != nil {
|
||||
slog.Error("Failed to initialize File Manager", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
startupFailed := false
|
||||
|
||||
if tapRuntimeCtx != nil {
|
||||
err := vi.ConfigureInterfaceStaticNet(context.Background(), "eth1", tapRuntimeCtx.Net.GuestCIDR)
|
||||
if err != nil {
|
||||
slog.Error("Failed to configure tag interface network", "error", err.Error())
|
||||
startupFailed = true
|
||||
}
|
||||
}
|
||||
|
||||
var exitCode int
|
||||
|
||||
if !startupFailed {
|
||||
exitCode = fn(ctx, vi, fm, tapRuntimeCtx)
|
||||
} else {
|
||||
exitCode = 1
|
||||
}
|
||||
|
||||
err := vi.Cancel()
|
||||
if err != nil {
|
||||
slog.Error("Failed to cancel VM context", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
select {
|
||||
case err := <-runErrCh:
|
||||
if err != nil {
|
||||
slog.Error("Failed to run the VM", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return exitCode
|
||||
}
|
||||
}
|
||||
}
|
||||
114
cmd/utils.go
114
cmd/utils.go
|
|
@ -1,19 +1,16 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"log/slog"
|
||||
|
||||
"github.com/AlexSSD7/linsk/cmd/runvm"
|
||||
"github.com/AlexSSD7/linsk/nettap"
|
||||
"github.com/AlexSSD7/linsk/osspecifics"
|
||||
"github.com/AlexSSD7/linsk/share"
|
||||
|
|
@ -32,9 +29,7 @@ func createStoreOrExit() *storage.Storage {
|
|||
return store
|
||||
}
|
||||
|
||||
type runVMFunc func(context.Context, *vm.VM, *vm.FileManager, *share.NetTapRuntimeContext) int
|
||||
|
||||
func runVM(passthroughArg string, fn runVMFunc, forwardPortsRules []vm.PortForwardingRule, unrestrictedNetworking bool, withNetTap bool) int {
|
||||
func runVM(passthroughArg string, fn runvm.RunVMFunc, forwardPortsRules []vm.PortForwardingRule, unrestrictedNetworking bool, withNetTap bool) int {
|
||||
store := createStoreOrExit()
|
||||
|
||||
vmImagePath, err := store.CheckVMImageExists()
|
||||
|
|
@ -197,116 +192,13 @@ func runVM(passthroughArg string, fn runVMFunc, forwardPortsRules []vm.PortForwa
|
|||
ShowDisplay: vmDebugFlag,
|
||||
}
|
||||
|
||||
return innerRunVM(vmCfg, tapRuntimeCtx, fn)
|
||||
}
|
||||
|
||||
func innerRunVM(vmCfg vm.VMConfig, tapRuntimeCtx *share.NetTapRuntimeContext, fn runVMFunc) int {
|
||||
vi, err := vm.NewVM(slog.Default().With("caller", "vm"), vmCfg)
|
||||
if err != nil {
|
||||
slog.Error("Failed to create vm instance", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
runErrCh := make(chan error, 1)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
ctx, ctxCancel := context.WithCancel(context.Background())
|
||||
defer ctxCancel()
|
||||
|
||||
interrupt := make(chan os.Signal, 2)
|
||||
signal.Notify(interrupt, syscall.SIGTERM, syscall.SIGINT)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
err := vi.Run()
|
||||
ctxCancel()
|
||||
runErrCh <- err
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for i := 0; ; i++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
signal.Reset()
|
||||
return
|
||||
case sig := <-interrupt:
|
||||
lg := slog.With("signal", sig)
|
||||
|
||||
switch {
|
||||
case i == 0:
|
||||
lg.Warn("Caught interrupt, safely shutting down")
|
||||
case i < 10:
|
||||
lg.Warn("Caught subsequent interrupt, please interrupt n more times to panic", "n", 10-i)
|
||||
default:
|
||||
panic("force interrupt")
|
||||
}
|
||||
|
||||
err := vi.Cancel()
|
||||
if err != nil {
|
||||
lg.Warn("Failed to cancel VM context", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
fm := vm.NewFileManager(slog.Default().With("caller", "file-manager"), vi)
|
||||
|
||||
for {
|
||||
select {
|
||||
case err := <-runErrCh:
|
||||
if err == nil {
|
||||
err = fmt.Errorf("operation canceled by user")
|
||||
}
|
||||
|
||||
slog.Error("Failed to start the VM", "error", err.Error())
|
||||
return 1
|
||||
case <-vi.SSHUpNotifyChan():
|
||||
err := fm.Init()
|
||||
if err != nil {
|
||||
slog.Error("Failed to initialize File Manager", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
startupFailed := false
|
||||
|
||||
if tapRuntimeCtx != nil {
|
||||
err := vi.ConfigureInterfaceStaticNet(context.Background(), "eth1", tapRuntimeCtx.Net.GuestCIDR)
|
||||
if err != nil {
|
||||
slog.Error("Failed to configure tag interface network", "error", err.Error())
|
||||
startupFailed = true
|
||||
}
|
||||
}
|
||||
|
||||
var exitCode int
|
||||
|
||||
if !startupFailed {
|
||||
exitCode = fn(ctx, vi, fm, tapRuntimeCtx)
|
||||
} else {
|
||||
exitCode = 1
|
||||
}
|
||||
|
||||
err = vi.Cancel()
|
||||
if err != nil {
|
||||
slog.Error("Failed to cancel VM context", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
select {
|
||||
case err := <-runErrCh:
|
||||
if err != nil {
|
||||
slog.Error("Failed to run the VM", "error", err.Error())
|
||||
return 1
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return exitCode
|
||||
}
|
||||
}
|
||||
return runvm.RunVM(vi, true, tapRuntimeCtx, fn)
|
||||
}
|
||||
|
||||
func getDevicePassthroughConfig(val string) (*vm.PassthroughConfig, error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue