clone: Convert to per-connection singleton-ish pattern
And convert the dialog VM handling to match other dialogs
This commit is contained in:
parent
b94a9fdffb
commit
58f872a205
|
@ -128,11 +128,23 @@ def do_we_default(conn, vol, path, ro, shared, devtype):
|
||||||
|
|
||||||
|
|
||||||
class vmmCloneVM(vmmGObjectUI):
|
class vmmCloneVM(vmmGObjectUI):
|
||||||
def __init__(self, orig_vm):
|
_instances = {}
|
||||||
vmmGObjectUI.__init__(self, "clone.ui", "vmm-clone")
|
|
||||||
self.orig_vm = orig_vm
|
|
||||||
|
|
||||||
self.conn = self.orig_vm.conn
|
@classmethod
|
||||||
|
def show_instance(cls, parentobj, vm):
|
||||||
|
try:
|
||||||
|
# Maintain one dialog per connection
|
||||||
|
uri = vm.conn.get_uri()
|
||||||
|
if uri not in cls._instances:
|
||||||
|
cls._instances[uri] = cls()
|
||||||
|
cls._instances[uri].show(parentobj.topwin, vm)
|
||||||
|
except Exception as e:
|
||||||
|
parentobj.err.show_err(
|
||||||
|
_("Error launching clone dialog: %s") % str(e))
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
vmmGObjectUI.__init__(self, "clone.ui", "vmm-clone")
|
||||||
|
self.vm = None
|
||||||
self.clone_design = None
|
self.clone_design = None
|
||||||
|
|
||||||
self.storage_list = {}
|
self.storage_list = {}
|
||||||
|
@ -169,10 +181,17 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
})
|
})
|
||||||
self.bind_escape_key_close()
|
self.bind_escape_key_close()
|
||||||
|
|
||||||
self.set_initial_state()
|
self._init_ui()
|
||||||
|
|
||||||
def show(self, parent):
|
@property
|
||||||
|
def conn(self):
|
||||||
|
if self.vm:
|
||||||
|
return self.vm.conn
|
||||||
|
return None
|
||||||
|
|
||||||
|
def show(self, parent, vm):
|
||||||
logging.debug("Showing clone wizard")
|
logging.debug("Showing clone wizard")
|
||||||
|
self.vm = vm
|
||||||
self.reset_state()
|
self.reset_state()
|
||||||
self.topwin.set_transient_for(parent)
|
self.topwin.set_transient_for(parent)
|
||||||
self.topwin.resize(1, 1)
|
self.topwin.resize(1, 1)
|
||||||
|
@ -184,7 +203,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
self.change_storage_close()
|
self.change_storage_close()
|
||||||
self.topwin.hide()
|
self.topwin.hide()
|
||||||
|
|
||||||
self.orig_vm = None
|
self.vm = None
|
||||||
self.clone_design = None
|
self.clone_design = None
|
||||||
self.storage_list = {}
|
self.storage_list = {}
|
||||||
self.target_list = []
|
self.target_list = []
|
||||||
|
@ -194,8 +213,6 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
self.conn = None
|
|
||||||
|
|
||||||
self.change_mac.destroy()
|
self.change_mac.destroy()
|
||||||
self.change_mac = None
|
self.change_mac = None
|
||||||
|
|
||||||
|
@ -217,7 +234,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
|
|
||||||
# First time setup
|
# First time setup
|
||||||
|
|
||||||
def set_initial_state(self):
|
def _init_ui(self):
|
||||||
blue = Gdk.Color.parse("#0072A8")[1]
|
blue = Gdk.Color.parse("#0072A8")[1]
|
||||||
self.widget("header").modify_bg(Gtk.StateType.NORMAL, blue)
|
self.widget("header").modify_bg(Gtk.StateType.NORMAL, blue)
|
||||||
|
|
||||||
|
@ -255,7 +272,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
|
|
||||||
def build_new_clone_design(self, new_name=None):
|
def build_new_clone_design(self, new_name=None):
|
||||||
design = Cloner(self.conn.get_backend())
|
design = Cloner(self.conn.get_backend())
|
||||||
design.original_guest = self.orig_vm.get_name()
|
design.original_guest = self.vm.get_name()
|
||||||
if not new_name:
|
if not new_name:
|
||||||
new_name = design.generate_clone_name()
|
new_name = design.generate_clone_name()
|
||||||
design.clone_name = new_name
|
design.clone_name = new_name
|
||||||
|
@ -295,7 +312,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
self.net_list[origmac] = net_row
|
self.net_list[origmac] = net_row
|
||||||
self.mac_list.append(origmac)
|
self.mac_list.append(origmac)
|
||||||
|
|
||||||
for net in self.orig_vm.get_network_devices():
|
for net in self.vm.get_network_devices():
|
||||||
mac = net.macaddr
|
mac = net.macaddr
|
||||||
net_dev = net.source
|
net_dev = net.source
|
||||||
net_type = net.type
|
net_type = net.type
|
||||||
|
@ -310,7 +327,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
|
|
||||||
elif net_type == VirtualNetworkInterface.TYPE_VIRTUAL:
|
elif net_type == VirtualNetworkInterface.TYPE_VIRTUAL:
|
||||||
net = None
|
net = None
|
||||||
for netobj in self.orig_vm.conn.list_nets():
|
for netobj in self.vm.conn.list_nets():
|
||||||
if netobj.get_name() == net_dev:
|
if netobj.get_name() == net_dev:
|
||||||
net = netobj
|
net = netobj
|
||||||
break
|
break
|
||||||
|
@ -340,7 +357,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
"""
|
"""
|
||||||
Determine which storage is cloneable, and which isn't
|
Determine which storage is cloneable, and which isn't
|
||||||
"""
|
"""
|
||||||
diskinfos = self.orig_vm.get_disk_devices()
|
diskinfos = self.vm.get_disk_devices()
|
||||||
cd = self.clone_design
|
cd = self.clone_design
|
||||||
|
|
||||||
storage_list = {}
|
storage_list = {}
|
||||||
|
@ -481,7 +498,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
failinfo = disk[STORAGE_INFO_FAILINFO]
|
failinfo = disk[STORAGE_INFO_FAILINFO]
|
||||||
target = disk[STORAGE_INFO_TARGET]
|
target = disk[STORAGE_INFO_TARGET]
|
||||||
|
|
||||||
orig_name = self.orig_vm.get_name()
|
orig_name = self.vm.get_name()
|
||||||
|
|
||||||
disk_label = os.path.basename(origpath)
|
disk_label = os.path.basename(origpath)
|
||||||
info_label = None
|
info_label = None
|
||||||
|
@ -676,10 +693,6 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
|
|
||||||
self.widget("vmm-change-storage").show_all()
|
self.widget("vmm-change-storage").show_all()
|
||||||
|
|
||||||
def set_orig_vm(self, new_orig):
|
|
||||||
self.orig_vm = new_orig
|
|
||||||
self.conn = self.orig_vm.conn
|
|
||||||
|
|
||||||
def change_mac_finish(self, ignore):
|
def change_mac_finish(self, ignore):
|
||||||
orig = self.widget("change-mac-orig").get_text()
|
orig = self.widget("change-mac-orig").get_text()
|
||||||
new = self.widget("change-mac-new").get_text()
|
new = self.widget("change-mac-new").get_text()
|
||||||
|
@ -798,7 +811,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
self.clone_design = cd
|
self.clone_design = cd
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _finish_cb(self, error, details):
|
def _finish_cb(self, error, details, conn):
|
||||||
self.reset_finish_cursor()
|
self.reset_finish_cursor()
|
||||||
|
|
||||||
if error is not None:
|
if error is not None:
|
||||||
|
@ -807,8 +820,8 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
self.err.show_err(error, details=details)
|
self.err.show_err(error, details=details)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
conn.schedule_priority_tick(pollvm=True)
|
||||||
self.close()
|
self.close()
|
||||||
self.conn.schedule_priority_tick(pollvm=True)
|
|
||||||
|
|
||||||
def finish(self, src_ignore):
|
def finish(self, src_ignore):
|
||||||
try:
|
try:
|
||||||
|
@ -826,13 +839,14 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
if self.clone_design.clone_disks:
|
if self.clone_design.clone_disks:
|
||||||
text = title + _(" and selected storage (this may take a while)")
|
text = title + _(" and selected storage (this may take a while)")
|
||||||
|
|
||||||
progWin = vmmAsyncJob(self._async_clone, [], self._finish_cb, [],
|
progWin = vmmAsyncJob(self._async_clone, [],
|
||||||
|
self._finish_cb, [self.conn],
|
||||||
title, text, self.topwin)
|
title, text, self.topwin)
|
||||||
progWin.run()
|
progWin.run()
|
||||||
|
|
||||||
def _async_clone(self, asyncjob):
|
def _async_clone(self, asyncjob):
|
||||||
try:
|
try:
|
||||||
self.orig_vm.set_cloning(True)
|
self.vm.set_cloning(True)
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
||||||
refresh_pools = []
|
refresh_pools = []
|
||||||
|
@ -859,7 +873,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
"VM clone.", poolname, exc_info=True)
|
"VM clone.", poolname, exc_info=True)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self.orig_vm.set_cloning(False)
|
self.vm.set_cloning(False)
|
||||||
|
|
||||||
def change_storage_browse(self, ignore):
|
def change_storage_browse(self, ignore):
|
||||||
def callback(src_ignore, txt):
|
def callback(src_ignore, txt):
|
||||||
|
|
|
@ -341,7 +341,6 @@ class vmmDetails(vmmGObjectUI):
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
"action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"action-view-manager": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"action-view-manager": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"action-clone-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
|
|
||||||
"details-closed": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"details-closed": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"details-opened": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"details-opened": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"customize-finished": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"customize-finished": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
|
|
|
@ -30,7 +30,6 @@ from gi.repository import Gtk
|
||||||
|
|
||||||
from . import packageutils
|
from . import packageutils
|
||||||
from .baseclass import vmmGObject
|
from .baseclass import vmmGObject
|
||||||
from .clone import vmmCloneVM
|
|
||||||
from .connmanager import vmmConnectionManager
|
from .connmanager import vmmConnectionManager
|
||||||
from .connect import vmmConnect
|
from .connect import vmmConnect
|
||||||
from .create import vmmCreate
|
from .create import vmmCreate
|
||||||
|
@ -55,7 +54,6 @@ class _ConnState(object):
|
||||||
|
|
||||||
self.probeConnection = probe
|
self.probeConnection = probe
|
||||||
|
|
||||||
self.windowClone = None
|
|
||||||
self.windowDetails = {}
|
self.windowDetails = {}
|
||||||
self.windowHost = None
|
self.windowHost = None
|
||||||
|
|
||||||
|
@ -179,7 +177,6 @@ class vmmEngine(vmmGObject):
|
||||||
self._systray = vmmSystray()
|
self._systray = vmmSystray()
|
||||||
self._systray.connect("action-toggle-manager", self._do_toggle_manager)
|
self._systray.connect("action-toggle-manager", self._do_toggle_manager)
|
||||||
self._systray.connect("action-show-domain", self._do_show_vm)
|
self._systray.connect("action-show-domain", self._do_show_vm)
|
||||||
self._systray.connect("action-clone-domain", self._do_show_clone)
|
|
||||||
self._systray.connect("action-exit-app", self.exit_app)
|
self._systray.connect("action-exit-app", self.exit_app)
|
||||||
|
|
||||||
self.add_gsettings_handle(
|
self.add_gsettings_handle(
|
||||||
|
@ -504,8 +501,6 @@ class vmmEngine(vmmGObject):
|
||||||
connstate = self._connstates[uri]
|
connstate = self._connstates[uri]
|
||||||
if connstate.windowHost:
|
if connstate.windowHost:
|
||||||
connstate.windowHost.cleanup()
|
connstate.windowHost.cleanup()
|
||||||
if connstate.windowClone:
|
|
||||||
connstate.windowClone.cleanup()
|
|
||||||
|
|
||||||
detailsmap = connstate.windowDetails
|
detailsmap = connstate.windowDetails
|
||||||
for win in list(detailsmap.values()):
|
for win in list(detailsmap.values()):
|
||||||
|
@ -656,7 +651,6 @@ class vmmEngine(vmmGObject):
|
||||||
obj = vmmDetails(self._connobjs[uri].get_vm(connkey))
|
obj = vmmDetails(self._connobjs[uri].get_vm(connkey))
|
||||||
obj.connect("action-exit-app", self.exit_app)
|
obj.connect("action-exit-app", self.exit_app)
|
||||||
obj.connect("action-view-manager", self._do_show_manager)
|
obj.connect("action-view-manager", self._do_show_manager)
|
||||||
obj.connect("action-clone-domain", self._do_show_clone)
|
|
||||||
obj.connect("details-opened", self.increment_window_counter)
|
obj.connect("details-opened", self.increment_window_counter)
|
||||||
obj.connect("details-closed", self.decrement_window_counter)
|
obj.connect("details-closed", self.decrement_window_counter)
|
||||||
|
|
||||||
|
@ -689,7 +683,6 @@ class vmmEngine(vmmGObject):
|
||||||
return self.windowManager
|
return self.windowManager
|
||||||
|
|
||||||
obj = vmmManager()
|
obj = vmmManager()
|
||||||
obj.connect("action-clone-domain", self._do_show_clone)
|
|
||||||
obj.connect("action-show-domain", self._do_show_vm)
|
obj.connect("action-show-domain", self._do_show_vm)
|
||||||
obj.connect("action-show-create", self._do_show_create)
|
obj.connect("action-show-create", self._do_show_create)
|
||||||
obj.connect("action-show-host", self._do_show_host)
|
obj.connect("action-show-host", self._do_show_host)
|
||||||
|
@ -735,23 +728,6 @@ class vmmEngine(vmmGObject):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
src.err.show_err(_("Error launching manager: %s") % str(e))
|
src.err.show_err(_("Error launching manager: %s") % str(e))
|
||||||
|
|
||||||
def _do_show_clone(self, src, uri, connkey):
|
|
||||||
conn = self._connobjs[uri]
|
|
||||||
connstate = self._connstates[uri]
|
|
||||||
orig_vm = conn.get_vm(connkey)
|
|
||||||
|
|
||||||
clone_window = connstate.windowClone
|
|
||||||
try:
|
|
||||||
if clone_window is None:
|
|
||||||
clone_window = vmmCloneVM(orig_vm)
|
|
||||||
connstate.windowClone = clone_window
|
|
||||||
else:
|
|
||||||
clone_window.set_orig_vm(orig_vm)
|
|
||||||
|
|
||||||
clone_window.show(src.topwin)
|
|
||||||
except Exception as e:
|
|
||||||
src.err.show_err(_("Error setting clone parameters: %s") % str(e))
|
|
||||||
|
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# Window launchers from virt-manager cli #
|
# Window launchers from virt-manager cli #
|
||||||
|
|
|
@ -95,7 +95,6 @@ class vmmManager(vmmGObjectUI):
|
||||||
"action-show-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
|
"action-show-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
|
||||||
"action-show-host": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
"action-show-host": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
||||||
"action-show-create": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
"action-show-create": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
||||||
"action-clone-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
|
|
||||||
"action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"manager-closed": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"manager-closed": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"manager-opened": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"manager-opened": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
|
|
|
@ -33,7 +33,6 @@ class vmmSystray(vmmGObject):
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
"action-toggle-manager": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"action-toggle-manager": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"action-view-manager": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"action-view-manager": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
"action-clone-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
|
|
||||||
"action-show-host": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
"action-show-host": (GObject.SignalFlags.RUN_FIRST, None, [str]),
|
||||||
"action-show-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
|
"action-show-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]),
|
||||||
"action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []),
|
"action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []),
|
||||||
|
|
|
@ -129,7 +129,7 @@ class VMActionMenu(_VMMenu):
|
||||||
|
|
||||||
self.add(Gtk.SeparatorMenuItem())
|
self.add(Gtk.SeparatorMenuItem())
|
||||||
self._add_action(_("Clone..."), "clone",
|
self._add_action(_("Clone..."), "clone",
|
||||||
_make_emit_cb("action-clone-domain"), iconname=None)
|
VMActionUI.clone, iconname=None)
|
||||||
self._add_action(_("Migrate..."), "migrate",
|
self._add_action(_("Migrate..."), "migrate",
|
||||||
VMActionUI.migrate, iconname=None)
|
VMActionUI.migrate, iconname=None)
|
||||||
self._add_action(_("_Delete"), "delete",
|
self._add_action(_("_Delete"), "delete",
|
||||||
|
@ -338,3 +338,8 @@ class VMActionUI(object):
|
||||||
def migrate(src, vm):
|
def migrate(src, vm):
|
||||||
from .migrate import vmmMigrateDialog
|
from .migrate import vmmMigrateDialog
|
||||||
vmmMigrateDialog.show_instance(src, vm)
|
vmmMigrateDialog.show_instance(src, vm)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clone(src, vm):
|
||||||
|
from .clone import vmmCloneVM
|
||||||
|
vmmCloneVM.show_instance(src, vm)
|
||||||
|
|
Loading…
Reference in New Issue