Make qvm run default to zsh and ensure workspace is mounted

This commit is contained in:
Joshua Bell 2026-01-27 01:28:32 -06:00
parent d5811679d6
commit 19f67670ab
2 changed files with 47 additions and 11 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
result result
^qvm ^qvm
vendor/ vendor/
/qvm

View file

@ -16,14 +16,20 @@ import (
) )
var runCmd = &cobra.Command{ var runCmd = &cobra.Command{
Use: "run <command> [args...]", Use: "run [command] [args...]",
Short: "Run a command in the VM workspace", Short: "Run a command in the VM workspace",
Long: `Execute a command in the VM at the current directory. Long: `Execute a command in the VM at the current directory.
The current directory is automatically registered as a workspace The current directory is automatically registered as a workspace
and mounted into the VM. The command runs in the mounted workspace.`, and mounted into the VM. The command runs in the mounted workspace.
Args: cobra.MinimumNArgs(1),
If no command is provided, starts an interactive zsh shell.`,
Args: cobra.ArbitraryArgs,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Default to zsh if no command provided
if len(args) == 0 {
args = []string{"zsh"}
}
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {
logging.Error(fmt.Sprintf("Failed to get current directory: %v", err)) logging.Error(fmt.Sprintf("Failed to get current directory: %v", err))
@ -50,21 +56,50 @@ and mounted into the VM. The command runs in the mounted workspace.`,
os.Exit(1) os.Exit(1)
} }
wasRunning := vm.IsRunning()
if !wasRunning {
logging.Info("VM is not running, starting it...")
cfg, err := config.Load() cfg, err := config.Load()
if err != nil { if err != nil {
logging.Error(err.Error()) logging.Error(err.Error())
os.Exit(1) os.Exit(1)
} }
wasRunning := vm.IsRunning()
if !wasRunning {
logging.Info("VM is not running, starting it...")
startResult := vm.Start(cfg, reg) startResult := vm.Start(cfg, reg)
if startResult.IsError() { if startResult.IsError() {
logging.Error(startResult.Error().Error()) logging.Error(startResult.Error().Error())
os.Exit(1) os.Exit(1)
} }
} else {
statusResult := vm.Status()
if statusResult.IsError() {
logging.Error(statusResult.Error().Error())
os.Exit(1)
}
status := statusResult.MustGet()
checkCmd := exec.Command("sshpass", "-p", "root", "ssh",
"-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "LogLevel=ERROR",
"-p", strconv.Itoa(status.SSHPort),
"root@localhost",
fmt.Sprintf("test -d /sys/bus/virtio/drivers/9pnet_virtio/*/mount_tag && grep -q 'ws_%s' /sys/bus/virtio/drivers/9pnet_virtio/*/mount_tag 2>/dev/null", ws.Hash))
if checkCmd.Run() != nil {
logging.Info("Workspace not available in running VM, restarting VM...")
stopResult := vm.Stop()
if stopResult.IsError() {
logging.Error(stopResult.Error().Error())
os.Exit(1)
}
startResult := vm.Start(cfg, reg)
if startResult.IsError() {
logging.Error(startResult.Error().Error())
os.Exit(1)
}
}
} }
statusResult := vm.Status() statusResult := vm.Status()
@ -74,8 +109,8 @@ and mounted into the VM. The command runs in the mounted workspace.`,
} }
status := statusResult.MustGet() status := statusResult.MustGet()
remoteCmd := fmt.Sprintf("mkdir -p '%s' && mount -t 9p ws_%s '%s' -o trans=virtio,version=9p2000.L,msize=104857600 2>/dev/null || true && cd '%s' && %s", remoteCmd := fmt.Sprintf("mkdir -p '%s' && (mountpoint -q '%s' || mount -t 9p ws_%s '%s' -o trans=virtio,version=9p2000.L,msize=104857600) && cd '%s' && %s",
ws.GuestPath, ws.Hash, ws.GuestPath, ws.GuestPath, strings.Join(args, " ")) ws.GuestPath, ws.GuestPath, ws.Hash, ws.GuestPath, ws.GuestPath, strings.Join(args, " "))
sshArgs := []string{ sshArgs := []string{
"-p", "root", "-p", "root",