[gnome-boxes/wip/image-import] tmp



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]