[gnome-boxes/wip/clone: 3/3] tmp



commit d91f9cc9b85e0489e21d3748200f0a9bd963a8cb
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Fri Apr 29 14:15:47 2016 +0100

    tmp

 src/Makefile.am               |    4 +++-
 src/actions-popover.vala      |   10 ++++++++++
 src/installed-media.vala      |    4 ++--
 src/libvirt-broker.vala       |    9 +++++++++
 src/libvirt-cloned-media.vala |   11 +++++++++++
 src/libvirt-machine.vala      |   21 +++++++++++++++++++++
 src/libvirt-media.vala        |    4 ++--
 src/libvirt-vm-cloner.vala    |   30 ++++++++++++++++++++++++++++++
 src/machine.vala              |    2 ++
 src/ovirt-machine.vala        |    2 ++
 src/remote-machine.vala       |    8 ++++++++
 src/vm-configurator.vala      |    8 ++++++++
 src/vm-importer.vala          |    6 +++++-
 13 files changed, 113 insertions(+), 6 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 407c58d..48a2bea 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -115,6 +115,7 @@ gnome_boxes_SOURCES =                               \
        installer-media.vala                    \
        installed-media.vala                    \
        keys-input-popover.vala                 \
+       libvirt-cloned-media.vala               \
        libvirt-media.vala                      \
        iso-extractor.vala                      \
        libvirt-broker.vala                     \
@@ -149,7 +150,8 @@ gnome_boxes_SOURCES =                               \
        vm-creator.vala                         \
        vm-importer.vala                        \
        libvirt-system-importer.vala            \
-       libvirt-vm-importer.vala        \
+       libvirt-vm-cloner.vala                  \
+       libvirt-vm-importer.vala                \
        vnc-display.vala                        \
        wizard-window.vala                      \
        wizard-source.vala                      \
diff --git a/src/actions-popover.vala b/src/actions-popover.vala
index c8d8f37..70160f1 100644
--- a/src/actions-popover.vala
+++ b/src/actions-popover.vala
@@ -7,6 +7,7 @@ private class Boxes.ActionsPopover: Gtk.Popover {
         {"pause",           pause_activated},
         {"force_shutdown",  force_shutdown_activated},
         {"delete",          delete_activated},
+        {"clone",           clone_activated},
         {"properties",      properties_activated},
         {"restart",         restart_activated}
     };
@@ -60,6 +61,11 @@ private class Boxes.ActionsPopover: Gtk.Popover {
             var action = action_group.lookup_action ("pause") as GLib.SimpleAction;
             action.set_enabled (machine.can_save);
 
+            // Clone
+            section.append (_("Clone"), "box.clone");
+            action = action_group.lookup_action ("clone") as GLib.SimpleAction;
+            action.set_enabled (machine.can_clone);
+
             // Delete
             section.append (_("Delete"), "box.delete");
             action = action_group.lookup_action ("delete") as GLib.SimpleAction;
@@ -122,6 +128,10 @@ private class Boxes.ActionsPopover: Gtk.Popover {
         App.app.delete_machines_undoable ((owned) items);
     }
 
+    private void clone_activated () {
+        (window.current_item as Machine).clone.begin ();
+    }
+
     private void properties_activated () {
         window.show_properties ();
     }
diff --git a/src/installed-media.vala b/src/installed-media.vala
index e1102b9..67e3518 100644
--- a/src/installed-media.vala
+++ b/src/installed-media.vala
@@ -35,10 +35,10 @@ private class Boxes.InstalledMedia : Boxes.InstallerMedia {
         }
     }
 
