UTM
UTM copied to clipboard
Time inside VM goes out of sync
Describe the issue When running VMs in the background over a long period of time, the time inside the VM goes out of sync after not using the VM for some time. This happens in all VMs regardless of the guest operating system.
Configuration
- UTM Version: 2.3.1 (38)
- Intel or Apple Silicon? Apple Silicon
I also have this issue, every time the host suspends. I thought the right thing to do was to install the qemu-guest-agent, but I cannot get that to work, as /dev/virtio-ports/org.qemu.guest_agent.0 doesn't exist.
@mdillavou for UTM VMs with "Full Graphics" display mode (default) you need to use SPICE guest agent instead of the QEMU guest agent. (sudo apt install spice-vdagent
) This might not be entirely useful for this issue, as spice-vdagent is only for the mouse and resolution features.
When running VMs through (non-SPICE) QEMU, it looks like the QEMU guest agent uses a serial port interface. QEMU wiki contains very similar looking arguments to enable the guest agent serial port like the ones in use by UTM for the SPICE agent (note that UTM uses QMP to communicate with running VMs). I am confused if these are compatible or even if they can be used at the same time.
I wanted to try this, so I pasted these lines to the QEMU tab of the UTM VM configuration UI:
-chardev qga_proxy,id=qga0
-device virtio-serial
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
Results in an error message when I attempt to start the VM:
qemu-aarch64-softmmu: -chardev qga_proxy,id=qga0: 'qga_proxy' is not a valid char driver name
I am out of my depth here, but I guess the QEMU included with UTM is built without the guest agent included.
As far as I know, SPICE only deals with the display and clipboard, not time.
For the guest agent, I configured mine with the following:
-chardev socket,path=qga.sock,server,nowait,id=qga0
-device virtio-serial
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
My VM started up fine, and I was able to successfully start the guest agent, as the /dev/virtio-ports/org.qemu.guest_agent.0
now exists, but it doesn't appear to do anything. I think the problem is the path=qga.sock
, as I am not sure what the host path should be as I don't know what UTM tries to connect to.
@mdillavou If you install socat
, then you can do this:
- Run the VM with these additional qemu arguments:
-chardev socket,path=qga.sock,server,nowait,id=qga0
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
- (Inside the VM): Start the
qemu-ga
- (In the host Mac): Run
socat unix-connect:/Users/$USERNAME/Library/Containers/com.utmapp.QEMUHelper/Data/qga.sock readline
- (In the socat session): Type in
{"execute":"guest-sync", "arguments":{"id":1234}}
and press enter (this is just a safety step to make sure guest and host communication is in sync) - (In the socat session): Type in
{"execute":"guest-set-time"}
and press enter. There's no need to specify thetime
argument since it can use host time.
Although this works, why not just run ntp in the guest (either manually or by restarting the ntp service)?
Technically all the additional QEMU arguments do is make a virtio serial port. It's just that it matches the name the qemu-ga
expects but in theory you could specify name=anythingyouwant
and run qemu-ga -p /dev/virtio-ports/anythingyouwant
. The path=qga.sock
is the entry point for communication to the /dev/virtio-ports/org.qemu.guest_agent
port, and since it's a relative path it ends up in the Data
folder of the com.utmapp.QEMUHelper
sandbox.
Interesting. That does work, but does UTM/qemu not come with an application to run on the host to connect to the socket and run those commands as appropriate? I suppose I could script something to manually connect an run every time my laptop wakes up.
I do use NTP in my guest. The problem is that:
- It can be slow to refresh, so I my time can be several minutes off without me noticing, and since I run in full screen, I've been late to meetings and my TOTP authentication fails
- If my computer has been asleep too long, then there is too much drift, and NTP won't update the clock. (I am running fedora 34 in my guest)
In my guest, I have a hot key to force the time to reset, but it'd be nice to not have to.
I'm thinking of adding (with a config toggle) a virtio serial port with
-chardev socket,port=4321,host=127.0.0.1,server,nowait,id=qga0
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
and use NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.didWakeNotification
in order to run the {"execute":"guest-set-time"}
command on host wakeup.
What do you think of in the System
pane under Advanced Settings
having a checkbox like Enable QEMU guest agent port
and Automatically sync guest time when host wakes up
?
Edit: Might be a while before I get this done since I need to figure out how UTM handles JSON and extend it for QEMU guest agent.
Any updates on this? Any successful workarounds?
I've taken some time to write a proper Swift program that sets the guest time when the host wakes. Here's the instructions on how to use it:
Steps before launching the VM
- Open the VM Configuration
- Go to the
QEMU
tab and scroll to the bottom. - Click on the text box with the grey text
New...
- Paste these two lines into it:
-chardev socket,port=4321,host=127.0.0.1,server,nowait,id=qga0
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
- Save the VM Configuration and Start the VM
Steps inside the VM
- Install the QEMU Guest Agent. On Debian/Ubuntu based systems run
sudo apt install qemu-guest-agent
. For other distros, you should be able to find aqemu-guest-agent
package. - Start the
qemu-ga
program. You can either start theqemu-guest-agent
service if your distro has it included in the package, otherwise just runqemu-ga -d
(which starts the QEMU Guest Agent in the background).
Steps on the Host Mac
- Download the
UTMSetTimeOnWake.swift
file from my gist. - In the Terminal, go to the directory containing the downloaded file.
- Run
swift UTMSetTimeOnWake.swift
- This will run continuously with no output, but when you wake your computer, it will automatically sync the guest time and print the message
Successfully re-synced guest time
.
Thanks! I added a cron job to start this up on boot and it works great.
a cron job to start this up on boot
If you're talking about starting up the Guest Agent inside the VM, it might be better to just use the init system service and enable it to run at boot.
a cron job to start this up on boot
If you're talking about starting up the Guest Agent inside the VM, it might be better to just use the init system service and enable it to run at boot.
Ah, no, I mean that swift script on the host.
In that case you might want to create a workflow that runs the script to the background, and add that to your Startup Applications?
Any reason why that would be better than a cron task?
Not really. If your current solution is working fine then just keep using it.
Is there a solution/workaround for a MacOS guest? I'm running Monterey and have seen the clock go out of sync.
For macOS guest I've used ChronyControl and then set
# As a VM the time can get badly out of sync. This allows big steps
makestep 1 -1
Since it can get wildly out of step. This may cause excess jumps, so it doesn't stop the problem, but it's a workaround.
this seemed to resolve it for me
sudo sntp -sS time.apple.com
I didn't use the container over the weekend and it was three days behind.
https://forums.macrumors.com/threads/time-synchronization-command-line-in-macos-big-sur.2279396/
Just a reminder for @osy to look into providing guest IP address using QEMU guest agent as well.
I think this may go into v4.2 instead as v4.1 is already getting late...
No problem, don't rush yourself. Would you like this to be in a separate issue then? Or do you want to track guest agent implementation in only one placee?
Let's just keep this here for now.
this seemed to resolve it for me
sudo sntp -sS time.apple.com
I didn't use the container over the weekend and it was three days behind.
https://forums.macrumors.com/threads/time-synchronization-command-line-in-macos-big-sur.2279396/
Thanks for this workaround!
Hello, I came across this issue while trying to sync time in my VM.
I found with UTM 4.2.5 I'm able to force a time sync in the guest VM by restarting qemu-guest-agent.service
/ qemu-ga
, causing the following log lines to be printed out by UTM:
2023-04-27 13:56:25.164 UTM[25390:347692] QMP disconnected
2023-04-27 13:56:25.164 UTM[25390:347692] QEMU guest agent has disconnected.
2023-04-27 13:56:25.186 UTM[25390:347692] QEMU guest agent has connected.
2023-04-27 13:56:25.187 UTM[25390:487901] Debug JSON send -> {
arguments = {
id = 1751658945;
};
execute = "guest-sync-delimited";
}
2023-04-27 13:56:25.187 UTM[25390:490494] Debug JSON recieved <- {
return = 1751658945;
}
2023-04-27 13:56:25.188 UTM[25390:487901] Debug JSON send -> {
arguments = {
time = 1682618185186910208;
};
execute = "guest-set-time";
}
I took this clue from https://github.com/utmapp/UTM/commit/d0d3b1bb2ad35966830c3f2bd6a46d1bfbbc992c.
My issue though, is that when I close my Macbook to place my host to sleep at t=x
, resuming from sleep y
seconds later, no guest-set-time
command is issued, resulting in drift where my host OS is at t=x+y
while the guest is still at t=x
.
May I request that additional hooks be added into UTM to call guest-set-time
when resuming the host from sleep?
Please also let me know if you'd like me to file a new issue. Thanks!
Edit: I see #5252 has been filed for this follow-up issue. Will follow there, thanks!