[gnome-boxes] vm-creator: Track & show installation progress



commit b11e1973d1ec31ce32337f9727c943093490f0b5
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Mon Aug 20 23:30:09 2012 +0300

    vm-creator: Track & show installation progress
    
    Its completely based on us knowing the guest disk usage after
    installation and we only know that in case of express installation. We
    do the same for non-express installations and live VMs.
    
    Another limitation is that we lose track of installations if user quits
    boxes in btw installation.
    
    On the bright side, we now have a more reliable way of knowing when
    installation is really complete for express installs.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=682300

 src/vm-creator.vala |   87 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 80 insertions(+), 7 deletions(-)
---
diff --git a/src/vm-creator.vala b/src/vm-creator.vala
index f71c8db..b337d54 100644
--- a/src/vm-creator.vala
+++ b/src/vm-creator.vala
@@ -4,6 +4,10 @@ using Osinfo;
 using GVir;
 
 private class Boxes.VMCreator {
+    // Seems installers aren't very consistent about exact number of bytes written so we ought to leave some margin
+    // of error. Its better to report '100%' done while its not exactly 100% than reporting '99%' done forever..
+    private const int INSTALL_COMPLETE_PERCENT = 99;
+
     public InstallerMedia? install_media { get; private set; }
 
     private Connection? connection { get { return App.app.default_connection; } }
@@ -107,8 +111,9 @@ private class Boxes.VMCreator {
                 warning ("Failed to start domain '%s': %s", domain.get_name (), error.message);
             }
             machine.disconnect (state_changed_id);
+            if (VMConfigurator.is_live_config (machine.domain_config) || !install_trackable ())
+                machine.info = null;
             machine.vm_creator = null;
-            machine.info = null;
         } else {
             if (VMConfigurator.is_live_config (machine.domain_config)) {
                 // No installation during live session, so lets delete the VM
@@ -124,9 +129,11 @@ private class Boxes.VMCreator {
     }
 
     private void update_machine_info (LibvirtMachine machine) {
-        if (VMConfigurator.is_install_config (machine.domain_config))
+        if (VMConfigurator.is_install_config (machine.domain_config)) {
             machine.info = _("Installing...");
-        else
+
+            track_install_progress (machine);
+        } else
             machine.info = _("Live");
     }
 
@@ -155,16 +162,82 @@ private class Boxes.VMCreator {
 
     private bool guest_installed_os (StorageVol volume) {
         try {
-            var info = volume.get_info ();
-
-            // If guest has used 1 MiB of storage, we assume it installed an OS on the volume
-            return (info.allocation >= Osinfo.MEBIBYTES);
+            if (install_trackable ())
+                // Great! We know how much storage installed guest consumes
+                return get_progress (volume) == INSTALL_COMPLETE_PERCENT;
+            else {
+                var info = volume.get_info ();
+
+                // If guest has used 1 MiB of storage, we assume it installed an OS on the volume
+                return (info.allocation >= Osinfo.MEBIBYTES);
+            }
         } catch (GLib.Error error) {
             warning ("Failed to get information from volume '%s': %s", volume.get_name (), error.message);
             return false;
         }
     }
 
+    int prev_progress = 0;
+    bool updating_install_progress;
+    private void track_install_progress (LibvirtMachine machine) {
+        if (!install_trackable ())
+            return;
+
+        var volume = get_storage_volume (connection, machine.domain, null);
+        return_if_fail (volume != null);
+
+        Timeout.add_seconds (6, () => {
+            if (prev_progress == 100) {
+                machine.info = null;
+
+                return false;
+            }
+
+            if (!updating_install_progress)
+                update_install_progress.begin (machine, volume);
+
+            return true;
+        });
+    }
+
+    private async void update_install_progress (LibvirtMachine machine, GVir.StorageVol volume) {
+        updating_install_progress = true;
+
+        int progress = 0;
+        try {
+            yield run_in_thread (() => {
+                progress = get_progress (volume);
+            });
+        } catch (GLib.Error error) {
+            warning ("Failed to get information from volume '%s': %s", volume.get_name (), error.message);
+        }
+        if (progress < 0)
+            return;
+
+        machine.info = _("%d%% Installed").printf (progress);
+        prev_progress = progress;
+        updating_install_progress = false;
+    }
+
+    private bool install_trackable () {
+        return (install_media != null && install_media.installed_size > 0);
+    }
+
+    private int get_progress (GVir.StorageVol volume) throws GLib.Error {
+        var volume_info = volume.get_info ();
+
+        var percent = (int) (volume_info.allocation * 100 /  install_media.installed_size);
+
+        // Make sure we don't display some rediculous figure in case we are wrong about installed size or libvirt
+        // gives us incorrect value for bytes written to disk.
+        percent = percent.clamp (0, INSTALL_COMPLETE_PERCENT);
+
+        if (percent == INSTALL_COMPLETE_PERCENT)
+            percent = 100;
+
+        return percent;
+    }
+
     private async void create_domain_name_and_title_from_media (out string name, out string title) throws GLib.Error {
         var base_title = install_media.label;
         title = base_title;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]