[gnome-boxes/wip/clone: 3/3] tmp
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-boxes/wip/clone: 3/3] tmp
- Date: Fri, 29 Apr 2016 20:50:57 +0000 (UTC)
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]