[gnome-boxes/wip/system-libvirt-import2] tmp



commit 5624f73835dac7152f4454d234fe1618f24ad9ef
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Tue Oct 15 20:49:41 2013 -0400

    tmp

 src/Makefile.am                     |    3 +
 src/app.vala                        |    2 +
 src/libvirt-broker.vala             |    8 ++-
 src/libvirt-system-importer.vala    |  130 +++++++++++++++++++++++++++++++++++
 src/libvirt-system-media.vala       |   28 ++++++++
 src/libvirt-system-vm-importer.vala |   50 +++++++++++++
 src/vm-configurator.vala            |    8 ++
 src/vm-importer.vala                |   12 ++-
 8 files changed, 235 insertions(+), 6 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 12c41db..cbfec97 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -88,6 +88,7 @@ gnome_boxes_SOURCES =                         \
        i-properties-provider.vala              \
        installer-media.vala                    \
        installed-media.vala                    \
+       libvirt-system-media.vala               \
        iso-extractor.vala                      \
        libvirt-broker.vala                     \
        libvirt-machine.vala                    \
@@ -113,6 +114,8 @@ gnome_boxes_SOURCES =                               \
        vm-configurator.vala                    \
        vm-creator.vala                         \
        vm-importer.vala                        \
+       libvirt-system-importer.vala            \
+       libvirt-system-vm-importer.vala         \
        vnc-display.vala                        \
        wizard-source.vala                      \
        wizard.vala                             \
