Skip to content

Commit

Permalink
devtool: refactor deploy-target
Browse files Browse the repository at this point in the history
Signed-off-by: Adrian Freihofer <[email protected]>
  • Loading branch information
afreof authored and deribaucourt committed Sep 27, 2023
1 parent b8a5ddd commit a80eabf
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 111 deletions.
5 changes: 4 additions & 1 deletion scripts/lib/devtool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,15 @@ def exec_fakeroot(d, cmd, **kwargs):
"""Run a command under fakeroot (pseudo, in fact) so that it picks up the appropriate file permissions"""
# Grab the command and check it actually exists
fakerootcmd = d.getVar('FAKEROOTCMD')
fakerootenv = d.getVar('FAKEROOTENV')
exec_fakeroot_no_d(fakerootcmd, fakerootenv, cmd, kwargs)

def exec_fakeroot_no_d(fakerootcmd, fakerootenv, cmd, **kwargs):
if not os.path.exists(fakerootcmd):
logger.error('pseudo executable %s could not be found - have you run a build yet? pseudo-native should install this and if you have run any build then that should have been built')
return 2
# Set up the appropriate environment
newenv = dict(os.environ)
fakerootenv = d.getVar('FAKEROOTENV')
for varvalue in fakerootenv.split():
if '=' in varvalue:
splitval = varvalue.split('=', 1)
Expand Down
230 changes: 120 additions & 110 deletions scripts/lib/devtool/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import argparse_oe
import oe.types

from devtool import exec_fakeroot, setup_tinfoil, check_workspace_recipe, DevtoolError
from devtool import exec_fakeroot_no_d, setup_tinfoil, check_workspace_recipe, DevtoolError

logger = logging.getLogger('devtool')

Expand Down Expand Up @@ -133,16 +133,11 @@ def _prepare_remote_script(deploy, verbose=False, dryrun=False, undeployall=Fals

return '\n'.join(lines)



def deploy(args, config, basepath, workspace):
"""Entry point for the devtool 'deploy' subcommand"""
def deploy_cached(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_process, fakerootcmd, fakerootenv, args):
import math
import oe.recipeutils
import oe.package

check_workspace_recipe(workspace, args.recipename, checksrc=False)

try:
host, destdir = args.target.split(':')
except ValueError:
Expand All @@ -152,116 +147,131 @@ def deploy(args, config, basepath, workspace):
if not destdir.endswith('/'):
destdir += '/'

recipe_outdir = srcdir
if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir):
raise DevtoolError('No files to deploy - have you built the %s '
'recipe? If so, the install step has not installed '
'any files.' % args.recipename)

if args.strip and not args.dry_run:
# Fakeroot copy to new destination
srcdir = recipe_outdir
recipe_outdir = os.path.join(workdir, 'devtool-deploy-target-stripped')
if os.path.isdir(recipe_outdir):
exec_fakeroot_no_d(fakerootcmd, fakerootenv, "rm -rf %s" % recipe_outdir, shell=True)
exec_fakeroot_no_d(fakerootcmd, fakerootenv, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True)
os.environ['PATH'] = ':'.join([os.environ['PATH'], path or ''])
oe.package.strip_execs(args.recipename, recipe_outdir, strip_cmd, libdir, base_libdir, max_process)

filelist = []
inodes = set({})
ftotalsize = 0
for root, _, files in os.walk(recipe_outdir):
for fn in files:
fstat = os.lstat(os.path.join(root, fn))
# Get the size in kiB (since we'll be comparing it to the output of du -k)
# MUST use lstat() here not stat() or getfilesize() since we don't want to
# dereference symlinks
if fstat.st_ino in inodes:
fsize = 0
else:
fsize = int(math.ceil(float(fstat.st_size)/1024))
inodes.add(fstat.st_ino)
ftotalsize += fsize
# The path as it would appear on the target
fpath = os.path.join(destdir, os.path.relpath(root, recipe_outdir), fn)
filelist.append((fpath, fsize))

if args.dry_run:
print('Files to be deployed for %s on target %s:' % (args.recipename, args.target))
for item, _ in filelist:
print(' %s' % item)
return 0

