summaryrefslogtreecommitdiffstats
path: root/planetlab/pssh/psshlib/psshutil.py
diff options
context:
space:
mode:
Diffstat (limited to 'planetlab/pssh/psshlib/psshutil.py')
-rw-r--r--planetlab/pssh/psshlib/psshutil.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/planetlab/pssh/psshlib/psshutil.py b/planetlab/pssh/psshlib/psshutil.py
new file mode 100644
index 0000000..ae1a24c
--- /dev/null
+++ b/planetlab/pssh/psshlib/psshutil.py
@@ -0,0 +1,108 @@
+# Copyright (c) 2009, Andrew McNabb
+# Copyright (c) 2003-2008, Brent N. Chun
+
+import fcntl
+import string
+import sys
+
+HOST_FORMAT = 'Host format is [user@]host[:port] [user]'
+
+
+def read_host_files(paths, default_user=None, default_port=None):
+ """Reads the given host files.
+
+ Returns a list of (host, port, user) triples.
+ """
+ hosts = []
+ if paths:
+ for path in paths:
+ hosts.extend(read_host_file(path, default_user=default_user))
+ return hosts
+
+
+def read_host_file(path, default_user=None, default_port=None):
+ """Reads the given host file.
+
+ Lines are of the form: host[:port] [login].
+ Returns a list of (host, port, user) triples.
+ """
+ lines = []
+ f = open(path)
+ for line in f:
+ lines.append(line.strip())
+ f.close()
+
+ hosts = []
+ for line in lines:
+ # Skip blank lines or lines starting with #
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+ host, port, user = parse_host_entry(line, default_user, default_port)
+ if host:
+ hosts.append((host, port, user))
+ return hosts
+
+
+# TODO: deprecate the second host field and standardize on the
+# [user@]host[:port] format.
+def parse_host_entry(line, default_user, default_port):
+ """Parses a single host entry.
+
+ This may take either the of the form [user@]host[:port] or
+ host[:port][ user].
+
+ Returns a (host, port, user) triple.
+ """
+ fields = line.split()
+ if len(fields) > 2:
+ sys.stderr.write('Bad line: "%s". Format should be'
+ ' [user@]host[:port] [user]\n' % line)
+ return None, None, None
+ host_field = fields[0]
+ host, port, user = parse_host(host_field, default_port=default_port)
+ if len(fields) == 2:
+ if user is None:
+ user = fields[1]
+ else:
+ sys.stderr.write('User specified twice in line: "%s"\n' % line)
+ return None, None, None
+ if user is None:
+ user = default_user
+ return host, port, user
+
+
+def parse_host_string(host_string, default_user=None, default_port=None):
+ """Parses a whitespace-delimited string of "[user@]host[:port]" entries.
+
+ Returns a list of (host, port, user) triples.
+ """
+ hosts = []
+ entries = host_string.split()
+ for entry in entries:
+ hosts.append(parse_host(entry, default_user, default_port))
+ return hosts
+
+
+def parse_host(host, default_user=None, default_port=None):
+ """Parses host entries of the form "[user@]host[:port]".
+
+ Returns a (host, port, user) triple.
+ """
+ # TODO: when we stop supporting Python 2.4, switch to using str.partition.
+ user = default_user
+ port = default_port
+ if '@' in host:
+ user, host = host.split('@', 1)
+ if ':' in host:
+ host, port = host.rsplit(':', 1)
+ return (host, port, user)
+
+
+def set_cloexec(filelike):
+ """Sets the underlying filedescriptor to automatically close on exec.
+
+ If set_cloexec is called for all open files, then subprocess.Popen does
+ not require the close_fds option.
+ """
+ fcntl.fcntl(filelike.fileno(), fcntl.FD_CLOEXEC, 1)