diff --git a/labgrid/driver/sshdriver.py b/labgrid/driver/sshdriver.py index fdee16b72..fd3f77bfe 100644 --- a/labgrid/driver/sshdriver.py +++ b/labgrid/driver/sshdriver.py @@ -356,24 +356,31 @@ def forward_unix_socket(self, unixsocket, localport=None): yield localport @Driver.check_active - @step(args=['src', 'dst']) - def scp(self, *, src, dst): + @step(args=['src', 'dst', 'recursive']) + def scp(self, *, src, dst, recursive=False): if not self._check_keepalive(): raise ExecutionError("Keepalive no longer running") - if src.startswith(':') == dst.startswith(':'): - raise ValueError("Either source or destination must be remote (start with :)") - if src.startswith(':'): - src = '_' + src - if dst.startswith(':'): + if all([f.startswith(':') for f in src]): + if dst.startswith(':'): + raise ValueError("Either source or destination must be remote (start with :)") + src = ['_' + f for f in src] + else: + if not dst.startswith(':'): + raise ValueError("Either source or destination must be remote (start with :)") dst = '_' + dst complete_cmd = [self._scp, "-S", self._ssh, "-F", "none", "-o", f"ControlPath={self.control.replace('%', '%%')}", - src, dst, + dst, ] + for f in src: + complete_cmd.insert(-1, f) + + if recursive: + complete_cmd.insert(1, "-r") if self.explicit_sftp_mode and self._scp_supports_explicit_sftp_mode(): complete_cmd.insert(1, "-s") diff --git a/labgrid/remote/client.py b/labgrid/remote/client.py index 3e30f7037..62380f903 100755 --- a/labgrid/remote/client.py +++ b/labgrid/remote/client.py @@ -69,7 +69,9 @@ class ServerError(Error): class InteractiveCommandError(Error): - pass + def __init__(self: Error, msg: str, exitcode: int): + super(InteractiveCommandError, self).__init__(msg) + self.exitcode = exitcode @attr.s(eq=False) @@ -1049,9 +1051,7 @@ async def console(self, place, target): break if not self.args.loop: if res: - exc = InteractiveCommandError("microcom error") - exc.exitcode = res - raise exc + raise InteractiveCommandError("microcom error", res) break await asyncio.sleep(1.0) @@ -1251,27 +1251,21 @@ def ssh(self): res = drv.interact(self.args.leftover) if res: - exc = InteractiveCommandError("ssh error") - exc.exitcode = res - raise exc + raise InteractiveCommandError("ssh error", res) def scp(self): drv = self._get_ssh() - res = drv.scp(src=self.args.src, dst=self.args.dst) + res = drv.scp(src=self.args.files[:-1], dst=self.args.files[-1], recursive=self.args.recursive) if res: - exc = InteractiveCommandError("scp error") - exc.exitcode = res - raise exc + raise InteractiveCommandError("scp error", res) def rsync(self): drv = self._get_ssh() res = drv.rsync(src=self.args.src, dst=self.args.dst, extra=self.args.leftover) if res: - exc = InteractiveCommandError("rsync error") - exc.exitcode = res - raise exc + raise InteractiveCommandError("rsync error", res) def sshfs(self): drv = self._get_ssh() @@ -1309,9 +1303,7 @@ def telnet(self): args = ["telnet", str(ip)] res = subprocess.call(args) if res: - exc = InteractiveCommandError("telnet error") - exc.exitcode = res - raise exc + raise InteractiveCommandError("telnet error", res) def video(self): place = self.get_acquired_place() @@ -1347,9 +1339,7 @@ def video(self): else: res = drv.stream(quality, controls=controls) if res: - exc = InteractiveCommandError("gst-launch-1.0 error") - exc.exitcode = res - raise exc + raise InteractiveCommandError("gst-launch-1.0 error", res) def audio(self): place = self.get_acquired_place() @@ -1358,9 +1348,7 @@ def audio(self): drv = self._get_driver_or_new(target, "USBAudioInputDriver", name=name) res = drv.play() if res: - exc = InteractiveCommandError("gst-launch-1.0 error") - exc.exitcode = res - raise exc + raise InteractiveCommandError("gst-launch-1.0 error", res) def _get_tmc(self): place = self.get_acquired_place() @@ -1934,8 +1922,10 @@ def main(): subparser = subparsers.add_parser("scp", help="transfer file via scp") subparser.add_argument("--name", "-n", help="optional resource name") - subparser.add_argument("src", help="source path (use :dir/file for remote side)") - subparser.add_argument("dst", help="destination path (use :dir/file for remote side)") + subparser.add_argument("--recursive", "-r", action="store_true", help="copy recursive") + subparser.add_argument( + "files", nargs="+", metavar="SRC/DST", help="source and destination path (use :dir/file for remote side)" + ) subparser.set_defaults(func=ClientSession.scp) subparser = subparsers.add_parser( diff --git a/man/labgrid-client.1 b/man/labgrid-client.1 index 630511c34..fdd76019a 100644 --- a/man/labgrid-client.1 +++ b/man/labgrid-client.1 @@ -203,7 +203,7 @@ not at all. .sp \fBssh\fP \fB[command]\fP Connect via SSH. Additional arguments are passed to ssh. .sp -\fBscp\fP \fB[source]\fP \fB[destination]\fP Transfer file via scp (use \(aq:dir/file\(aq for the remote side) +\fBscp\fP \fB[sources...]\fP \fB[destination]\fP Transfer file via scp (use \(aq:dir/file\(aq for the remote side) .sp \fBrsync\fP \fB[source]\fP \fB[destination]\fP Transfer files via rsync (use \(aq:dir/file\(aq for the remote side) .sp diff --git a/man/labgrid-client.rst b/man/labgrid-client.rst index 59f43c5a6..26068af3c 100644 --- a/man/labgrid-client.rst +++ b/man/labgrid-client.rst @@ -194,7 +194,7 @@ LABGRID-CLIENT COMMANDS ``ssh`` ``[command]`` Connect via SSH. Additional arguments are passed to ssh. -``scp`` ``[source]`` ``[destination]`` Transfer file via scp (use ':dir/file' for the remote side) +``scp`` ``[sources...]`` ``[destination]`` Transfer file via scp (use ':dir/file' for the remote side) ``rsync`` ``[source]`` ``[destination]`` Transfer files via rsync (use ':dir/file' for the remote side)