forked from pool/python-parallax
Accepting request 1033892 from devel:languages:python
OBS-URL: https://build.opensuse.org/request/show/1033892 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-parallax?expand=0&rev=20
This commit is contained in:
@@ -1,80 +0,0 @@
|
||||
From f5ccee901d346873adbe5d979b5b70d0ba029570 Mon Sep 17 00:00:00 2001
|
||||
From: liangxin1300 <XLiang@suse.com>
|
||||
Date: Fri, 24 Apr 2020 07:05:13 +0800
|
||||
Subject: [PATCH] Add ssh_key option used by -i option of ssh/scp
|
||||
|
||||
---
|
||||
parallax/__init__.py | 21 +++++++++++++--------
|
||||
1 file changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/parallax/__init__.py b/parallax/__init__.py
|
||||
index fc1a6e7..1008ca2 100644
|
||||
--- a/parallax/__init__.py
|
||||
+++ b/parallax/__init__.py
|
||||
@@ -87,6 +87,7 @@ class Options(object):
|
||||
askpass = False # Ask for a password
|
||||
outdir = None # Write stdout to a file per host in this directory
|
||||
errdir = None # Write stderr to a file per host in this directory
|
||||
+ ssh_key = None # Specific ssh key used by ssh/scp -i option
|
||||
ssh_options = [] # Extra options to pass to SSH
|
||||
ssh_extra = [] # Extra arguments to pass to SSH
|
||||
verbose = False # Warning and diagnostic messages
|
||||
@@ -138,19 +139,21 @@ class _CallOutputBuilder(object):
|
||||
return ret
|
||||
|
||||
|
||||
-def _build_call_cmd(host, port, user, cmdline, options, extra):
|
||||
+def _build_call_cmd(host, port, user, cmdline, opts):
|
||||
cmd = ['ssh', host,
|
||||
'-o', 'NumberOfPasswordPrompts=1',
|
||||
'-o', 'SendEnv=PARALLAX_NODENUM PARALLAX_HOST']
|
||||
- if options:
|
||||
- for opt in options:
|
||||
+ if opts.ssh_options:
|
||||
+ for opt in opts.ssh_options:
|
||||
cmd += ['-o', opt]
|
||||
if user:
|
||||
cmd += ['-l', user]
|
||||
if port:
|
||||
cmd += ['-p', port]
|
||||
- if extra:
|
||||
- cmd.extend(extra)
|
||||
+ if opts.ssh_key:
|
||||
+ cmd += ['-i', opts.ssh_key]
|
||||
+ if opts.ssh_extra:
|
||||
+ cmd.extend(opts.ssh_extra)
|
||||
if cmdline:
|
||||
cmd.append(cmdline)
|
||||
return cmd
|
||||
@@ -173,9 +176,7 @@ def call(hosts, cmdline, opts=Options()):
|
||||
warn_message=opts.warn_message,
|
||||
callbacks=_CallOutputBuilder())
|
||||
for host, port, user in _expand_host_port_user(hosts):
|
||||
- cmd = _build_call_cmd(host, port, user, cmdline,
|
||||
- options=opts.ssh_options,
|
||||
- extra=opts.ssh_extra)
|
||||
+ cmd = _build_call_cmd(host, port, user, cmdline, opts)
|
||||
t = Task(host, port, user, cmd,
|
||||
stdin=opts.input_stream,
|
||||
verbose=opts.verbose,
|
||||
@@ -219,6 +220,8 @@ def _build_copy_cmd(host, port, user, src, dst, opts):
|
||||
cmd += ['-P', port]
|
||||
if opts.recursive:
|
||||
cmd.append('-r')
|
||||
+ if opts.ssh_key:
|
||||
+ cmd += ['-i', opts.ssh_key]
|
||||
if opts.ssh_extra:
|
||||
cmd.extend(opts.ssh_extra)
|
||||
cmd.append(src)
|
||||
@@ -312,6 +315,8 @@ def _build_slurp_cmd(host, port, user, src, dst, opts):
|
||||
cmd += ['-P', port]
|
||||
if opts.recursive:
|
||||
cmd.append('-r')
|
||||
+ if opts.ssh_key:
|
||||
+ cmd += ['-i', opts.ssh_key]
|
||||
if opts.ssh_extra:
|
||||
cmd.extend(opts.ssh_extra)
|
||||
if user:
|
||||
--
|
||||
2.21.1
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
From 1b253513291fe6022b7b832547e43b372886059c Mon Sep 17 00:00:00 2001
|
||||
From: liangxin1300 <XLiang@suse.com>
|
||||
Date: Thu, 16 Jul 2020 00:19:26 +0800
|
||||
Subject: [PATCH] Change format of scp command for ipv6 compatible
|
||||
|
||||
---
|
||||
parallax/__init__.py | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/parallax/__init__.py b/parallax/__init__.py
|
||||
index 1008ca2..50a2268 100644
|
||||
--- a/parallax/__init__.py
|
||||
+++ b/parallax/__init__.py
|
||||
@@ -226,9 +226,9 @@ def _build_copy_cmd(host, port, user, src, dst, opts):
|
||||
cmd.extend(opts.ssh_extra)
|
||||
cmd.append(src)
|
||||
if user:
|
||||
- cmd.append('%s@%s:%s' % (user, host, dst))
|
||||
+ cmd.append('%s@[%s]:%s' % (user, host, dst))
|
||||
else:
|
||||
- cmd.append('%s:%s' % (host, dst))
|
||||
+ cmd.append('[%s]:%s' % (host, dst))
|
||||
return cmd
|
||||
|
||||
|
||||
@@ -320,9 +320,9 @@ def _build_slurp_cmd(host, port, user, src, dst, opts):
|
||||
if opts.ssh_extra:
|
||||
cmd.extend(opts.ssh_extra)
|
||||
if user:
|
||||
- cmd.append('%s@%s:%s' % (user, host, src))
|
||||
+ cmd.append('%s@[%s]:%s' % (user, host, src))
|
||||
else:
|
||||
- cmd.append('%s:%s' % (host, src))
|
||||
+ cmd.append('[%s]:%s' % (host, src))
|
||||
cmd.append(dst)
|
||||
return cmd
|
||||
|
||||
--
|
||||
2.21.1
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
From 22cd571ceb360c66279512af3690347e1d6a768d Mon Sep 17 00:00:00 2001
|
||||
From: liangxin1300 <XLiang@suse.com>
|
||||
Date: Tue, 12 Jul 2022 10:06:06 +0800
|
||||
Subject: [PATCH] Fix: task: Don't use ssh if command running on local
|
||||
(bsc#1200833)
|
||||
|
||||
** Problem
|
||||
When a command is running on local, it will failed if local ssh service stopped
|
||||
** Solution
|
||||
Run this command directly, without ssh
|
||||
---
|
||||
parallax/__init__.py | 22 ++++++++++++++++++++--
|
||||
parallax/task.py | 6 ++++--
|
||||
2 files changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/parallax/__init__.py b/parallax/__init__.py
|
||||
index 50a2268..aa6ebd9 100644
|
||||
--- a/parallax/__init__.py
|
||||
+++ b/parallax/__init__.py
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
+import socket
|
||||
|
||||
DEFAULT_PARALLELISM = 32
|
||||
DEFAULT_TIMEOUT = 0 # "infinity" by default
|
||||
@@ -176,7 +177,11 @@ def call(hosts, cmdline, opts=Options()):
|
||||
warn_message=opts.warn_message,
|
||||
callbacks=_CallOutputBuilder())
|
||||
for host, port, user in _expand_host_port_user(hosts):
|
||||
- cmd = _build_call_cmd(host, port, user, cmdline, opts)
|
||||
+ is_local = is_local_host(host)
|
||||
+ if is_local:
|
||||
+ cmd = [cmdline]
|
||||
+ else:
|
||||
+ cmd = _build_call_cmd(host, port, user, cmdline, opts)
|
||||
t = Task(host, port, user, cmd,
|
||||
stdin=opts.input_stream,
|
||||
verbose=opts.verbose,
|
||||
@@ -184,7 +189,8 @@ def call(hosts, cmdline, opts=Options()):
|
||||
print_out=opts.print_out,
|
||||
inline=opts.inline,
|
||||
inline_stdout=opts.inline_stdout,
|
||||
- default_user=opts.default_user)
|
||||
+ default_user=opts.default_user,
|
||||
+ is_local=is_local)
|
||||
manager.add_task(t)
|
||||
try:
|
||||
return manager.run()
|
||||
@@ -366,3 +372,15 @@ def slurp(hosts, src, dst, opts=Options()):
|
||||
return manager.run()
|
||||
except FatalError as err:
|
||||
raise IOError(str(err))
|
||||
+
|
||||
+
|
||||
+def is_local_host(host):
|
||||
+ """
|
||||
+ Check if the host is local
|
||||
+ """
|
||||
+ try:
|
||||
+ socket.inet_aton(host)
|
||||
+ hostname = socket.gethostbyaddr(host)[0]
|
||||
+ except:
|
||||
+ hostname = host
|
||||
+ return hostname == socket.gethostname()
|
||||
diff --git a/parallax/task.py b/parallax/task.py
|
||||
index 5e05f30..5307b06 100644
|
||||
--- a/parallax/task.py
|
||||
+++ b/parallax/task.py
|
||||
@@ -39,7 +39,8 @@ class Task(object):
|
||||
print_out=False,
|
||||
inline=False,
|
||||
inline_stdout=False,
|
||||
- default_user=None):
|
||||
+ default_user=None,
|
||||
+ is_local=False):
|
||||
|
||||
# Backwards compatibility:
|
||||
if not isinstance(verbose, bool):
|
||||
@@ -66,6 +67,7 @@ class Task(object):
|
||||
self.pretty_host = host
|
||||
self.port = port
|
||||
self.cmd = cmd
|
||||
+ self.is_local = is_local
|
||||
|
||||
if user and user != default_user:
|
||||
self.pretty_host = '@'.join((user, self.pretty_host))
|
||||
@@ -126,7 +128,7 @@ class Task(object):
|
||||
close_fds=False, preexec_fn=os.setsid, env=environ)
|
||||
else:
|
||||
self.proc = Popen(self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE,
|
||||
- close_fds=False, start_new_session=True, env=environ)
|
||||
+ close_fds=False, start_new_session=True, env=environ, shell=self.is_local)
|
||||
|
||||
self.timestamp = time.time()
|
||||
if self.inputbuffer:
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
From 31024ba3eafebbf73b188b6a102c4d8f00669705 Mon Sep 17 00:00:00 2001
|
||||
From: nicholasyang <nicholas.yang@suse.com>
|
||||
Date: Tue, 27 Sep 2022 12:08:17 +0800
|
||||
Subject: [PATCH 4/5] Fix: Error: inherit from Exception instead of
|
||||
BaseExceptin
|
||||
|
||||
---
|
||||
parallax/__init__.py | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/parallax/__init__.py b/parallax/__init__.py
|
||||
index aa6ebd9..209c6f7 100644
|
||||
--- a/parallax/__init__.py
|
||||
+++ b/parallax/__init__.py
|
||||
@@ -55,14 +55,14 @@ def to_ascii(s):
|
||||
return s
|
||||
|
||||
|
||||
-class Error(BaseException):
|
||||
+class Error(Exception):
|
||||
"""
|
||||
Returned instead of a result for a host
|
||||
in case of an error during the processing for
|
||||
that host.
|
||||
"""
|
||||
def __init__(self, msg, task):
|
||||
- super(BaseException, self).__init__()
|
||||
+ super(Exception, self).__init__()
|
||||
self.msg = msg
|
||||
self.task = task
|
||||
|
||||
--
|
||||
2.37.3
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
From 38bac0eb3cb20e9df8cbbf585cf9353793ffdba2 Mon Sep 17 00:00:00 2001
|
||||
From: nicholasyang <nicholas.yang@suse.com>
|
||||
Date: Tue, 27 Sep 2022 12:08:17 +0800
|
||||
Subject: [PATCH 5/5] Dev: add parallax.run() to return non-zero rc without
|
||||
raising exceptions
|
||||
|
||||
---
|
||||
README.md | 15 ++++++++---
|
||||
parallax/__init__.py | 60 +++++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 70 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/README.md b/README.md
|
||||
index beb5620..268f6db 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -32,10 +32,17 @@ Share and enjoy!
|
||||
|
||||
Executes the given command on a set of hosts, collecting the output.
|
||||
|
||||
- Returns a dict mapping the hostname of
|
||||
- each host either to a tuple containing a return code,
|
||||
- stdout and stderr, or an `parallax.Error` instance
|
||||
- describing the error.
|
||||
+ Returns a dict mapping the hostname of each host either to a tuple containing
|
||||
+ a return code, stdout and stderr when return code is 0, or an `parallax.Error`
|
||||
+ instance describing the error when return code is not 0.
|
||||
+
|
||||
+* `parallax.run(hosts, cmdline, opts)`
|
||||
+
|
||||
+ Executes the given command on a set of hosts, collecting the output.
|
||||
+
|
||||
+ Returns a dict mapping the hostname of each host either to a tuple containing
|
||||
+ a return code, stdout and stderr, or an `parallax.Error` instance describing
|
||||
+ the error when ssh error occurred.
|
||||
|
||||
* `parallax.copy(hosts, src, dst, opts)`
|
||||
|
||||
diff --git a/parallax/__init__.py b/parallax/__init__.py
|
||||
index 209c6f7..a3dc75e 100644
|
||||
--- a/parallax/__init__.py
|
||||
+++ b/parallax/__init__.py
|
||||
@@ -162,7 +162,7 @@ def _build_call_cmd(host, port, user, cmdline, opts):
|
||||
|
||||
def call(hosts, cmdline, opts=Options()):
|
||||
"""
|
||||
- Executes the given command on a set of hosts, collecting the output
|
||||
+ Executes the given command on a set of hosts, collecting the output. Return Error when exit status != 0.
|
||||
Returns {host: (rc, stdout, stdin) | Error}
|
||||
"""
|
||||
if opts.outdir and not os.path.exists(opts.outdir):
|
||||
@@ -384,3 +384,61 @@ def is_local_host(host):
|
||||
except:
|
||||
hostname = host
|
||||
return hostname == socket.gethostname()
|
||||
+
|
||||
+def run(hosts, cmdline, opts=Options()):
|
||||
+ """
|
||||
+ Executes the given command on a set of hosts, collecting the output. Return Error when ssh error occurred.
|
||||
+ Returns {host: (rc, stdout, stdin) | Error}
|
||||
+ """
|
||||
+ if opts.outdir and not os.path.exists(opts.outdir):
|
||||
+ os.makedirs(opts.outdir)
|
||||
+ if opts.errdir and not os.path.exists(opts.errdir):
|
||||
+ os.makedirs(opts.errdir)
|
||||
+ manager = Manager(limit=opts.limit,
|
||||
+ timeout=opts.timeout,
|
||||
+ askpass=opts.askpass,
|
||||
+ outdir=opts.outdir,
|
||||
+ errdir=opts.errdir,
|
||||
+ warn_message=opts.warn_message,
|
||||
+ callbacks=_RunOutputBuilder())
|
||||
+ for host, port, user in _expand_host_port_user(hosts):
|
||||
+ is_local = is_local_host(host)
|
||||
+ if is_local:
|
||||
+ cmd = [cmdline]
|
||||
+ else:
|
||||
+ cmd = _build_call_cmd(host, port, user, cmdline, opts)
|
||||
+ t = Task(host, port, user, cmd,
|
||||
+ stdin=opts.input_stream,
|
||||
+ verbose=opts.verbose,
|
||||
+ quiet=opts.quiet,
|
||||
+ print_out=opts.print_out,
|
||||
+ inline=opts.inline,
|
||||
+ inline_stdout=opts.inline_stdout,
|
||||
+ default_user=opts.default_user,
|
||||
+ is_local=is_local)
|
||||
+ manager.add_task(t)
|
||||
+ try:
|
||||
+ return manager.run()
|
||||
+ except FatalError as err:
|
||||
+ raise IOError(str(err))
|
||||
+
|
||||
+
|
||||
+class _RunOutputBuilder(object):
|
||||
+ def __init__(self):
|
||||
+ self.finished_tasks = []
|
||||
+
|
||||
+ def finished(self, task, n):
|
||||
+ """Called when Task is complete"""
|
||||
+ self.finished_tasks.append(task)
|
||||
+
|
||||
+ def result(self, manager):
|
||||
+ """Called when all Tasks are complete to generate result"""
|
||||
+ ret = {}
|
||||
+ for task in self.finished_tasks:
|
||||
+ if task.exitstatus == 255:
|
||||
+ ret[task.host] = Error(', '.join(task.failures), task)
|
||||
+ else:
|
||||
+ ret[task.host] = (task.exitstatus,
|
||||
+ task.outputbuffer or manager.outdir,
|
||||
+ task.errorbuffer or manager.errdir)
|
||||
+ return ret
|
||||
--
|
||||
2.37.3
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c16703202ff67aed4740c0727df304abe9f3e7851e653533b24de21b338d9081
|
||||
size 17371
|
||||
3
parallax-1.0.8.tar.gz
Normal file
3
parallax-1.0.8.tar.gz
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:071f4413a0d49838af19359f10dca161aabbbece81175ddae72a51618321f046
|
||||
size 15921
|
||||
@@ -1,3 +1,20 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Nov 7 02:18:35 UTC 2022 - XinLiang <XLiang@suse.com>
|
||||
|
||||
- Fix: manager: file descriptor leakage
|
||||
- Release 1.0.8
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Nov 3 02:16:52 UTC 2022 - XinLiang <XLiang@suse.com>
|
||||
|
||||
- Release 1.0.7
|
||||
- Remove patches since already included:
|
||||
Remove patch 0001-Add-ssh_key-option-used-by-i-option-of-ssh-scp.patch
|
||||
Remove patch 0002-Change-format-of-scp-command-for-ipv6-compatible.patch
|
||||
Remove patch 0003-Fix-task-Don-t-use-ssh-if-command-running-on-local-b.patch
|
||||
Remove patch 0004-Fix-Error-inherit-from-Exception-instead-of-BaseExce.patch
|
||||
Remove patch 0005-Dev-add-parallax.run-to-return-non-zero-rc-without-r.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Sep 28 02:34:51 UTC 2022 - Nicholas Yang <nicholas.yang@suse.com>
|
||||
|
||||
|
||||
@@ -18,18 +18,13 @@
|
||||
|
||||
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
|
||||
Name: python-parallax
|
||||
Version: 1.0.6
|
||||
Version: 1.0.8
|
||||
Release: 0
|
||||
Summary: Python module for multi-node SSH command execution and file copy
|
||||
License: BSD-3-Clause
|
||||
Group: Development/Languages/Python
|
||||
URL: https://github.com/krig/parallax/
|
||||
Source: https://files.pythonhosted.org/packages/source/p/parallax/parallax-%{version}.tar.gz
|
||||
Patch1: 0001-Add-ssh_key-option-used-by-i-option-of-ssh-scp.patch
|
||||
Patch2: 0002-Change-format-of-scp-command-for-ipv6-compatible.patch
|
||||
Patch3: 0003-Fix-task-Don-t-use-ssh-if-command-running-on-local-b.patch
|
||||
Patch4: 0004-Fix-Error-inherit-from-Exception-instead-of-BaseExce.patch
|
||||
Patch5: 0005-Dev-add-parallax.run-to-return-non-zero-rc-without-r.patch
|
||||
|
||||
BuildRequires: %{python_module setuptools}
|
||||
BuildRequires: fdupes
|
||||
@@ -54,11 +49,6 @@ multiple nodes using SCP.
|
||||
|
||||
%prep
|
||||
%setup -q -n parallax-%{version}
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
|
||||
%build
|
||||
%python_build
|
||||
|
||||
Reference in New Issue
Block a user