summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-04-23 20:29:51 +0200
committerGitHub <noreply@github.com>2021-04-23 20:29:51 +0200
commite5b739e963a246aa1cc3161a514eb4c287e2292d (patch)
tree1990f735de1a3e5bb27b6095af58af6fab2b6da0 /python
parent821d9e4d36d7520973d6f2cd146feebb9918227a (diff)
parentb5eb482ebe251e1505bb86c30a583feb1eef1e38 (diff)
downloadvyos-1x-e5b739e963a246aa1cc3161a514eb4c287e2292d.tar.gz
vyos-1x-e5b739e963a246aa1cc3161a514eb4c287e2292d.zip
Merge pull request #817 from erkin/current
T3356: Add support for custom source address for connections
Diffstat (limited to 'python')
-rw-r--r--python/vyos/remote.py64
1 files changed, 44 insertions, 20 deletions
diff --git a/python/vyos/remote.py b/python/vyos/remote.py
index ef103f707..3f24d4b33 100644
--- a/python/vyos/remote.py
+++ b/python/vyos/remote.py
@@ -14,6 +14,7 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import os
+import socket
import sys
import tempfile
from ftplib import FTP
@@ -23,80 +24,103 @@ import urllib.request
from vyos.util import cmd
from paramiko import SSHClient
+
def upload_ftp(local_path, hostname, remote_path,\
- username='anonymous', password='', port=21):
+ username='anonymous', password='', port=21, source=None):
with open(local_path, 'rb') as file:
- with FTP() as conn:
+ with FTP(source_address=source) as conn:
conn.connect(hostname, port)
conn.login(username, password)
conn.storbinary(f'STOR {remote_path}', file)
def download_ftp(local_path, hostname, remote_path,\
- username='anonymous', password='', port=21):
+ username='anonymous', password='', port=21, source=None):
with open(local_path, 'wb') as file:
- with FTP() as conn:
+ with FTP(source_address=source) as conn:
conn.connect(hostname, port)
conn.login(username, password)
conn.retrbinary(f'RETR {remote_path}', file.write)
def upload_sftp(local_path, hostname, remote_path,\
- username=None, password=None, port=22):
+ username=None, password=None, port=22, source=None):
+ sock = None
+ if source:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.bind((source, 0))
+ sock.connect((hostname, port))
with SSHClient() as ssh:
ssh.load_system_host_keys()
- ssh.connect(hostname, port, username, password)
+ ssh.connect(hostname, port, username, password, sock=sock)
with ssh.open_sftp() as sftp:
sftp.put(local_path, remote_path)
+ if sock:
+ sock.shutdown()
+ sock.close()
def download_sftp(local_path, hostname, remote_path,\
- username=None, password=None, port=22):
+ username=None, password=None, port=22, source=None):
+ sock = None
+ if source:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.bind((source, 0))
+ sock.connect((hostname, port))
with SSHClient() as ssh:
ssh.load_system_host_keys()
- ssh.connect(hostname, port, username, password)
+ ssh.connect(hostname, port, username, password, sock=sock)
with ssh.open_sftp() as sftp:
sftp.get(remote_path, local_path)
+ if sock:
+ sock.shutdown()
+ sock.close()
-def upload_tftp(local_path, hostname, remote_path, port=69):
+def upload_tftp(local_path, hostname, remote_path, port=69, source=None):
+ source_option = f'--interface {source}' if source else ''
with open(local_path, 'rb') as file:
- cmd(f'curl -s -T - tftp://{hostname}:{port}/{remote_path}', stderr=None, input=file.read()).encode()
+ cmd(f'curl {source_option} -s -T - tftp://{hostname}:{port}/{remote_path}',\
+ stderr=None, input=file.read()).encode()
-def download_tftp(local_path, hostname, remote_path, port=69):
+def download_tftp(local_path, hostname, remote_path, port=69, source=None):
+ source_option = f'--interface {source}' if source else ''
with open(local_path, 'wb') as file:
- file.write(cmd(f'curl -s tftp://{hostname}:{port}/{remote_path}', stderr=None).encode())
+ file.write(cmd(f'curl {source_option} -s tftp://{hostname}:{port}/{remote_path}',\
+ stderr=None).encode())
def download_http(urlstring, local_path):
with open(local_path, 'wb') as file:
with urllib.request.urlopen(urlstring) as response:
file.write(response.read())
-def download(local_path, urlstring):
+def download(local_path, urlstring, source=None):
"""
Dispatch the appropriate download function for the given URL and save to local path.
"""
url = urllib.parse.urlparse(urlstring)
if url.scheme == 'http' or url.scheme == 'https':
+ if source:
+ print("Warning: Custom source address not supported for HTTP connections.", file=sys.stderr)
download_http(urlstring, local_path)
elif url.scheme == 'ftp':
username = url.username if url.username else 'anonymous'
- download_ftp(local_path, url.hostname, url.path, username, url.password)
+ download_ftp(local_path, url.hostname, url.path, username, url.password, source=source)
elif url.scheme == 'sftp' or url.scheme == 'scp':
- download_sftp(local_path, url.hostname, url.path, url.username, url.password)
+ download_sftp(local_path, url.hostname, url.path, url.username, url.password, source=source)
elif url.scheme == 'tftp':
- download_tftp(local_path, url.hostname, url.path)
+ download_tftp(local_path, url.hostname, url.path, source=source)
else:
ValueError(f'Unsupported URL scheme: {url.scheme}')
-def upload(local_path, urlstring):
+def upload(local_path, urlstring, source=None):
"""
Dispatch the appropriate upload function for the given URL and upload from local path.
"""
url = urllib.parse.urlparse(urlstring)
if url.scheme == 'ftp':
username = url.username if url.username else 'anonymous'
- upload_ftp(local_path, url.hostname, url.path, username, url.password)
+ upload_ftp(local_path, url.hostname, url.path, username, url.password, source=source)
elif url.scheme == 'sftp' or url.scheme == 'scp':
- upload_sftp(local_path, url.hostname, url.path, url.username, url.password)
+ upload_sftp(local_path, url.hostname, url.path, url.username, url.password, source=source)
elif url.scheme == 'tftp':
- upload_tftp(local_path, url.hostname, url.path)
+ upload_tftp(local_path, url.hostname, url.path, source=source)
else:
ValueError(f'Unsupported URL scheme: {url.scheme}')