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) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
store := createStoreOrExit()
|
store := createStoreOrExit()
|
||||||
|
|
||||||
err := store.BuildVMImageWithInterruptHandler(vmDebugFlag, buildOverwriteFlag)
|
exitCode := store.RunCLIImageBuild(vmDebugFlag, buildOverwriteFlag)
|
||||||
if err != nil {
|
if exitCode != 0 {
|
||||||
slog.Error("Failed to build VM image", "error", err.Error())
|
os.Exit(exitCode)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Info("VM image built successfully", "path", store.GetVMImagePath())
|
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
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/AlexSSD7/linsk/cmd/runvm"
|
||||||
"github.com/AlexSSD7/linsk/nettap"
|
"github.com/AlexSSD7/linsk/nettap"
|
||||||
"github.com/AlexSSD7/linsk/osspecifics"
|
"github.com/AlexSSD7/linsk/osspecifics"
|
||||||
"github.com/AlexSSD7/linsk/share"
|
"github.com/AlexSSD7/linsk/share"
|
||||||
|
|
@ -32,9 +29,7 @@ func createStoreOrExit() *storage.Storage {
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
type runVMFunc func(context.Context, *vm.VM, *vm.FileManager, *share.NetTapRuntimeContext) int
|
func runVM(passthroughArg string, fn runvm.RunVMFunc, forwardPortsRules []vm.PortForwardingRule, unrestrictedNetworking bool, withNetTap bool) int {
|
||||||
|
|
||||||
func runVM(passthroughArg string, fn runVMFunc, forwardPortsRules []vm.PortForwardingRule, unrestrictedNetworking bool, withNetTap bool) int {
|
|
||||||
store := createStoreOrExit()
|
store := createStoreOrExit()
|
||||||
|
|
||||||
vmImagePath, err := store.CheckVMImageExists()
|
vmImagePath, err := store.CheckVMImageExists()
|
||||||
|
|
@ -197,116 +192,13 @@ func runVM(passthroughArg string, fn runVMFunc, forwardPortsRules []vm.PortForwa
|
||||||
ShowDisplay: vmDebugFlag,
|
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)
|
vi, err := vm.NewVM(slog.Default().With("caller", "vm"), vmCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Failed to create vm instance", "error", err.Error())
|
slog.Error("Failed to create vm instance", "error", err.Error())
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
runErrCh := make(chan error, 1)
|
return runvm.RunVM(vi, true, tapRuntimeCtx, fn)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDevicePassthroughConfig(val string) (*vm.PassthroughConfig, error) {
|
func getDevicePassthroughConfig(val string) (*vm.PassthroughConfig, error) {
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/AlexSSD7/linsk/cmd/runvm"
|
||||||
"github.com/AlexSSD7/linsk/osspecifics"
|
"github.com/AlexSSD7/linsk/osspecifics"
|
||||||
|
"github.com/AlexSSD7/linsk/share"
|
||||||
"github.com/AlexSSD7/linsk/utils"
|
"github.com/AlexSSD7/linsk/utils"
|
||||||
"github.com/AlexSSD7/linsk/vm"
|
"github.com/AlexSSD7/linsk/vm"
|
||||||
"github.com/alessio/shellescape"
|
"github.com/alessio/shellescape"
|
||||||
|
|
@ -88,99 +87,29 @@ func createQEMUImg(outPath string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *BuildContext) BuildWithInterruptHandler() error {
|
func (bc *BuildContext) RunCLIBuild() int {
|
||||||
defer func() {
|
return runvm.RunVM(bc.vi, false, nil, func(ctx context.Context, v *vm.VM, fm *vm.FileManager, ntrc *share.NetTapRuntimeContext) int {
|
||||||
err := bc.vi.Cancel()
|
|
||||||
if err != nil {
|
|
||||||
bc.logger.Error("Failed to cancel VM context", "error", err.Error())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
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)
|
|
||||||
defer signal.Reset()
|
|
||||||
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
err := bc.vi.Run()
|
|
||||||
ctxCancel()
|
|
||||||
runErrCh <- err
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case sig := <-interrupt:
|
|
||||||
lg := slog.With("signal", sig)
|
|
||||||
|
|
||||||
if i == 0 {
|
|
||||||
lg.Warn("Caught interrupt, safely shutting down")
|
|
||||||
} else if i < 10 {
|
|
||||||
lg.Warn("Caught subsequent interrupt, please interrupt n more times to panic", "n", 10-i)
|
|
||||||
} else {
|
|
||||||
panic("force interrupt")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := bc.vi.Cancel()
|
|
||||||
if err != nil {
|
|
||||||
lg.Warn("Failed to cancel VM context", "error", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case err := <-runErrCh:
|
|
||||||
if err == nil {
|
|
||||||
return fmt.Errorf("operation canceled by user")
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.Wrap(err, "start vm")
|
|
||||||
case <-bc.vi.SSHUpNotifyChan():
|
|
||||||
sc, err := bc.vi.DialSSH()
|
sc, err := bc.vi.DialSSH()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "dial vm ssh")
|
bc.logger.Error("Failed to dial VM SSH", "error", err.Error())
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() { _ = sc.Close() }()
|
defer func() { _ = sc.Close() }()
|
||||||
|
|
||||||
bc.logger.Info("VM OS installation in progress")
|
bc.logger.Info("VM OS installation in progress")
|
||||||
|
|
||||||
err = runAlpineSetupCmd(sc, []string{"openssh", "lvm2", "util-linux", "cryptsetup", "vsftpd", "samba", "netatalk"})
|
err = runAlpineSetup(sc, []string{"openssh", "lvm2", "util-linux", "cryptsetup", "vsftpd", "samba", "netatalk"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "run alpine setup cmd")
|
bc.logger.Error("Failed to set up Alpine Linux", "error", err.Error())
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bc.vi.Cancel()
|
return 0
|
||||||
if err != nil {
|
})
|
||||||
return errors.Wrap(err, "cancel vm context")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
func runAlpineSetup(sc *ssh.Client, pkgs []string) error {
|
||||||
case err := <-runErrCh:
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "run vm")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runAlpineSetupCmd(sc *ssh.Client, pkgs []string) error {
|
|
||||||
sess, err := sc.NewSession()
|
sess, err := sc.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "new session")
|
return errors.Wrap(err, "new session")
|
||||||
|
|
@ -204,6 +133,7 @@ func runAlpineSetupCmd(sc *ssh.Client, pkgs []string) error {
|
||||||
cmd += " && mount /dev/vda3 /mnt && chroot /mnt apk add " + strings.Join(pkgsQuoted, " ")
|
cmd += " && mount /dev/vda3 /mnt && chroot /mnt apk add " + strings.Join(pkgsQuoted, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:dupword
|
||||||
cmd += `&& chroot /mnt ash -c 'echo "PasswordAuthentication no" >> /etc/ssh/sshd_config && addgroup -g 1000 linsk && adduser -D -h /mnt -G linsk linsk -u 1000 && touch /etc/network/interfaces'`
|
cmd += `&& chroot /mnt ash -c 'echo "PasswordAuthentication no" >> /etc/ssh/sshd_config && addgroup -g 1000 linsk && adduser -D -h /mnt -G linsk linsk -u 1000 && touch /etc/network/interfaces'`
|
||||||
|
|
||||||
err = sess.Run(cmd)
|
err = sess.Run(cmd)
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,9 @@ func (s *Storage) download(url string, hash []byte, out string, applyReaderMiddl
|
||||||
_, err := os.Stat(out)
|
_, err := os.Stat(out)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return errors.Wrap(err, "file already exists")
|
return errors.Wrap(err, "file already exists")
|
||||||
} else {
|
} else if !errors.Is(err, os.ErrNotExist) {
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
|
||||||
return errors.Wrap(err, "stat out path")
|
return errors.Wrap(err, "stat out path")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.OpenFile(out, os.O_CREATE|os.O_WRONLY, 0400)
|
f, err := os.OpenFile(out, os.O_CREATE|os.O_WRONLY, 0400)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func validateFileHash(path string, hash []byte) error {
|
||||||
sum := h.Sum(nil)
|
sum := h.Sum(nil)
|
||||||
|
|
||||||
if !bytes.Equal(sum, hash) {
|
if !bytes.Equal(sum, hash) {
|
||||||
return fmt.Errorf("hash mismatch: want '%v', have '%v'", hex.EncodeToString(hash), hex.EncodeToString(sum))
|
return fmt.Errorf("hash mismatch: want '%v', have '%v' (path '%v')", hex.EncodeToString(hash), hex.EncodeToString(sum), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package storage
|
||||||
import (
|
import (
|
||||||
"compress/bzip2"
|
"compress/bzip2"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -69,33 +68,37 @@ func (s *Storage) GetAarch64EFIImagePath() string {
|
||||||
return filepath.Join(s.path, constants.GetAarch64EFIImageName())
|
return filepath.Join(s.path, constants.GetAarch64EFIImageName())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) BuildVMImageWithInterruptHandler(showBuilderVMDisplay bool, overwrite bool) error {
|
func (s *Storage) RunCLIImageBuild(showBuilderVMDisplay bool, overwrite bool) int {
|
||||||
vmImagePath := s.GetVMImagePath()
|
vmImagePath := s.GetVMImagePath()
|
||||||
removed, err := checkExistsOrRemove(vmImagePath, overwrite)
|
removed, err := checkExistsOrRemove(vmImagePath, overwrite)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "check exists or remove")
|
slog.Error("Failed to check for (and remove) existing VM image", "error", err.Error())
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
baseImagePath, err := s.CheckDownloadBaseImage()
|
baseImagePath, err := s.CheckDownloadBaseImage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "check/download base image")
|
slog.Error("Failed to check or download base VM image", "error", err.Error())
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
biosPath, err := s.CheckDownloadVMBIOS()
|
biosPath, err := s.CheckDownloadVMBIOS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "check/download vm bios")
|
slog.Error("Failed to check or download VM BIOS", "error", err.Error())
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
s.logger.Info("Building VM image", "tags", constants.GetAlpineBaseImageTags(), "overwriting", removed, "dst", vmImagePath)
|
s.logger.Info("Building VM image", "tags", constants.GetAlpineBaseImageTags(), "overwriting", removed, "dst", vmImagePath)
|
||||||
|
|
||||||
buildCtx, err := imgbuilder.NewBuildContext(s.logger.With("subcaller", "imgbuilder"), baseImagePath, vmImagePath, showBuilderVMDisplay, biosPath)
|
buildCtx, err := imgbuilder.NewBuildContext(s.logger.With("subcaller", "imgbuilder"), baseImagePath, vmImagePath, showBuilderVMDisplay, biosPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "create new img build context")
|
slog.Error("Failed to create new image build context", "error", err.Error())
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
err = buildCtx.BuildWithInterruptHandler()
|
exitCode := buildCtx.RunCLIBuild()
|
||||||
if err != nil {
|
if exitCode != 0 {
|
||||||
return errors.Wrap(err, "do build")
|
return exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.Remove(baseImagePath)
|
err = os.Remove(baseImagePath)
|
||||||
|
|
@ -105,7 +108,7 @@ func (s *Storage) BuildVMImageWithInterruptHandler(showBuilderVMDisplay bool, ov
|
||||||
s.logger.Info("Removed base image", "path", baseImagePath)
|
s.logger.Info("Removed base image", "path", baseImagePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) CheckVMImageExists() (string, error) {
|
func (s *Storage) CheckVMImageExists() (string, error) {
|
||||||
|
|
@ -152,9 +155,7 @@ func (s *Storage) CheckDownloadAarch64EFIImage() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// EFI image doesn't exist. Download one.
|
// EFI image doesn't exist. Download one.
|
||||||
err := s.download(constants.GetAarch64EFIImageBZ2URL(), constants.GetAarch64EFIImageHash(), efiImagePath, func(r io.Reader) io.Reader {
|
err := s.download(constants.GetAarch64EFIImageBZ2URL(), constants.GetAarch64EFIImageHash(), efiImagePath, bzip2.NewReader)
|
||||||
return bzip2.NewReader(r)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "download base alpine image")
|
return "", errors.Wrap(err, "download base alpine image")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue