Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for running VM as temporary snapshot #3067

Merged
merged 6 commits into from
May 8, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Managers/UTMQemuSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) NSURL *imgPath;
@property (nonatomic, nullable) NSString *snapshot;
@property (nonatomic) NSInteger qmpPort;
@property (nonatomic) BOOL runAsSnapshot;

- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithConfiguration:(UTMQemuConfiguration *)configuration imgPath:(NSURL *)imgPath;
Expand Down
4 changes: 4 additions & 0 deletions Managers/UTMQemuSystem.m
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,10 @@ - (void)argsFromConfiguration {
[self pushArgv:@"-device"];
[self pushArgv:@"virtio-rng-pci"];
}

if (self.runAsSnapshot) {
[self pushArgv:@"-snapshot"];
}
}

- (void)argsFromUser {
Expand Down
12 changes: 9 additions & 3 deletions Managers/UTMQemuVirtualMachine.m
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,15 @@ - (void)_vmStartWithCompletion:(void (^)(NSError * _Nullable))completion {
}
}

if (self.isRunningAsSnapshot) {
self.system.runAsSnapshot = self.isRunningAsSnapshot;
} else {
// Loading save states isn't possible when -snapshot is used
conath marked this conversation as resolved.
Show resolved Hide resolved
if (self.viewState.hasSaveState) {
self.system.snapshot = kSuspendSnapshotName;
}
}

if (!_ioService) {
_ioService = [self inputOutputService];
}
Expand All @@ -309,9 +318,6 @@ - (void)_vmStartWithCompletion:(void (^)(NSError * _Nullable))completion {
completion(spiceError);
return;
}
if (self.viewState.hasSaveState) {
self.system.snapshot = kSuspendSnapshotName;
}
// start QEMU (this can be in parallel with QMP connect below)
__weak typeof(self) weakSelf = self;
__block NSError *qemuStartError = nil;
Expand Down
8 changes: 8 additions & 0 deletions Managers/UTMVirtualMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ NS_ASSUME_NONNULL_BEGIN
/// This property is observable and must only be accessed on the main thread.
@property (nonatomic, readonly) BOOL isBusy;

/// Whether the next start of this VM should have the -snapshot flag set
///
/// This will be passed to UTMQemuSystem,
/// and will be cleared when the VM stops or has an error.
///
/// This property is observable and must only be accessed on the main thread.
@property (nonatomic) BOOL isRunningAsSnapshot;

/// Checks if a save state exists
///
/// This property is observable and must only be accessed on the main thread.
Expand Down
8 changes: 8 additions & 0 deletions Managers/UTMVirtualMachine.m
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ - (BOOL)isBusy {
return (_state == kVMPausing || _state == kVMResuming || _state == kVMStarting || _state == kVMStopping);
}

- (void)setIsRunningAsSnapshot:(BOOL)isNextRunAsSnapshot {
[self propertyWillChange];
_isRunningAsSnapshot = isNextRunAsSnapshot;
}

- (NSString *)stateLabel {
switch (_state) {
case kVMStopped:
Expand Down Expand Up @@ -274,6 +279,9 @@ - (void)changeState:(UTMVMState)state {
if (state == kVMStarted) {
[self startScreenshotTimer];
}
if (state == kVMStopped) {
[self setIsRunningAsSnapshot:NO];
}
}

- (NSURL *)packageURLForName:(NSString *)name {
Expand Down
11 changes: 11 additions & 0 deletions Platform/Shared/VMContextMenuModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,22 @@ struct VMContextMenuModifier: ViewModifier {
Label("Stop", systemImage: "stop.fill")
}.help("Stop the running VM.")
} else {
Divider()

Button {
data.run(vm: vm)
} label: {
Label("Run", systemImage: "play.fill")
}.help("Run the VM in the foreground.")

Button {
vm.isRunningAsSnapshot = true
data.run(vm: vm)
} label: {
Label("Run without saving changes", systemImage: "play")
}.help("Run the VM in the foreground, without saving data changes to disk.")

Divider()
}
Button {
shareItem = .utmCopy(vm)
Expand Down
7 changes: 7 additions & 0 deletions Platform/iOS/Display/VMToolbarActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ import SwiftUI
}
}

var isRunningAsSnapshot: Bool {
guard let viewController = viewController else {
return false
}
return viewController.vm.isRunningAsSnapshot
}

private func optionalObjectWillChange() {
if #available(iOS 14, *) {
self.objectWillChange.send()
Expand Down
2 changes: 2 additions & 0 deletions Platform/iOS/Display/VMToolbarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ struct VMToolbarView: View {
} label: {
Label(state.isRunning ? "Pause" : "Play", systemImage: state.isRunning ? "pause" : "play")
}.offset(offset(for: 6))
.disabled(state.isRunningAsSnapshot)
.opacity(state.isRunningAsSnapshot ? 0.5 : 1.0)
Button {
state.restartPressed()
} label: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ extension VMDisplayMetalWindowController: VMMetalViewInputDelegate {
syncCapsLock()
qemuVM.requestInputTablet(true)
metalView?.releaseMouse()
self.window?.subtitle = ""
self.window?.subtitle = defaultSubtitle
}

func mouseMove(absolutePoint: CGPoint, button: CSInputButton) {
Expand Down
13 changes: 13 additions & 0 deletions Platform/macOS/Display/VMDisplayQemuDisplayController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ class VMDisplayQemuWindowController: VMDisplayWindowController {
vm?.config as? UTMQemuConfiguration
}

var defaultSubtitle: String {
if qemuVM.isRunningAsSnapshot {
return NSLocalizedString("Disposable Mode", comment: "VMDisplayQemuDisplayController")
} else {
return ""
}
}

override func enterLive() {
qemuVM.ioDelegate = self
startPauseToolbarItem.isEnabled = true
Expand All @@ -32,10 +40,15 @@ class VMDisplayQemuWindowController: VMDisplayWindowController {
startPauseToolbarItem.isEnabled = false
}
#endif
if qemuVM.isRunningAsSnapshot {
startPauseToolbarItem.isEnabled = false
startPauseToolbarItem.toolTip = NSLocalizedString("Disabled when running without saving changes.", comment: "VMDisplayQemuDisplayController")
}
drivesToolbarItem.isEnabled = vmQemuConfig.countDrives > 0
sharedFolderToolbarItem.isEnabled = qemuVM.hasShareDirectoryEnabled
usbToolbarItem.isEnabled = qemuVM.hasUsbRedirection
window!.title = vmQemuConfig.name
window!.subtitle = defaultSubtitle
super.enterLive()
}
}
Expand Down