The new argument for osc build --host will perform the build on a remote host. It is a shortcut for rsync -az -e ssh `pwd` user@hostname:/remote/dir rsync -az -e ssh prefer-dir \ user@hotname:/remote/dir/__prefer-rpms__/prefer-dir ssh user@hostname "cd /remote/dir/package; osc build *build-args" rsync -az -e ssh user@hostname:/remote/dir/__keep-pkgs__ keep-pkgs iow it copy the current directory to the /remote/directory on hostname (if not specified, the ~/ is supplied) and then run the osc build on hostname. All global and local arguments are supplied to the remote osc build, but few local (--host, --keep-pkgs, --prefer-pkgs) are changed. It support the OSC_ variables, so running with OSC_BUILD_ROOT=/somewhere osc build --host ... will push the variable to the remove osc process There are known issues: * --rsync-dest, --rsync-src and --overlay is not implemented --- osc/commandline.py | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/osc/commandline.py b/osc/commandline.py index b28e208..4cb8f40 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -5082,6 +5082,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='take previous build from DIR (special values: _self, _link)') @cmdln.option('--shell', action='store_true', help=SUPPRESS_HELP) + @cmdln.option('--host', metavar='HOST', + help='perform the build on a remote server - user@server:~/remote/directory') def do_build(self, subcmd, opts, *args): """${cmd_name}: Build a package on your local machine @@ -5180,7 +5182,134 @@ Please submit there instead, or use --nodevelproject to force direct submission. raise oscerr.WrongOptions('--offline and --preload are mutually exclusive') print 'Building %s for %s/%s' % (args[2], args[0], args[1]) - return osc.build.main(self.get_api_url(), opts, args) + if not opts.host: + return osc.build.main(self.get_api_url(), opts, args) + else: + return self._do_rbuild(subcmd, opts, *args) + + def _do_rbuild(self, subcmd, opts, *args): + + # drop the --argument, value tuple from the list + def drop_arg2(lst, name): + while name in lst: + i = lst.index(name) + lst.pop(i+1) + lst.pop(i) + return lst + + # not yet implemented options + if opts.rsyncsrc: + raise oscerr.WrongArgs("Using --rsync-src with --host is not yet implemented") + if opts.rsyncdest: + raise oscerr.WrongArgs("Using --rsync-dest with --host is not yet implemented") + if opts.overlay: + raise oscerr.WrongArgs("Using --overlay with --host is not yet implemented") + + cwd = os.getcwdu() + basename = os.path.basename(cwd) + if not ':' in opts.host: + hostname = opts.host + hostpath = "~/" + else: + hostname, hostpath = opts.host.split(':', 1) + + # arguments for build: use all arguments behind build and drop --host 'HOST' + hostargs = sys.argv[sys.argv.index(subcmd)+1:] + drop_arg2(hostargs, '--host') + + # global arguments: use first '-' up to subcmd + gi = 0 + for i, a in enumerate(sys.argv): + if a == subcmd: + break + if a[0] == '-': + gi = i + break + + if gi: + hostglobalargs = sys.argv[gi : sys.argv.index(subcmd)+1] + else: + hostglobalargs = (subcmd, ) + + # keep-pkgs + hostkeep = None + if opts.keep_pkgs: + drop_arg2(hostargs, '-k') + drop_arg2(hostargs, '--keep-pkgs') + hostkeep = os.path.join( + hostpath, + basename, + "__keep_pkgs__", + "") # <--- this adds last '/', thus triggers correct rsync behavior + hostargs.append('--keep-pkgs') + hostargs.append(hostkeep) + + ### run all commands ### + # 1.) rsync sources + rsync_source_cmd = ['rsync', '-az', '-delete', '-e', 'ssh', cwd, "%s:%s" % (hostname, hostpath)] + print 'Run: %s' % " ".join(rsync_source_cmd) + ret = subprocess.call(rsync_source_cmd) + if ret != 0: + return ret + + # 2.) rsync prefer-pkgs dirs + if opts.prefer_pkgs: + + drop_arg2(hostargs, '-p') + drop_arg2(hostargs, '--prefer-pkgs') + + for pdir in opts.prefer_pkgs: + + # drop the last '/' from pdir name - this is because + # rsync foo remote:/bar create /bar/foo on remote machine + # rsync foo/ remote:/bar copy the content of foo in the /bar + if pdir[-1:] == os.path.sep: + pdir = pdir[:-1] + + hostprefer = os.path.join( + hostpath, + basename, + "__prefer-pkgs__", + os.path.basename(os.path.abspath(pdir))) + hostargs.append('--prefer-pkgs') + hostargs.append(hostprefer) + + rsync_prefer_cmd = ['rsync', '-az', '-delete', '-e', 'ssh', + pdir, + "%s:%s" % (hostname, os.path.dirname(hostprefer))] + print 'Run: %s' % " ".join(rsync_prefer_cmd) + ret = subprocess.call(rsync_prefer_cmd) + if ret != 0: + return ret + + # 3.) call osc build + osc_cmd = "osc" + for var in ('OSC_SU_WRAPPER', 'OSC_BUILD_ROOT', 'OSC_PACKAGECACHEDIR'): + if os.getenv(var): + osc_cmd = "%s=%s %s" % (var, os.getenv(var), osc_cmd) + + ssh_cmd = \ + ['ssh', hostname, + "cd %(remote_dir)s; %(osc_cmd)s %(global_args)s %(local_args)s" % dict( + remote_dir = os.path.join(hostpath, basename), + osc_cmd = osc_cmd, + global_args = " ".join(hostglobalargs), + local_args = " ".join(hostargs)) + ] + print 'Run: %s' % " ".join(ssh_cmd) + build_ret = subprocess.call(ssh_cmd) + if build_ret != 0: + return build_ret + + # 4.) get keep-pkgs back + if opts.keep_pkgs: + ret = rsync_keep_cmd = ['rsync', '-az', '-e', 'ssh', "%s:%s" % (hostname, hostkeep), opts.keep_pkgs] + print 'Run: %s' % " ".join(rsync_keep_cmd) + ret = subprocess.call(rsync_keep_cmd) + if ret != 0: + return ret + + return build_ret @cmdln.option('--local-package', action='store_true', -- 1.7.11.5