mirror of https://gitee.com/openkylin/libvirt.git
Make virsh reconnect when losing connection
When the daemon libvirtd restarts, a connected virsh gets a SIGPIPE and dies. This change the behaviour to try to reconnect if the signal was received or command error indicated a connection or RPC failure. Note that the failing command is not restarted. * tools/virsh.c: catch SIGPIPE signals as well as connection related failures, add some automatic reconnection code and appropriate error messages.
This commit is contained in:
parent
7be9270c24
commit
056623f3d7
|
@ -30,6 +30,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <libxml/parser.h>
|
#include <libxml/parser.h>
|
||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
|
@ -397,6 +398,60 @@ out:
|
||||||
last_error = NULL;
|
last_error = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detection of disconnections and automatic reconnection support
|
||||||
|
*/
|
||||||
|
static int disconnected = 0; /* we may have been disconnected */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vshCatchDisconnect:
|
||||||
|
*
|
||||||
|
* We get here when a SIGPIPE is being raised, we can't do much in the
|
||||||
|
* handler, just save the fact it was raised
|
||||||
|
*/
|
||||||
|
static void vshCatchDisconnect(int sig, siginfo_t * siginfo,
|
||||||
|
void* context ATTRIBUTE_UNUSED) {
|
||||||
|
if ((sig == SIGPIPE) || (siginfo->si_signo == SIGPIPE))
|
||||||
|
disconnected++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vshSetupSignals:
|
||||||
|
*
|
||||||
|
* Catch SIGPIPE signals which may arise when disconnection
|
||||||
|
* from libvirtd occurs
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
vshSetupSignals(void) {
|
||||||
|
struct sigaction sig_action;
|
||||||
|
|
||||||
|
sig_action.sa_sigaction = vshCatchDisconnect;
|
||||||
|
sig_action.sa_flags = SA_SIGINFO;
|
||||||
|
sigemptyset(&sig_action.sa_mask);
|
||||||
|
|
||||||
|
sigaction(SIGPIPE, &sig_action, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vshReconnect:
|
||||||
|
*
|
||||||
|
* Reconnect after an
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
vshReconnect(vshControl *ctl) {
|
||||||
|
if (ctl->conn != NULL)
|
||||||
|
virConnectClose(ctl->conn);
|
||||||
|
|
||||||
|
ctl->conn = virConnectOpenAuth(ctl->name,
|
||||||
|
virConnectAuthPtrDefault,
|
||||||
|
ctl->readonly ? VIR_CONNECT_RO : 0);
|
||||||
|
if (!ctl->conn)
|
||||||
|
vshError(ctl, "%s", _("Failed to reconnect to the hypervisor"));
|
||||||
|
else
|
||||||
|
vshError(ctl, "%s", _("Reconnected to the hypervisor"));
|
||||||
|
disconnected = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------
|
/* ---------------
|
||||||
* Commands
|
* Commands
|
||||||
|
@ -8334,6 +8389,9 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
|
||||||
while (cmd) {
|
while (cmd) {
|
||||||
struct timeval before, after;
|
struct timeval before, after;
|
||||||
|
|
||||||
|
if ((ctl->conn == NULL) || (disconnected != 0))
|
||||||
|
vshReconnect(ctl);
|
||||||
|
|
||||||
if (ctl->timing)
|
if (ctl->timing)
|
||||||
GETTIMEOFDAY(&before);
|
GETTIMEOFDAY(&before);
|
||||||
|
|
||||||
|
@ -8345,6 +8403,17 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
|
||||||
if (ret == FALSE)
|
if (ret == FALSE)
|
||||||
virshReportError(ctl);
|
virshReportError(ctl);
|
||||||
|
|
||||||
|
/* try to automatically catch disconnections */
|
||||||
|
if ((ret == FALSE) &&
|
||||||
|
((disconnected != 0) ||
|
||||||
|
((last_error != NULL) &&
|
||||||
|
(((last_error->code == VIR_ERR_SYSTEM_ERROR) &&
|
||||||
|
(last_error->domain == VIR_FROM_REMOTE)) ||
|
||||||
|
(last_error->code == VIR_ERR_RPC) ||
|
||||||
|
(last_error->code == VIR_ERR_NO_CONNECT) ||
|
||||||
|
(last_error->code == VIR_ERR_INVALID_CONN)))))
|
||||||
|
vshReconnect(ctl);
|
||||||
|
|
||||||
if (STREQ(cmd->def->name, "quit")) /* hack ... */
|
if (STREQ(cmd->def->name, "quit")) /* hack ... */
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -8675,9 +8744,11 @@ vshError(vshControl *ctl, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
if (ctl != NULL) {
|
||||||
vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
|
va_start(ap, format);
|
||||||
va_end(ap);
|
vshOutputLogFile(ctl, VSH_ERR_ERROR, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
fputs(_("error: "), stderr);
|
fputs(_("error: "), stderr);
|
||||||
|
|
||||||
|
@ -8753,6 +8824,9 @@ vshInit(vshControl *ctl)
|
||||||
/* set up the library error handler */
|
/* set up the library error handler */
|
||||||
virSetErrorFunc(NULL, virshErrorHandler);
|
virSetErrorFunc(NULL, virshErrorHandler);
|
||||||
|
|
||||||
|
/* set up the signals handlers to catch disconnections */
|
||||||
|
vshSetupSignals();
|
||||||
|
|
||||||
ctl->conn = virConnectOpenAuth(ctl->name,
|
ctl->conn = virConnectOpenAuth(ctl->name,
|
||||||
virConnectAuthPtrDefault,
|
virConnectAuthPtrDefault,
|
||||||
ctl->readonly ? VIR_CONNECT_RO : 0);
|
ctl->readonly ? VIR_CONNECT_RO : 0);
|
||||||
|
|
Loading…
Reference in New Issue