implemented deploy
diff --git a/aos/build/build.py b/aos/build/build.py
index b1e02e3..6a728ed 100755
--- a/aos/build/build.py
+++ b/aos/build/build.py
@@ -10,6 +10,24 @@
import shutil
import errno
+def aos_path():
+ return os.path.join(os.path.dirname(__file__), '..')
+
+def get_ip(device):
+ FILENAME = os.path.normpath(os.path.join(aos_path(), '..', 'output', 'ip_base.txt'))
+ if not os.access(FILENAME, os.R_OK):
+ os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
+ with open(FILENAME, 'w') as f:
+ f.write('10.9.71')
+ with open(FILENAME, 'r') as f:
+ base = f.readline()
+ if device == 'prime':
+ return base + '.179'
+ elif device == 'robot':
+ return base + '.2'
+ else:
+ raise Exception('Unknown device %s to get an IP address for.' % device)
+
class Processor(object):
class UnknownPlatform(Exception):
def __init__(self, message):
@@ -18,12 +36,13 @@
class Platform(object):
def outdir(self):
return os.path.join(
- Processor.aos_path(), '..', 'output', self.outname())
+ aos_path(), '..', 'output', self.outname())
def build_ninja(self):
return os.path.join(self.outdir(), 'build.ninja')
- def aos_path():
- return os.path.join(os.path.dirname(__file__), '..')
+ def do_deploy(self, dry_run, command):
+ real_command = (('echo',) + command) if dry_run else command
+ subprocess.check_call(real_command, stdin=open(os.devnull, 'r'))
class CRIOProcessor(Processor):
class Platform(Processor.Platform):
@@ -48,6 +67,11 @@
def compiler(self):
return 'gcc'
+ def deploy(self, dry_run):
+ self.do_deploy(dry_run,
+ ('ncftpput', get_ip('robot'), '/',
+ os.path.join(self.outdir(), 'lib', 'FRC_UserProgram.out')))
+
def __init__(self):
super(CRIOProcessor, self).__init__()
@@ -95,10 +119,43 @@
def outname(self):
return str(self)
+ def deploy(self, dry_run):
+ """Downloads code to the prime in a way that avoids clashing too badly with starter
+ """
+ SUM = 'md5sum'
+ TARGET_DIR = '/home/driver/robot_code/bin'
+ TEMP_DIR = '/tmp/aos_downloader'
+ TARGET = 'driver@' + get_ip('prime')
+
+ from_dir = os.path.join(self.outdir(), 'outputs')
+ sums = subprocess.check_output((SUM,) + tuple(os.listdir(from_dir)),
+ stdin=open(os.devnull, 'r'),
+ cwd=from_dir)
+ to_download = subprocess.check_output(
+ ('ssh', TARGET,
+ """rm -rf {TMPDIR} && mkdir {TMPDIR} && cd {TO_DIR}
+ && echo '{SUMS}' | {SUM} --check --quiet
+ |& grep -F FAILED | sed 's/^\\(.*\\): FAILED.*"'$'"/\\1/g'""".format(
+ TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR, SUMS=sums, SUM=SUM)))
+ if not to_download:
+ print("Nothing to download", file=sys.stderr)
+ return
+ self.do_deploy(
+ dry_run,
+ ('scp', '-o', 'Compression yes') + to_download
+ + (('%s:%s' % (TARGET, TEMP_DIR)),))
+ if not dry_run:
+ subprocess.check_call(
+ ('ssh', TARGET,
+ """mv {TMPDIR}/* {TO_DIR}
+ && echo 'Done moving new executables into place'
+ && ionice -c 3 bash -c 'sync && sync && sync'""".format(
+ TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR)))
+
ARCHITECTURES = ['arm', 'amd64']
COMPILERS = ['clang', 'gcc']
- def __init__(self):
+ def __init__(self, is_test, is_deploy):
super(Processor, self).__init__()
platforms = []
@@ -108,7 +165,13 @@
platforms.append(
PrimeProcessor.Platform(architecture, compiler, debug))
self.platforms = frozenset(platforms)
- self.default_platforms = self.select_platforms(debug=False)
+ if is_test:
+ self.default_platforms = self.select_platforms(architecture='amd64', debug=True)
+ elif is_deploy:
+ # TODO(brians): Switch to deploying the code built with clang.
+ self.default_platforms = self.select_platforms(architecture='arm', compiler='gcc', debug=False)
+ else:
+ self.default_platforms = self.select_platforms(debug=False)
def build_env(self):
return {}
@@ -221,7 +284,8 @@
if args.processor == 'crio':
processor = CRIOProcessor()
elif args.processor == 'prime':
- processor = PrimeProcessor()
+ processor = PrimeProcessor(args.action_name == 'tests',
+ args.action_name == 'deploy')
else:
parser.exit(status=1, message='Unknown processor "%s".' % args.processor)
@@ -242,9 +306,9 @@
def download_externals(argument):
subprocess.check_call(
- (os.path.join(Processor.aos_path(), 'build', 'download_externals.sh'),
+ (os.path.join(aos_path(), 'build', 'download_externals.sh'),
argument),
- stdin=open('/dev/null', 'r'))
+ stdin=open(os.devnull, 'r'))
if processor.is_crio():
download_externals('crio')
@@ -255,8 +319,8 @@
class ToolsConfig(object):
def __init__(self):
- self.variables = {'AOS': Processor.aos_path()}
- with open(os.path.join(Processor.aos_path(), 'build', 'tools_config'), 'r') as f:
+ self.variables = {'AOS': aos_path()}
+ with open(os.path.join(aos_path(), 'build', 'tools_config'), 'r') as f:
for line in f:
if line[0] == '#':
pass
@@ -288,7 +352,7 @@
else:
raise e
pattern = re.compile('.*\.gyp[i]$')
- for dirname, _, files in os.walk(os.path.join(Processor.aos_path(), '..')):
+ for dirname, _, files in os.walk(os.path.join(aos_path(), '..')):
for f in [f for f in files if pattern.match(f)]:
if (os.stat(os.path.join(dirname, f)).st_mtime > build_mtime):
return True
@@ -304,10 +368,10 @@
gyp = subprocess.Popen(
(tools_config['GYP'],
'--check',
- '--depth=%s' % os.path.join(Processor.aos_path(), '..'),
+ '--depth=%s' % os.path.join(aos_path(), '..'),
'--no-circular-check',
'-f', 'ninja',
- '-I%s' % os.path.join(Processor.aos_path(), 'build', 'aos.gypi'),
+ '-I%s' % os.path.join(aos_path(), 'build', 'aos.gypi'),
'-I/dev/stdin', '-Goutput_dir=output',
'-DOS=%s' % platform.os(),
'-DPLATFORM=%s' % platform.gyp_platform(),
@@ -331,7 +395,7 @@
subprocess.check_call(
('sed', '-i',
's/nm -gD/nm/g', platform.build_ninja()),
- stdin=open('/dev/null', 'r'))
+ stdin=open(os.devnull, 'r'))
print('Done running gyp.', file=sys.stderr)
else:
print("Not running gyp.", file=sys.stderr)
@@ -343,14 +407,17 @@
subprocess.check_call(
(tools_config['NINJA'],
'-C', platform.outdir()) + tuple(targets),
- stdin=open('/dev/null', 'r'),
+ stdin=open(os.devnull, 'r'),
env=build_env)
except subprocess.CalledProcessError as e:
if unknown_platform_error is not None:
print(unknown_platform_error, file=sys.stderr)
raise e
- # TODO(brians): deploy and tests
+ if args.action_name == 'deploy':
+ platform.deploy(args.dry_run)
+
+ # TODO(brians): tests
print('Done building %s...' % platform, file=sys.stderr)
if __name__ == '__main__':