[gnome-boxes] Start making use of libvirt-gconfig



commit 1cb45c3a406529788689ea44271039f5ac3f8c00
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Fri Dec 2 01:59:05 2011 +0200

    Start making use of libvirt-gconfig
    
    Instead of manually writing the libvirt's XML strings, we now make use
    of libvirt-gconfig to deal with the XML for us.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=666315

 configure.ac             |    2 +-
 src/Makefile.am          |    1 +
 src/vm-configurator.vala |  199 ++++++++++++++++++++++++++++++++++++++++++++++
 src/vm-creator.vala      |  199 ++++------------------------------------------
 4 files changed, 217 insertions(+), 184 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index bd70d5e..026f3b6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,7 +50,7 @@ GOBJECT_INTROSPECTION_MIN_VERSION=0.9.6
 GTK_MIN_VERSION=3.3.3
 GTK_VNC_MIN_VERSION=0.4.4
 LIBVIRT_GLIB_MIN_VERSION=0.0.3
-LIBVIRT_GCONFIG_MIN_VERSION=0.0.1
+LIBVIRT_GCONFIG_MIN_VERSION=0.0.3
 LIBXML2_MIN_VERSION=2.7.8
 SPICE_GTK_MIN_VERSION=0.7.98
 GUDEV_MIN_VERSION=167
diff --git a/src/Makefile.am b/src/Makefile.am
index f7b857b..4d529a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,6 +57,7 @@ gnome_boxes_SOURCES =				\
 	unattended-installer.vala 		\
 	util.vala				\
 	vm-creator.vala 			\
+	vm-configurator.vala 			\
 	vnc-display.vala			\
 	win7-installer.vala 			\
 	winxp-installer.vala 			\
