X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/1d3dfa297c66bab4919bd20fae11d66a7f363607..850c53f1cbab8c60c6be4964d10e8a2d3b3eb22b:/daemons/import-export diff --git a/daemons/import-export b/daemons/import-export index cecdc19..21d1d34 100755 --- a/daemons/import-export +++ b/daemons/import-export @@ -23,7 +23,7 @@ """ -# pylint: disable-msg=C0103 +# pylint: disable=C0103 # C0103: Invalid name import-export import errno @@ -43,8 +43,8 @@ from ganeti import utils from ganeti import errors from ganeti import serializer from ganeti import objects -from ganeti import locking from ganeti import impexpd +from ganeti import netutils #: How many lines to keep in the status file @@ -53,9 +53,6 @@ MAX_RECENT_OUTPUT_LINES = 20 #: Don't update status file more than once every 5 seconds (unless forced) MIN_UPDATE_INTERVAL = 5.0 -#: Give child process up to 5 seconds to exit after sending a signal -CHILD_LINGER_TIMEOUT = 5.0 - #: How long to wait for a connection to be established DEFAULT_CONNECT_TIMEOUT = 60 @@ -131,7 +128,7 @@ class StatusFile: @param port: TCP/UDP port """ - assert isinstance(port, (int, long)) and 0 < port < 2**16 + assert isinstance(port, (int, long)) and 0 < port < (2 ** 16) self._data.listen_port = port def GetListenPort(self): @@ -203,7 +200,7 @@ class StatusFile: self._data.mtime = time.time() utils.WriteFile(self._path, - data=serializer.DumpJson(self._data.ToDict(), indent=True), + data=serializer.DumpJson(self._data.ToDict()), mode=0400) @@ -255,7 +252,7 @@ def ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd, poller.register(fd, select.POLLIN) if options.connect_timeout and mode == constants.IEM_IMPORT: - listen_timeout = locking.RunningTimeout(options.connect_timeout, True) + listen_timeout = utils.RunningTimeout(options.connect_timeout, True) else: listen_timeout = None @@ -270,13 +267,19 @@ def ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd, timeout = None if listen_timeout and not exit_timeout: + assert mode == constants.IEM_IMPORT and options.connect_timeout if status_file.GetConnected(): listen_timeout = None elif listen_timeout.Remaining() < 0: - logging.info("Child process didn't establish connection in time") + errmsg = ("Child process didn't establish connection in time" + " (%0.0fs), sending SIGTERM" % options.connect_timeout) + logging.error(errmsg) + status_file.AddRecentOutput(errmsg) + status_file.Update(True) + child.Kill(signal.SIGTERM) exit_timeout = \ - locking.RunningTimeout(CHILD_LINGER_TIMEOUT, True) + utils.RunningTimeout(constants.CHILD_LINGER_TIMEOUT, True) # Next block will calculate timeout else: # Not yet connected, check again in a second @@ -292,11 +295,10 @@ def ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd, notify_status = child_io_proc.NotifyDd() if notify_status: # Schedule next notification - dd_stats_timeout = locking.RunningTimeout(DD_STATISTICS_INTERVAL, - True) + dd_stats_timeout = utils.RunningTimeout(DD_STATISTICS_INTERVAL, True) else: # Try again soon (dd isn't ready yet) - dd_stats_timeout = locking.RunningTimeout(1.0, True) + dd_stats_timeout = utils.RunningTimeout(1.0, True) if dd_stats_timeout: dd_timeout = max(0, dd_stats_timeout.Remaining() * 1000) @@ -324,9 +326,9 @@ def ProcessChildIO(child, socat_stderr_read_fd, dd_stderr_read_fd, " to exit", exit_timeout.Remaining()) else: logging.info("Giving child process %0.2f seconds to exit", - CHILD_LINGER_TIMEOUT) + constants.CHILD_LINGER_TIMEOUT) exit_timeout = \ - locking.RunningTimeout(CHILD_LINGER_TIMEOUT, True) + utils.RunningTimeout(constants.CHILD_LINGER_TIMEOUT, True) else: poller.unregister(fd) del fdmap[fd] @@ -351,7 +353,7 @@ def ParseOptions(): @return: Arguments to program """ - global options # pylint: disable-msg=W0603 + global options # pylint: disable=W0603 parser = optparse.OptionParser(usage=("%%prog {%s|%s}" % (constants.IEM_IMPORT, @@ -366,6 +368,10 @@ def ParseOptions(): help="X509 CA file") parser.add_option("--bind", dest="bind", action="store", type="string", help="Bind address") + parser.add_option("--ipv4", dest="ipv4", action="store_true", + help="Use IPv4 only") + parser.add_option("--ipv6", dest="ipv6", action="store_true", + help="Use IPv6 only") parser.add_option("--host", dest="host", action="store", type="string", help="Remote hostname") parser.add_option("--port", dest="port", action="store", type="int", @@ -405,9 +411,9 @@ def ParseOptions(): parser.error("Invalid mode: %s" % mode) # Normalize and check parameters - if options.host is not None: + if options.host is not None and not netutils.IPAddress.IsValid(options.host): try: - options.host = utils.HostInfo.NormalizeName(options.host) + options.host = netutils.Hostname.GetNormalizedName(options.host) except errors.OpPrereqError, err: parser.error("Invalid hostname '%s': %s" % (options.host, err)) @@ -427,6 +433,9 @@ def ParseOptions(): parser.error("Magic must match regular expression %s" % constants.IE_MAGIC_RE.pattern) + if options.ipv4 and options.ipv6: + parser.error("Can only use one of --ipv4 and --ipv6") + return (status_file_path, mode) @@ -532,6 +541,7 @@ def main(): [socat_stderr_write_fd, dd_stderr_write_fd, dd_pid_write_fd, exp_size_write_fd]) try: + def _ForwardSignal(signum, _): """Forwards signals to child process. @@ -578,7 +588,7 @@ def main(): errmsg = "Exited with status %s" % (child.returncode, ) status_file.SetExitStatus(child.returncode, errmsg) - except Exception, err: # pylint: disable-msg=W0703 + except Exception, err: # pylint: disable=W0703 logging.exception("Unhandled error occurred") status_file.SetExitStatus(constants.EXIT_FAILURE, "Unhandled error occurred: %s" % (err, ))