extraoptions = ''
if args.no_host_check:
extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
if not args.show_status:
extraoptions += ' -q'

scp_sshexec = ''
ssh_sshexec = 'ssh'
if args.ssh_exec:
scp_sshexec = "-S %s" % args.ssh_exec
ssh_sshexec = args.ssh_exec
scp_port = ''
ssh_port = ''
if args.port:
scp_port = "-P %s" % args.port
ssh_port = "-p %s" % args.port

if args.key:
extraoptions += ' -i %s' % args.key

# In order to delete previously deployed files and have the manifest file on
# the target, we write out a shell script and then copy it to the target
# so we can then run it (piping tar output to it).
# (We cannot use scp here, because it doesn't preserve symlinks.)
tmpdir = tempfile.mkdtemp(prefix='devtool')
try:
tmpscript = '/tmp/devtool_deploy.sh'
tmpfilelist = os.path.join(os.path.dirname(tmpscript), 'devtool_deploy.list')
shellscript = _prepare_remote_script(deploy=True,
verbose=args.show_status,
nopreserve=args.no_preserve,
nocheckspace=args.no_check_space)
# Write out the script to a file
with open(os.path.join(tmpdir, os.path.basename(tmpscript)), 'w') as f:
f.write(shellscript)
# Write out the file list
with open(os.path.join(tmpdir, os.path.basename(tmpfilelist)), 'w') as f:
f.write('%d\n' % ftotalsize)
for fpath, fsize in filelist:
f.write('%s %d\n' % (fpath, fsize))
# Copy them to the target
ret = subprocess.call("scp %s %s %s %s/* %s:%s" % (scp_sshexec, scp_port, extraoptions, tmpdir, args.target, os.path.dirname(tmpscript)), shell=True)
if ret != 0:
raise DevtoolError('Failed to copy script to %s - rerun with -s to '
'get a complete error message' % args.target)
finally:
shutil.rmtree(tmpdir)

# Now run the script
ret = exec_fakeroot_no_d(fakerootcmd, fakerootenv, 'tar cf - . | %s %s %s %s \'sh %s %s %s %s\'' % (ssh_sshexec, ssh_port, extraoptions, args.target, tmpscript, args.recipename, destdir, tmpfilelist), cwd=recipe_outdir, shell=True)
if ret != 0:
raise DevtoolError('Deploy failed - rerun with -s to get a complete '
'error message')

logger.info('Successfully deployed %s' % recipe_outdir)

files_list = []
for root, _, files in os.walk(recipe_outdir):
for filename in files:
filename = os.path.relpath(os.path.join(root, filename), recipe_outdir)
files_list.append(os.path.join(destdir, filename))

def deploy(args, config, basepath, workspace):
"""Entry point for the devtool 'deploy' subcommand"""
check_workspace_recipe(workspace, args.recipename, checksrc=False)

tinfoil = setup_tinfoil(basepath=basepath)
try:
try:
rd = tinfoil.parse_recipe(args.recipename)

srcdir = rd.getVar('D')
workdir = rd.getVar('WORKDIR')
path = rd.getVar('PATH')
strip_cmd = rd.getVar('STRIP')
libdir = rd.getVar('libdir'),
base_libdir = rd.getVar('base_libdir')
max_process = int(rd.getVar("BB_NUMBER_THREADS") or os.cpu_count() or 1)
fakerootcmd = rd.getVar('FAKEROOTCMD')
fakerootenv = rd.getVar('FAKEROOTENV')
deploy_cached(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_process, fakerootcmd, fakerootenv, args)
except Exception as e:
raise DevtoolError('Exception parsing recipe %s: %s' %
(args.recipename, e))
recipe_outdir = rd.getVar('D')
if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir):
raise DevtoolError('No files to deploy - have you built the %s '
'recipe? If so, the install step has not installed '
'any files.' % args.recipename)

