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

Time inside VM goes out of sync #3218

Closed
JaiganeshKumaran opened this issue Oct 28, 2021 · 23 comments
Closed

Time inside VM goes out of sync #3218

JaiganeshKumaran opened this issue Oct 28, 2021 · 23 comments
Labels
qemu QEMU related
Milestone

Comments

@JaiganeshKumaran
Copy link

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
@mdillavou
Copy link

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.

@conath
Copy link
Contributor

conath commented Oct 29, 2021

@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.

@mdillavou
Copy link

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.

@ktprograms
Copy link
Contributor

ktprograms commented Nov 4, 2021

@mdillavou If you install socat, then you can do this:

  1. 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
  1. (Inside the VM): Start the qemu-ga
  2. (In the host Mac): Run socat unix-connect:/Users/$USERNAME/Library/Containers/com.utmapp.QEMUHelper/Data/qga.sock readline
  3. (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)
  4. (In the socat session): Type in {"execute":"guest-set-time"} and press enter. There's no need to specify the time 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.

@mdillavou
Copy link

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:

  1. 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
  2. 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.

@ktprograms
Copy link
Contributor

ktprograms commented Nov 7, 2021

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.

@conath conath added enhancement New feature or request qemu QEMU related and removed enhancement New feature or request labels Nov 11, 2021
@navels
Copy link

navels commented Jan 10, 2022

Any updates on this? Any successful workarounds?

@ktprograms
Copy link
Contributor

ktprograms commented Jan 11, 2022

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

  1. Open the VM Configuration
  2. Go to the QEMU tab and scroll to the bottom.
  3. Click on the text box with the grey text New...
  4. 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
  1. Save the VM Configuration and Start the VM

Steps inside the VM

  1. 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 a qemu-guest-agent package.
  2. Start the qemu-ga program. You can either start the qemu-guest-agent service if your distro has it included in the package, otherwise just run qemu-ga -d (which starts the QEMU Guest Agent in the background).

Steps on the Host Mac

  1. Download the UTMSetTimeOnWake.swift file from my gist.
  2. In the Terminal, go to the directory containing the downloaded file.
  3. Run swift UTMSetTimeOnWake.swift
  4. 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.

@navels
Copy link

navels commented Jan 12, 2022

Thanks! I added a cron job to start this up on boot and it works great.

@ktprograms
Copy link
Contributor

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.

@navels
Copy link

navels commented Jan 13, 2022

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.

@ktprograms
Copy link
Contributor

In that case you might want to create a workflow that runs the script to the background, and add that to your Startup Applications?

@navels
Copy link

navels commented Jan 13, 2022

Any reason why that would be better than a cron task?

@ktprograms
Copy link
Contributor

Not really. If your current solution is working fine then just keep using it.

@lukaso
Copy link

lukaso commented May 31, 2022

Is there a solution/workaround for a MacOS guest? I'm running Monterey and have seen the clock go out of sync.

@lukaso
Copy link

lukaso commented Jun 4, 2022

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.

@wheel5up
Copy link

wheel5up commented Dec 5, 2022

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/

@osy osy added this to the v4.1 milestone Dec 14, 2022
@ktprograms
Copy link
Contributor

Just a reminder for @osy to look into providing guest IP address using QEMU guest agent as well.

@osy
Copy link
Contributor

osy commented Dec 31, 2022

I think this may go into v4.2 instead as v4.1 is already getting late...

@ktprograms
Copy link
Contributor

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?

@osy
Copy link
Contributor

osy commented Dec 31, 2022

Let's just keep this here for now.

@osy osy modified the milestones: v4.1, v4.2 Dec 31, 2022
@jtran19
Copy link

jtran19 commented Jan 5, 2023

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!

@osy osy closed this as completed in d0d3b1b Mar 12, 2023
osy added a commit that referenced this issue Mar 12, 2023
Automatically set guest time on GA connect and VM resume.

Resolves #3218
@ahrex
Copy link

ahrex commented Apr 27, 2023

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 d0d3b1b.

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
qemu QEMU related
Projects
None yet
Development

No branches or pull requests

10 participants