[gnome-boxes/wip/image-import] tmp
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-boxes/wip/image-import] tmp
- Date: Tue, 4 Jun 2013 00:59:30 +0000 (UTC)
commit 9de866e501f5fb5b2bab8075b98548a5addfd2ae
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date: Wed Feb 13 16:32:33 2013 +0200
tmp
src/Makefile.am | 2 +
src/installed-media.vala | 38 +++++++++++++++++++++++++++
src/installer-media.vala | 8 ++++-
src/media-manager.vala | 19 +++++++++++---
src/util-app.vala | 7 +++++
src/vm-configurator.vala | 39 ++++++++++++----------------
src/vm-creator.vala | 13 +++++----
src/vm-importer.vala | 64 ++++++++++++++++++++++++++++++++++++++++++++++
src/wizard-source.vala | 3 ++
src/wizard.vala | 2 +-
10 files changed, 160 insertions(+), 35 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 3c1b7c1..12c41db 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -87,6 +87,7 @@ gnome_boxes_SOURCES = \
editable-entry.vala \
i-properties-provider.vala \
installer-media.vala \
+ installed-media.vala \
iso-extractor.vala \
libvirt-broker.vala \
libvirt-machine.vala \
@@ -111,6 +112,7 @@ gnome_boxes_SOURCES = \
util-app.vala \
vm-configurator.vala \
vm-creator.vala \
+ vm-importer.vala \
vnc-display.vala \
wizard-source.vala \
wizard.vala \
diff --git a/src/installed-media.vala b/src/installed-media.vala
new file mode 100644
index 0000000..003cd97
--- /dev/null
+++ b/src/installed-media.vala
@@ -0,0 +1,38 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+using GVirConfig;
+
+private class Boxes.InstalledMedia : Boxes.InstallerMedia {
+ public override bool need_user_input_for_vm_creation { get { return false; } }
+ public override bool ready_to_create { get { return true; } }
+ public override bool live { get { return false; } }
+
+ public string format { get { return device_file.has_suffix (".qcow2")? "qcow2" : "raw"; } }
+
+ private string architecture = "x86_64"; // FIXME: Hardcode for now
+
+ public InstalledMedia (string path) throws GLib.Error {
+ if (!path.has_suffix (".qcow2") || !path.has_suffix (".img"))
+ throw new Boxes.Error.INVALID (_("Only QEMU QCOW Image (v2) and raw formats supported."));
+
+ device_file = path;
+ label = path;
+ from_image = true;
+ }
+
+ public override void setup_domain_config (Domain domain) {}
+
+ public override GLib.List<Pair<string,string>> get_vm_properties () {
+ var properties = new GLib.List<Pair<string,string>> ();
+
+ properties.append (new Pair<string,string> (_("System"), label));
+
+ return properties;
+ }
+
+ public override bool is_architecture_compatible (string architecture) {
+ var compatibility = compare_cpu_architectures (architecture, this.architecture);
+
+ return compatibility != CPUArchCompatibility.INCOMPATIBLE;
+ }
+}
diff --git a/src/installer-media.vala b/src/installer-media.vala
index 7b567ab..6d5db5b 100644
--- a/src/installer-media.vala
+++ b/src/installer-media.vala
@@ -32,7 +32,7 @@ private class Boxes.InstallerMedia : GLib.Object {
}
}
- public bool live { get { return os_media == null || os_media.live; } }
+ public virtual bool live { get { return os_media == null || os_media.live; } }
public InstallerMedia.from_iso_info (string path,
string label,
@@ -97,7 +97,7 @@ private class Boxes.InstallerMedia : GLib.Object {
return properties;
}
- public bool is_architecture_compatible (string architecture) {
+ public virtual bool is_architecture_compatible (string architecture) {
if (os_media == null) // Unknown media
return true;
@@ -106,6 +106,10 @@ private class Boxes.InstallerMedia : GLib.Object {
return compatibility != CPUArchCompatibility.INCOMPATIBLE;
}
+ public virtual VMCreator get_vm_creator () {
+ return new VMCreator (this);
+ }
+
protected void add_cd_config (Domain domain,
DomainDiskType type,
string iso_path,
diff --git a/src/media-manager.vala b/src/media-manager.vala
index 902f1b3..270bd76 100644
--- a/src/media-manager.vala
+++ b/src/media-manager.vala
@@ -25,21 +25,32 @@ private class Boxes.MediaManager : Object {
public async InstallerMedia create_installer_media_for_path (string path,
Cancellable? cancellable = null) throws
GLib.Error {
- var media = yield new InstallerMedia.for_path (path, this, cancellable);
+ var media = is_mime_type (path, "application/x-cd-image") ?
+ yield new InstallerMedia.for_path (path, this, cancellable) :
+ new InstalledMedia (path);
return create_installer_media_from_media (media);
}
public async InstallerMedia? create_installer_media_from_config (GVirConfig.Domain config) {
var path = VMConfigurator.get_source_media_path (config);
+ if (path == null)
+ return null;
+
+ if (VMConfigurator.is_import_config (config))
+ try {
+ return new InstalledMedia (path);
+ } catch (GLib.Error error) {
+ debug ("%s", error.message);
+
+ return null;
+ }
+
var label = config.title;
Os? os = null;
Media? os_media = null;
- if (path == null)
- return null;
-
try {
var os_id = VMConfigurator.get_os_id (config);
if (os_id != null) {
diff --git a/src/util-app.vala b/src/util-app.vala
index 0370b0c..836c153 100644
--- a/src/util-app.vala
+++ b/src/util-app.vala
@@ -529,6 +529,13 @@ namespace Boxes {
return tokens[1];
}
+ public bool is_mime_type (string filename, string mime_type) {
+ var file_type = ContentType.guess (filename, null, null);
+ var supertype = ContentType.from_mime_type (mime_type);
+
+ return ContentType.is_a (file_type, supertype);
+ }
+
namespace UUID {
[CCode (cname = "uuid_generate", cheader_filename = "uuid/uuid.h")]
internal extern static void generate ([CCode (array_length = false)] uchar[] uuid);
diff --git a/src/vm-configurator.vala b/src/vm-configurator.vala
index 8e8cc67..886eec9 100644
--- a/src/vm-configurator.vala
+++ b/src/vm-configurator.vala
@@ -13,13 +13,16 @@ private class Boxes.VMConfigurator {
private const string BOXES_XML = "<gnome-boxes>%s</gnome-boxes>";
private const string LIVE_STATE = "live";
private const string INSTALLATION_STATE = "installation";
+ private const string IMPORT_STATE = "importing";
private const string INSTALLED_STATE = "installed";
private const string LIVE_XML = "<os-state>" + LIVE_STATE + "</os-state>";
private const string INSTALLATION_XML = "<os-state>" + INSTALLATION_STATE + "</os-state>";
+ private const string IMPORT_XML = "<os-state>" + IMPORT_STATE + "</os-state>";
private const string INSTALLED_XML = "<os-state>" + INSTALLED_STATE + "</os-state>";
private const string OS_ID_XML = "<os-id>%s</os-id>";
private const string MEDIA_ID_XML = "<media-id>%s</media-id>";
+ private const string MEDIA_XML = "<media>%s</media>";
private const string NUM_REBOOTS_XML = "<num-reboots>%u</num-reboots>";
public static Domain create_domain_config (InstallerMedia install_media, string target_path,
Capabilities caps)
@@ -124,12 +127,16 @@ private class Boxes.VMConfigurator {
return get_os_state (domain) == LIVE_STATE;
}
- public static StorageVol create_volume_config (string name, int64 storage) throws GLib.Error {
+ public static bool is_import_config (Domain domain) {
+ return get_os_state (domain) == IMPORT_STATE;
+ }
+
+ public static StorageVol create_volume_config (string name, int64 storage, string format) throws
GLib.Error {
var volume = new StorageVol ();
volume.set_name (name);
volume.set_capacity (storage);
var target = new StorageVolTarget ();
- target.set_format ("qcow2");
+ target.set_format (format);
var permissions = get_default_permissions ();
target.set_permissions (permissions);
volume.set_target (target);
@@ -166,6 +173,10 @@ private class Boxes.VMConfigurator {
return get_custom_xml_node (domain, "media-id");
}
+ public static string? get_source_media_path (Domain domain) {
+ return get_custom_xml_node (domain, "media");
+ }
+
public static uint get_num_reboots (Domain domain) {
var str = get_custom_xml_node (domain, "num-reboots");
return (str != null)? int.parse (str) : 0;
@@ -286,26 +297,6 @@ private class Boxes.VMConfigurator {
return get_custom_xml_node (domain, "os-state");
}
- public static string? get_source_media_path (Domain domain) {
- string path = null;
-
- var devices = domain.get_devices ();
- foreach (var device in devices) {
- if (!(device is DomainDisk))
- continue;
-
- var disk = device as DomainDisk;
- var disk_type = disk.get_guest_device_type ();
- if (disk_type == DomainDiskGuestDeviceType.CDROM) {
- path = disk.get_source ().dup ();
-
- break;
- }
- }
-
- return path;
- }
-
private static string? get_custom_xml_node (Domain domain, string node_name) {
var xml = domain.get_custom_xml (BOXES_NS_URI);
if (xml != null) {
@@ -340,10 +331,13 @@ private class Boxes.VMConfigurator {
InstallerMedia? install_media,
uint num_reboots = 0,
bool installed = false) {
+ return_if_fail (install_media != null || installed);
string custom_xml;
if (installed)
custom_xml = INSTALLED_XML;
+ else if (install_media is InstalledMedia)
+ custom_xml = IMPORT_XML;
else
custom_xml = (install_media.live) ? LIVE_XML : INSTALLATION_XML;
@@ -352,6 +346,7 @@ private class Boxes.VMConfigurator {
custom_xml += Markup.printf_escaped (OS_ID_XML, install_media.os.id);
if (install_media.os_media != null)
custom_xml += Markup.printf_escaped (MEDIA_ID_XML, install_media.os_media.id);
+ custom_xml += Markup.printf_escaped (MEDIA_XML, install_media.device_file);
}
if (num_reboots != 0)
diff --git a/src/vm-creator.vala b/src/vm-creator.vala
index 3bcdd02..e1951f8 100644
--- a/src/vm-creator.vala
+++ b/src/vm-creator.vala
@@ -8,7 +8,8 @@ private class Boxes.VMCreator {
// of error. Its better to report '100%' done while its not exactly 100% than reporting '99%' done
forever..
private const int INSTALL_COMPLETE_PERCENT = 99;
- public InstallerMedia? install_media { get; private set; }
+ public InstallerMedia? install_media { get; protected set; }
+ protected virtual string target_volume_format { get { return "qcow2"; } }
private Connection? connection { owned get { return App.app.default_connection; } }
private ulong state_changed_id;
@@ -60,7 +61,7 @@ private class Boxes.VMCreator {
return LibvirtBroker.get_default ().add_domain (App.app.default_source, App.app.default_connection,
domain);
}
- public void launch_vm (LibvirtMachine machine) throws GLib.Error {
+ public virtual void launch_vm (LibvirtMachine machine) throws GLib.Error {
if (!(install_media is UnattendedInstaller) || !(install_media as
UnattendedInstaller).express_install) {
ulong signal_id = 0;
@@ -82,7 +83,7 @@ private class Boxes.VMCreator {
update_machine_info (machine);
}
- private async void continue_installation (LibvirtMachine machine) {
+ protected virtual async void continue_installation (LibvirtMachine machine) {
install_media = yield MediaManager.get_instance ().create_installer_media_from_config
(machine.domain_config);
num_reboots = VMConfigurator.get_num_reboots (machine.domain_config);
var name = machine.domain.get_name ();
@@ -171,7 +172,7 @@ private class Boxes.VMCreator {
}
}
- private void update_machine_info (LibvirtMachine machine) {
+ protected virtual void update_machine_info (LibvirtMachine machine) {
if (VMConfigurator.is_install_config (machine.domain_config)) {
machine.info = _("Installing...");
@@ -180,7 +181,7 @@ private class Boxes.VMCreator {
machine.info = _("Live");
}
- private void set_post_install_config (LibvirtMachine machine) {
+ protected void set_post_install_config (LibvirtMachine machine) {
debug ("Setting post-installation configuration on '%s'", machine.name);
try {
var config = machine.domain.get_config (GVir.DomainXMLFlags.INACTIVE);
@@ -306,7 +307,7 @@ private class Boxes.VMCreator {
private async StorageVol create_target_volume (string name, int64 storage) throws GLib.Error {
var pool = yield get_storage_pool ();
- var config = VMConfigurator.create_volume_config (name, storage);
+ var config = VMConfigurator.create_volume_config (name, storage, target_volume_format);
var volume = pool.create_volume (config);
return volume;
diff --git a/src/vm-importer.vala b/src/vm-importer.vala
new file mode 100644
index 0000000..ad67f28
--- /dev/null
+++ b/src/vm-importer.vala
@@ -0,0 +1,64 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+using Osinfo;
+using GVir;
+
+private class Boxes.VMImporter : Boxes.VMCreator {
+ public InstalledMedia source_media { get { return install_media as InstalledMedia; } }
+ protected override string target_volume_format { get { return source_media.format; } }
+
+ public VMImporter (InstalledMedia source_media) {
+ base (source_media);
+ }
+
+ public VMImporter.for_import_completion (LibvirtMachine machine) {
+ base.for_install_completion (machine);
+ }
+
+ public override void launch_vm (LibvirtMachine machine) throws GLib.Error {
+ machine.vm_creator = this;
+ machine.config.access_last_time = get_real_time ();
+ update_machine_info (machine);
+
+ import_vm.begin (machine);
+ }
+
+ protected override async void continue_installation (LibvirtMachine machine) {
+ install_media = yield MediaManager.get_instance ().create_installer_media_from_config
(machine.domain_config);
+ machine.vm_creator = this;
+ update_machine_info (machine);
+
+ yield import_vm (machine);
+ }
+
+ protected override void update_machine_info (LibvirtMachine machine) {
+ machine.info = _("Importing...");
+ }
+
+ private async void import_vm (LibvirtMachine machine) {
+ try {
+ var source = File.new_for_path (source_media.device_file);
+ var destination_path = machine.storage_volume.get_path ();
+ var destination = File.new_for_path (destination_path);
+
+ yield copy_file (source, destination);
+ } catch (GLib.Error error) {
+ warning ("Failed to import box '%s' from file '%s': %s",
+ machine.name,
+ source_media.device_file,
+ error.message);
+ var ui_message = _("Box import from file '%s' failed.").printf (source_media.device_file);
+ App.app.notificationbar.display_error (ui_message);
+ machine.delete ();
+
+ return;
+ }
+
+ set_post_install_config (machine);
+ try {
+ machine.domain.start (0);
+ } catch (GLib.Error error) {
+ warning ("Failed to start domain '%s': %s", machine.domain.get_name (), error.message);
+ }
+ }
+}
diff --git a/src/wizard-source.vala b/src/wizard-source.vala
index 591223e..c1c5502 100644
--- a/src/wizard-source.vala
+++ b/src/wizard-source.vala
@@ -309,6 +309,9 @@ private class Boxes.WizardSource: GLib.Object {
dialog.local_only = true;
dialog.filter = new Gtk.FileFilter ();
dialog.filter.add_mime_type ("application/x-cd-image");
+ dialog.filter.add_pattern ("*.img");
+ dialog.filter.add_pattern ("*.disk");
+ dialog.filter.add_pattern ("*.qcow2");
var ret = false;
if (dialog.run () == Gtk.ResponseType.ACCEPT) {
uri = dialog.get_uri ();
diff --git a/src/wizard.vala b/src/wizard.vala
index 67f3669..1b7a02a 100644
--- a/src/wizard.vala
+++ b/src/wizard.vala
@@ -302,7 +302,7 @@ private class Boxes.Wizard: Boxes.UI {
yield install_media.prepare (progress, null);
- vm_creator = new VMCreator (install_media);
+ vm_creator = install_media.get_vm_creator ();
prep_progress.fraction = 1.0;
page = WizardPage.SETUP;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]