From 088cdc51a3c621c06c0086641ebad6644997ac3a Mon Sep 17 00:00:00 2001 From: Fedor Korotkov Date: Mon, 23 May 2022 09:49:15 -0400 Subject: [PATCH] Option to run with VNC (#97) * Option to run with VNC So copy/paste is working. For example, `tart run --vnc latest`. Related to 14 * Add VNC task first * Indicate the wait --- Sources/tart/Commands/IP.swift | 4 ++-- Sources/tart/Commands/Run.swift | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Sources/tart/Commands/IP.swift b/Sources/tart/Commands/IP.swift index 75d417c..905c049 100644 --- a/Sources/tart/Commands/IP.swift +++ b/Sources/tart/Commands/IP.swift @@ -17,7 +17,7 @@ struct IP: AsyncParsableCommand { let vmDir = try VMStorageLocal().open(name) let vmConfig = try VMConfig.init(fromURL: vmDir.configURL) - guard let ip = try await resolveIP(vmConfig, secondsToWait: wait) else { + guard let ip = try await IP.resolveIP(vmConfig, secondsToWait: wait) else { print("no IP address found, is your VM running?") Foundation.exit(1) @@ -33,7 +33,7 @@ struct IP: AsyncParsableCommand { } } - private func resolveIP(_ config: VMConfig, secondsToWait: UInt16) async throws -> IPv4Address? { + static public func resolveIP(_ config: VMConfig, secondsToWait: UInt16) async throws -> IPv4Address? { let waitUntil = Calendar.current.date(byAdding: .second, value: Int(secondsToWait), to: Date.now)! let vmMacAddress = MACAddress(fromString: config.macAddress.string)! diff --git a/Sources/tart/Commands/Run.swift b/Sources/tart/Commands/Run.swift index ddd7ba3..8def563 100644 --- a/Sources/tart/Commands/Run.swift +++ b/Sources/tart/Commands/Run.swift @@ -5,6 +5,9 @@ import Virtualization var vm: VM? +struct IPNotFound: Error { +} + struct Run: AsyncParsableCommand { static var configuration = CommandConfiguration(abstract: "Run a VM") @@ -14,13 +17,36 @@ struct Run: AsyncParsableCommand { @Flag var noGraphics: Bool = false @Flag var recovery: Bool = false + + @Flag var vnc: Bool = false @MainActor func run() async throws { + if recovery && vnc { + print("You can't run in recovery and use VNC!") + Foundation.exit(1) + } + let vmDir = try VMStorageLocal().open(name) vm = try VM(vmDir: vmDir) await withThrowingTaskGroup(of: Void.self) { group in + if vnc { + group.addTask(operation: { + do { + print("Waiting for the VM to boot...") + let resolvedIP = try await IP.resolveIP(vm!.config, secondsToWait: 60) + guard let ip = resolvedIP else { + throw IPNotFound() + } + let url = URL(string: "vnc://\(ip)")! + print("Opening \(url)") + NSWorkspace.shared.open(url) + } catch { + print("Failed to get an IP for screen sharing: \(error)") + } + }) + } group.addTask { do { try await vm!.run(recovery) @@ -33,7 +59,7 @@ struct Run: AsyncParsableCommand { } } - if noGraphics { + if noGraphics || vnc { dispatchMain() } else { runUI()