-    public InstalledMedia (string path) throws GLib.Error {
+    public InstalledMedia (string path, bool known_qcow2 = false) throws GLib.Error {
         var supported = false;
 
-        if (path.has_prefix ("/dev/"))
+        if (known_qcow2 || path.has_prefix ("/dev/"))
             supported = true; // Let's assume it's device file in raw format
         else
             foreach (var extension in supported_extensions) {
diff --git a/src/libvirt-broker.vala b/src/libvirt-broker.vala
index c79758c..d7d81c2 100644
--- a/src/libvirt-broker.vala
+++ b/src/libvirt-broker.vala
@@ -71,6 +71,12 @@ private class Boxes.LibvirtBroker : Boxes.Broker {
 
     // New == Added after Boxes launch
     private async void try_add_new_domain (CollectionSource source, GVir.Connection connection, GVir.Domain 
domain) {
+        if (domain.get_name ().has_prefix ("guestfs-")) {
+            debug ("Ignoring guestfs domain '%s'", domain.get_name ());
+
+            return;
+        }
+
         try {
             yield add_domain (source, connection, domain);
         } catch (GLib.Error error) {
@@ -96,6 +102,9 @@ private class Boxes.LibvirtBroker : Boxes.Broker {
             } else if (VMConfigurator.is_libvirt_system_import_config (config)) {
                 debug ("Continuing import of '%s', ..", machine.name);
                 new LibvirtVMImporter.for_import_completion (machine);
+            } else if (VMConfigurator.is_libvirt_cloning_config (config)) {
+                debug ("Continuing cloning of '%s', ..", machine.name);
+                new LibvirtVMCloner.for_cloning_completion (machine);
             }
         } catch (GLib.Error error) {
             warning ("Failed to create source '%s': %s", source.name, error.message);
diff --git a/src/libvirt-cloned-media.vala b/src/libvirt-cloned-media.vala
new file mode 100644
index 0000000..39656e3
--- /dev/null
+++ b/src/libvirt-cloned-media.vala
@@ -0,0 +1,11 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+private class Boxes.LibvirtClonedMedia : Boxes.LibvirtMedia  {
+    public LibvirtClonedMedia (string path, GVirConfig.Domain domain_config) throws GLib.Error {
+        base (path, domain_config, true);
+    }
+
+    public override VMCreator get_vm_creator () {
+        return new LibvirtVMCloner (this);
+    }
+}
diff --git a/src/libvirt-machine.vala b/src/libvirt-machine.vala
index 9d7f471..1b41ab6 100644
--- a/src/libvirt-machine.vala
+++ b/src/libvirt-machine.vala
@@ -32,6 +32,7 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
     public override bool suspend_at_exit { get { return connection == App.app.default_connection && 
!run_in_bg; } }
     public override bool can_save { get { return !saving && state != MachineState.SAVED; } }
     public override bool can_restart { get { return state == MachineState.RUNNING || state == 
MachineState.SAVED; } }
+    public override bool can_clone { get { return !importing; } }
     protected override bool should_autosave {
         get {
             return (base.should_autosave &&
@@ -680,6 +681,26 @@ private class Boxes.LibvirtMachine: Boxes.Machine {
         try_shutdown ();
     }
 
+    public override async void clone () {
+        debug ("Cloning '%s'..", domain_config.name);
+        can_delete = false;
+
+        try {
+            // Any better way of cloning the config?
+            var xml = domain_config.to_xml ();
+            var config = new GVirConfig.Domain.from_xml (xml);
+            config.set_uuid (null);
+
+            var media = new LibvirtClonedMedia (storage_volume.get_path (), config);
+            var vm_cloner = media.get_vm_creator ();
+            var cloned = yield vm_cloner.create_vm (null);
+            vm_cloner.launch_vm (cloned);
+        } catch (GLib.Error error) {
+            warning ("Failed to clone %s: %s", domain_config.name, error.message);
+        }
+        can_delete = true;
+    }
+
     public string? get_ip_address () {
         if (system_virt_connection == null || !is_on)
             return null;
diff --git a/src/libvirt-media.vala b/src/libvirt-media.vala
index 7e9d0b3..93157ed 100644
--- a/src/libvirt-media.vala
+++ b/src/libvirt-media.vala
@@ -11,8 +11,8 @@ private class Boxes.LibvirtMedia : Boxes.InstalledMedia {
 
     public Domain domain_config { get; private set; }
 
-    public LibvirtMedia (string path, Domain domain_config) throws GLib.Error {
-        base (path);
+    public LibvirtMedia (string path, Domain domain_config, bool known_qcow2 = false) throws GLib.Error {
+        base (path, known_qcow2);
 
         this.domain_config = domain_config;
         label = domain_config.title?? domain_config.name;
diff --git a/src/libvirt-vm-cloner.vala b/src/libvirt-vm-cloner.vala
new file mode 100644
index 0000000..5df27f9
--- /dev/null
+++ b/src/libvirt-vm-cloner.vala
@@ -0,0 +1,30 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+private class Boxes.LibvirtVMCloner : Boxes.LibvirtVMImporter {
+    public LibvirtVMCloner (InstalledMedia source_media) {
+        base (source_media);
+    }
+
+    public LibvirtVMCloner.for_cloning_completion (LibvirtMachine machine) {
+        base.for_import_completion (machine);
+    }
+
+    protected override async void post_import_setup (LibvirtMachine machine) {
+        try {
+            var image_path = machine.storage_volume.get_path ();
+            var argv = new string[] { "virt-sysprep", "-a", image_path };
+            string std_output, std_error;
+
+            yield exec (argv, null, out std_output, out std_error);
+
+            if (std_error != "")
+                debug ("Error output from virt-sysprep command: %s", std_error);
+            debug ("Standard output from virt-sysprep command: %s", std_output);
+        } catch (GLib.Error error) {
+            // We don't want hard dep on libguestfs-tools so it's OK if virt-sysprep command fails
+            debug ("Failed to run virt-sysprep: %s. You're on your own.", error.message);
+        }
+
+        yield base.post_import_setup (machine);
+    }
+}
diff --git a/src/machine.vala b/src/machine.vala
index 61f664f..5903200 100644
--- a/src/machine.vala
+++ b/src/machine.vala
@@ -16,6 +16,7 @@ private abstract class Boxes.Machine: Boxes.CollectionItem, Boxes.IPropertiesPro
 
     public virtual bool can_save { get { return false; } }
     public abstract bool can_restart { get; }
+    public abstract bool can_clone { get; }
     public bool can_delete { get; protected set; default = true; }
     public bool under_construction { get; protected set; default = false; }
 
@@ -359,6 +360,7 @@ private abstract class Boxes.Machine: Boxes.CollectionItem, Boxes.IPropertiesPro
 
     public abstract async void connect_display (ConnectFlags flags) throws GLib.Error;
     public abstract void restart ();
+    public abstract async void clone ();
 
     public virtual void disconnect_display () {
         if (display == null)
diff --git a/src/ovirt-machine.vala b/src/ovirt-machine.vala
index 807d1d0..20896ab 100644
--- a/src/ovirt-machine.vala
+++ b/src/ovirt-machine.vala
@@ -4,6 +4,7 @@ using Gtk;
 
 private class Boxes.OvirtMachine: Boxes.Machine {
     public override bool can_restart { get { return false; } }
+    public override bool can_clone { get { return false; } }
 
     private Ovirt.Vm vm;
     private Ovirt.Proxy proxy;
@@ -79,6 +80,7 @@ private class Boxes.OvirtMachine: Boxes.Machine {
     }
 
     public override void restart () {} // See FIXME on RemoteMachine.restart
+    public override async void clone () {}
 
     private void update_info () {
         var uri = Xml.URI.parse (source.uri);
diff --git a/src/remote-machine.vala b/src/remote-machine.vala
index 26809f5..2e48600 100644
--- a/src/remote-machine.vala
+++ b/src/remote-machine.vala
@@ -3,6 +3,7 @@ using Gtk;
 
 private class Boxes.RemoteMachine: Boxes.Machine, Boxes.IPropertiesProvider {
     public override bool can_restart { get { return false; } }
+    public override bool can_clone { get { return true; } }
 
     public RemoteMachine (CollectionSource source) throws Boxes.Error {
         if (source.source_type != "spice" &&
@@ -99,6 +100,13 @@ private class Boxes.RemoteMachine: Boxes.Machine, Boxes.IPropertiesProvider {
     //        restart and this method is currently used for that purpose only.
     public override void restart () {}
 
+    public override async void clone () {
+        var name = "Clone of %s".printf (source.name);
+        var source = new CollectionSource (name, source.source_type, source.uri);
+        source.save ();
+        App.app.add_collection_source.begin (source);
+    }
+
     private void update_info () {
         var uri = Xml.URI.parse (source.uri);
         if (uri == null || uri.server == name) // By default server is chosen as name
diff --git a/src/vm-configurator.vala b/src/vm-configurator.vala
index d39456f..6cb4756 100644
--- a/src/vm-configurator.vala
+++ b/src/vm-configurator.vala
@@ -15,11 +15,13 @@ private class Boxes.VMConfigurator {
     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 LIBVIRT_CLONING_STATE = "libvirt-cloning";
     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 LIBVIRT_CLONING_XML = "<os-state>" + LIBVIRT_CLONING_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>";
@@ -138,6 +140,10 @@ private class Boxes.VMConfigurator {
         return get_os_state (domain) == LIBVIRT_SYS_IMPORT_STATE;
     }
 
+    public static bool is_libvirt_cloning_config (Domain domain) {
+        return get_os_state (domain) == LIBVIRT_CLONING_STATE;
+    }
+
     public static bool is_boxes_installed (Domain domain) {
         return get_os_state (domain) == INSTALLED_STATE;
     }
@@ -420,6 +426,8 @@ private class Boxes.VMConfigurator {
             custom_xml = INSTALLED_XML;
         else if (install_media is LibvirtMedia)
             custom_xml = LIBVIRT_SYS_IMPORT_XML;
+        else if (install_media is LibvirtClonedMedia)
+            custom_xml = LIBVIRT_CLONING_XML;
         else if (install_media is InstalledMedia)
             custom_xml = IMPORT_XML;
         else
diff --git a/src/vm-importer.vala b/src/vm-importer.vala
index f8e4901..2eb8c9a 100644
--- a/src/vm-importer.vala
+++ b/src/vm-importer.vala
@@ -30,6 +30,10 @@ private class Boxes.VMImporter : Boxes.VMCreator {
         yield import_vm (machine);
     }
 
+    protected virtual async void post_import_setup (LibvirtMachine machine) {
+        set_post_install_config (machine);
+    }
+
     private async void import_vm (LibvirtMachine machine) {
         try {
             var destination_path = machine.storage_volume.get_path ();
@@ -50,7 +54,7 @@ private class Boxes.VMImporter : Boxes.VMCreator {
             return;
         }
 
-        set_post_install_config (machine);
+        yield post_import_setup (machine);
         if (start_after_import) {
             try {
                 machine.domain.start (0);


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