[virt-tools-list] [RFC PATCH v3 5/7] virtManager: config: Make guest time sync configurable

Michael Weiser michael.weiser at gmx.de
Mon Dec 9 21:53:15 UTC 2019


Add a global default and per-vm setting for enabling and disabling guest
time sync on resume operations. These settings will live in the local
dconf system and not travel with the domain xml as could alternatively
be implemented using the metadata element.

Signed-off-by: Michael Weiser <michael.weiser at gmx.de>
---
 .../org.virt-manager.virt-manager.gschema.xml | 12 +++++++
 ui/preferences.ui                             | 15 ++++++++
 ui/vmwindow.ui                                | 16 +++++++++
 virtManager/config.py                         |  9 +++++
 virtManager/object/domain.py                  | 36 +++++++++++++++----
 virtManager/preferences.py                    |  8 +++++
 virtManager/vmwindow.py                       | 20 +++++++++++
 7 files changed, 110 insertions(+), 6 deletions(-)

diff --git a/data/org.virt-manager.virt-manager.gschema.xml b/data/org.virt-manager.virt-manager.gschema.xml
index 511d6d13..bfcfde47 100644
--- a/data/org.virt-manager.virt-manager.gschema.xml
+++ b/data/org.virt-manager.virt-manager.gschema.xml
@@ -25,6 +25,12 @@
       <summary>Automatically resize guest when window size changes</summary>
       <description>Automatically change guest resolution along with virt-manager window. Only works with spice with a vdagent set up. -1 = global default, 0 = off, 1 = on.</description>
     </key>
+
+    <key name="sync-guest-time-on-resume" type="i">
+      <default>-1</default>
+      <summary>Automatically sync guest date and time on resume</summary>
+      <description>Automatically sync guest date and time when resuming from saved or paused state or reserting to a running state from a snapshot. Only works if a guest agent is running inside the guest. -1 = global default, 0 = off, 1 = on.</description>
+    </key>
   </schema>
 
 
@@ -65,6 +71,12 @@
       <description>Enable libguestfs VM inspection for things like OS icons, installed applications, etc. This only works if python libguestfs bindings are installed.</description>
     </key>
 
+    <key name="sync-guest-time-on-resume" type="b">
+      <default>true</default>
+      <summary>Automatically sync guest date and time on resume</summary>
+      <description>Automatically sync guest date and time when resuming from saved or paused state or reserting to a running state from a snapshot. Only works if a guest agent is running inside the guest.</description>
+    </key>
+
     <key name="manager-window-height" type="i">
       <default>0</default>
       <summary>Default manager window height</summary>
diff --git a/ui/preferences.ui b/ui/preferences.ui
index 1de17b33..81aabb4d 100644
--- a/ui/preferences.ui
+++ b/ui/preferences.ui
@@ -139,6 +139,21 @@
                             <property name="top_attach">1</property>
                           </packing>
                         </child>
+                        <child>
+                          <object class="GtkCheckButton" id="prefs-sync-guest-time-on-resume">
+                            <property name="label" translatable="yes">_Sync guest time on resume</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_underline">True</property>
+                            <property name="draw_indicator">True</property>
+                            <signal name="toggled" handler="on_prefs_sync_guest_time_on_resume_toggled" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">3</property>
+                          </packing>
+                        </child>
                       </object>
                     </child>
                   </object>
diff --git a/ui/vmwindow.ui b/ui/vmwindow.ui
index 6c78890a..4d226835 100644
--- a/ui/vmwindow.ui
+++ b/ui/vmwindow.ui
@@ -115,6 +115,22 @@
                         <signal name="activate" handler="on_details_menu_usb_redirection" swapped="no"/>
                       </object>
                     </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem" id="separator1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkCheckMenuItem" id="details-menu-sync-guest-time-on-resume">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="tooltip_text" translatable="yes">Requires guest agent to work</property>
+                        <property name="label" translatable="yes">_Sync guest time on resume</property>
+                        <property name="use_underline">True</property>
+                        <signal name="toggled" handler="on_details_menu_sync_guest_time_on_resume_toggled" swapped="no"/>
+                      </object>
+                    </child>
                   </object>
                 </child>
               </object>
