OSError: Int or String expected received with pysftp.Connection in kubernetes

553 views Asked by At

I am trying to connect SFTP server using pysftp. I receive below error on pysftp.Connection() in Jupyter notebook running in Kubernetes inside IBM Elyra. Python version is 3.7.6 and pysftp 0.2.9 with paramiko 3.0.0.

OS is 'VERSION="20.04 LTS (Focal Fossa)"'

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
/usr/local/bin/kernel-launchers/python/scripts/launch_ipykernel.py in <module>
----> 1 sftp_conn = pysftp.Connection(host=sftp_info['host'],port= sftp_info['port'], username= sftp_info['login'], password=sftp_info['password'],cnopts=cnopts)

/opt/conda/lib/python3.7/site-packages/pysftp/__init__.py in __init__(self, host, username, private_key, password, port, private_key_pass, ciphers, log, cnopts, default_path)
    138         # Begin the SSH transport.
    139         self._transport = None
--> 140         self._start_transport(host, port)
    141         self._transport.use_compression(self._cnopts.compression)
    142         self._set_authentication(password, private_key, private_key_pass)

/opt/conda/lib/python3.7/site-packages/pysftp/__init__.py in _start_transport(self, host, port)
    174         '''start the transport and set the ciphers if specified.'''
    175         try:
--> 176             self._transport = paramiko.Transport((host, port))
    177             # Set security ciphers if set
    178             if self._cnopts.ciphers is not None:

/opt/conda/lib/python3.7/site-packages/paramiko/transport.py in __init__(self, sock, default_window_size, default_max_packet_size, gss_kex, gss_deleg_creds, disabled_algorithms, server_sig_algs)
    428             reason = "No suitable address family"
    429             addrinfos = socket.getaddrinfo(
--> 430                 hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
    431             )
    432             for family, socktype, proto, canonname, sockaddr in addrinfos:

/opt/conda/lib/python3.7/socket.py in getaddrinfo(host, port, family, type, proto, flags)
    750     # and socket type values to enum constants.
    751     addrlist = []
--> 752     for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
    753         af, socktype, proto, canonname, sa = res
    754         addrlist.append((_intenum_converter(af, AddressFamily),

OSError: Int or String expected

Connection should work and I should be be able to list directories. Current code is


import pysftp

cnopts = pysftp.CnOpts(knownhosts=None)
# cnopts.hostkeys = None
key = pysftp.RSAKey(data=decodebytes(keydata))


cnopts.hostkeys.add(sftp_info["host"], "ssh-rsa", key)

sfc = pysftp.Connection(
    host=sftp_info["host"],
    port=sftp_info["port"],
    username=sftp_info["login"],
    password=sftp_info["password"],
    cnopts=cnopts,
)

sfc.listdir()

The host does not have ~/.ssh/known_hosts and it throws a warning

/opt/conda/lib/python3.7/site-packages/pysftp/__init__.py:61: UserWarning: Failed to load HostKeys from /home/jovyan/.ssh/known_hosts.  You will need to explicitly load HostKeys (cnopts.hostkeys.load(filename)) or disableHostKey checking (cnopts.hostkeys = None).
  warnings.warn(wmsg, UserWarning)

I have tried to emulate same python version and pysftp and paramiko libraries on local environment running in Docker environment and the code works. The last command generates

>>> sfc.listdir()
['data', 'fire']

Local OS is VERSION="10 (buster)" based on docker image used FROM python:3.7.6. I used the specific version to match what is available in kubernetes. But in docker environment 3.7.6 or latest 3.7.16 both work without issues. In docker environment by default OS has ~/.ssh/known_hosts file. I have tried connecting by removing this file and connection to SFTP server works in Docker.

I have also tried using paramiko directly as suggested in some threads on SO. But, it has exactly the same behaviour.

I am not sure, where should I start the investigation to isolate the problem.

1

There are 1 answers

0
arundeep78 On

Thanks to pointer from @Martin, what I need to change was the type of port, which was being returned by another library and was being returned as numpy.int64! Finally can continue with actual program :D

sfc = pysftp.Connection(
host=sftp_info["host"],
port=int(sftp_info["port"]), # cast to int from numpy.int64
username=sftp_info["login"],
password=sftp_info["password"],
cnopts=cnopts)