if args.strip and not args.dry_run:
# Fakeroot copy to new destination
srcdir = recipe_outdir
recipe_outdir = os.path.join(rd.getVar('WORKDIR'), 'devtool-deploy-target-stripped')
if os.path.isdir(recipe_outdir):
exec_fakeroot(rd, "rm -rf %s" % recipe_outdir, shell=True)
exec_fakeroot(rd, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True)
os.environ['PATH'] = ':'.join([os.environ['PATH'], rd.getVar('PATH') or ''])
oe.package.strip_execs(args.recipename, recipe_outdir, rd.getVar('STRIP'), rd.getVar('libdir'),
rd.getVar('base_libdir'), rd)

filelist = []
inodes = set({})
ftotalsize = 0
for root, _, files in os.walk(recipe_outdir):
for fn in files:
fstat = os.lstat(os.path.join(root, fn))
# Get the size in kiB (since we'll be comparing it to the output of du -k)
# MUST use lstat() here not stat() or getfilesize() since we don't want to
# dereference symlinks
if fstat.st_ino in inodes:
fsize = 0
else:
fsize = int(math.ceil(float(fstat.st_size)/1024))
inodes.add(fstat.st_ino)
ftotalsize += fsize
# The path as it would appear on the target
fpath = os.path.join(destdir, os.path.relpath(root, recipe_outdir), fn)
filelist.append((fpath, fsize))

if args.dry_run:
print('Files to be deployed for %s on target %s:' % (args.recipename, args.target))
for item, _ in filelist:
print(' %s' % item)
return 0

extraoptions = ''
if args.no_host_check:
extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
if not args.show_status:
extraoptions += ' -q'

scp_sshexec = ''
ssh_sshexec = 'ssh'
if args.ssh_exec:
scp_sshexec = "-S %s" % args.ssh_exec
ssh_sshexec = args.ssh_exec
scp_port = ''
ssh_port = ''
if args.port:
scp_port = "-P %s" % args.port
ssh_port = "-p %s" % args.port

if args.key:
extraoptions += ' -i %s' % args.key

# In order to delete previously deployed files and have the manifest file on
# the target, we write out a shell script and then copy it to the target
# so we can then run it (piping tar output to it).
# (We cannot use scp here, because it doesn't preserve symlinks.)
tmpdir = tempfile.mkdtemp(prefix='devtool')
try:
tmpscript = '/tmp/devtool_deploy.sh'
tmpfilelist = os.path.join(os.path.dirname(tmpscript), 'devtool_deploy.list')
shellscript = _prepare_remote_script(deploy=True,
verbose=args.show_status,
nopreserve=args.no_preserve,
nocheckspace=args.no_check_space)
# Write out the script to a file
with open(os.path.join(tmpdir, os.path.basename(tmpscript)), 'w') as f:
f.write(shellscript)
# Write out the file list
with open(os.path.join(tmpdir, os.path.basename(tmpfilelist)), 'w') as f:
f.write('%d\n' % ftotalsize)
for fpath, fsize in filelist:
f.write('%s %d\n' % (fpath, fsize))
# Copy them to the target
ret = subprocess.call("scp %s %s %s %s/* %s:%s" % (scp_sshexec, scp_port, extraoptions, tmpdir, args.target, os.path.dirname(tmpscript)), shell=True)
if ret != 0:
raise DevtoolError('Failed to copy script to %s - rerun with -s to '
'get a complete error message' % args.target)
finally:
shutil.rmtree(tmpdir)

# Now run the script
ret = exec_fakeroot(rd, 'tar cf - . | %s %s %s %s \'sh %s %s %s %s\'' % (ssh_sshexec, ssh_port, extraoptions, args.target, tmpscript, args.recipename, destdir, tmpfilelist), cwd=recipe_outdir, shell=True)
if ret != 0:
raise DevtoolError('Deploy failed - rerun with -s to get a complete '
'error message')

logger.info('Successfully deployed %s' % recipe_outdir)

files_list = []
for root, _, files in os.walk(recipe_outdir):
for filename in files:
filename = os.path.relpath(os.path.join(root, filename), recipe_outdir)
files_list.append(os.path.join(destdir, filename))
finally:
tinfoil.shutdown()

Expand Down

0 comments on commit a80eabf

Please sign in to comment.