Date: Mon Oct 12 10:34:57 2015 +0200
From: Petr Tesarik <ptesarik@suse.com>
Subject: Add a network check with configurable timeout
References: bsc#944201
Patch-mainline: v0.8.16
Git-commit a6bb017c8563ea147a968d0b614aa8a08f1a2ad3

Before accessing a remote host, check that the network layer is
ready. The tool will stop waiting if network status does not change
within a configurable timeout (KDUMP_NET_TIMEOUT), but it will try
to save it anyway, because the underlying helpers might have an
alternative way to connect to the remote host.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>

---
 kdumptool/define_opt.h   |    1 +
 kdumptool/email.cc       |   12 +++++++++++-
 kdumptool/sshtransfer.cc |   13 +++++++++++++
 kdumptool/transfer.cc    |   19 +++++++++++++++++++
 sysconfig.kdump.in       |   11 +++++++++++
 5 files changed, 55 insertions(+), 1 deletion(-)

--- a/kdumptool/define_opt.h
+++ b/kdumptool/define_opt.h
@@ -34,6 +34,7 @@ DEFINE_OPT(KDUMP_POSTSCRIPT, String, "",
 DEFINE_OPT(KDUMP_COPY_KERNEL, Bool, "", DUMP)
 DEFINE_OPT(KDUMPTOOL_FLAGS, String, "", DUMP)
 DEFINE_OPT(KDUMP_NETCONFIG, String, "auto", MKINITRD)
+DEFINE_OPT(KDUMP_NET_TIMEOUT, Int, 30, DUMP)
 DEFINE_OPT(KDUMP_SMTP_SERVER, String, "", DUMP)
 DEFINE_OPT(KDUMP_SMTP_USER, String, "", DUMP)
 DEFINE_OPT(KDUMP_SMTP_PASSWORD, String, "", DUMP)
--- a/kdumptool/email.cc
+++ b/kdumptool/email.cc
@@ -30,6 +30,7 @@
 #include "configuration.h"
 #include "util.h"
 #include "stringutil.h"
+#include "routable.h"
 
 using std::string;
 
@@ -212,8 +213,17 @@ void Email::send()
     Debug::debug()->dbg("Host: %s", host.c_str());
 
     // default to "smtp" (25) port instead of 587
-    if (host.find(':') == string::npos)
+    string hostname;
+    size_t colonpos = host.find(':');
+    if (colonpos == string::npos) {
+        hostname = host;
         host += ":25";
+    } else
+	hostname = host.substr(0, colonpos);
+
+    Routable rt(hostname);
+    if (!rt.check(config->KDUMP_NET_TIMEOUT.value()))
+	throw KError("SMTP server not reachable");
 
     ret = smtp_set_server(session, strdup(host.c_str()));
     if (ret == 0)
--- a/kdumptool/sshtransfer.cc
+++ b/kdumptool/sshtransfer.cc
@@ -31,6 +31,7 @@
 #include "process.h"
 #include "socket.h"
 #include "sshtransfer.h"
+#include "routable.h"
 
 using std::string;
 using std::cerr;
@@ -51,6 +52,12 @@ SSHTransfer::SSHTransfer(const RootDirUR
     Debug::debug()->trace("SSHTransfer::SSHTransfer(%s)",
 			  target.getURL().c_str());
 
+    // Check network status
+    Configuration *config = Configuration::config();
+    Routable rt(target.getHostname());
+    if (!rt.check(config->KDUMP_NET_TIMEOUT.value()))
+	cerr << "WARNING: Dump target not reachable" << endl;
+
     string remote;
     FilePath fp = target.getPath();
     fp.appendPath(getSubDir());
@@ -359,6 +366,12 @@ SFTPTransfer::SFTPTransfer(const RootDir
 	cerr << "WARNING: First dump target used; rest ignored." << endl;
     const RootDirURL &parser = urlv.front();
 
+    // Check network status
+    Configuration *config = Configuration::config();
+    Routable rt(parser.getHostname());
+    if (!rt.check(config->KDUMP_NET_TIMEOUT.value()))
+	cerr << "WARNING: Dump target not reachable" << endl;
+
     Debug::debug()->trace("SFTPTransfer::SFTPTransfer(%s)",
 			  parser.getURL().c_str());
 
--- a/kdumptool/transfer.cc
+++ b/kdumptool/transfer.cc
@@ -37,6 +37,7 @@
 #include "stringutil.h"
 #include "configuration.h"
 #include "sshtransfer.h"
+#include "routable.h"
 
 using std::fopen;
 using std::fread;
@@ -458,6 +459,12 @@ void FTPTransfer::open(DataProvider *dat
     RootDirURLVector &urlv = getURLVector();
     const RootDirURL &parser = urlv.front();
 
+    // Check network status
+    Configuration *config = Configuration::config();
+    Routable rt(parser.getHostname());
+    if (!rt.check(config->KDUMP_NET_TIMEOUT.value()))
+	cerr << "WARNING: Dump target not reachable" << endl;
+
     // set the URL
     FilePath full_url = parser.getURL();
     full_url.appendPath(getSubDir()).appendPath(target_file);
@@ -495,6 +502,12 @@ RootDirURL NFSTransfer::translate(const
     StringVector options;
     options.push_back("nolock");
 
+    // Check network status
+    Configuration *config = Configuration::config();
+    Routable rt(parser.getHostname());
+    if (!rt.check(config->KDUMP_NET_TIMEOUT.value()))
+	cerr << "WARNING: Dump target not reachable" << endl;
+
     string mountedDir = parser.getPath();
     FileUtil::nfsmount(parser.getHostname(), mountedDir,
         DEFAULT_MOUNTPOINT, options);
@@ -566,6 +579,12 @@ CIFSTransfer::CIFSTransfer(const RootDir
 RootDirURL CIFSTransfer::translate(const RootDirURL &parser)
     throw (KError)
 {
+    // Check network status
+    Configuration *config = Configuration::config();
+    Routable rt(parser.getHostname());
+    if (!rt.check(config->KDUMP_NET_TIMEOUT.value()))
+	cerr << "WARNING: Dump target not reachable" << endl;
+
     KString share = parser.getPath();
     share.ltrim("/");
     string::size_type first_slash = share.find("/");
--- a/sysconfig.kdump.in
+++ b/sysconfig.kdump.in
@@ -301,6 +301,17 @@ KDUMPTOOL_FLAGS=""
 #
 KDUMP_NETCONFIG="auto"
 
+## Type:        integer
+## Default:     30
+## ServiceRestart:      kdump
+#
+# Timeout for network changes. Kdumptool gives up waiting for a working
+# network setup when it does not change for the given number of seconds.
+#
+# See also: kdump(5)
+#
+KDUMP_NET_TIMEOUT=30
+
 ## Type:        string
 ## Default:     ""
 ## ServiceRestart:	kdump
