Commit 2c30e9d7 authored by Alexander Schreiber's avatar Alexander Schreiber
Browse files

Added TcpPing to do ping-alike via TCP connect(2) with defined source address.

To be used to replace the currently fping(8) based reachability test.

Reviewed-by: imsnah
parent 386b57af
......@@ -32,7 +32,7 @@ import re
import socket
import tempfile
import shutil
from errno import ENOENT, ENOTDIR, EISDIR, EEXIST
from errno import ENOENT, ENOTDIR, EISDIR, EEXIST, EADDRNOTAVAIL, ECONNREFUSED
from ganeti import logger
from ganeti import errors
......@@ -786,3 +786,36 @@ def GetLocalIPAddresses():
" output: %s" % (result.cmd, result.fail_reason, result.output))
return _ParseIpOutput(result.output)
def TcpPing(source, target, port, timeout=10, live_port_needed=True):
"""Simple ping implementation using TCP connect(2).
Try to do a TCP connect(2) from the specified source IP to the specified
target IP and the specified target port. If live_port_needed is set to true,
requires the remote end to accept the connection. The timeout is specified
in seconds and defaults to 10 seconds
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sucess = False
try:
sock.bind((source, 0))
except socket.error, (errcode, errstring):
if errcode == EADDRNOTAVAIL:
success = False
sock.settimeout(timeout)
try:
sock.connect((target, port))
sock.close()
success = True
except socket.timeout:
success = False
except socket.error, (errcode, errstring):
success = (not live_port_needed) and (errcode == ECONNREFUSED)
return success
......@@ -27,14 +27,17 @@ import time
import tempfile
import os.path
import md5
import socket
from errno import EADDRNOTAVAIL
import ganeti
from ganeti.utils import IsProcessAlive, Lock, Unlock, RunCmd, \
RemoveFile, CheckDict, MatchNameComponent, FormatUnit, \
ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
ShellQuote, ShellQuoteArgs, _ParseIpOutput
ShellQuote, ShellQuoteArgs, _ParseIpOutput, TcpPing
from ganeti.errors import LockError, UnitParseError
class TestIsProcessAlive(unittest.TestCase):
"""Testing case for IsProcessAlive"""
def setUp(self):
......@@ -467,5 +470,57 @@ class TestIpAdressList(unittest.TestCase):
self._test(output, ['127.0.0.1', '10.0.0.1', '1.2.3.4'])
class TestTcpPing(unittest.TestCase):
"""Testcase for TCP version of ping - against listen(2)ing port"""
def setUp(self):
self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listener.bind(("127.0.0.1", 0))
self.listenerport = self.listener.getsockname()[1]
self.listener.listen(1)
def tearDown(self):
self.listener.shutdown(socket.SHUT_RDWR)
del self.listener
del self.listenerport
def testTcpPingToLocalHostAccept(self):
self.assert_(TcpPing("127.0.0.1",
"127.0.0.1",
self.listenerport,
timeout=10,
live_port_needed=True),
"failed to connect to test listener")
class TestTcpPingDeaf(unittest.TestCase):
"""Testcase for TCP version of ping - against non listen(2)ing port"""
def setUp(self):
self.deaflistener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.deaflistener.bind(("127.0.0.1", 0))
self.deaflistenerport = self.deaflistener.getsockname()[1]
def tearDown(self):
del self.deaflistener
del self.deaflistenerport
def testTcpPingToLocalHostAcceptDeaf(self):
self.failIf(TcpPing("127.0.0.1",
"127.0.0.1",
self.deaflistenerport,
timeout=10, # timeout for blocking operations
live_port_needed=True), # need successful connect(2)
"successfully connected to deaf listener")
def testTcpPingToLocalHostNoAccept(self):
self.assert_(TcpPing("127.0.0.1",
"127.0.0.1",
self.deaflistenerport,
timeout=10, # timeout for blocking operations
live_port_needed=False), # ECONNREFUSED is OK
"failed to ping alive host on deaf port")
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment