diff --git a/tests/virsh-optparse b/tests/virsh-optparse index 214ae41ab8..39e6cde951 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 @@ -65,7 +65,7 @@ for args in \ '--count 2 test' \ '--count=2 test' \ ; do - virsh -d0 -c $test_url setvcpus $args >out 2>>err || fail=1 + virsh -k0 -d0 -c $test_url setvcpus $args >out 2>>err || fail=1 LC_ALL=C sort out | compare exp-out - || fail=1 done diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index f2a26f9e3e..fbde3da0db 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -8785,7 +8785,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 9b8429f875..02835d9cec 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -315,6 +315,46 @@ 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 (interval > 0 && + 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 +380,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 +456,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 +3151,10 @@ vshUsage(void) " -d | --debug=NUM debug level [0-4]\n" " -e | --escape 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 +3344,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 +3352,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 +3365,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 +3400,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 +3552,11 @@ main(int argc, char **argv) ctl->log_fd = -1; /* Initialize log file descriptor */ ctl->debug = VSH_DEBUG_DEFAULT; ctl->escapeChar = "^]"; /* Same default as telnet */ + + /* In order to distinguish default from setting to 0 */ + ctl->keepalive_interval = -1; + ctl->keepalive_count = -1; + ctl->eventPipe[0] = -1; ctl->eventPipe[1] = -1; ctl->eventTimerId = -1; diff --git a/tools/virsh.h b/tools/virsh.h index 62a1eed904..3e0251b621 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); diff --git a/tools/virsh.pod b/tools/virsh.pod index cefce1bb6a..5c74bb328c 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -74,6 +74,18 @@ alphabetic character, @, [, ], \, ^, _. Ignore all other arguments, and behave as if the B command were given instead. +=item B<-k>, B<--keepalive-interval> I + +Set an I (in seconds) for sending keepalive messages to +check whether connection to the server is still alive. Setting the +interval to 0 disables client keepalive mechanism. + +=item B<-K>, B<--keepalive-count> I + +Set a number of times keepalive message can be sent without getting an +answer from the server without marking the connection dead. There is +no effect to this setting in case the I is set to 0. + =item B<-l>, B<--log> I Output logging details to I.