diff options
Diffstat (limited to 'buildtools/examples/run_on_target.py')
-rwxr-xr-x | buildtools/examples/run_on_target.py | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/buildtools/examples/run_on_target.py b/buildtools/examples/run_on_target.py new file mode 100755 index 0000000..79c5730 --- /dev/null +++ b/buildtools/examples/run_on_target.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 + +# +# Sample run-on-target script +# This is a script that can be used as cross-execute parameter to samba +# configuration process, running the command on a remote target for which +# the cross-compiled configure test was compiled. +# +# To use: +# ./configure \ +# --cross-compile \ +# '--cross-execute=./buildtools/example/run_on_target.py --host=<host>' +# +# A more elaborate example: +# ./configure \ +# --cross-compile \ +# '--cross-execute=./buildtools/example/run_on_target.py --host=<host> --user=<user> "--ssh=ssh -i <some key file>" --destdir=/path/to/dir' +# +# Typically this is to be used also with --cross-answers, so that the +# cross answers file gets built and further builds can be made without +# the help of a remote target. +# +# The following assumptions are made: +# 1. rsync is available on build machine and target machine +# 2. A running ssh service on target machine with password-less shell login +# 3. A directory writable by the password-less login user +# 4. The tests on the target can run and provide reliable results +# from the login account's home directory. This is significant +# for example in locking tests which +# create files in the current directory. As a workaround to this +# assumption, the TESTDIR environment variable can be set on the target +# (using ssh command line or server config) and the tests shall +# chdir to that directory. +# + +import sys +import os +import subprocess +from optparse import OptionParser + +# those are defaults, but can be overidden using command line +SSH = 'ssh' +USER = None +HOST = 'localhost' + + +def xfer_files(ssh, srcdir, host, user, targ_destdir): + """Transfer executable files to target + + Use rsync to copy the directory containing program to run + INTO a destination directory on the target. An exact copy + of the source directory is created on the target machine, + possibly deleting files on the target machine which do not + exist on the source directory. + + The idea is that the test may include files in addition to + the compiled binary, and all of those files reside alongside + the binary in a source directory. + + For example, if the test to run is /foo/bar/test and the + destination directory on the target is /tbaz, then /tbaz/bar + on the target shall be an exact copy of /foo/bar on the source, + including deletion of files inside /tbaz/bar which do not exist + on the source. + """ + + userhost = host + if user: + userhost = '%s@%s' % (user, host) + + cmd = 'rsync --verbose -rl --ignore-times --delete -e "%s" %s %s:%s/' % \ + (ssh, srcdir, userhost, targ_destdir) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = p.communicate() + if p.returncode != 0: + raise Exception('failed syncing files\n stdout:\n%s\nstderr:%s\n' + % (out, err)) + + +def exec_remote(ssh, host, user, destdir, targdir, prog, args): + """Run a test on the target + + Using password-less ssh, run the compiled binary on the target. + + An assumption is that there's no need to cd into the target dir, + same as there's no need to do it on a native build. + """ + userhost = host + if user: + userhost = '%s@%s' % (user, host) + + cmd = '%s %s %s/%s/%s' % (ssh, userhost, destdir, targdir, prog) + if args: + cmd = cmd + ' ' + ' '.join(args) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = p.communicate() + return (p.returncode, out) + + +def main(argv): + usage = "usage: %prog [options] <prog> [args]" + parser = OptionParser(usage) + + parser.add_option('--ssh', help="SSH client and additional flags", + default=SSH) + parser.add_option('--host', help="target host name or IP address", + default=HOST) + parser.add_option('--user', help="login user on target", + default=USER) + parser.add_option('--destdir', help="work directory on target", + default='~') + + (options, args) = parser.parse_args(argv) + if len(args) < 1: + parser.error("please supply test program to run") + + progpath = args[0] + + # assume that a test that was not compiled fails (e.g. getconf) + if progpath[0] != '/': + return (1, "") + + progdir = os.path.dirname(progpath) + prog = os.path.basename(progpath) + targ_progdir = os.path.basename(progdir) + + xfer_files( + options.ssh, + progdir, + options.host, + options.user, + options.destdir) + + (rc, out) = exec_remote(options.ssh, + options.host, + options.user, + options.destdir, + targ_progdir, + prog, args[1:]) + return (rc, out) + + +if __name__ == '__main__': + (rc, out) = main(sys.argv[1:]) + sys.stdout.write(out) + sys.exit(rc) |