[gnome-boxes] Start making use of libvirt-gconfig
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-boxes] Start making use of libvirt-gconfig
- Date: Thu, 15 Dec 2011 23:23:02 +0000 (UTC)
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]