diff --git a/src/app.vala b/src/app.vala
index d835ac2..3d02c8d 100644
--- a/src/app.vala
+++ b/src/app.vala
@@ -82,6 +82,7 @@ private class Boxes.App: Boxes.UI {
     public Properties properties;
     public DisplayPage display_page;
     public EmptyBoxes empty_boxes;
+    public LibvirtSystemImporter system_importer;
     public string? uri { get; set; }
     public Collection collection;
     public CollectionFilter filter;
@@ -572,6 +573,7 @@ private class Boxes.App: Boxes.UI {
         wizard = new Wizard ();
         properties = new Properties ();
         empty_boxes = new EmptyBoxes ();
+        system_importer = new LibvirtSystemImporter ();
 
         var vbox_actor = new Clutter.Actor ();
         vbox_actor.name = "top-vbox";
diff --git a/src/libvirt-broker.vala b/src/libvirt-broker.vala
index 2073570..af4adf2 100644
--- a/src/libvirt-broker.vala
+++ b/src/libvirt-broker.vala
@@ -53,12 +53,16 @@ private class Boxes.LibvirtBroker : Boxes.Broker {
             var machine = add_domain (source, connection, domain);
             var config = machine.domain_config;
 
+            // These instance will take care of their own lifecycles
             if (VMConfigurator.is_install_config (config) || VMConfigurator.is_live_config (config)) {
                 debug ("Continuing installation/live session for '%s', ..", machine.name);
-                new VMCreator.for_install_completion (machine); // This instance will take care of its own 
lifecycle
+                new VMCreator.for_install_completion (machine);
             } else if (VMConfigurator.is_import_config (config)) {
                 debug ("Continuing import of '%s', ..", machine.name);
-                new VMImporter.for_import_completion (machine); // This instance will take care of its own 
lifecycle
+                new VMImporter.for_import_completion (machine);
+            } else if (VMConfigurator.is_libvirt_system_import_config (config)) {
+                debug ("Continuing import of '%s', ..", machine.name);
+                new LibvirtSystemVMImporter.for_import_completion (machine);
             }
         } catch (GLib.Error error) {
             warning ("Failed to create source '%s': %s", source.name, error.message);
diff --git a/src/libvirt-system-importer.vala b/src/libvirt-system-importer.vala
new file mode 100644
index 0000000..a31cf4b
--- /dev/null
+++ b/src/libvirt-system-importer.vala
@@ -0,0 +1,130 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+using GVir;
+
+errordomain Boxes.LibvirtSystemImporterError {
+    NO_SUITABLE_DISK
+}
+
+private class Boxes.LibvirtSystemImporter: GLib.Object {
+    public bool import_needed {
+        get {
+            return (domains.length () + pools.length ()) != 0;
+        }
+    }
+
+    private GVir.Connection connection;
+    private GLib.List<GVir.Domain> domains;
+    private GLib.List<GVir.StoragePool> pools;
+
+    public LibvirtSystemImporter () {
+        App.app.call_when_ready (() => {
+            // FIXME: should be equality check but to we are doing opposite for now to articially trigger it
+            if (App.app.collection.items.length != 0)
+                import.begin ();
+        });
+    }
+
+    private async void import () {
+        connection = new GVir.Connection ("qemu+unix:///system");
+
+        try {
+            yield connection.open_read_only_async (null);
+            debug ("Connected to system libvirt, now fetching domains..");
+            yield connection.fetch_domains_async (null);
+        } catch (GLib.Error error) {
+            warning ("Failed to connect to system libvirt: %s", error.message);
+
+            return;
+        }
+
+        domains = connection.get_domains ();
+        debug ("Fetched %u domains from system libvirt.", domains.length ());
+        GVirConfig.Domain[] configs = {};
+        string[] disk_paths = {};
+
+        foreach (var domain in domains) {
+            GVirConfig.Domain config;
+            string disk_path;
+
+            try {
+                get_domain_info (domain, out config, out disk_path);
+                configs += config;
+                disk_paths += disk_path;
+            } catch (GLib.Error error) {
+                warning ("%s", error.message);
+            }
+        }
+
+        try {
+            yield ensure_disks_readable (disk_paths);
+        } catch (GLib.Error error) {
+            warning ("Failed to make all libvirt system disks readable: %s", error.message);
+
+            return;
+        }
+
+        for (var i = 0; i < configs.length; i++)
+            import_domain.begin (configs[i], disk_paths[i], null, (obj, result) => {
+                try {
+                    import_domain.end (result);
+                } catch (GLib.Error error) {
+                    warning ("Failed to import '%s': %s", configs[i].name, error.message);
+                }
+            });
+    }
+
+    private void get_domain_info (Domain domain, out GVirConfig.Domain config, out string disk_path) throws 
GLib.Error {
+        debug ("Fetching config for '%s' from system libvirt.", domain.get_name ());
+        config = domain.get_config (DomainXMLFlags.INACTIVE);
+        debug ("Finding a suitable disk to import for '%s' from system libvirt.", domain.get_name ());
+        disk_path = get_disk_path (config);
+    }
+
+    private async void import_domain (GVirConfig.Domain config,
+                                      string            disk_path,
+                                      Cancellable?      cancellable = null) throws GLib.Error {
+        debug ("Importing '%s' from system libvirt..", config.name);
+
+        var media = new LibvirtSystemMedia (disk_path, config);
+        var vm_importer = media.get_vm_creator ();
+        var machine = yield vm_importer.create_vm (cancellable);
+        vm_importer.launch_vm (machine);
+    }
+
+    private string get_disk_path (GVirConfig.Domain config) throws 
LibvirtSystemImporterError.NO_SUITABLE_DISK {
+        string disk_path = null;
+
+        var devices = config.get_devices ();
+        foreach (var device in devices) {
+            if (!(device is GVirConfig.DomainDisk))
+                continue;
+
+            var disk = device as GVirConfig.DomainDisk;
+            if (disk.get_guest_device_type () == GVirConfig.DomainDiskGuestDeviceType.DISK) {
+                disk_path = disk.get_source ();
+
+                break;
+            }
+        }
+
+        if (disk_path == null)
+            throw new LibvirtSystemImporterError.NO_SUITABLE_DISK
+                                    (_("Failed to find suitable disk to import for box '%s'"), config.name);
+
+        return disk_path;
+    }
+
+    private async void ensure_disks_readable (string[] disk_paths) throws GLib.Error {
+        string[] argv = {};
+
+        argv += "pkexec";
+        argv += "chmod";
+        argv += "a+r";
+        foreach (var disk_path in disk_paths)
+            argv += disk_path;
+
+        debug ("Making all libvirt system disks readable..");
+        yield exec (argv, null);
+        debug ("Made all libvirt system disks readable.");
+    }
+}
diff --git a/src/libvirt-system-media.vala b/src/libvirt-system-media.vala
new file mode 100644
index 0000000..030f5d4
--- /dev/null
+++ b/src/libvirt-system-media.vala
@@ -0,0 +1,28 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+using GVirConfig;
+
+private class Boxes.LibvirtSystemMedia : Boxes.InstalledMedia {
+    protected override string? architecture {
+        owned get {
+            return domain_config.get_os ().get_arch ();
+        }
+    }
+
+    public Domain domain_config { get; private set; }
+
+    public LibvirtSystemMedia (string path, Domain domain_config) throws GLib.Error {
+        base (path);
+
+        this.domain_config = domain_config;
+        label = domain_config.title?? domain_config.name;
+
+        // Just initializing for sake for completion (and to avoid crashes). The CPU & RAM config comes from 
the
+        // imported domain and storage volume is overwritten as well.
+        resources = OSDatabase.get_default_resources ();
+    }
+
+    public override VMCreator get_vm_creator () {
+        return new LibvirtSystemVMImporter (this);
+    }
+}
diff --git a/src/libvirt-system-vm-importer.vala b/src/libvirt-system-vm-importer.vala
new file mode 100644
index 0000000..6191d3f
--- /dev/null
+++ b/src/libvirt-system-vm-importer.vala
@@ -0,0 +1,50 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+using Osinfo;
+using GVirConfig;
+
+private class Boxes.LibvirtSystemVMImporter : Boxes.VMImporter {
+    public LibvirtSystemVMImporter (InstalledMedia source_media) {
+        base (source_media);
+        start_after_import = false;
+    }
+
+    public LibvirtSystemVMImporter.for_import_completion (LibvirtMachine machine) {
+        base.for_install_completion (machine);
+        start_after_import = false;
+    }
+
+    protected override void create_domain_base_name_and_title (out string base_name, out string base_title) {
+        var media = install_media as LibvirtSystemMedia;
+
+        base_name = media.domain_config.name;
+        base_title = media.domain_config.title?? base_name;
+    }
+
+    protected override async Domain create_domain_config (string          name,
+                                                          string          title,
+                                                          GVir.StorageVol volume,
+                                                          Cancellable?    cancellable) throws GLib.Error {
+        var media = install_media as LibvirtSystemMedia;
+        var config = media.domain_config;
+
+        config.name = name;
+        config.title = title;
+
+        var devices = config.get_devices ();
+        foreach (var device in devices) {
+            if (!(device is DomainDisk))
+                continue;
+
+            var disk = device as DomainDisk;
+            if (disk.get_source () == media.device_file) {
+                disk.set_source (volume.get_path ());
+
+                break;
+            }
+        }
+        config.set_devices (devices);
+
+        return config;
+    }
+}
diff --git a/src/vm-configurator.vala b/src/vm-configurator.vala
index 491a2ec..b1669cd 100644
--- a/src/vm-configurator.vala
+++ b/src/vm-configurator.vala
@@ -14,10 +14,12 @@ private class Boxes.VMConfigurator {
     private const string LIVE_STATE = "live";
     private const string INSTALLATION_STATE = "installation";
     private const string IMPORT_STATE = "importing";
+    private const string LIBVIRT_SYS_IMPORT_STATE = "libvirt-system-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 LIBVIRT_SYS_IMPORT_XML = "<os-state>" + LIBVIRT_SYS_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>";
@@ -133,6 +135,10 @@ private class Boxes.VMConfigurator {
         return get_os_state (domain) == IMPORT_STATE;
     }
 
+    public static bool is_libvirt_system_import_config (Domain domain) {
+        return get_os_state (domain) == LIBVIRT_SYS_IMPORT_STATE;
+    }
+
     public static StorageVol create_volume_config (string name, int64 storage) throws GLib.Error {
         var volume = new StorageVol ();
         volume.set_name (name);
@@ -340,6 +346,8 @@ private class Boxes.VMConfigurator {
             custom_xml = INSTALLED_XML;
         else if (install_media is InstalledMedia)
             custom_xml = IMPORT_XML;
+        else if (install_media is LibvirtSystemMedia)
+            custom_xml = LIBVIRT_SYS_IMPORT_XML;
         else
             custom_xml = (install_media.live) ? LIVE_XML : INSTALLATION_XML;
 
diff --git a/src/vm-importer.vala b/src/vm-importer.vala
index 262451a..a53232c 100644
--- a/src/vm-importer.vala
+++ b/src/vm-importer.vala
@@ -6,6 +6,8 @@ using GVir;
 private class Boxes.VMImporter : Boxes.VMCreator {
     public InstalledMedia source_media { get { return install_media as InstalledMedia; } }
 
+    protected bool start_after_import = true;
+
     public VMImporter (InstalledMedia source_media) {
         base (source_media);
     }
@@ -56,10 +58,12 @@ private class Boxes.VMImporter : Boxes.VMCreator {
         }
 
         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);
+        if (start_after_import) {
+            try {
+                machine.domain.start (0);
+            } catch (GLib.Error error) {
+                warning ("Failed to start domain '%s': %s", machine.domain.get_name (), error.message);
+            }
         }
         machine.info = null;
         machine.vm_creator = null;


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