diff --git a/virtManager/config.py b/virtManager/config.py
index 55c6f06b..68b000f6 100644
--- a/virtManager/config.py
+++ b/virtManager/config.py
@@ -387,6 +387,15 @@ class vmmConfig(object):
         self.conf.set("/enable-libguestfs-vm-inspection", val)
 
 
+    # guest time sync on resume
+    def on_sync_guest_time_on_resume_changed(self, cb):
+        return self.conf.notify_add("/sync-guest-time-on-resume", cb)
+    def get_sync_guest_time_on_resume(self):
+        return self.conf.get("/sync-guest-time-on-resume")
+    def set_sync_guest_time_on_resume(self, val):
+        self.conf.set("/sync-guest-time-on-resume", val)
+
+
     # Stats history and interval length
     def get_stats_history_length(self):
         return 120
diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py
index bad7108e..ea6fad62 100644
--- a/virtManager/object/domain.py
+++ b/virtManager/object/domain.py
@@ -1162,6 +1162,14 @@ class vmmDomain(vmmLibvirtObject):
     def refresh_snapshots(self):
         self._snapshot_list = None
 
+    def can_set_guest_time(self):
+        """
+        We can set the guest time if it's a test connection or a qemu
+        connection with an agent channel configured.
+        """
+        return (self.conn.is_test() or
+                (self.conn.is_qemu() and self._get_agent()))
+
     def _set_time(self):
         """
         Try to set VM time to the current value. This is typically useful when
@@ -1174,17 +1182,19 @@ class vmmDomain(vmmLibvirtObject):
         Heavily based on
         https://github.com/openstack/nova/commit/414df1e56ea9df700756a1732125e06c5d97d792.
         """
+        # Do not set time if disabled by the user
+        if not self.get_sync_guest_time_on_resume():
+            log.debug("Not syncing guest time because of user setting")
+            return
+
         # Only run the API for qemu and test drivers, they are the only ones
         # that support it. This will save spamming logs with error output.
-        if not self.conn.is_qemu() and not self.conn.is_test():
+        # For qemu, only run the API if the VM has the qemu guest agent in
+        # the XML.
+        if not self.can_set_guest_time():
             return
 
         if self.conn.is_qemu():
-            # For qemu, only run the API if the VM has the qemu guest agent in
-            # the XML.
-            if not self._get_agent():
-                return
-
             # wait for agent to come online
             maxwait = 5
             sleep = 0.5
@@ -1597,6 +1607,20 @@ class vmmDomain(vmmLibvirtObject):
         return self.config.set_pervm(self.get_uuid(), "/console-password",
                                      ("", -1))
 
+    def on_sync_guest_time_on_resume_changed(self, *args, **kwargs):
+        return self.config.listen_pervm(self.get_uuid(),
+                                        "/sync-guest-time-on-resume",
+                                        *args, **kwargs)
+    def set_sync_guest_time_on_resume(self, value):
+        self.config.set_pervm(self.get_uuid(), "/sync-guest-time-on-resume",
+                              value)
+    def get_sync_guest_time_on_resume(self):
+        ret = self.config.get_pervm(self.get_uuid(),
+                                    "/sync-guest-time-on-resume")
+        if ret == -1:
+            return self.config.get_sync_guest_time_on_resume()
+        return ret
+
     def get_cache_dir(self):
         ret = os.path.join(self.conn.get_cache_dir(), self.get_uuid())
         if not os.path.exists(ret):
diff --git a/virtManager/preferences.py b/virtManager/preferences.py
index 26d004fd..7366f51d 100644
--- a/virtManager/preferences.py
+++ b/virtManager/preferences.py
@@ -38,6 +38,7 @@ class vmmPreferences(vmmGObjectUI):
         self.refresh_view_system_tray()
         self.refresh_xmleditor()
         self.refresh_libguestfs()
+        self.refresh_sync_guest_time_on_resume()
         self.refresh_update_interval()
         self.refresh_console_accels()
         self.refresh_console_scaling()
@@ -68,6 +69,7 @@ class vmmPreferences(vmmGObjectUI):
             "on_prefs_system_tray_toggled": self.change_view_system_tray,
             "on_prefs_xmleditor_toggled": self.change_xmleditor,
             "on_prefs_libguestfs_toggled": self.change_libguestfs,
