Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 636738 Details for
Bug 872254
user libvirtd need to shut down cleanly when the session dies
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Save all domains when session bus dies or system is being shutdown
libvirt-save-with-session.patch (text/plain), 10.19 KB, created by
Alexander Larsson
on 2012-11-01 16:18:43 UTC
(
hide
)
Description:
Save all domains when session bus dies or system is being shutdown
Filename:
MIME Type:
Creator:
Alexander Larsson
Created:
2012-11-01 16:18:43 UTC
Size:
10.19 KB
patch
obsolete
>Return-Path: alexl@redhat.com >Received: from zmta06.collab.prod.int.phx2.redhat.com (LHLO > zmta06.collab.prod.int.phx2.redhat.com) (10.5.81.13) by > zmail20.collab.prod.int.phx2.redhat.com with LMTP; Tue, 9 Oct 2012 11:26:39 > -0400 (EDT) >Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) > by zmta06.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id D4A8516044F > for <alexl@mail.corp.redhat.com>; Tue, 9 Oct 2012 11:26:39 -0400 (EDT) >Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) > by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q99FQV94016417; > Tue, 9 Oct 2012 11:26:34 -0400 >From: Alexander Larsson <alexl@redhat.com> >To: libvir-list@redhat.com >Cc: Alexander Larsson <alexl@redhat.com> >Subject: [PATCH 2/2] Shut down session libvirtd cleanly >Date: Tue, 9 Oct 2012 17:26:29 +0200 >Message-Id: <1349796389-6122-3-git-send-email-alexl@redhat.com> >In-Reply-To: <1349796389-6122-1-git-send-email-alexl@redhat.com> >References: <1349796389-6122-1-git-send-email-alexl@redhat.com> >X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 > >When the session dies or when the system is going to be shut down >we save all active VMs and exit libvirtd. > >Additionally whenever there is an active domain we hold a >shutdown inhibitor to avoid shutting down before all the >VMs are saved. >--- > daemon/libvirtd.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 244 insertions(+) > >diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c >index b49acc5..c3bf2ce 100644 >--- a/daemon/libvirtd.c >+++ b/daemon/libvirtd.c >@@ -98,6 +98,11 @@ > > #include "configmake.h" > >+#ifdef HAVE_DBUS >+# include <dbus/dbus.h> >+# include "virdbus.h" >+#endif >+ > #if HAVE_SASL > virNetSASLContextPtr saslCtxt = NULL; > #endif >@@ -769,6 +774,212 @@ static int daemonSetupSignals(virNetServerPtr srv) > return 0; > } > >+#ifdef HAVE_DBUS >+ >+static DBusConnection *sessionBus; >+static DBusConnection *systemBus; >+static virConnectPtr sessionConnection; >+static int numActiveDomains; >+static bool hasInhibit; >+static bool callingInhibit; >+static int inhibitFd = -1; >+ >+static void runSaveAllDomains(void *opaque) >+{ >+ virNetServerPtr srv = opaque; >+ int numDomains, i; >+ int state; >+ virDomainPtr *domains = NULL; >+ unsigned int *flags = NULL; >+ >+ numDomains = virConnectListAllDomains(sessionConnection, &domains, VIR_CONNECT_LIST_DOMAINS_ACTIVE); >+ if (numDomains < 0) >+ goto cleanup; >+ >+ if (VIR_ALLOC_N(flags, numDomains) < 0) { >+ virReportOOMError(); >+ goto cleanup; >+ } >+ >+ /* First we pause all VMs to make them stop dirtying >+ pages, etc. We remember if any VMs were paused so >+ we can restore that on resume. */ >+ for (i = 0 ; i < numDomains ; i++) { >+ flags[i] = VIR_DOMAIN_SAVE_RUNNING; >+ if (virDomainGetState (domains[i], &state, NULL, 0) == 0) { >+ if (state == VIR_DOMAIN_PAUSED) { >+ flags[i] = VIR_DOMAIN_SAVE_PAUSED; >+ } >+ } >+ virDomainSuspend (domains[i]); >+ } >+ >+ /* Then we save the VMs to disk */ >+ for (i = 0 ; i < numDomains ; i++) >+ virDomainManagedSave (domains[i], flags[i]); >+ >+ VIR_FREE (domains); >+ VIR_FREE (flags); >+ >+ cleanup: >+ if (domains != NULL) { >+ for (i = 0 ; i < numDomains ; i++) >+ virDomainFree (domains[i]); >+ VIR_FREE (domains); >+ } >+ if (flags != NULL) >+ VIR_FREE (flags); >+ >+ /* We don't need any shutdown inhibit lock anymore now */ >+ if (inhibitFd != -1) { >+ if (VIR_CLOSE (inhibitFd) < 0) >+ virReportSystemError(errno, "%s", _("failed to close file")); >+ inhibitFd = -1; >+ } >+ >+ /* Exit libvirtd cleanly */ >+ virNetServerQuit (srv); >+} >+ >+/* We do this in a thread to not block the main loop */ >+static void saveAllDomains(virNetServerPtr srv) >+{ >+ virThread thr; >+ virObjectRef(srv); >+ if (virThreadCreate(&thr, false, runSaveAllDomains, srv) < 0) { >+ virObjectUnref(srv); >+ } >+} >+ >+static void gotInhibitReply (DBusPendingCall *pending, >+ void *opaque ATTRIBUTE_UNUSED) >+{ >+ DBusMessage *reply; >+ int fd; >+ >+ callingInhibit = false; >+ >+ reply = dbus_pending_call_steal_reply (pending); >+ if (reply == NULL) >+ return; >+ >+ if (dbus_message_get_args (reply, NULL, >+ DBUS_TYPE_UNIX_FD, &fd, >+ DBUS_TYPE_INVALID)) { >+ if (hasInhibit) >+ inhibitFd = fd; >+ else { >+ /* We stopped the last VM since we made the inhibit call */ >+ if (VIR_CLOSE (fd) < 0) { >+ virReportSystemError(errno, "%s", _("failed to close file")); >+ } >+ } >+ } >+ dbus_message_unref (reply); >+} >+ >+/* As per: http://www.freedesktop.org/wiki/Software/systemd/inhibit */ >+static void callInhibit(const char *what, >+ const char *who, >+ const char *why, >+ const char *mode) >+{ >+ DBusMessage *message; >+ DBusPendingCall *pendingReply; >+ >+ if (systemBus == NULL) >+ return; >+ >+ /* Only one outstanding call at a time */ >+ if (callingInhibit) >+ 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, >+ gotInhibitReply, >+ NULL, NULL); >+ callingInhibit = true; >+ } >+ dbus_message_unref (message); >+} >+ >+ >+static void numActiveDomainsChanged(void) >+{ >+ if (numActiveDomains > 0 && !hasInhibit) { >+ callInhibit("shutdown", _("Libvirt"), _("Virtual machines need to be saved"), "delay"); >+ hasInhibit = true; >+ } else if (numActiveDomains == 0 && hasInhibit) { >+ if (inhibitFd != -1) { >+ if (VIR_CLOSE (inhibitFd) < 0) { >+ virReportSystemError(errno, "%s", _("failed to close file")); >+ } >+ inhibitFd = -1; >+ } >+ hasInhibit = false; >+ } >+} >+ >+static int lifecycleEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED, >+ virDomainPtr dom ATTRIBUTE_UNUSED, >+ int event, >+ int detail ATTRIBUTE_UNUSED, >+ void *opaque ATTRIBUTE_UNUSED) >+{ >+ if (event == VIR_DOMAIN_EVENT_STOPPED) >+ numActiveDomains--; >+ else if (event == VIR_DOMAIN_EVENT_STARTED) >+ numActiveDomains++; >+ >+ numActiveDomainsChanged(); >+ >+ return 0; >+} >+ >+static DBusHandlerResult handleSessionMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED, >+ DBusMessage *message, >+ void *userData) >+{ >+ virNetServerPtr srv = userData; >+ >+ if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) { >+ saveAllDomains (srv); >+ } >+ >+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; >+} >+ >+static DBusHandlerResult handleSystemMessageFunc(DBusConnection *connection ATTRIBUTE_UNUSED, >+ DBusMessage *message, >+ void *userData) >+{ >+ virNetServerPtr srv = userData; >+ >+ if (dbus_message_is_signal(message, "org.freedesktop.login1.Manager", "PrepareForShutdown")) { >+ saveAllDomains (srv); >+ } >+ >+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; >+} >+#endif >+ > static void daemonRunStateInit(void *opaque) > { > virNetServerPtr srv = opaque; >@@ -785,6 +996,39 @@ static void daemonRunStateInit(void *opaque) > return; > } > >+#ifdef HAVE_DBUS >+ /* Tie the non-priviledged libvirtd to the session/shutdown lifecycle */ >+ if (!virNetServerIsPrivileged(srv)) { >+ >+ sessionBus = virDBusGetSessionBus (); >+ if (sessionBus != NULL) { >+ dbus_connection_add_filter(sessionBus, >+ handleSessionMessageFunc, srv, NULL); >+ } >+ >+ systemBus = virDBusGetSystemBus (); >+ if (systemBus != NULL) { >+ dbus_connection_add_filter(systemBus, >+ handleSystemMessageFunc, srv, NULL); >+ dbus_bus_add_match(systemBus, >+ "type='signal',sender='org.freedesktop.login1', interface='org.freedesktop.login1.Manager'", >+ NULL); >+ } >+ >+ sessionConnection = virConnectOpen("qemu:///session"); >+ if (sessionConnection != NULL) { >+ numActiveDomains = virConnectNumOfDomains(sessionConnection); >+ virConnectDomainEventRegisterAny(sessionConnection, >+ NULL, >+ VIR_DOMAIN_EVENT_ID_LIFECYCLE, >+ VIR_DOMAIN_EVENT_CALLBACK (lifecycleEventCallback), >+ NULL, NULL); >+ numActiveDomainsChanged(); >+ } >+ >+ } >+#endif >+ > /* Only now accept clients from network */ > virNetServerUpdateServices(srv, true); > virObjectUnref(srv); >-- >1.7.12.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 872254
:
636737
| 636738