提交 31330926 编写于 作者: D Daniel P. Berrange

Inhibit desktop shutdown while any virtual machines are running

Use the freedesktop inhibition DBus service to prevent host
shutdown or session logout while any VMs are running.
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
上级 79b8a569
......@@ -37,6 +37,7 @@
#include "virfile.h"
#include "event.h"
#include "virnetservermdns.h"
#include "virdbus.h"
#ifndef SA_SIGINFO
# define SA_SIGINFO 0
......@@ -102,6 +103,8 @@ struct _virNetServer {
unsigned int autoShutdownTimeout;
size_t autoShutdownInhibitions;
bool autoShutdownCallingInhibit;
int autoShutdownInhibitFd;
virNetServerClientPrivNew clientPrivNew;
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
......@@ -390,7 +393,8 @@ virNetServerPtr virNetServerNew(size_t min_workers,
srv->clientPrivPreExecRestart = clientPrivPreExecRestart;
srv->clientPrivFree = clientPrivFree;
srv->clientPrivOpaque = clientPrivOpaque;
srv->privileged = geteuid() == 0 ? true : false;
srv->privileged = geteuid() == 0;
srv->autoShutdownInhibitFd = -1;
if (mdnsGroupName &&
!(srv->mdnsGroupName = strdup(mdnsGroupName))) {
......@@ -716,10 +720,104 @@ void virNetServerAutoShutdown(virNetServerPtr srv,
}
#ifdef HAVE_DBUS
static void virNetServerGotInhibitReply(DBusPendingCall *pending,
void *opaque)
{
virNetServerPtr srv = opaque;
DBusMessage *reply;
int fd;
virNetServerLock(srv);
srv->autoShutdownCallingInhibit = false;
VIR_DEBUG("srv=%p", srv);
reply = dbus_pending_call_steal_reply(pending);
if (reply == NULL)
goto cleanup;
if (dbus_message_get_args(reply, NULL,
DBUS_TYPE_UNIX_FD, &fd,
DBUS_TYPE_INVALID)) {
if (srv->autoShutdownInhibitions) {
srv->autoShutdownInhibitFd = fd;
} else {
/* We stopped the last VM since we made the inhibit call */
VIR_FORCE_CLOSE(fd);
}
}
dbus_message_unref(reply);
cleanup:
virNetServerUnlock(srv);
}
/* As per: http://www.freedesktop.org/wiki/Software/systemd/inhibit */
static void virNetServerCallInhibit(virNetServerPtr srv,
const char *what,
const char *who,
const char *why,
const char *mode)
{
DBusMessage *message;
DBusPendingCall *pendingReply;
DBusConnection *systemBus;
VIR_DEBUG("srv=%p what=%s who=%s why=%s mode=%s",
srv, NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode));
if (!(systemBus = virDBusGetSystemBus()))
return;
/* Only one outstanding call at a time */
if (srv->autoShutdownCallingInhibit)
return;
message = dbus_message_new_method_call("org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"Inhibit");
if (message == NULL)
return;
dbus_message_append_args(message,
DBUS_TYPE_STRING, &what,
DBUS_TYPE_STRING, &who,
DBUS_TYPE_STRING, &why,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID);
pendingReply = NULL;
if (dbus_connection_send_with_reply(systemBus, message,
&pendingReply,
25*1000)) {
dbus_pending_call_set_notify(pendingReply,
virNetServerGotInhibitReply,
srv, NULL);
srv->autoShutdownCallingInhibit = true;
}
dbus_message_unref(message);
}
#endif
void virNetServerAddShutdownInhibition(virNetServerPtr srv)
{
virNetServerLock(srv);
srv->autoShutdownInhibitions++;
VIR_DEBUG("srv=%p inhibitions=%zu", srv, srv->autoShutdownInhibitions);
#ifdef HAVE_DBUS
if (srv->autoShutdownInhibitions == 1)
virNetServerCallInhibit(srv,
"shutdown",
_("Libvirt"),
_("Virtual machines need to be saved"),
"delay");
#endif
virNetServerUnlock(srv);
}
......@@ -728,6 +826,12 @@ void virNetServerRemoveShutdownInhibition(virNetServerPtr srv)
{
virNetServerLock(srv);
srv->autoShutdownInhibitions--;
VIR_DEBUG("srv=%p inhibitions=%zu", srv, srv->autoShutdownInhibitions);
if (srv->autoShutdownInhibitions == 0)
VIR_FORCE_CLOSE(srv->autoShutdownInhibitFd);
virNetServerUnlock(srv);
}
......@@ -1065,6 +1169,8 @@ void virNetServerDispose(void *obj)
virNetServerPtr srv = obj;
int i;
VIR_FORCE_CLOSE(srv->autoShutdownInhibitFd);
for (i = 0 ; i < srv->nservices ; i++)
virNetServerServiceToggle(srv->services[i], false);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册