+            "on_prefs_sync_guest_time_on_resume_toggled": self.change_sync_guest_time_on_resume,
             "on_prefs_stats_update_interval_changed": self.change_update_interval,
             "on_prefs_console_accels_toggled": self.change_console_accels,
             "on_prefs_console_scaling_changed": self.change_console_scaling,
@@ -220,6 +222,10 @@ class vmmPreferences(vmmGObjectUI):
             self._orig_libguestfs_val = val
         self.widget("prefs-libguestfs").set_active(bool(val))
 
+    def refresh_sync_guest_time_on_resume(self):
+        val = self.config.get_sync_guest_time_on_resume()
+        self.widget("prefs-sync-guest-time-on-resume").set_active(bool(val))
+
     def refresh_update_interval(self):
         self.widget("prefs-stats-update-interval").set_value(
             self.config.get_stats_update_interval())
@@ -385,6 +391,8 @@ class vmmPreferences(vmmGObjectUI):
                self.widget("prefs-libguestfs").get_sensitive())
         uiutil.set_grid_row_visible(
                 self.widget("prefs-libguestfs-warn-box"), vis)
+    def change_sync_guest_time_on_resume(self, src):
+        self.config.set_sync_guest_time_on_resume(src.get_active())
 
     def change_update_interval(self, src):
         self.config.set_stats_update_interval(src.get_value_as_int())
diff --git a/virtManager/vmwindow.py b/virtManager/vmwindow.py
index 54e37399..b4cf20fc 100644
--- a/virtManager/vmwindow.py
+++ b/virtManager/vmwindow.py
@@ -90,6 +90,11 @@ class vmmVMWindow(vmmGObjectUI):
         self._vmmenu = None
         self.init_menus()
 
+        self._refresh_sync_guest_time_on_resume_from_settings()
+        self.add_gsettings_handle(
+            self.vm.on_sync_guest_time_on_resume_changed(
+                self._refresh_sync_guest_time_on_resume_from_settings))
+
         self.builder.connect_signals({
             "on_close_details_clicked": self.close,
             "on_details_menu_close_activate": self.close,
@@ -111,6 +116,8 @@ class vmmVMWindow(vmmGObjectUI):
             "on_details_menu_virtual_manager_activate": self.control_vm_menu,
             "on_details_menu_screenshot_activate": self.control_vm_screenshot,
             "on_details_menu_usb_redirection": self.control_vm_usb_redirection,
+            "on_details_menu_sync_guest_time_on_resume_toggled": (
+                self.details_sync_guest_time_on_resume_changed),
             "on_details_menu_view_toolbar_activate": self.toggle_toolbar,
             "on_details_menu_view_manager_activate": self.view_manager,
             "on_details_menu_view_details_toggled": self.details_console_changed,
@@ -472,6 +479,9 @@ class vmmVMWindow(vmmGObjectUI):
                        self.vm.has_spicevmc_type_redirdev())
         self.widget("details-menu-usb-redirection").set_sensitive(can_usb)
 
+        sync_time = self.widget("details-menu-sync-guest-time-on-resume")
+        sync_time.set_sensitive(self.vm.can_set_guest_time())
+
     def control_vm_run(self, src_ignore):
         if self._details.vmwindow_has_unapplied_changes():
             return
@@ -501,6 +511,16 @@ class vmmVMWindow(vmmGObjectUI):
                                       widget=spice_usbdev_widget,
                                       buttons=Gtk.ButtonsType.CLOSE)
 
+    def _refresh_sync_guest_time_on_resume_from_settings(self):
+        sync_time = self.widget("details-menu-sync-guest-time-on-resume")
+        does_sync_time = self.vm.get_sync_guest_time_on_resume()
+        sync_time.set_active(does_sync_time)
+
+    def details_sync_guest_time_on_resume_changed(self, src):
+        if not src.get_sensitive():
+            return
+        self.vm.set_sync_guest_time_on_resume(src.get_active())
+
     def _take_screenshot(self):
         image = self.console.details_viewer_get_pixbuf()
 
-- 
2.24.0





More information about the virt-tools-list mailing list