Introducing keepalive similarly to Guannan around 2 years ago. Since
we want to introduce keepalive for every connection, it makes sense to
wrap the connecting function into new virsh one that can deal
keepalive as well.
Function vshConnect() is now used for connecting and keepalive added
in that function (if possible) helps preventing long waits e.g. while
nework goes down during migration.
This patch also adds the options for keepalive tuning into virsh and
fails connecting only when keepalives are explicitly requested and
cannot be set (whether it is due to missing support in connected
driver or remote server). If not explicitely requested, a debug
message is printed (hence the addition to virsh-optparse test).
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1073506
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=822839
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
tests/virsh-optparse | 3 +-
tools/virsh-domain.c | 2 +-
tools/virsh.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++-----
tools/virsh.h | 5 ++++
4 files changed, 78 insertions(+), 9 deletions(-)
diff --git a/tests/virsh-optparse b/tests/virsh-optparse
index 214ae41..7d4c699 100755
--- a/tests/virsh-optparse
+++ b/tests/virsh-optparse
@@ -1,7 +1,7 @@
#!/bin/sh
# Ensure that virsh option parsing doesn't regress
-# Copyright (C) 2011-2012 Red Hat, Inc.
+# Copyright (C) 2011-2012, 2014 Red Hat, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@ fi
cat <<\EOF > exp-out || framework_failure
+Failed to setup keepalive on connection
setvcpus: <domain> trying as domain NAME
setvcpus: count(optdata): 2
setvcpus: domain(optdata): test
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 1d3c5f0..3e989ee 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -8781,7 +8781,7 @@ doMigrate(void *opaque)
virConnectPtr dconn = NULL;
virDomainPtr ddom = NULL;
- dconn = virConnectOpenAuth(desturi, virConnectAuthPtrDefault, 0);
+ dconn = vshConnect(ctl, desturi, false);
if (!dconn)
goto out;
diff --git a/tools/virsh.c b/tools/virsh.c
index 9b8429f..73c58a5 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -315,6 +315,45 @@ vshCatchDisconnect(virConnectPtr conn ATTRIBUTE_UNUSED,
disconnected++;
}
+/* Main Function which should be used for connecting.
+ * This function properly handles keepalive settings. */
+virConnectPtr
+vshConnect(vshControl *ctl, const char *uri, bool readonly)
+{
+ virConnectPtr c = NULL;
+ int interval = 5; /* Default */
+ int count = 6; /* Default */
+ bool keepalive_forced = false;
+
+ if (ctl->keepalive_interval >= 0) {
+ interval = ctl->keepalive_interval;
+ keepalive_forced = true;
+ }
+ if (ctl->keepalive_count > 0) {
+ count = ctl->keepalive_count;
+ keepalive_forced = true;
+ }
+
+ c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
+ readonly ? VIR_CONNECT_RO : 0);
+ if (!c)
+ return NULL;
+
+ if (virConnectSetKeepAlive(c, interval, count) != 0) {
+ if (keepalive_forced) {
+ vshError(ctl, "%s",
+ _("Cannot setup keepalive on connection "
+ "as requested, disconnecting"));
+ virConnectClose(c);
+ return NULL;
+ }
+ vshDebug(ctl, VSH_ERR_INFO, "%s",
+ _("Failed to setup keepalive on connection\n"));
+ }
+
+ return c;
+}
+
/*
* vshReconnect:
*
@@ -340,9 +379,8 @@ vshReconnect(vshControl *ctl)
"disconnect from the hypervisor"));
}
- ctl->conn = virConnectOpenAuth(ctl->name,
- virConnectAuthPtrDefault,
- ctl->readonly ? VIR_CONNECT_RO : 0);
+ ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly);
+
if (!ctl->conn) {
if (disconnected)
vshError(ctl, "%s", _("Failed to reconnect to the
hypervisor"));
@@ -417,8 +455,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd)
ctl->useSnapshotOld = false;
ctl->readonly = ro;
- ctl->conn = virConnectOpenAuth(ctl->name, virConnectAuthPtrDefault,
- ctl->readonly ? VIR_CONNECT_RO : 0);
+ ctl->conn = vshConnect(ctl, ctl->name, ctl->readonly);
if (!ctl->conn) {
vshError(ctl, "%s", _("Failed to connect to the
hypervisor"));
@@ -3113,6 +3150,10 @@ vshUsage(void)
" -d | --debug=NUM debug level [0-4]\n"
" -e | --escape <char> set escape sequence for
console\n"
" -h | --help this help\n"
+ " -k | --keepalive-interval=NUM\n"
+ " keepalive interval in seconds, 0
for disable\n"
+ " -K | --keepalive-count=NUM\n"
+ " number of possible missed
keepalive messages\n"
" -l | --log=FILE output logging to file\n"
" -q | --quiet quiet mode\n"
" -r | --readonly connect readonly\n"
@@ -3302,7 +3343,7 @@ vshAllowedEscapeChar(char c)
static bool
vshParseArgv(vshControl *ctl, int argc, char **argv)
{
- int arg, len, debug;
+ int arg, len, debug, keepalive;
size_t i;
int longindex = -1;
struct option opt[] = {
@@ -3310,6 +3351,8 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
{"debug", required_argument, NULL, 'd'},
{"escape", required_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'},
+ {"keepalive-interval", required_argument, NULL, 'k'},
+ {"keepalive-count", required_argument, NULL, 'K'},
{"log", required_argument, NULL, 'l'},
{"quiet", no_argument, NULL, 'q'},
{"readonly", no_argument, NULL, 'r'},
@@ -3321,7 +3364,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
/* Standard (non-command) options. The leading + ensures that no
* argument reordering takes place, so that command options are
* not confused with top-level virsh options. */
- while ((arg = getopt_long(argc, argv, "+:c:d:e:hl:qrtvV", opt,
&longindex)) != -1) {
+ while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt,
&longindex)) != -1) {
switch (arg) {
case 'c':
VIR_FREE(ctl->name);
@@ -3356,6 +3399,24 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
vshUsage();
exit(EXIT_SUCCESS);
break;
+ case 'k':
+ if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0 ||
+ keepalive < 0) {
+ vshError(ctl, _("option -%s requires a positive numeric
argument"),
+ longindex == -1 ? "-k" :
"--keepalive-interval");
+ exit(EXIT_FAILURE);
+ }
+ ctl->keepalive_interval = keepalive;
+ break;
+ case 'K':
+ if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0 ||
+ keepalive < 0) {
+ vshError(ctl, _("option -%s requires a positive numeric
argument"),
+ longindex == -1 ? "-K" :
"--keepalive-count");
+ exit(EXIT_FAILURE);
+ }
+ ctl->keepalive_count = keepalive;
+ break;
case 'l':
vshCloseLogFile(ctl);
ctl->logfile = vshStrdup(ctl, optarg);
@@ -3490,6 +3551,8 @@ main(int argc, char **argv)
ctl->log_fd = -1; /* Initialize log file descriptor */
ctl->debug = VSH_DEBUG_DEFAULT;
ctl->escapeChar = "^]"; /* Same default as telnet */
+ ctl->keepalive_interval = -1; /* In order to distinguish default
+ * from setting to 0 */
ctl->eventPipe[0] = -1;
ctl->eventPipe[1] = -1;
ctl->eventTimerId = -1;
diff --git a/tools/virsh.h b/tools/virsh.h
index 62a1eed..3e0251b 100644
--- a/tools/virsh.h
+++ b/tools/virsh.h
@@ -249,6 +249,9 @@ struct _vshControl {
const char *escapeChar; /* String representation of
console escape character */
+ int keepalive_interval; /* Client keepalive interval */
+ int keepalive_count; /* Client keepalive count */
+
# ifndef WIN32
struct termios termattr; /* settings of the tty terminal */
# endif
@@ -269,6 +272,8 @@ void vshOutputLogFile(vshControl *ctl, int log_level, const char
*format,
ATTRIBUTE_FMT_PRINTF(3, 0);
void vshCloseLogFile(vshControl *ctl);
+virConnectPtr vshConnect(vshControl *ctl, const char *uri, bool readonly);
+
const char *vshCmddefGetInfo(const vshCmdDef *cmd, const char *info);
const vshCmdDef *vshCmddefSearch(const char *cmdname);
bool vshCmddefHelp(vshControl *ctl, const char *name);
--
1.9.0