[gnome-boxes] Create VM based on host capabilities



commit 0daf0ad6b226ebc31ebc385b433bd590ff77b28f
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Thu May 3 07:34:42 2012 +0300

    Create VM based on host capabilities
    
    Choose the virtualization type (KVM or Qemu), architecture and features
    (acpi, apic and pae) of the created domain based on host capabilities and
    installer media.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=674209

 src/installer-media.vala |    8 ++++
 src/vm-configurator.vala |   87 ++++++++++++++++++++++++++++++++++++++++++---
 src/vm-creator.vala      |    3 +-
 3 files changed, 91 insertions(+), 7 deletions(-)
---
diff --git a/src/installer-media.vala b/src/installer-media.vala
index c912f9c..a726161 100644
--- a/src/installer-media.vala
+++ b/src/installer-media.vala
@@ -67,6 +67,14 @@ private class Boxes.InstallerMedia : Object {
         resources = media_manager.os_db.get_resources_for_os (os, architecture);
     }
 
+    public bool is_architecture_compatible (string architecture) {
+        return os_media == null || // Unknown media
+               os_media.architecture == architecture ||
+               (os_media.architecture == "i386" && architecture == "i686") ||
+               (os_media.architecture == "i386" && architecture == "x86_64") ||
+               (os_media.architecture == "i686" && architecture == "x86_64");
+    }
+
     private async GUdev.Device? get_device_from_path (string path, Client client, Cancellable? cancellable) {
         try {
             var mount_dir = File.new_for_commandline_arg (path);
diff --git a/src/vm-configurator.vala b/src/vm-configurator.vala
index 2066f4a..bffda50 100644
--- a/src/vm-configurator.vala
+++ b/src/vm-configurator.vala
@@ -3,6 +3,10 @@
 using Osinfo;
 using GVirConfig;
 
+private errordomain Boxes.VMConfiguratorError {
+    NO_GUEST_CAPS,
+}
+
 private class Boxes.VMConfigurator {
     private const string BOXES_NS = "boxes";
     private const string BOXES_NS_URI = "http://live.gnome.org/Boxes/";;
@@ -13,7 +17,8 @@ private class Boxes.VMConfigurator {
     private const string INSTALLATION_XML = "<os-state>" + INSTALLATION_STATE + "</os-state>";
     private const string INSTALLED_XML = "<os-state>" + INSTALLED_STATE + "</os-state>";
 
-    public Domain create_domain_config (InstallerMedia install_media, string target_path) {
+    public Domain create_domain_config (InstallerMedia install_media, string target_path, Capabilities caps)
+                                        throws VMConfiguratorError {
         var domain = new Domain ();
 
         var xml = (install_media.live) ? LIVE_XML : INSTALLATION_XML;
@@ -22,13 +27,24 @@ private class Boxes.VMConfigurator {
             domain.set_custom_xml (xml, BOXES_NS, BOXES_NS_URI);
         } catch (GLib.Error error) { assert_not_reached (); /* We are so screwed if this happens */ }
 
+        var best_caps = get_best_guest_caps (caps, install_media);
         domain.memory = install_media.resources.ram / KIBIBYTES;
         domain.vcpu = install_media.resources.n_cpus;
-        domain.set_virt_type (DomainVirtType.KVM);
 
-        set_os_config (domain, install_media);
+        var virt_type = guest_kvm_enabled (best_caps) ? DomainVirtType.KVM : DomainVirtType.QEMU;
+        domain.set_virt_type (virt_type);
+
+        set_os_config (domain, install_media, best_caps);
+
+        string[] features = {};
+        if (guest_supports_feature (best_caps, "acpi"))
+            features += "acpi";
+        if (guest_supports_feature (best_caps, "apic"))
+            features += "apic";
+        if (guest_supports_feature (best_caps, "pae"))
+            features += "pae";
+        domain.set_features (features);
 
-        domain.set_features ({ "acpi", "apic", "pae" });
         var clock = new DomainClock ();
         if (install_media.os != null && install_media.os.short_id.contains ("win"))
             clock.set_offset (DomainClockOffset.LOCALTIME);
@@ -214,10 +230,10 @@ private class Boxes.VMConfigurator {
         domain.set_os (os);
     }
 
-    private void set_os_config (Domain domain, InstallerMedia install_media) {
+    private void set_os_config (Domain domain, InstallerMedia install_media, CapabilitiesGuest guest_caps) {
         var os = new DomainOs ();
         os.set_os_type (DomainOsType.HVM);
-        os.set_arch ("x86_64");
+        os.set_arch (guest_caps.get_arch ().get_name ());
 
         var boot_devices = new GLib.List<DomainOsBootDevice> ();
         set_direct_boot_params (os, install_media);
@@ -292,4 +308,63 @@ private class Boxes.VMConfigurator {
 
         return null;
     }
+
+    private CapabilitiesGuest get_best_guest_caps (Capabilities caps, InstallerMedia install_media)
+                                                   throws VMConfiguratorError {
+        var guests_caps = caps.get_guests ();
+
+        // First find all compatible guest caps
+        var compat_guests_caps = new GLib.List<CapabilitiesGuest> ();
+        foreach (var guest_caps in guests_caps) {
+            var guest_arch = guest_caps.get_arch ().get_name ();
+
+            if (install_media.is_architecture_compatible (guest_arch))
+                compat_guests_caps.append (guest_caps);
+        }
+
+        // Now lets see if there is any KVM-enabled guest caps
+        foreach (var guest_caps in compat_guests_caps)
+            if (guest_kvm_enabled (guest_caps))
+                return guest_caps;
+
+        // No KVM-enabled guest caps :( We at least need Qemu
+        foreach (var guest_caps in compat_guests_caps)
+            if (guest_is_qemu (guest_caps))
+                return guest_caps;
+
+        // No guest caps or none compatible
+        // FIXME: Better error messsage than this please?
+        throw new VMConfiguratorError.NO_GUEST_CAPS (_("Incapable host system"));
+    }
+
+    private static bool guest_kvm_enabled (CapabilitiesGuest guest_caps) {
+        var arch = guest_caps.get_arch ();
+        foreach (var domain in arch.get_domains ())
+            if (domain.get_virt_type () == DomainVirtType.KVM)
+                return true;
+
+        return false;
+    }
+
+    private static bool guest_is_qemu (CapabilitiesGuest guest_caps) {
+        var arch = guest_caps.get_arch ();
+        foreach (var domain in arch.get_domains ())
+            if (domain.get_virt_type () == DomainVirtType.QEMU)
+                return true;
+
+        return false;
+    }
+
+    private static bool guest_supports_feature (CapabilitiesGuest guest_caps, string feature_name) {
+        var supports = false;
+
+        foreach (var feature in guest_caps.get_features ())
+            if (feature_name == feature.get_name ()) {
+                supports = true;
+
+                break;
+            }
+
+        return supports;
+    }
 }
diff --git a/src/vm-creator.vala b/src/vm-creator.vala
index 806d6cf..4b06414 100644
--- a/src/vm-creator.vala
+++ b/src/vm-creator.vala
@@ -63,7 +63,8 @@ private class Boxes.VMCreator {
         }
 
         var volume = yield create_target_volume (name, install_media.resources.storage);
-        var config = configurator.create_domain_config (install_media, volume.get_path ());
+        var caps = yield connection.get_capabilities_async (cancellable);
+        var config = configurator.create_domain_config (install_media, volume.get_path (), caps);
         config.name = name;
         config.title = title;
 



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