Implement debug shell in run cmd

This commit is contained in:
AlexSSD7 2023-09-01 14:40:17 +01:00
commit 2d832c2b63
2 changed files with 104 additions and 82 deletions

View file

@ -86,7 +86,22 @@ var runCmd = &cobra.Command{
fmt.Fprintf(os.Stderr, "===========================\n[Network File Share Config]\nThe network file share was started. Please use the credentials below to connect to the file server.\n\nType: "+strings.ToUpper(shareBackendFlag)+"\nURL: %v\nUsername: linsk\nPassword: %v\n===========================\n", shareURI, sharePWD) fmt.Fprintf(os.Stderr, "===========================\n[Network File Share Config]\nThe network file share was started. Please use the credentials below to connect to the file server.\n\nType: "+strings.ToUpper(shareBackendFlag)+"\nURL: %v\nUsername: linsk\nPassword: %v\n===========================\n", shareURI, sharePWD)
ctxWait := true
if debugShellFlag {
slog.Warn("Starting a debug VM shell")
err := runVMShell(ctx, i)
if err != nil {
slog.Error("Failed to run VM shell", "error", err.Error())
} else {
ctxWait = false
}
}
if ctxWait {
<-ctx.Done() <-ctx.Done()
}
return 0 return 0
}, vmOpts.Ports, unrestrictedNetworkingFlag, vmOpts.EnableTap)) }, vmOpts.Ports, unrestrictedNetworkingFlag, vmOpts.EnableTap))
}, },
@ -99,11 +114,13 @@ var (
ftpExtIPFlag string ftpExtIPFlag string
shareBackendFlag string shareBackendFlag string
smbUseExternAddrFlag bool smbUseExternAddrFlag bool
debugShellFlag bool
) )
func init() { func init() {
runCmd.Flags().BoolVarP(&luksFlag, "luks", "l", false, "Use cryptsetup to open a LUKS volume (password will be prompted).") runCmd.Flags().BoolVarP(&luksFlag, "luks", "l", false, "Use cryptsetup to open a LUKS volume (password will be prompted).")
runCmd.Flags().BoolVar(&allowLUKSLowMemoryFlag, "allow-luks-low-memory", false, "Allow VM memory allocation lower than 2048 MiB when LUKS is enabled.") runCmd.Flags().BoolVar(&allowLUKSLowMemoryFlag, "allow-luks-low-memory", false, "Allow VM memory allocation lower than 2048 MiB when LUKS is enabled.")
runCmd.Flags().BoolVar(&debugShellFlag, "debug-shell", false, "Start a VM shell when the network file share is active.")
var defaultShareType string var defaultShareType string
switch runtime.GOOS { switch runtime.GOOS {

View file

@ -9,6 +9,7 @@ import (
"github.com/AlexSSD7/linsk/share" "github.com/AlexSSD7/linsk/share"
"github.com/AlexSSD7/linsk/vm" "github.com/AlexSSD7/linsk/vm"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"golang.org/x/term" "golang.org/x/term"
@ -41,22 +42,40 @@ var shellCmd = &cobra.Command{
} }
os.Exit(runVM(passthroughArg, func(ctx context.Context, i *vm.VM, fm *vm.FileManager, trc *share.NetTapRuntimeContext) int { os.Exit(runVM(passthroughArg, func(ctx context.Context, i *vm.VM, fm *vm.FileManager, trc *share.NetTapRuntimeContext) int {
sc, err := i.DialSSH() if trc != nil {
slog.Info("Tap networking is active", "host-ip", trc.Net.HostIP, "vm-ip", trc.Net.GuestIP)
}
err := runVMShell(ctx, i)
if err != nil { if err != nil {
slog.Error("Failed to dial VM SSH", "error", err.Error()) slog.Error("Failed to run VM shell", "error", err.Error())
return 1 return 1
} }
if trc != nil { return 0
slog.Info("Tap networking is active", "host-ip", trc.Net.HostIP, "vm-ip", trc.Net.GuestIP) }, forwardPortRules, true, enableTapNetFlag))
},
}
var forwardPortsFlagStr string
var enableTapNetFlag bool
func init() {
shellCmd.Flags().StringVar(&forwardPortsFlagStr, "forward-ports", "", "Extra TCP port forwarding rules. Syntax: '<HOST PORT>:<VM PORT>' OR '<HOST BIND IP>:<HOST PORT>:<VM PORT>'. Multiple rules split by comma are accepted.")
shellCmd.Flags().BoolVar(&enableTapNetFlag, "enable-net-tap", false, "Enables host-VM tap networking.")
}
func runVMShell(ctx context.Context, vi *vm.VM) error {
sc, err := vi.DialSSH()
if err != nil {
return errors.Wrap(err, "dial ssh")
} }
defer func() { _ = sc.Close() }() defer func() { _ = sc.Close() }()
sess, err := sc.NewSession() sess, err := sc.NewSession()
if err != nil { if err != nil {
slog.Error("Failed to create new VM SSH session", "error", err.Error()) return errors.Wrap(err, "new vm ssh session")
return 1
} }
defer func() { _ = sess.Close() }() defer func() { _ = sess.Close() }()
@ -64,8 +83,7 @@ var shellCmd = &cobra.Command{
termFD := int(os.Stdin.Fd()) termFD := int(os.Stdin.Fd())
termState, err := term.MakeRaw(termFD) termState, err := term.MakeRaw(termFD)
if err != nil { if err != nil {
slog.Error("Failed to make raw terminal", "error", err.Error()) return errors.Wrap(err, "make raw terminal")
return 1
} }
defer func() { defer func() {
@ -77,14 +95,13 @@ var shellCmd = &cobra.Command{
termFDGetSize := termFD termFDGetSize := termFD
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// Another Windows workaround :/ // Workaround for Windows.
termFDGetSize = int(os.Stdout.Fd()) termFDGetSize = int(os.Stdout.Fd())
} }
termWidth, termHeight, err := term.GetSize(termFDGetSize) termWidth, termHeight, err := term.GetSize(termFDGetSize)
if err != nil { if err != nil {
slog.Error("Failed to get terminal size", "error", err.Error()) return errors.Wrap(err, "get terminal size")
return 1
} }
termModes := ssh.TerminalModes{ termModes := ssh.TerminalModes{
@ -100,8 +117,7 @@ var shellCmd = &cobra.Command{
err = sess.RequestPty(term, termHeight, termWidth, termModes) err = sess.RequestPty(term, termHeight, termWidth, termModes)
if err != nil { if err != nil {
slog.Error("Failed to request VM SSH pty", "error", err.Error()) return errors.Wrap(err, "request vm ssh pty")
return 1
} }
sess.Stdin = os.Stdin sess.Stdin = os.Stdin
@ -110,8 +126,7 @@ var shellCmd = &cobra.Command{
err = sess.Shell() err = sess.Shell()
if err != nil { if err != nil {
slog.Error("Start VM SSH shell", "error", err.Error()) return errors.Wrap(err, "start vm ssh shell")
return 1
} }
doneCh := make(chan struct{}, 1) doneCh := make(chan struct{}, 1)
@ -130,15 +145,5 @@ var shellCmd = &cobra.Command{
case <-doneCh: case <-doneCh:
} }
return 0 return nil
}, forwardPortRules, true, enableTapNetFlag))
},
}
var forwardPortsFlagStr string
var enableTapNetFlag bool
func init() {
shellCmd.Flags().StringVar(&forwardPortsFlagStr, "forward-ports", "", "Extra TCP port forwarding rules. Syntax: '<HOST PORT>:<VM PORT>' OR '<HOST BIND IP>:<HOST PORT>:<VM PORT>'. Multiple rules split by comma are accepted.")
shellCmd.Flags().BoolVar(&enableTapNetFlag, "enable-net-tap", false, "Enables host-VM tap networking.")
} }