[gnome-boxes] properties: Allow changing of RAM & storage size
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-boxes] properties: Allow changing of RAM & storage size
- Date: Mon, 5 Mar 2012 16:14:57 +0000 (UTC)
commit e75c506ab73506751bfd2cdedb943aff17e2f137
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date: Thu Feb 23 16:04:33 2012 +0200
properties: Allow changing of RAM & storage size
https://bugzilla.gnome.org/show_bug.cgi?id=664774
src/i-properties-provider.vala | 31 ++++++++++
src/libvirt-machine.vala | 119 +++++++++++++++++++++++++++++++++++++++-
src/properties.vala | 44 ++++++++------
src/spice-display.vala | 3 +
src/util.vala | 6 +-
src/vm-creator.vala | 2 +-
6 files changed, 181 insertions(+), 24 deletions(-)
---
diff --git a/src/i-properties-provider.vala b/src/i-properties-provider.vala
index 84eb7d4..068b780 100644
--- a/src/i-properties-provider.vala
+++ b/src/i-properties-provider.vala
@@ -2,6 +2,7 @@
using Gtk;
public delegate void PropertyStringChanged (string value) throws Boxes.Error;
+public delegate void PropertySizeChanged (uint64 value) throws Boxes.Error;
private interface Boxes.IPropertiesProvider: GLib.Object {
public abstract List<Pair<string, Widget>> get_properties (Boxes.PropertiesPage page);
@@ -30,5 +31,35 @@ private interface Boxes.IPropertiesProvider: GLib.Object {
add_property (ref list, name, entry);
}
+
+ protected void add_size_property (ref List<Pair<string, Widget>> list,
+ string name,
+ uint64 size,
+ uint64 min,
+ uint64 max,
+ uint64 step,
+ PropertySizeChanged? changed = null) {
+ var scale = new Gtk.HScale.with_range (min, max, step);
+
+ scale.format_value.connect ((scale, value) => {
+ return format_size (((uint64) value) * Osinfo.KIBIBYTES, FormatSizeFlags.IEC_UNITS);
+ });
+
+ scale.set_value (size);
+ scale.hexpand = true;
+ scale.vexpand = true;
+ scale.margin_bottom = 20;
+
+ if (changed != null)
+ scale.value_changed.connect (() => {
+ try {
+ changed ((uint64) scale.get_value ());
+ } catch (Boxes.Error error) {
+ warning (error.message);
+ }
+ });
+
+ add_property (ref list, name, scale);
+ }
}
diff --git a/src/libvirt-machine.vala b/src/libvirt-machine.vala
index a932844..f2f0bb6 100644
--- a/src/libvirt-machine.vala
+++ b/src/libvirt-machine.vala
@@ -82,6 +82,9 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
double net_write;
}
+ private uint ram_update_timeout = 0;
+ private uint storage_update_timeout = 0;
+
static const int STATS_SIZE = 20;
private MachineStat[] stats;
construct {
@@ -241,6 +244,11 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
add_string_property (ref list, _("URI"), display.uri);
break;
+ case PropertiesPage.SYSTEM:
+ add_ram_property (ref list);
+ add_storage_property (ref list);
+ break;
+
case PropertiesPage.DISPLAY:
add_string_property (ref list, _("Protocol"), display.protocol);
break;
@@ -331,7 +339,7 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
try {
if (connection == app.default_connection) {
- var volume = get_storage_volume (connection, domain);
+ var volume = get_storage_volume (connection, domain, null);
if (volume != null)
volume.delete (0);
}
@@ -348,7 +356,7 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
private GVir.DomainDisk? get_domain_disk () throws GLib.Error {
var disk = null as GVir.DomainDisk;
- var volume = get_storage_volume (connection, domain);
+ var volume = get_storage_volume (connection, domain, null);
foreach (var device in domain.get_devices ()) {
if (device is GVir.DomainDisk) {
@@ -383,4 +391,111 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
return net;
}
+
+ private void add_ram_property (ref List list) {
+ try {
+ var max_ram = connection.get_node_info ().memory;
+
+ add_size_property (ref list,
+ _("RAM"),
+ domain_config.memory,
+ Osinfo.MEBIBYTES / Osinfo.KIBIBYTES,
+ max_ram,
+ Osinfo.MEBIBYTES / Osinfo.KIBIBYTES,
+ on_ram_changed);
+ } catch (GLib.Error error) {}
+ }
+
+ private void on_ram_changed (uint64 value) {
+ // Ensure that we don't end-up changing RAM like a 1000 times a second while user moves the slider..
+ if (ram_update_timeout != 0)
+ Source.remove (ram_update_timeout);
+
+ ram_update_timeout = Timeout.add_seconds (1, () => {
+ domain_config.memory = value;
+ try {
+ domain.set_config (domain_config);
+ debug ("RAM changed to %llu", value);
+ notify_reboot_required ();
+ } catch (GLib.Error error) {
+ warning ("Failed to change RAM of box '%s' to %llu: %s",
+ domain.get_name (),
+ value,
+ error.message);
+ }
+ ram_update_timeout = 0;
+
+ return false;
+ });
+ }
+
+ private void notify_reboot_required () {
+ Notificationbar.OKFunc reboot = () => {
+ debug ("Rebooting '%s'..", name);
+ try {
+ domain.reboot (0);
+ } catch (GLib.Error error) {
+ warning ("Failed to reboot '%s': %s", domain.get_name (), error.message);
+ }
+ };
+ var message = _("Changes require restart of '%s'. Attempt restart?").printf (name);
+ app.notificationbar.display_for_action (message, Gtk.Stock.YES, (owned) reboot);
+ }
+
+ private void add_storage_property (ref List list) {
+ StoragePool pool;
+
+ var volume = get_storage_volume (connection, domain, out pool);
+ if (volume == null)
+ return;
+
+ try {
+ var volume_info = volume.get_info ();
+ var pool_info = pool.get_info ();
+ var max_storage = (volume_info.capacity + pool_info.available) / Osinfo.KIBIBYTES;
+
+ add_size_property (ref list,
+ _("Storage"),
+ volume_info.capacity / Osinfo.KIBIBYTES,
+ volume_info.capacity / Osinfo.KIBIBYTES,
+ max_storage,
+ Osinfo.GIBIBYTES / Osinfo.KIBIBYTES,
+ on_storage_changed);
+ } catch (GLib.Error error) {
+ warning ("Failed to get information on volume '%s' or it's parent pool: %s",
+ volume.get_name (),
+ error.message);
+ }
+ }
+
+ private void on_storage_changed (uint64 value) {
+ // Ensure that we don't end-up changing storage like a 1000 times a second while user moves the slider..
+ if (storage_update_timeout != 0)
+ Source.remove (storage_update_timeout);
+
+ storage_update_timeout = Timeout.add_seconds (1, () => {
+ var volume = get_storage_volume (connection, domain, null);
+ if (volume == null)
+ return false;
+
+ try {
+ if (is_running ()) {
+ var disk = get_domain_disk ();
+ if (disk != null)
+ disk.resize (value, 0);
+ } else
+ // Currently this never happens as properties page cant be reached without starting the machine
+ volume.resize (value * Osinfo.KIBIBYTES, StorageVolResizeFlags.NONE);
+ debug ("Storage changed to %llu", value);
+ } catch (GLib.Error error) {
+ warning ("Failed to change storage capacity of volume '%s' to %llu: %s",
+ volume.get_name (),
+ value,
+ error.message);
+ }
+ storage_update_timeout = 0;
+
+ return false;
+ });
+ }
}
diff --git a/src/properties.vala b/src/properties.vala
index 75aa148..cc4a23a 100644
--- a/src/properties.vala
+++ b/src/properties.vala
@@ -3,6 +3,7 @@ using Gtk;
private enum Boxes.PropertiesPage {
LOGIN,
+ SYSTEM,
DISPLAY,
DEVICES,
@@ -28,6 +29,7 @@ private class Boxes.Properties: Boxes.UI {
private class PageWidget {
public Gtk.Widget widget;
public string name;
+ public bool empty;
private Gtk.Grid grid;
@@ -37,6 +39,10 @@ private class Boxes.Properties: Boxes.UI {
name = _("Login");
break;
+ case PropertiesPage.SYSTEM:
+ name = _("System");
+ break;
+
case PropertiesPage.DISPLAY:
name = _("Display");
break;
@@ -59,28 +65,27 @@ private class Boxes.Properties: Boxes.UI {
label.hexpand = false;
grid.attach (label, 0, 0, 2, 1);
- int current_row = 1;
- foreach (var p in machine.get_properties (page)) {
- var label_name = new Gtk.Label (p.first);
- label_name.modify_fg (Gtk.StateType.NORMAL, get_color ("grey"));
- label_name.margin_left = 25;
- label_name.halign = Gtk.Align.START;
- label_name.hexpand = false;
- grid.attach (label_name, 0, current_row, 1, 1);
- var widget = p.second;
- widget.halign = Gtk.Align.START;
- grid.attach (widget, 1, current_row, 1, 1);
-
- current_row += 1;
+ var properties = machine.get_properties (page);
+ empty = properties.length () == 0;
+ if (!empty) {
+ int current_row = 1;
+ foreach (var property in properties) {
+ var label_name = new Gtk.Label (property.first);
+ label_name.modify_fg (Gtk.StateType.NORMAL, get_color ("grey"));
+ label_name.margin_left = 25;
+ label_name.halign = Gtk.Align.START;
+ label_name.hexpand = false;
+ grid.attach (label_name, 0, current_row, 1, 1);
+ var widget = property.second;
+ grid.attach (widget, 1, current_row, 1, 1);
+
+ current_row += 1;
+ }
}
grid.show_all ();
widget = grid;
}
-
- public bool is_empty () {
- return false;
- }
}
public Properties (App app) {
@@ -105,10 +110,11 @@ private class Boxes.Properties: Boxes.UI {
return;
for (var i = 0; i < PropertiesPage.LAST; i++) {
- var page = new PageWidget (i, app.current_item as Machine);
+ var machine = app.current_item as Machine;
+ var page = new PageWidget (i, machine);
notebook.append_page (page.widget, null);
- if (!page.is_empty ())
+ if (!page.empty)
list_append (listmodel, page.name);
}
diff --git a/src/spice-display.vala b/src/spice-display.vala
index e36f6ca..7a64e74 100644
--- a/src/spice-display.vala
+++ b/src/spice-display.vala
@@ -129,6 +129,7 @@ private class Boxes.SpiceDisplay: Boxes.Display, Boxes.IPropertiesProvider {
var toggle = new Gtk.Switch ();
gtk_session.bind_property ("auto-clipboard", toggle, "active",
BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
+ toggle.halign = Gtk.Align.START;
add_property (ref list, _("Share clipboard"), toggle);
try {
@@ -136,6 +137,7 @@ private class Boxes.SpiceDisplay: Boxes.Display, Boxes.IPropertiesProvider {
var display = get_display (0);
display.bind_property ("resize-guest", toggle, "active",
BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
+ toggle.halign = Gtk.Align.START;
add_property (ref list, _("Resize guest"), toggle);
} catch (Boxes.Error error) {
warning (error.message);
@@ -146,6 +148,7 @@ private class Boxes.SpiceDisplay: Boxes.Display, Boxes.IPropertiesProvider {
var toggle = new Gtk.Switch ();
gtk_session.bind_property ("auto-usbredir", toggle, "active",
BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE);
+ toggle.halign = Gtk.Align.START;
add_property (ref list, _("USB redirection"), toggle);
break;
}
diff --git a/src/util.vala b/src/util.vala
index 2388b2b..dd9e436 100644
--- a/src/util.vala
+++ b/src/util.vala
@@ -310,8 +310,10 @@ namespace Boxes {
return val.value;
}
- public GVir.StorageVol? get_storage_volume (GVir.Connection connection, GVir.Domain domain) {
- var pool = connection.find_storage_pool_by_name (Config.PACKAGE_TARNAME);
+ public GVir.StorageVol? get_storage_volume (GVir.Connection connection,
+ GVir.Domain domain,
+ out GVir.StoragePool pool) {
+ pool = connection.find_storage_pool_by_name (Config.PACKAGE_TARNAME);
if (pool == null)
// Absence of our pool just means that disk was not created by us.
return null;
diff --git a/src/vm-creator.vala b/src/vm-creator.vala
index d2674c1..6881db0 100644
--- a/src/vm-creator.vala
+++ b/src/vm-creator.vala
@@ -86,7 +86,7 @@ private class Boxes.VMCreator {
// steps for this domain.
return;
- var volume = get_storage_volume (connection, domain);
+ var volume = get_storage_volume (connection, domain, null);
if (guest_installed_os (volume)) {
post_install_setup (domain);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]