[gnome-boxes/allow-setting-number-of-vcpus: 5/5] libvirt-machine-properties: Allow the assignment of vCPUs



commit 9bf53c57235445687cc2477954db3d1787a54658
Author: Felipe Borges <felipeborges gnome org>
Date:   Wed Jan 29 17:36:53 2020 +0100

    libvirt-machine-properties: Allow the assignment of vCPUs
    
    This adds an UI option allowing users to assign how many cores
    they want a guest to use.
    
    Fixes #52

 src/i-properties-provider.vala      | 25 ++++++++++++
 src/libvirt-machine-properties.vala | 80 +++++++++++++++++++++++++++++++++++--
 src/vm-configurator.vala            |  4 +-
 3 files changed, 104 insertions(+), 5 deletions(-)
---
diff --git a/src/i-properties-provider.vala b/src/i-properties-provider.vala
index eae6e730..3ed89e08 100644
--- a/src/i-properties-provider.vala
+++ b/src/i-properties-provider.vala
@@ -169,6 +169,31 @@ public SizeProperty (string          name,
     }
 }
 
+private class Boxes.IntegerProperty : Boxes.Property {
+    public signal void changed (int value);
+
+    public int value {
+        get {
+            return (widget as Gtk.SpinButton).get_value_as_int ();
+        }
+    }
+
+    public IntegerProperty (string name,
+                            double min,
+                            double max,
+                            double step,
+                            double value) {
+        var spinbutton = new Gtk.SpinButton.with_range (min, max, step);
+        spinbutton.value = value;
+
+        spinbutton.value_changed.connect (() => {
+            changed (spinbutton.get_value_as_int ());
+        });
+
+        base (name, spinbutton, null);
+    }
+}
+
 private class Boxes.StringProperty : Boxes.Property {
     public string text {
         get { return (widget as Gtk.Label).label; }
diff --git a/src/libvirt-machine-properties.vala b/src/libvirt-machine-properties.vala
index 16af2237..5f5392e3 100644
--- a/src/libvirt-machine-properties.vala
+++ b/src/libvirt-machine-properties.vala
@@ -127,7 +127,7 @@ public string collect_logs () {
 
             get_resources_properties (ref list);
 
-            add_run_in_bg_property (ref list);
+            add_footer_properties (ref list);
 
             break;
 
@@ -650,9 +650,80 @@ private void resize_storage_volume (uint64 size) throws GLib.Error {
         return machine.domain.get_snapshots ();
     }
 
-    private void add_run_in_bg_property (ref List<Boxes.Property> list) {
+    private void add_footer_properties (ref List<Boxes.Property> list) {
+        var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
+
+        var set_vcpus_property = get_set_vcpus_property ();
+        box.pack_start (set_vcpus_property, false, false, 0);
+
+        var run_in_bg_property = get_run_in_bg_property ();
+        box.pack_end (run_in_bg_property, false, false, 0);
+
+        add_property (ref list, null, box, null);
+    }
+
+    private Gtk.Widget? get_set_vcpus_property () {
+        try {
+            var host_topology = machine.connection.get_node_info ();
+            var max_vcpus = host_topology.cores * host_topology.sockets * host_topology.threads;
+
+            var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10);
+            box.hexpand = false;
+            var label = new Gtk.Label ("");
+            label.set_markup ("<span color=\"grey\">%s</span>".printf (_("CPUs: ")));
+            label.halign = Gtk.Align.START;
+            box.add (label);
+
+            var property = new IntegerProperty (_("CPUs: "), 1, max_vcpus, 1, 
machine.domain_config.get_vcpus ());
+            property.changed.connect (on_vcpus_changed);
+            box.add (property.widget);
+
+            return box;
+        } catch (GLib.Error error) {
+            debug ("Failed to detect the number of vCPUs of %s: %s", machine.domain.get_name (), 
error.message);
+        }
+
+        return null;
+    }
+
+    private void on_vcpus_changed (Boxes.Property property, int vcpus) {
+        try {
+            if (machine.domain_config.get_vcpus () == vcpus)
+                return;
+
+            var config = machine.domain.get_config (GVir.DomainXMLFlags.INACTIVE);
+            config.set_vcpus (vcpus);
+            if (config.get_class ().find_property ("current-vcpus") != null)
+                config.set ("current-vcpus", vcpus);
+
+            var guest_topology = new GVirConfig.CapabilitiesCpuTopology ();
+            guest_topology.set_cores (vcpus);
+            guest_topology.set_sockets (1);
+            guest_topology.set_threads (1);
+
+            var cpu = machine.domain_config.get_cpu ();
+            cpu.set_topology (guest_topology);
+            config.set_cpu (cpu);
+
+            machine.domain.set_config (config);
+            debug ("vCPus changed to %d", vcpus);
+
+            if (machine.is_on) {
+                // TODO: unify the reboot requests for non-properties
+                var message = _("Changes require restart of ā€œ%sā€.").printf (machine.name);
+                machine.window.notificationbar.dismiss_all ();
+                machine.window.notificationbar.display_for_action (message, _("_Restart"), () => {
+                    machine.restart ();
+                });
+            }
+        } catch (GLib.Error error) {
+            debug ("Failed to set the number of vCPUs for %s : %s", machine.domain.get_name (), 
error.message);
+        }
+    }
+
+    private Gtk.Widget? get_run_in_bg_property () {
         if (machine.connection != App.app.default_connection)
-            return; // We only autosuspend machines on default connection so this property is N/A to other 
machines
+            return null; // We only autosuspend machines on default connection so this property is N/A to 
other machines
 
         var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 20);
         box.halign = Gtk.Align.END;
@@ -665,6 +736,7 @@ private void add_run_in_bg_property (ref List<Boxes.Property> list) {
         machine.bind_property ("run-in-bg", toggle, "active",
                                BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
         toggle.halign = Gtk.Align.START;
+        toggle.valign = Gtk.Align.CENTER;
         box.add (toggle);
         label.mnemonic_widget = toggle;
 
@@ -676,7 +748,7 @@ private void add_run_in_bg_property (ref List<Boxes.Property> list) {
                                               _("ā€œ%sā€ will be paused automatically to save 
resources.").printf (name);
         });
 
-        add_property (ref list, null, box, null);
+        return box;
     }
 
     private Boxes.SnapshotsProperty add_snapshots_property (ref List<Boxes.Property> list) {
diff --git a/src/vm-configurator.vala b/src/vm-configurator.vala
index 26aabfe6..730d7b31 100644
--- a/src/vm-configurator.vala
+++ b/src/vm-configurator.vala
@@ -256,7 +256,9 @@ public static async void update_existing_domain (Domain          domain,
 
         try {
             var cpu = domain.get_cpu ();
-            if (cpu != null && is_boxes_installed (domain)) {
+            if (cpu != null &&
+                (cpu.get_mode () != DomainCpuMode.HOST_PASSTHROUGH) &&
+                is_boxes_installed (domain)) {
                 var capabilities = yield connection.get_capabilities_async (null);
                 set_cpu_config (domain, capabilities);
             }


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