scripts/rpc: Make sure address argument is properly interpreted

In case the addr argument was not an existing unix socket file the rpc
client would consider it to be an actual ip address. As a result
connect() would be called with improper set of arguments. This could
cause the rpc.py to block for undesired amount of time until connect()
finally decided to return (seen on some fedora33 builds).

This was affecting sh wrapper functions like waitforlisten() which
use rpc.py to determine if given app is ready to be talk to blocking
execution of the tests for way too long then intendent.

To avoid such a scenario determine the format of the address and use
routines proper for given address family.

Signed-off-by: Michal Berger <michalx.berger@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7777 (master)

(cherry picked from commit 6c1a1a3dca)
Change-Id: Iaac701d72c772629fa7c6478ff4781b0c5d485d5
Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8018
Reviewed-by: Karol Latecki <karol.latecki@intel.com>
Reviewed-by: Michal Berger <michalx.berger@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Michal Berger 2021-05-21 19:50:08 +02:00 committed by Tomasz Zawadzki
parent fb67ea5148
commit 10b7805b0f

View File

@ -14,6 +14,22 @@ def print_json(s):
print(json.dumps(s, indent=2).strip('"')) print(json.dumps(s, indent=2).strip('"'))
def get_addr_type(addr):
try:
socket.inet_pton(socket.AF_INET, addr)
return socket.AF_INET
except Exception as e:
pass
try:
socket.inet_pton(socket.AF_INET6, addr)
return socket.AF_INET6
except Exception as e:
pass
if os.path.exists(addr):
return socket.AF_UNIX
return None
class JSONRPCException(Exception): class JSONRPCException(Exception):
def __init__(self, message): def __init__(self, message):
self.message = message self.message = message
@ -54,23 +70,24 @@ class JSONRPCClient(object):
def _connect(self, addr, port): def _connect(self, addr, port):
try: try:
if os.path.exists(addr): addr_type = get_addr_type(addr)
if addr_type == socket.AF_UNIX:
self._logger.debug("Trying to connect to UNIX socket: %s", addr) self._logger.debug("Trying to connect to UNIX socket: %s", addr)
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect(addr) self.sock.connect(addr)
elif port: elif addr_type == socket.AF_INET6:
if ':' in addr:
self._logger.debug("Trying to connect to IPv6 address addr:%s, port:%i", addr, port) self._logger.debug("Trying to connect to IPv6 address addr:%s, port:%i", addr, port)
for res in socket.getaddrinfo(addr, port, socket.AF_INET6, socket.SOCK_STREAM, socket.SOL_TCP): for res in socket.getaddrinfo(addr, port, socket.AF_INET6, socket.SOCK_STREAM, socket.SOL_TCP):
af, socktype, proto, canonname, sa = res af, socktype, proto, canonname, sa = res
self.sock = socket.socket(af, socktype, proto) self.sock = socket.socket(af, socktype, proto)
self.sock.connect(sa) self.sock.connect(sa)
else: elif addr_type == socket.AF_INET:
self._logger.debug("Trying to connect to IPv4 address addr:%s, port:%i'", addr, port) self._logger.debug("Trying to connect to IPv4 address addr:%s, port:%i'", addr, port)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((addr, port)) self.sock.connect((addr, port))
else: else:
raise socket.error("Unix socket '%s' does not exist" % addr) raise socket.error("Invalid or non-existing address: '%s'" % addr)
except socket.error as ex: except socket.error as ex:
raise JSONRPCException("Error while connecting to %s\n" raise JSONRPCException("Error while connecting to %s\n"
"Is SPDK application running?\n" "Is SPDK application running?\n"