summaryrefslogtreecommitdiff
path: root/lorrycontroller/hosts.py
diff options
context:
space:
mode:
Diffstat (limited to 'lorrycontroller/hosts.py')
-rw-r--r--lorrycontroller/hosts.py38
1 files changed, 38 insertions, 0 deletions
diff --git a/lorrycontroller/hosts.py b/lorrycontroller/hosts.py
index 39cae57..fb892dc 100644
--- a/lorrycontroller/hosts.py
+++ b/lorrycontroller/hosts.py
@@ -14,6 +14,10 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import abc
+import shlex
+import urllib.parse
+
+import cliapp
class DownstreamHost(abc.ABC):
@@ -119,3 +123,37 @@ class UpstreamHost(abc.ABC):
DownstreamHost.prepare_repo.
'''
pass
+
+
+class SshCommand:
+ def __init__(self, urlstring, **options):
+ try:
+ url = urllib.parse.urlsplit(urlstring, allow_fragments=False)
+ url.port
+ except ValueError:
+ raise cliapp.AppException('Invalid URL: %s' % urlstring)
+
+ if url.scheme != 'ssh':
+ raise cliapp.AppException('Not an SSH URL: %s' % urlstring)
+ if url.path not in ['', '/']:
+ raise cliapp.AppException('Unexpected path part in SSH URL')
+ if url.query != '':
+ raise cliapp.AppException('Unexpected query part in SSH URL')
+ if url.password is not None:
+ raise cliapp.AppException('Unexpected password in SSH URL')
+
+ self._ssh_args = ['ssh', '-oBatchMode=yes']
+ for key, value in options.items():
+ self._ssh_args.append('-o%s=%s' % (key, value))
+ if url.username is not None:
+ self._ssh_args.append('-oUser=%s' % url.username)
+ if url.port is not None:
+ self._ssh_args.append('-p%i' % url.port)
+ self._ssh_args.append(url.hostname)
+
+ def run(self, args):
+ quoted_args = [shlex.quote(arg) for arg in args]
+ stdout = cliapp.runcmd(self._ssh_args + quoted_args)
+ if isinstance(stdout, bytes):
+ stdout = stdout.decode('utf-8', errors='replace')
+ return stdout