mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-03-29 02:50:19 +03:00
uihelpers: Move a few more functions closer to their callers
This commit is contained in:
parent
20088ab8fb
commit
58d5e0b799
@ -18,6 +18,7 @@
|
||||
# MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import os
|
||||
import logging
|
||||
import socket
|
||||
|
||||
@ -28,7 +29,6 @@ from gi.repository import Gtk
|
||||
# pylint: enable=E0611
|
||||
|
||||
from virtManager.baseclass import vmmGObjectUI
|
||||
from virtManager import uihelpers
|
||||
|
||||
HV_XEN = 0
|
||||
HV_QEMU = 1
|
||||
@ -99,6 +99,23 @@ class vmmConnect(vmmGObjectUI):
|
||||
|
||||
self.reset_state()
|
||||
|
||||
@staticmethod
|
||||
def default_uri(always_system=False):
|
||||
if os.path.exists('/var/lib/xen'):
|
||||
if (os.path.exists('/dev/xen/evtchn') or
|
||||
os.path.exists("/proc/xen")):
|
||||
return 'xen:///'
|
||||
|
||||
if (os.path.exists("/usr/bin/qemu") or
|
||||
os.path.exists("/usr/bin/qemu-kvm") or
|
||||
os.path.exists("/usr/bin/kvm") or
|
||||
os.path.exists("/usr/libexec/qemu-kvm")):
|
||||
if always_system or os.geteuid() == 0:
|
||||
return "qemu:///system"
|
||||
else:
|
||||
return "qemu:///session"
|
||||
return None
|
||||
|
||||
def cancel(self, ignore1=None, ignore2=None):
|
||||
logging.debug("Cancelling open connection")
|
||||
self.close()
|
||||
@ -148,7 +165,7 @@ class vmmConnect(vmmGObjectUI):
|
||||
return self.widget("connect-remote").get_active()
|
||||
|
||||
def set_default_hypervisor(self):
|
||||
default = uihelpers.default_uri(always_system=True)
|
||||
default = self.default_uri(always_system=True)
|
||||
if not default or default.startswith("qemu"):
|
||||
self.widget("hypervisor").set_active(1)
|
||||
elif default.startswith("xen"):
|
||||
|
@ -129,6 +129,33 @@ class vmmConnection(vmmGObject):
|
||||
self._init_virtconn()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def pretty_hv(gtype, domtype):
|
||||
"""
|
||||
Convert XML <domain type='foo'> and <os><type>bar</type>
|
||||
into a more human relevant string.
|
||||
"""
|
||||
|
||||
gtype = gtype.lower()
|
||||
domtype = domtype.lower()
|
||||
|
||||
label = domtype
|
||||
if domtype == "kvm":
|
||||
if gtype == "xen":
|
||||
label = "xenner"
|
||||
elif domtype == "xen":
|
||||
if gtype == "xen":
|
||||
label = "xen (paravirt)"
|
||||
elif gtype == "hvm":
|
||||
label = "xen (fullvirt)"
|
||||
elif domtype == "test":
|
||||
if gtype == "xen":
|
||||
label = "test (xen)"
|
||||
elif gtype == "hvm":
|
||||
label = "test (hvm)"
|
||||
|
||||
return label
|
||||
|
||||
#################
|
||||
# Init routines #
|
||||
#################
|
||||
@ -713,6 +740,8 @@ class vmmConnection(vmmGObject):
|
||||
if p.get_name() == name:
|
||||
return p
|
||||
return None
|
||||
def get_default_pool(self):
|
||||
return self.get_pool_by_name("default")
|
||||
|
||||
def get_vol_by_path(self, path):
|
||||
for pool in self.pools.values():
|
||||
|
@ -679,7 +679,7 @@ class vmmCreate(vmmGObjectUI):
|
||||
continue
|
||||
dom = guest.domains[0]
|
||||
domtype = dom.hypervisor_type
|
||||
label = uihelpers.pretty_hv(gtype, domtype)
|
||||
label = self.conn.pretty_hv(gtype, domtype)
|
||||
|
||||
# Don't add multiple rows for each arch
|
||||
for m in model:
|
||||
|
@ -165,6 +165,18 @@ class vmmCreateInterface(vmmGObjectUI):
|
||||
# Initialization routines #
|
||||
###########################
|
||||
|
||||
@staticmethod
|
||||
def iface_in_use_by(conn, name):
|
||||
use_str = ""
|
||||
for i in conn.list_interface_names():
|
||||
iface = conn.get_interface(i)
|
||||
if name in iface.get_slave_names():
|
||||
if use_str:
|
||||
use_str += ", "
|
||||
use_str += iface.get_name()
|
||||
|
||||
return use_str
|
||||
|
||||
@staticmethod
|
||||
def build_interface_startmode_combo(combo):
|
||||
model = Gtk.ListStore(str)
|
||||
@ -558,8 +570,8 @@ class vmmCreateInterface(vmmGObjectUI):
|
||||
|
||||
for row in row_dict.values():
|
||||
name = row[INTERFACE_ROW_NAME]
|
||||
row[INTERFACE_ROW_IN_USE_BY] = uihelpers.iface_in_use_by(self.conn,
|
||||
name)
|
||||
row[INTERFACE_ROW_IN_USE_BY] = self.iface_in_use_by(self.conn,
|
||||
name)
|
||||
|
||||
for row in row_dict.values():
|
||||
model.append(row)
|
||||
|
@ -150,10 +150,10 @@ class vmmDeleteDialog(vmmGObjectUI):
|
||||
title = _("Are you sure you want to delete the storage?")
|
||||
message = (_("The following paths will be deleted:\n\n%s") %
|
||||
"\n".join(devs))
|
||||
ret = uihelpers.chkbox_helper(self,
|
||||
self.config.get_confirm_delstorage,
|
||||
self.config.set_confirm_delstorage,
|
||||
text1=title, text2=message)
|
||||
ret = self.err.chkbox_helper(
|
||||
self.config.get_confirm_delstorage,
|
||||
self.config.set_confirm_delstorage,
|
||||
text1=title, text2=message)
|
||||
if not ret:
|
||||
return
|
||||
|
||||
|
@ -1100,7 +1100,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
if not self.widget("config-apply").get_sensitive():
|
||||
return False
|
||||
|
||||
if not uihelpers.chkbox_helper(self,
|
||||
if not self.err.chkbox_helper(
|
||||
self.config.get_confirm_unapplied,
|
||||
self.config.set_confirm_unapplied,
|
||||
text1=(_("There are unapplied changes. Would you like to apply "
|
||||
@ -2243,7 +2243,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
def remove_device(self, dev_type, dev_id_info):
|
||||
logging.debug("Removing device: %s %s", dev_type, dev_id_info)
|
||||
|
||||
if not uihelpers.chkbox_helper(self, self.config.get_confirm_removedev,
|
||||
if not self.err.chkbox_helper(self.config.get_confirm_removedev,
|
||||
self.config.set_confirm_removedev,
|
||||
text1=(_("Are you sure you want to remove this device?"))):
|
||||
return
|
||||
@ -2360,7 +2360,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
if self.is_visible():
|
||||
self.vm.refresh_xml()
|
||||
except libvirt.libvirtError, e:
|
||||
if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
if util.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
self.close()
|
||||
return
|
||||
raise
|
||||
|
@ -34,7 +34,6 @@ from virtinst import Guest
|
||||
from virtinst import util
|
||||
from virtinst import VirtualController
|
||||
|
||||
from virtManager import uihelpers
|
||||
from virtManager.libvirtobject import vmmLibvirtObject
|
||||
|
||||
|
||||
@ -1011,7 +1010,7 @@ class vmmDomain(vmmLibvirtObject):
|
||||
def get_hv_type(self):
|
||||
return self.get_xmlobj().type
|
||||
def get_pretty_hv_type(self):
|
||||
return uihelpers.pretty_hv(self.get_abi_type(), self.get_hv_type())
|
||||
return self.conn.pretty_hv(self.get_abi_type(), self.get_hv_type())
|
||||
def get_arch(self):
|
||||
return self.get_xmlobj().os.arch
|
||||
def get_init(self):
|
||||
@ -1274,7 +1273,7 @@ class vmmDomain(vmmLibvirtObject):
|
||||
try:
|
||||
return self._backend.hasManagedSaveImage(0)
|
||||
except libvirt.libvirtError, e:
|
||||
if not uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
if not util.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
raise
|
||||
return False
|
||||
|
||||
@ -1573,7 +1572,7 @@ class vmmDomain(vmmLibvirtObject):
|
||||
info = self._backend.info()
|
||||
self._update_status(info[0])
|
||||
except libvirt.libvirtError, e:
|
||||
if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
if util.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
return
|
||||
raise
|
||||
|
||||
|
@ -203,7 +203,7 @@ class vmmEngine(vmmGObject):
|
||||
if ret:
|
||||
tryuri = "qemu:///system"
|
||||
else:
|
||||
tryuri = uihelpers.default_uri(always_system=True)
|
||||
tryuri = vmmConnect.default_uri(always_system=True)
|
||||
|
||||
if tryuri is None:
|
||||
manager.set_startup_error(msg)
|
||||
@ -901,7 +901,7 @@ class vmmEngine(vmmGObject):
|
||||
"libvirt version or hypervisor."))
|
||||
return
|
||||
|
||||
if not uihelpers.chkbox_helper(src, self.config.get_confirm_poweroff,
|
||||
if not src.err.chkbox_helper(self.config.get_confirm_poweroff,
|
||||
self.config.set_confirm_poweroff,
|
||||
text1=_("Are you sure you want to save '%s'?" % vm.get_name())):
|
||||
return
|
||||
@ -971,7 +971,7 @@ class vmmEngine(vmmGObject):
|
||||
conn = self._lookup_conn(uri)
|
||||
vm = conn.get_vm(uuid)
|
||||
|
||||
if not uihelpers.chkbox_helper(src,
|
||||
if not src.err.chkbox_helper(
|
||||
self.config.get_confirm_forcepoweroff,
|
||||
self.config.set_confirm_forcepoweroff,
|
||||
text1=_("Are you sure you want to force poweroff '%s'?" %
|
||||
@ -988,7 +988,7 @@ class vmmEngine(vmmGObject):
|
||||
conn = self._lookup_conn(uri)
|
||||
vm = conn.get_vm(uuid)
|
||||
|
||||
if not uihelpers.chkbox_helper(src, self.config.get_confirm_pause,
|
||||
if not src.err.chkbox_helper(self.config.get_confirm_pause,
|
||||
self.config.set_confirm_pause,
|
||||
text1=_("Are you sure you want to pause '%s'?" %
|
||||
vm.get_name())):
|
||||
@ -1051,7 +1051,7 @@ class vmmEngine(vmmGObject):
|
||||
conn = self._lookup_conn(uri)
|
||||
vm = conn.get_vm(uuid)
|
||||
|
||||
if not uihelpers.chkbox_helper(src, self.config.get_confirm_poweroff,
|
||||
if not src.err.chkbox_helper(self.config.get_confirm_poweroff,
|
||||
self.config.set_confirm_poweroff,
|
||||
text1=_("Are you sure you want to poweroff '%s'?" %
|
||||
vm.get_name())):
|
||||
@ -1065,7 +1065,7 @@ class vmmEngine(vmmGObject):
|
||||
conn = self._lookup_conn(uri)
|
||||
vm = conn.get_vm(uuid)
|
||||
|
||||
if not uihelpers.chkbox_helper(src, self.config.get_confirm_poweroff,
|
||||
if not src.err.chkbox_helper(self.config.get_confirm_poweroff,
|
||||
self.config.set_confirm_poweroff,
|
||||
text1=_("Are you sure you want to reboot '%s'?" %
|
||||
vm.get_name())):
|
||||
@ -1104,7 +1104,7 @@ class vmmEngine(vmmGObject):
|
||||
conn = self._lookup_conn(uri)
|
||||
vm = conn.get_vm(uuid)
|
||||
|
||||
if not uihelpers.chkbox_helper(src,
|
||||
if not src.err.chkbox_helper(
|
||||
self.config.get_confirm_forcepoweroff,
|
||||
self.config.set_confirm_forcepoweroff,
|
||||
text1=_("Are you sure you want to force reset '%s'?" %
|
||||
|
@ -179,6 +179,30 @@ class vmmErrorDialog(vmmGObject):
|
||||
secondary_text=text2,
|
||||
chktext=chktext)
|
||||
|
||||
def chkbox_helper(self, getcb, setcb, text1, text2=None,
|
||||
alwaysrecord=False,
|
||||
default=True,
|
||||
chktext=_("Don't ask me again")):
|
||||
"""
|
||||
Helper to prompt user about proceeding with an operation
|
||||
Returns True if the 'yes' or 'ok' button was selected, False otherwise
|
||||
|
||||
@alwaysrecord: Don't require user to select 'yes' to record chkbox value
|
||||
@default: What value to return if getcb tells us not to prompt
|
||||
"""
|
||||
do_prompt = getcb()
|
||||
if not do_prompt:
|
||||
return default
|
||||
|
||||
res = self.warn_chkbox(text1=text1, text2=text2,
|
||||
chktext=chktext,
|
||||
buttons=Gtk.ButtonsType.YES_NO)
|
||||
response, skip_prompt = res
|
||||
if alwaysrecord or response:
|
||||
setcb(not skip_prompt)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
class _errorDialog (Gtk.MessageDialog):
|
||||
"""
|
||||
|
@ -1003,7 +1003,7 @@ class vmmHost(vmmGObjectUI):
|
||||
if interface is None:
|
||||
return
|
||||
|
||||
if not uihelpers.chkbox_helper(self, self.config.get_confirm_interface,
|
||||
if not self.err.chkbox_helper(self.config.get_confirm_interface,
|
||||
self.config.set_confirm_interface,
|
||||
text1=_("Are you sure you want to stop the interface "
|
||||
"'%s'?" % interface.get_name())):
|
||||
@ -1018,7 +1018,7 @@ class vmmHost(vmmGObjectUI):
|
||||
if interface is None:
|
||||
return
|
||||
|
||||
if not uihelpers.chkbox_helper(self, self.config.get_confirm_interface,
|
||||
if not self.err.chkbox_helper(self.config.get_confirm_interface,
|
||||
self.config.set_confirm_interface,
|
||||
text1=_("Are you sure you want to start the interface "
|
||||
"'%s'?" % interface.get_name())):
|
||||
@ -1160,7 +1160,7 @@ class vmmHost(vmmGObjectUI):
|
||||
# This can fail if other interfaces are busted, so ignore errors
|
||||
used_by = None
|
||||
try:
|
||||
used_by = uihelpers.iface_in_use_by(self.conn, name)
|
||||
used_by = vmmCreateInterface.iface_in_use_by(self.conn, name)
|
||||
except Exception, e:
|
||||
logging.debug("Error looking up iface usage: %s", e)
|
||||
self.widget("interface-inuseby").set_text(used_by or "-")
|
||||
|
@ -24,7 +24,6 @@ from gi.repository import GObject
|
||||
|
||||
import logging
|
||||
|
||||
from virtManager import uihelpers
|
||||
from virtManager.baseclass import vmmGObject
|
||||
|
||||
|
||||
@ -54,6 +53,21 @@ class vmmLibvirtObject(vmmGObject):
|
||||
|
||||
self.connect("config-changed", self._reparse_xml)
|
||||
|
||||
@staticmethod
|
||||
def log_redefine_xml_diff(obj, origxml, newxml):
|
||||
objname = "<%s name=%s>" % (obj.__class__.__name__, obj.get_name())
|
||||
if origxml == newxml:
|
||||
logging.debug("Redefine requested for %s, but XML didn't change!",
|
||||
objname)
|
||||
return
|
||||
|
||||
import difflib
|
||||
diff = "".join(difflib.unified_diff(origxml.splitlines(1),
|
||||
newxml.splitlines(1),
|
||||
fromfile="Original XML",
|
||||
tofile="New XML"))
|
||||
logging.debug("Redefining %s with XML diff:\n%s", objname, diff)
|
||||
|
||||
def _cleanup(self):
|
||||
pass
|
||||
|
||||
@ -205,7 +219,7 @@ class vmmLibvirtObject(vmmGObject):
|
||||
return self._xmlobj_to_define
|
||||
|
||||
def _redefine_helper(self, origxml, newxml):
|
||||
uihelpers.log_redefine_xml_diff(self, origxml, newxml)
|
||||
self.log_redefine_xml_diff(self, origxml, newxml)
|
||||
|
||||
if origxml != newxml:
|
||||
self._define(newxml)
|
||||
|
@ -790,7 +790,7 @@ class vmmManager(vmmGObjectUI):
|
||||
desc = desc or ""
|
||||
row[ROW_HINT] = util.xml_escape(desc)
|
||||
except libvirt.libvirtError, e:
|
||||
if uihelpers.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
if util.exception_is_libvirt_error(e, "VIR_ERR_NO_DOMAIN"):
|
||||
return
|
||||
raise
|
||||
|
||||
|
@ -523,7 +523,7 @@ class vmmSnapshotPage(vmmGObjectUI):
|
||||
xmlobj.description = desc
|
||||
newxml = xmlobj.get_xml_config()
|
||||
|
||||
uihelpers.log_redefine_xml_diff(snap, origxml, newxml)
|
||||
self.vm.log_redefine_xml_diff(snap, origxml, newxml)
|
||||
if newxml == origxml:
|
||||
return
|
||||
self.vm.create_snapshot(newxml, redefine=True)
|
||||
|
@ -179,7 +179,7 @@ class vmmStorageBrowser(vmmGObjectUI):
|
||||
|
||||
if not self._first_run:
|
||||
self._first_run = True
|
||||
pool = uihelpers.get_default_pool(self.conn)
|
||||
pool = self.conn.get_default_pool()
|
||||
uihelpers.set_row_selection(
|
||||
self.widget("pool-list"), pool and pool.get_uuid() or None)
|
||||
# Manually trigger vol_selected, so buttons are in the correct state
|
||||
|
@ -28,8 +28,6 @@ from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
# pylint: enable=E0611
|
||||
|
||||
import libvirt
|
||||
|
||||
import virtinst
|
||||
from virtManager import config
|
||||
|
||||
@ -63,9 +61,16 @@ def set_sparse_tooltip(widget):
|
||||
widget.set_tooltip_text(sparse_str)
|
||||
|
||||
|
||||
def _get_default_dir(conn):
|
||||
pool = conn.get_default_pool()
|
||||
if pool:
|
||||
return pool.get_target_path()
|
||||
return config.running_config.get_default_image_dir(conn)
|
||||
|
||||
|
||||
def host_disk_space(conn):
|
||||
pool = get_default_pool(conn)
|
||||
path = get_default_dir(conn)
|
||||
pool = conn.get_default_pool()
|
||||
path = _get_default_dir(conn)
|
||||
|
||||
avail = 0
|
||||
if pool and pool.is_active():
|
||||
@ -98,7 +103,7 @@ def update_host_space(conn, widget):
|
||||
|
||||
|
||||
def check_default_pool_active(err, conn):
|
||||
default_pool = get_default_pool(conn)
|
||||
default_pool = conn.get_default_pool()
|
||||
if default_pool and not default_pool.is_active():
|
||||
res = err.yes_no(_("Default pool is not active."),
|
||||
_("Storage pool '%s' is not active. "
|
||||
@ -118,6 +123,121 @@ def check_default_pool_active(err, conn):
|
||||
return True
|
||||
|
||||
|
||||
def _get_ideal_path_info(conn, name):
|
||||
path = _get_default_dir(conn)
|
||||
suffix = ".img"
|
||||
return (path, name, suffix)
|
||||
|
||||
|
||||
def get_ideal_path(conn, name):
|
||||
target, name, suffix = _get_ideal_path_info(conn, name)
|
||||
return os.path.join(target, name) + suffix
|
||||
|
||||
|
||||
def get_default_path(conn, name, collidelist=None):
|
||||
collidelist = collidelist or []
|
||||
pool = conn.get_default_pool()
|
||||
|
||||
default_dir = _get_default_dir(conn)
|
||||
|
||||
def path_exists(p):
|
||||
return os.path.exists(p) or p in collidelist
|
||||
|
||||
if not pool:
|
||||
# Use old generating method
|
||||
origf = os.path.join(default_dir, name + ".img")
|
||||
f = origf
|
||||
|
||||
n = 1
|
||||
while path_exists(f) and n < 100:
|
||||
f = os.path.join(default_dir, name +
|
||||
"-" + str(n) + ".img")
|
||||
n += 1
|
||||
|
||||
if path_exists(f):
|
||||
f = origf
|
||||
|
||||
path = f
|
||||
else:
|
||||
target, ignore, suffix = _get_ideal_path_info(conn, name)
|
||||
|
||||
# Sanitize collidelist to work with the collision checker
|
||||
newcollidelist = []
|
||||
for c in collidelist:
|
||||
if c and os.path.dirname(c) == pool.get_target_path():
|
||||
newcollidelist.append(os.path.basename(c))
|
||||
|
||||
path = virtinst.StorageVolume.find_free_name(
|
||||
pool.get_backend(), name,
|
||||
suffix=suffix, collidelist=newcollidelist)
|
||||
|
||||
path = os.path.join(target, path)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def check_path_search_for_qemu(err, conn, path):
|
||||
if conn.is_remote() or not conn.is_qemu_system():
|
||||
return
|
||||
|
||||
user = config.running_config.default_qemu_user
|
||||
|
||||
for i in conn.caps.host.secmodels:
|
||||
if i.model == "dac":
|
||||
label = i.baselabels.get("kvm") or i.baselabels.get("qemu")
|
||||
if not label:
|
||||
continue
|
||||
pwuid = pwd.getpwuid(int(label.split(":")[0].replace("+", "")))
|
||||
if pwuid:
|
||||
user = pwuid[0]
|
||||
|
||||
skip_paths = config.running_config.get_perms_fix_ignore()
|
||||
broken_paths = virtinst.VirtualDisk.check_path_search_for_user(
|
||||
conn.get_backend(),
|
||||
path, user)
|
||||
for p in broken_paths:
|
||||
if p in skip_paths:
|
||||
broken_paths.remove(p)
|
||||
|
||||
if not broken_paths:
|
||||
return
|
||||
|
||||
logging.debug("No search access for dirs: %s", broken_paths)
|
||||
resp, chkres = err.warn_chkbox(
|
||||
_("The emulator may not have search permissions "
|
||||
"for the path '%s'.") % path,
|
||||
_("Do you want to correct this now?"),
|
||||
_("Don't ask about these directories again."),
|
||||
buttons=Gtk.ButtonsType.YES_NO)
|
||||
|
||||
if chkres:
|
||||
config.running_config.add_perms_fix_ignore(broken_paths)
|
||||
if not resp:
|
||||
return
|
||||
|
||||
logging.debug("Attempting to correct permission issues.")
|
||||
errors = virtinst.VirtualDisk.fix_path_search_for_user(conn.get_backend(),
|
||||
path, user)
|
||||
if not errors:
|
||||
return
|
||||
|
||||
errmsg = _("Errors were encountered changing permissions for the "
|
||||
"following directories:")
|
||||
details = ""
|
||||
for path, error in errors.items():
|
||||
if path not in broken_paths:
|
||||
continue
|
||||
details += "%s : %s\n" % (path, error)
|
||||
|
||||
logging.debug("Permission errors:\n%s", details)
|
||||
|
||||
ignore, chkres = err.err_chkbox(errmsg, details,
|
||||
_("Don't ask about these directories again."))
|
||||
|
||||
if chkres:
|
||||
config.running_config.add_perms_fix_ignore(errors.keys())
|
||||
|
||||
|
||||
#########################################
|
||||
# VM <interface> device listing helpers #
|
||||
#########################################
|
||||
@ -678,70 +798,6 @@ class VMActionMenu(_VMMenu):
|
||||
child.get_child().set_label(text)
|
||||
|
||||
|
||||
#####################################
|
||||
# Path permissions checker for qemu #
|
||||
#####################################
|
||||
|
||||
def check_path_search_for_qemu(err, conn, path):
|
||||
if conn.is_remote() or not conn.is_qemu_system():
|
||||
return
|
||||
|
||||
user = config.running_config.default_qemu_user
|
||||
|
||||
for i in conn.caps.host.secmodels:
|
||||
if i.model == "dac":
|
||||
label = i.baselabels.get("kvm") or i.baselabels.get("qemu")
|
||||
if not label:
|
||||
continue
|
||||
pwuid = pwd.getpwuid(int(label.split(":")[0].replace("+", "")))
|
||||
if pwuid:
|
||||
user = pwuid[0]
|
||||
|
||||
skip_paths = config.running_config.get_perms_fix_ignore()
|
||||
broken_paths = virtinst.VirtualDisk.check_path_search_for_user(
|
||||
conn.get_backend(),
|
||||
path, user)
|
||||
for p in broken_paths:
|
||||
if p in skip_paths:
|
||||
broken_paths.remove(p)
|
||||
|
||||
if not broken_paths:
|
||||
return
|
||||
|
||||
logging.debug("No search access for dirs: %s", broken_paths)
|
||||
resp, chkres = err.warn_chkbox(
|
||||
_("The emulator may not have search permissions "
|
||||
"for the path '%s'.") % path,
|
||||
_("Do you want to correct this now?"),
|
||||
_("Don't ask about these directories again."),
|
||||
buttons=Gtk.ButtonsType.YES_NO)
|
||||
|
||||
if chkres:
|
||||
config.running_config.add_perms_fix_ignore(broken_paths)
|
||||
if not resp:
|
||||
return
|
||||
|
||||
logging.debug("Attempting to correct permission issues.")
|
||||
errors = virtinst.VirtualDisk.fix_path_search_for_user(conn.get_backend(),
|
||||
path, user)
|
||||
if not errors:
|
||||
return
|
||||
|
||||
errmsg = _("Errors were encountered changing permissions for the "
|
||||
"following directories:")
|
||||
details = ""
|
||||
for path, error in errors.items():
|
||||
if path not in broken_paths:
|
||||
continue
|
||||
details += "%s : %s\n" % (path, error)
|
||||
|
||||
logging.debug("Permission errors:\n%s", details)
|
||||
|
||||
ignore, chkres = err.err_chkbox(errmsg, details,
|
||||
_("Don't ask about these directories again."))
|
||||
|
||||
if chkres:
|
||||
config.running_config.add_perms_fix_ignore(errors.keys())
|
||||
|
||||
|
||||
################
|
||||
@ -762,83 +818,11 @@ def spin_get_helper(widget):
|
||||
txt = widget.get_text()
|
||||
|
||||
try:
|
||||
ret = int(txt)
|
||||
return int(txt)
|
||||
except:
|
||||
ret = adj.get_value()
|
||||
return ret
|
||||
return adj.get_value()
|
||||
|
||||
|
||||
def get_ideal_path_info(conn, name):
|
||||
path = get_default_dir(conn)
|
||||
suffix = ".img"
|
||||
return (path, name, suffix)
|
||||
|
||||
|
||||
def get_ideal_path(conn, name):
|
||||
target, name, suffix = get_ideal_path_info(conn, name)
|
||||
return os.path.join(target, name) + suffix
|
||||
|
||||
|
||||
def get_default_pool(conn):
|
||||
pool = None
|
||||
for uuid in conn.list_pool_uuids():
|
||||
p = conn.get_pool(uuid)
|
||||
if p.get_name() == "default":
|
||||
pool = p
|
||||
|
||||
return pool
|
||||
|
||||
|
||||
def get_default_dir(conn):
|
||||
pool = get_default_pool(conn)
|
||||
|
||||
if pool:
|
||||
return pool.get_target_path()
|
||||
else:
|
||||
return config.running_config.get_default_image_dir(conn)
|
||||
|
||||
|
||||
def get_default_path(conn, name, collidelist=None):
|
||||
collidelist = collidelist or []
|
||||
pool = get_default_pool(conn)
|
||||
|
||||
default_dir = get_default_dir(conn)
|
||||
|
||||
def path_exists(p):
|
||||
return os.path.exists(p) or p in collidelist
|
||||
|
||||
if not pool:
|
||||
# Use old generating method
|
||||
origf = os.path.join(default_dir, name + ".img")
|
||||
f = origf
|
||||
|
||||
n = 1
|
||||
while path_exists(f) and n < 100:
|
||||
f = os.path.join(default_dir, name +
|
||||
"-" + str(n) + ".img")
|
||||
n += 1
|
||||
|
||||
if path_exists(f):
|
||||
f = origf
|
||||
|
||||
path = f
|
||||
else:
|
||||
target, ignore, suffix = get_ideal_path_info(conn, name)
|
||||
|
||||
# Sanitize collidelist to work with the collision checker
|
||||
newcollidelist = []
|
||||
for c in collidelist:
|
||||
if c and os.path.dirname(c) == pool.get_target_path():
|
||||
newcollidelist.append(os.path.basename(c))
|
||||
|
||||
path = virtinst.StorageVolume.find_free_name(
|
||||
pool.get_backend(), name,
|
||||
suffix=suffix, collidelist=newcollidelist)
|
||||
|
||||
path = os.path.join(target, path)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def browse_local(parent, dialog_name, conn, start_folder=None,
|
||||
_type=None, dialog_type=None,
|
||||
@ -926,70 +910,6 @@ def browse_local(parent, dialog_name, conn, start_folder=None,
|
||||
return ret
|
||||
|
||||
|
||||
def pretty_hv(gtype, domtype):
|
||||
"""
|
||||
Convert XML <domain type='foo'> and <os><type>bar</type>
|
||||
into a more human relevant string.
|
||||
"""
|
||||
|
||||
gtype = gtype.lower()
|
||||
domtype = domtype.lower()
|
||||
|
||||
label = domtype
|
||||
if domtype == "kvm":
|
||||
if gtype == "xen":
|
||||
label = "xenner"
|
||||
elif domtype == "xen":
|
||||
if gtype == "xen":
|
||||
label = "xen (paravirt)"
|
||||
elif gtype == "hvm":
|
||||
label = "xen (fullvirt)"
|
||||
elif domtype == "test":
|
||||
if gtype == "xen":
|
||||
label = "test (xen)"
|
||||
elif gtype == "hvm":
|
||||
label = "test (hvm)"
|
||||
|
||||
return label
|
||||
|
||||
|
||||
def iface_in_use_by(conn, name):
|
||||
use_str = ""
|
||||
for i in conn.list_interface_names():
|
||||
iface = conn.get_interface(i)
|
||||
if name in iface.get_slave_names():
|
||||
if use_str:
|
||||
use_str += ", "
|
||||
use_str += iface.get_name()
|
||||
|
||||
return use_str
|
||||
|
||||
|
||||
def chkbox_helper(src, getcb, setcb, text1, text2=None,
|
||||
alwaysrecord=False,
|
||||
default=True,
|
||||
chktext=_("Don't ask me again")):
|
||||
"""
|
||||
Helper to prompt user about proceeding with an operation
|
||||
Returns True if the 'yes' or 'ok' button was selected, False otherwise
|
||||
|
||||
@alwaysrecord: Don't require user to select 'yes' to record chkbox value
|
||||
@default: What value to return if getcb tells us not to prompt
|
||||
"""
|
||||
do_prompt = getcb()
|
||||
if not do_prompt:
|
||||
return default
|
||||
|
||||
res = src.err.warn_chkbox(text1=text1, text2=text2,
|
||||
chktext=chktext,
|
||||
buttons=Gtk.ButtonsType.YES_NO)
|
||||
response, skip_prompt = res
|
||||
if alwaysrecord or response:
|
||||
setcb(not skip_prompt)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def get_list_selection(widget):
|
||||
selection = widget.get_selection()
|
||||
active = selection.get_selected()
|
||||
@ -1055,40 +975,3 @@ def set_grid_row_visible(child, visible):
|
||||
for child in parent.get_children():
|
||||
if child_get_property(parent, child, "top-attach") == row:
|
||||
child.set_visible(visible)
|
||||
|
||||
|
||||
def default_uri(always_system=False):
|
||||
if os.path.exists('/var/lib/xen'):
|
||||
if (os.path.exists('/dev/xen/evtchn') or
|
||||
os.path.exists("/proc/xen")):
|
||||
return 'xen:///'
|
||||
|
||||
if (os.path.exists("/usr/bin/qemu") or
|
||||
os.path.exists("/usr/bin/qemu-kvm") or
|
||||
os.path.exists("/usr/bin/kvm") or
|
||||
os.path.exists("/usr/libexec/qemu-kvm")):
|
||||
if always_system or os.geteuid() == 0:
|
||||
return "qemu:///system"
|
||||
else:
|
||||
return "qemu:///session"
|
||||
return None
|
||||
|
||||
|
||||
def exception_is_libvirt_error(e, error):
|
||||
return (hasattr(libvirt, error) and
|
||||
e.get_error_code() == getattr(libvirt, error))
|
||||
|
||||
|
||||
def log_redefine_xml_diff(obj, origxml, newxml):
|
||||
objname = "<%s name=%s>" % (obj.__class__.__name__, obj.get_name())
|
||||
if origxml == newxml:
|
||||
logging.debug("Redefine requested for %s, but XML didn't change!",
|
||||
objname)
|
||||
return
|
||||
|
||||
import difflib
|
||||
diff = "".join(difflib.unified_diff(origxml.splitlines(1),
|
||||
newxml.splitlines(1),
|
||||
fromfile="Original XML",
|
||||
tofile="New XML"))
|
||||
logging.debug("Redefining %s with XML diff:\n%s", objname, diff)
|
||||
|
@ -442,6 +442,11 @@ def is_error_nosupport(err):
|
||||
return False
|
||||
|
||||
|
||||
def exception_is_libvirt_error(e, error):
|
||||
return (hasattr(libvirt, error) and
|
||||
e.get_error_code() == getattr(libvirt, error))
|
||||
|
||||
|
||||
def local_libvirt_version():
|
||||
"""
|
||||
Lookup the local libvirt library version, but cache the value since
|
||||
|
Loading…
x
Reference in New Issue
Block a user