Give better errors if PolicyKit auth fails

Coupled with a recent libvirt patch, try and give more info about
a couple common policykit failure scenarios, like launching virt-manager
over SSH or VNC.

Do this by checking to see if we have a 'session' with ConsoleKit: the
above culprits don't give the user a local session, which causes
PolicyKit to deny.
This commit is contained in:
Cole Robinson 2012-01-27 18:31:21 -05:00
parent 8a92690a55
commit 2f10fc668c
2 changed files with 78 additions and 25 deletions

View File

@ -20,11 +20,11 @@
import logging
import os
import traceback
import re
import socket
import threading
import time
import socket
import traceback
import dbus
import libvirt
@ -48,6 +48,34 @@ def _is_virtinst_test_uri(uri):
except:
return False
def _do_we_have_session():
pid = os.getpid()
try:
bus = dbus.SystemBus()
except:
logging.exception("Error getting system bus handle")
return False
# Check ConsoleKit
try:
manager = dbus.Interface(bus.get_object(
"org.freedesktop.ConsoleKit",
"/org/freedesktop/ConsoleKit/Manager"),
"org.freedesktop.ConsoleKit.Manager")
except:
logging.exception("Couldn't connect to ConsoleKit")
return False
try:
ret = manager.GetSessionForUnixProcess(pid)
logging.debug("Found ConsoleKit session=%s" % ret)
except:
logging.exception("Failed to lookup pid session")
return False
return True
class vmmConnection(vmmGObject):
STATE_DISCONNECTED = 0
@ -1151,6 +1179,7 @@ class vmmConnection(vmmGObject):
libexc = None
exc = None
tb = None
warnconsole = False
try:
self.vmm = self._try_open()
except libvirt.libvirtError, libexc:
@ -1173,6 +1202,15 @@ class vmmConnection(vmmGObject):
logging.debug("User cancelled auth, not raising any error.")
break
if (libexc and
libexc.get_error_code() == libvirt.VIR_ERR_AUTH_FAILED and
"not authorized" in libexc.get_error_message().lower()):
logging.debug("Looks like we might have failed policykit "
"auth. Checking to see if we have a valid "
"console session")
if not self.is_remote() and not _do_we_have_session():
warnconsole = True
if (libexc and
libexc.get_error_code() == libvirt.VIR_ERR_AUTH_FAILED and
"GSSAPI Error" in libexc.get_error_message() and
@ -1180,7 +1218,7 @@ class vmmConnection(vmmGObject):
if self._acquire_tgt():
continue
self.connectError = "%s\n\n%s" % (exc, tb)
self.connectError = (str(exc), tb, warnconsole)
break
# We want to kill off this thread asap, so schedule an
@ -1208,7 +1246,7 @@ class vmmConnection(vmmGObject):
if self.state == self.STATE_DISCONNECTED:
if self.connectError:
self.idle_emit("connect-error", self.connectError)
self.idle_emit("connect-error", *self.connectError)
self.connectError = None
@ -1706,4 +1744,4 @@ vmmGObject.signal_new(vmmConnection, "mediadev-removed", [str])
vmmGObject.signal_new(vmmConnection, "resources-sampled", [])
vmmGObject.signal_new(vmmConnection, "state-changed", [])
vmmGObject.signal_new(vmmConnection, "connect-error", [str])
vmmGObject.signal_new(vmmConnection, "connect-error", [str, str, bool])

View File

@ -644,27 +644,42 @@ class vmmManager(vmmGObjectUI):
conn.open()
return True
def _connect_error(self, conn, details):
if conn.get_driver() == "xen" and not conn.is_remote():
self.err.show_err(
_("Unable to open a connection to the Xen hypervisor/daemon.\n\n" +
"Verify that:\n" +
" - A Xen host kernel was booted\n" +
" - The Xen service has been started\n"),
details=details,
title=_("Virtual Machine Manager Connection Failure"))
def _connect_error(self, conn, shortmsg, tb, warnconsole):
shortmsg = shortmsg.strip(" \n")
tb = tb.strip(" \n")
msg = _("Unable to connect to libvirt:\n\n%s\n\n") % shortmsg
if conn.is_xen() and not conn.is_remote():
msg += _("Verify that:\n"
" - A Xen host kernel was booted\n"
" - The Xen service has been started\n")
msg = msg.strip("\n")
details = "%s\n\n%s" % (msg, tb)
else:
hint = ''
if re.search(r"nc: .* -- 'U'", details):
hint = _("\n - The remote netcat understands the '-U' option")
self.err.show_err(
_("Unable to open a connection to the libvirt "
"management daemon.\n\n" +
"Libvirt URI is: %s\n\n" % conn.get_uri() +
"Verify that:\n" +
" - The 'libvirtd' daemon has been started") + hint,
details=details,
title=_("Virtual Machine Manager Connection Failure"))
hints = []
if conn.is_remote() and re.search(r"nc: .* -- 'U'", details):
hints.append(
_("\n - The remote netcat understands the '-U' option"))
if warnconsole:
msg += _("Could not detect a local session: if you are \n"
"running virt-manager over ssh -X or VNC, you \n"
"may not be able to connect to libvirt as a \n"
"regular user. Try running as root.\n\n")
else:
msg += _("Verify that:\n" +
" - The 'libvirtd' daemon has been started")
for hint in hints:
msg += hint
msg = msg.strip("\n")
details = (("%s\n\n" % msg) +
(_("Libvirt URI is: %s\n\n") % conn.get_uri()) +
tb)
self.err.show_err(msg, details,
title=_("Virtual Machine Manager Connection Failure"))
####################################