blob: dc14df1f58722b7de32423560d58e0d3f572c617 [file] [log] [blame]
Brian Silvermanaf485d62015-10-12 00:37:14 -04001# This file is run by shell scripts generated by the aos_downloader Skylark
2# macro. Everything before the first -- is a hard-coded list of files to
3# download.
4
Brian Silvermand54068e2015-10-14 17:56:05 -04005from __future__ import print_function
6
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -08007import argparse
Brian Silvermanaf485d62015-10-12 00:37:14 -04008import sys
Austin Schuh2c4ee252021-10-17 23:15:39 -07009from tempfile import TemporaryDirectory
Brian Silvermanaf485d62015-10-12 00:37:14 -040010import subprocess
Brian Silvermand54068e2015-10-14 17:56:05 -040011import re
Austin Schuh2c4ee252021-10-17 23:15:39 -070012import stat
Brian Silvermand54068e2015-10-14 17:56:05 -040013import os
Austin Schuh2c4ee252021-10-17 23:15:39 -070014import shutil
Brian Silvermanaf485d62015-10-12 00:37:14 -040015
Austin Schuh71f6fa72019-08-31 18:23:02 -070016
Brian Silvermanbd7860e2020-01-05 17:52:40 -080017def install(ssh_target, pkg, ssh_path, scp_path):
Austin Schuh71f6fa72019-08-31 18:23:02 -070018 """Installs a package from NI on the ssh target."""
19 print("Installing", pkg)
20 PKG_URL = "http://download.ni.com/ni-linux-rt/feeds/2015/arm/ipk/cortexa9-vfpv3/" + pkg
21 subprocess.check_call(["wget", PKG_URL, "-O", pkg])
22 try:
Austin Schuh71f6fa72019-08-31 18:23:02 -070023 subprocess.check_call(
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080024 [scp_path, "-S", ssh_path, pkg, ssh_target + ":/tmp/" + pkg])
25 subprocess.check_call(
26 [ssh_path, ssh_target, "opkg", "install", "/tmp/" + pkg])
27 subprocess.check_call([ssh_path, ssh_target, "rm", "/tmp/" + pkg])
Austin Schuh71f6fa72019-08-31 18:23:02 -070028 finally:
29 subprocess.check_call(["rm", pkg])
Austin Schuhb64799c2015-12-19 22:35:51 -080030
31
Brian Silvermanaf485d62015-10-12 00:37:14 -040032def main(argv):
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080033 parser = argparse.ArgumentParser()
Austin Schuhdcffd092021-10-17 21:51:39 -070034 parser.add_argument(
35 "--target",
36 type=str,
37 default="roborio-971-frc.local",
38 help="Target to deploy code to.")
39 parser.add_argument(
40 "--type",
41 type=str,
42 choices=["roborio", "pi"],
43 required=True,
44 help="Target type for deployment")
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080045 parser.add_argument(
Austin Schuhdcffd092021-10-17 21:51:39 -070046 "srcs", type=str, nargs='+', help="List of files to copy over")
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080047 args = parser.parse_args(argv[1:])
Brian Silvermanaf485d62015-10-12 00:37:14 -040048
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080049 srcs = args.srcs
Austin Schuhb64799c2015-12-19 22:35:51 -080050
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080051 destination = args.target
Austin Schuh71f6fa72019-08-31 18:23:02 -070052
53 result = re.match("(?:([^:@]+)@)?([^:@]+)(?::([^:@]+))?", destination)
54 if not result:
Austin Schuhdcffd092021-10-17 21:51:39 -070055 print(
56 "Not sure how to parse destination \"%s\"!" % destination,
57 file=sys.stderr)
Austin Schuh71f6fa72019-08-31 18:23:02 -070058 return 1
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080059 user = None
Austin Schuh71f6fa72019-08-31 18:23:02 -070060 if result.group(1):
61 user = result.group(1)
62 hostname = result.group(2)
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080063
Austin Schuh71f6fa72019-08-31 18:23:02 -070064 if result.group(3):
65 target_dir = result.group(3)
66
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080067 if user is None:
68 if args.type == "pi":
James Kuszmaulbe46f7f2020-10-03 13:40:57 -070069 user = "pi"
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080070 elif args.type == "roborio":
James Kuszmaulbe46f7f2020-10-03 13:40:57 -070071 user = "admin"
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080072 target_dir = "/home/" + user + "/robot_code"
73
Austin Schuh71f6fa72019-08-31 18:23:02 -070074 ssh_target = "%s@%s" % (user, hostname)
75
Brian Silvermanbd7860e2020-01-05 17:52:40 -080076 ssh_path = "external/ssh/ssh"
77 scp_path = "external/ssh/scp"
78
Austin Schuh2c4ee252021-10-17 23:15:39 -070079 # Since rsync is pretty fixed in what it can do, build up a temporary
80 # directory with the exact contents we want the target to have. This
81 # is faster than multiple SSH connections.
82 with TemporaryDirectory() as temp_dir:
83 pwd = os.getcwd()
84 # Bazel gives us the same file twice, so dedup here rather than
85 # in starlark
86 copied = set()
87 for s in srcs:
88 if ":" in s:
89 folder = os.path.join(temp_dir, s[s.find(":") + 1:])
90 os.makedirs(folder, exist_ok=True)
91 s = os.path.join(pwd, s[:s.find(":")])
92 destination = os.path.join(folder, os.path.basename(s))
93 else:
94 s = os.path.join(pwd, s)
95 destination = os.path.join(temp_dir, os.path.basename(s))
Austin Schuhdcffd092021-10-17 21:51:39 -070096
Austin Schuh2c4ee252021-10-17 23:15:39 -070097 if s in copied:
98 continue
99 copied.add(s)
100 if s.endswith(".stripped"):
101 destination = destination[:destination.find(".stripped")]
102 shutil.copy2(s, destination)
103 # Make sure the folder that gets created on the roboRIO has open
104 # permissions or the executables won't be visible to init.
105 os.chmod(temp_dir, 0o775)
106 # Starter needs to be SUID so we transition from lvuser to admin.
107 os.chmod(os.path.join(temp_dir, "starterd"), 0o775 | stat.S_ISUID)
Austin Schuhdcffd092021-10-17 21:51:39 -0700108
Austin Schuh2c4ee252021-10-17 23:15:39 -0700109 rsync_cmd = ([
110 "external/rsync/usr/bin/rsync",
111 "-e",
112 ssh_path,
113 "-c",
114 "-r",
115 "-v",
116 "--perms",
117 "-l",
118 temp_dir + "/",
119 ])
120
121 # If there is only 1 file to transfer, we would overwrite the destination
122 # folder. In that case, specify the full path to the target.
123 if len(srcs) == 1:
124 rsync_cmd += ["%s:%s/%s" % (ssh_target, target_dir, srcs[0])]
Austin Schuh71f6fa72019-08-31 18:23:02 -0700125 else:
Austin Schuh2c4ee252021-10-17 23:15:39 -0700126 rsync_cmd += ["%s:%s" % (ssh_target, target_dir)]
Austin Schuh71f6fa72019-08-31 18:23:02 -0700127
Austin Schuh2c4ee252021-10-17 23:15:39 -0700128 try:
129 subprocess.check_call(rsync_cmd)
130 except subprocess.CalledProcessError as e:
131 if e.returncode == 127 or e.returncode == 12:
132 print("Unconfigured roboRIO, installing rsync.")
133 install(ssh_target, "libattr1_2.4.47-r0.36_cortexa9-vfpv3.ipk",
134 ssh_path, scp_path)
135 install(ssh_target, "libacl1_2.2.52-r0.36_cortexa9-vfpv3.ipk",
136 ssh_path, scp_path)
137 install(ssh_target, "rsync_3.1.0-r0.7_cortexa9-vfpv3.ipk",
138 ssh_path, scp_path)
139 subprocess.check_call(rsync_cmd)
140 elif e.returncode == 11:
141 # Directory wasn't created, make it and try again. This keeps the happy path fast.
142 subprocess.check_call(
143 [ssh_path, ssh_target, "mkdir", "-p", target_dir])
144 subprocess.check_call(rsync_cmd)
145 else:
146 raise e
Austin Schuh71f6fa72019-08-31 18:23:02 -0700147
148
149if __name__ == "__main__":
150 main(sys.argv)