diff --git a/src/vm-configurator.vala b/src/vm-configurator.vala
new file mode 100644
index 0000000..d4b61df
--- /dev/null
+++ b/src/vm-configurator.vala
@@ -0,0 +1,199 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+using Osinfo;
+using GVirConfig;
+
+private class Boxes.VMConfigurator {
+    public Domain create_domain_config (InstallerMedia install_media,
+                                        string         name,
+                                        string         target_path,
+                                        Resources      resources) {
+
+        var domain = new Domain ();
+        domain.name = name;
+        domain.memory = resources.ram / KIBIBYTES;
+        domain.vcpu = resources.n_cpus;
+        domain.set_virt_type (DomainVirtType.KVM);
+
+        set_os_config (domain, install_media);
+
+        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);
+        else
+            clock.set_offset (DomainClockOffset.UTC);
+        domain.set_clock (clock);
+
+        set_target_media_config (domain, target_path);
+        set_unattended_floppy_config (domain, install_media);
+        set_source_media_config (domain, install_media);
+
+        var input = new DomainInput ();
+        input.set_bus (DomainInputBus.USB);
+        input.set_device_type (DomainInputDeviceType.TABLET);
+        domain.add_device (input);
+
+        var graphics = new DomainGraphicsSpice ();
+        graphics.set_autoport (true);
+        domain.add_device (graphics);
+
+        set_video_config (domain, install_media);
+
+        domain.set_lifecycle (DomainLifecycleEvent.ON_POWEROFF, DomainLifecycleAction.DESTROY);
+        domain.set_lifecycle (DomainLifecycleEvent.ON_REBOOT, DomainLifecycleAction.DESTROY);
+        domain.set_lifecycle (DomainLifecycleEvent.ON_CRASH, DomainLifecycleAction.DESTROY);
+
+        var console = new DomainConsole ();
+        console.set_source (new DomainChardevSourcePty ());
+        domain.add_device (console);
+
+        var iface = new DomainInterfaceUser ();
+        domain.add_device (iface);
+
+        return domain;
+    }
+
+    public void post_install_setup (Domain domain) {
+        set_os_config (domain);
+        domain.set_lifecycle (DomainLifecycleEvent.ON_REBOOT, DomainLifecycleAction.RESTART);
+    }
+
+    public StorageVol create_volume_config (string name, int64 storage) throws GLib.Error {
+        var volume = new StorageVol ();
+        volume.set_name (name);
+        volume.set_capacity (storage);
+        var target = new StorageVolTarget ();
+        target.set_format ("qcow2");
+        var permissions = get_default_permissions ();
+        target.set_permissions (permissions);
+        volume.set_target (target);
+
+        return volume;
+    }
+
+    public StoragePool get_pool_config () throws GLib.Error {
+        var pool_path = get_pkgconfig ("images");
+        ensure_directory (pool_path);
+
+        var pool = new StoragePool ();
+        pool.set_pool_type (StoragePoolType.DIR);
+        pool.set_name (Config.PACKAGE_TARNAME);
+
+        var source = new StoragePoolSource ();
+        source.set_directory (pool_path);
+        pool.set_source (source);
+
+        var target = new StoragePoolTarget ();
+        target.set_path (pool_path);
+        var permissions = get_default_permissions ();
+        target.set_permissions (permissions);
+        pool.set_target (target);
+
+        return pool;
+    }
+
+    private void set_target_media_config (Domain domain, string target_path) {
+        var disk = new DomainDisk ();
+        disk.set_type (DomainDiskType.FILE);
+        disk.set_guest_device_type (DomainDiskGuestDeviceType.DISK);
+        disk.set_driver_name ("qemu");
+        disk.set_driver_type ("qcow2");
+        disk.set_source (target_path);
+        disk.set_target_dev ("hda");
+        disk.set_target_bus (DomainDiskBus.IDE);
+
+        domain.add_device (disk);
+    }
+
+    private void set_source_media_config (Domain domain, InstallerMedia install_media) {
+        var disk = new DomainDisk ();
+        disk.set_guest_device_type (DomainDiskGuestDeviceType.CDROM);
+        disk.set_driver_name ("qemu");
+        disk.set_driver_type ("raw");
+        disk.set_source (install_media.device_file);
+        disk.set_target_dev ("hdc");
+        disk.set_target_bus (DomainDiskBus.IDE);
+
+        if (install_media.from_image)
+            disk.set_type (DomainDiskType.FILE);
+        else
+            disk.set_type (DomainDiskType.BLOCK);
+
+        domain.add_device (disk);
+    }
+
+    private void set_unattended_floppy_config (Domain domain, InstallerMedia install_media) {
+        if (!(install_media is UnattendedInstaller))
+            return;
+
+        var floppy_path = (install_media as UnattendedInstaller).floppy_path;
+        if (floppy_path == null)
+            return;
+
+        var disk = new DomainDisk ();
+        disk.set_type (DomainDiskType.FILE);
+        disk.set_guest_device_type (DomainDiskGuestDeviceType.FLOPPY);
+        disk.set_driver_name ("qemu");
+        disk.set_driver_type ("raw");
+        disk.set_source (floppy_path);
+        disk.set_target_dev ("fd");
+
+        domain.add_device (disk);
+    }
+
+    private void set_os_config (Domain domain, InstallerMedia? install_media = null) {
+        var os = new DomainOs ();
+        os.set_os_type (DomainOsType.HVM);
+        os.set_arch ("x86_64");
+
+        var boot_devices = new GLib.List<DomainOsBootDevice> ();
+        if (install_media != null) {
+            set_direct_boot_params (os, install_media);
+            boot_devices.append (DomainOsBootDevice.CDROM);
+        }
+        boot_devices.append (DomainOsBootDevice.HD);
+        os.set_boot_devices (boot_devices);
+
+        domain.set_os (os);
+    }
+
+    private void set_direct_boot_params (DomainOs os, InstallerMedia install_media) {
+        if (!(install_media is UnattendedInstaller))
+            return;
+
+        var unattended = install_media as UnattendedInstaller;
+
+        var kernel_path = unattended.kernel_path;
+        var initrd_path = unattended.initrd_path;
+
+        if (kernel_path == null || initrd_path == null)
+            return;
+
+        os.set_kernel (kernel_path);
+        os.set_ramdisk (initrd_path);
+        os.set_cmdline ("ks=floppy");
+    }
+
+    private void set_video_config (Domain domain, InstallerMedia install_media) {
+        var video = new DomainVideo ();
+
+        // FIXME: Should be QXL for every OS. Work-around for a Qemu bug
+        if (install_media is Win7Installer)
+            video.set_model (DomainVideoModel.VGA);
+        else
+            video.set_model (DomainVideoModel.QXL);
+
+        domain.add_device (video);
+    }
+
+    private StoragePermissions get_default_permissions () {
+        var permissions = new StoragePermissions ();
+
+        permissions.set_owner ((uint) Posix.getuid ());
+        permissions.set_group ((uint) Posix.getgid ());
+        permissions.set_mode (744);
+
+        return permissions;
+    }
+}
diff --git a/src/vm-creator.vala b/src/vm-creator.vala
index 3492fb1..844cb9f 100644
--- a/src/vm-creator.vala
+++ b/src/vm-creator.vala
@@ -5,24 +5,16 @@ using GVir;
 
 private class Boxes.VMCreator {
     private Connection connection;
-
-    private static Regex direct_boot_regex;
-    private static Regex cdrom_boot_regex;
-    private static Regex on_reboot_regex;
-
-    static construct {
-        direct_boot_regex = /<kernel>.*<\/cmdline>/msx;
-        cdrom_boot_regex = /<boot.*dev=.cdrom.\/>/msx;
-        on_reboot_regex = /<on_reboot>destroy/msx;
-    }
+    private VMConfigurator configurator;
 
     public VMCreator (App app, string uri) throws GLib.Error {
         connection = new Connection (uri);
+        configurator = new VMConfigurator ();
     }
 
-    public async GVir.Domain create_and_launch_vm (InstallerMedia install_media,
-                                                   Resources      resources,
-                                                   Cancellable?   cancellable) throws GLib.Error {
+    public async Domain create_and_launch_vm (InstallerMedia install_media,
+                                              Resources      resources,
+                                              Cancellable?   cancellable) throws GLib.Error {
         if (!connection.is_open ())
             yield connect (cancellable);
 
@@ -35,10 +27,12 @@ private class Boxes.VMCreator {
         else
             name = install_media.label;
 
-        var volume = yield create_target_volume (name, resources.storage);
+        var domain_name = name;
+        for (var i = 1; connection.find_domain_by_name (domain_name) != null; i++)
+            domain_name = name + "-" + i.to_string ();
 
-        var xml = get_virt_xml (install_media, name, volume.get_path (), resources);
-        var config = new GVirConfig.Domain.from_xml (xml);
+        var volume = yield create_target_volume (name, resources.storage);
+        var config = configurator.create_domain_config (install_media, domain_name, volume.get_path (), resources);
 
         Domain domain;
         if (install_media.live)
@@ -70,13 +64,14 @@ private class Boxes.VMCreator {
     }
 
     private void post_install_setup (Domain domain, GVirConfig.Domain config, bool permanent) {
+        configurator.post_install_setup (config);
+
         try {
-            var new_config = create_post_install_config (config);
             if (permanent) {
-                domain.set_config (new_config);
+                domain.set_config (config);
                 domain.start (0);
             } else {
-                var new_domain = connection.create_domain (new_config);
+                var new_domain = connection.create_domain (config);
                 new_domain.start (0);
             }
         } catch (GLib.Error error) {
@@ -96,65 +91,12 @@ private class Boxes.VMCreator {
         }
     }
 
-    private GVirConfig.Domain create_post_install_config (GVirConfig.Domain config) throws GLib.Error {
-        // FIXME: We really should use GVirConfig API (as soon as its available) to modify the configuration XML.
-        var xml = config.to_xml ();
-        xml = direct_boot_regex.replace (xml, -1, 0, "");
-        xml = cdrom_boot_regex.replace (xml, -1, 0, "");
-        xml = on_reboot_regex.replace (xml, -1, 0, "<on_reboot>restart");
-
-        return new GVirConfig.Domain.from_xml (xml);
-    }
-
     private async void connect (Cancellable? cancellable) throws GLib.Error {
         yield connection.open_async (cancellable);
         yield connection.fetch_domains_async (cancellable);
         yield connection.fetch_storage_pools_async (cancellable);
     }
 
-    private string get_virt_xml (InstallerMedia install_media, string name, string target_path, Resources resources) {
-        // FIXME: This information should come from libosinfo
-        var clock_offset = "utc";
-        if (install_media.os != null && install_media.os.short_id.contains ("win"))
-            clock_offset = "localtime";
-
-        var domain_name = name;
-        for (var i = 1; connection.find_domain_by_name (domain_name) != null; i++)
-            domain_name = name + "-" + i.to_string ();
-
-        var ram = (resources.ram / KIBIBYTES).to_string ();
-        return "<domain type='kvm'>\n" +
-               "  <name>" +  domain_name + "</name>\n" +
-               "  <memory>" + ram + "</memory>\n" +
-               "  <vcpu>" + resources.n_cpus.to_string () + "</vcpu>\n" +
-               "  <os>\n" +
-               "    <type arch='x86_64'>hvm</type>\n" +
-               "    <boot dev='cdrom'/>\n" +
-               "    <boot dev='hd'/>\n" +
-               get_direct_boot_xml (install_media) +
-               "  </os>\n" +
-               "  <features>\n" +
-               "    <acpi/><apic/><pae/>\n" +
-               "  </features>\n" +
-               "  <clock offset='" + clock_offset + "'/>\n" +
-               "  <on_poweroff>destroy</on_poweroff>\n" +
-               "  <on_reboot>destroy</on_reboot>\n" +
-               "  <on_crash>destroy</on_crash>\n" +
-               "  <devices>\n" +
-               get_target_media_xml (target_path) +
-               get_unattended_dir_floppy_xml (install_media) +
-               get_source_media_xml (install_media) +
-               "    <interface type='user'>\n" +
-               "      <mac address='00:11:22:33:44:55'/>\n" +
-               "    </interface>\n" +
-               "    <input type='tablet' bus='usb'/>\n" +
-               "    <graphics type='spice' autoport='yes' />\n" +
-               "    <console type='pty'/>\n" +
-               get_video_xml (install_media) +
-               "  </devices>\n" +
-               "</domain>";
-    }
-
     private async StorageVol create_target_volume (string name, int64 storage) throws GLib.Error {
         var pool = yield get_storage_pool ();
 
@@ -162,117 +104,16 @@ private class Boxes.VMCreator {
         for (var i = 1; pool.get_volume (volume_name) != null; i++)
             volume_name = name + "-" + i.to_string () + ".qcow2";
 
-        var storage_str = (storage / GIBIBYTES).to_string ();
-        var xml = "<volume>\n" +
-                  "  <name>" + volume_name + "</name>\n" +
-                  "  <capacity unit='G'>" + storage_str + "</capacity>\n" +
-                  "  <target>\n" +
-                  "    <format type='qcow2'/>\n" +
-                  "    <permissions>\n" +
-                  "      <owner>" + get_uid () + "</owner>\n" +
-                  "      <group>" + get_gid () + "</group>\n" +
-                  "      <mode>0744</mode>\n" +
-                  "      <label>virt-image-" + name + "</label>\n" +
-                  "    </permissions>\n" +
-                  "  </target>\n" +
-                  "</volume>";
-        var config = new GVirConfig.StorageVol.from_xml (xml);
+        var config = configurator.create_volume_config (volume_name, storage);
         var volume = pool.create_volume (config);
 
         return volume;
     }
 
-    private string get_target_media_xml (string target_path) {
-        return "    <disk type='file' device='disk'>\n" +
-               "      <driver name='qemu' type='qcow2'/>\n" +
-               "      <source file='" + target_path + "'/>\n" +
-               "      <target dev='hda' bus='ide'/>\n" +
-               "    </disk>\n";
-    }
-
-    private string get_source_media_xml (InstallerMedia install_media) {
-        string type, source_attr;
-
-        if (install_media.from_image) {
-            type = "file";
-            source_attr = "file" ;
-        } else {
-            type = "block";
-            source_attr = "dev";
-        }
-
-        return "    <disk type='" + type + "'\n" +
-               "          device='cdrom'>\n" +
-               "      <driver name='qemu' type='raw'/>\n" +
-               "      <source " + source_attr + "='" +
-                                  install_media.device_file + "'/>\n" +
-               "      <target dev='hdc' bus='ide'/>\n" +
-               "      <readonly/>\n" +
-               "    </disk>\n";
-    }
-
-    private string get_unattended_dir_floppy_xml (InstallerMedia install_media) {
-        if (!(install_media is UnattendedInstaller))
-            return "";
-
-        var floppy_path = (install_media as UnattendedInstaller).floppy_path;
-        if (floppy_path == null)
-            return "";
-
-        return "    <disk type='file' device='floppy'>\n" +
-               "      <driver name='qemu' type='raw'/>\n" +
-               "      <source file='" + floppy_path + "'/>\n" +
-               "      <target dev='fd'/>\n" +
-               "    </disk>\n";
-    }
-
-    private string get_direct_boot_xml (InstallerMedia install_media) {
-        if (!(install_media is UnattendedInstaller))
-            return "";
-
-        var unattended = install_media as UnattendedInstaller;
-
-        var kernel_path = unattended.kernel_path;
-        var initrd_path = unattended.initrd_path;
-
-        if (kernel_path == null || initrd_path == null)
-            return "";
-
-        return "    <kernel>" + kernel_path + "</kernel>\n" +
-               "    <initrd>" + initrd_path + "</initrd>\n" +
-               "    <cmdline>ks=floppy</cmdline>\n";
-    }
-
-    private string get_video_xml (InstallerMedia install_media) {
-        // FIXME: Should be 'qxl' for every OS. Work-around for a Qemu bug
-        var type = (install_media is Win7Installer) ? "vga" : "qxl";
-
-        return "    <video>\n" +
-               "      <model type='" + type + "'/>\n" +
-               "    </video>\n";
-    }
-
     private async StoragePool get_storage_pool () throws GLib.Error {
         var pool = connection.find_storage_pool_by_name (Config.PACKAGE_TARNAME);
         if (pool == null) {
-            var pool_path = get_pkgconfig ("images");
-            ensure_directory (pool_path);
-            var xml = "<pool type='dir'>\n" +
-                      "<name>" + Config.PACKAGE_TARNAME + "</name>\n" +
-                      "  <source>\n" +
-                      "    <directory path='" + pool_path + "'/>\n" +
-                      "  </source>\n" +
-                      "  <target>\n" +
-                      "    <path>" + pool_path + "</path>\n" +
-                      "    <permissions>\n" +
-                      "      <owner>" + get_uid () + "</owner>\n" +
-                      "      <group>" + get_gid () + "</group>\n" +
-                      "      <mode>0744</mode>\n" +
-                      "      <label>" + Config.PACKAGE_TARNAME + "</label>\n" +
-                      "    </permissions>\n" +
-                      "  </target>\n" +
-                      "</pool>";
-            var config = new GVirConfig.StoragePool.from_xml (xml);
+            var config = configurator.get_pool_config ();
             pool = connection.create_storage_pool (config, 0);
             yield pool.build_async (0, null);
             yield pool.start_async (0, null);
@@ -283,12 +124,4 @@ private class Boxes.VMCreator {
 
         return pool;
     }
-
-    private string get_uid () {
-        return ((uint32) Posix.getuid ()).to_string ();
-    }
-
-    private string get_gid () {
-        return ((uint32) Posix.getgid ()).to_string ();
-    }
 }



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