blob: 181a721d8410115cdcbc4ef05ff5ec11532cc89d [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
Ravago Jonesa66eed22022-11-26 15:35:36 -080017def install(ssh_target, pkg, channel, 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)
Ravago Jonesa66eed22022-11-26 15:35:36 -080020 PKG_URL = f"http://download.ni.com/ni-linux-rt/feeds/academic/2023/arm/{channel}/cortexa9-vfpv3/{pkg}"
Austin Schuh71f6fa72019-08-31 18:23:02 -070021 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()
Ravago Jones5127ccc2022-07-31 16:32:45 -070034 parser.add_argument("--target",
35 type=str,
36 default="roborio-971-frc.local",
37 help="Target to deploy code to.")
38 parser.add_argument("--type",
39 type=str,
Jim Ostrowski8a1480f2024-01-20 00:31:51 -080040 choices=["roborio", "pi", "orin"],
Ravago Jones5127ccc2022-07-31 16:32:45 -070041 required=True,
42 help="Target type for deployment")
43 parser.add_argument("srcs",
44 type=str,
45 nargs='+',
46 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:
Ravago Jones5127ccc2022-07-31 16:32:45 -070055 print("Not sure how to parse destination \"%s\"!" % destination,
56 file=sys.stderr)
Austin Schuh71f6fa72019-08-31 18:23:02 -070057 return 1
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080058 user = None
Austin Schuh71f6fa72019-08-31 18:23:02 -070059 if result.group(1):
60 user = result.group(1)
61 hostname = result.group(2)
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080062
Austin Schuh71f6fa72019-08-31 18:23:02 -070063 if result.group(3):
64 target_dir = result.group(3)
65
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080066 if user is None:
Jim Ostrowski8a1480f2024-01-20 00:31:51 -080067 if args.type == "pi" or args.type == "orin":
James Kuszmaulbe46f7f2020-10-03 13:40:57 -070068 user = "pi"
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080069 elif args.type == "roborio":
James Kuszmaulbe46f7f2020-10-03 13:40:57 -070070 user = "admin"
Austin Schuhc0ec2a82022-02-24 17:26:29 -080071 target_dir = "/home/" + user + "/bin"
James Kuszmaul2d8fa2a2020-03-01 13:51:50 -080072
Austin Schuh71f6fa72019-08-31 18:23:02 -070073 ssh_target = "%s@%s" % (user, hostname)
74
Brian Silvermanbd7860e2020-01-05 17:52:40 -080075 ssh_path = "external/ssh/ssh"
76 scp_path = "external/ssh/scp"
77
Ravago Jonesedad5ae2022-11-26 15:57:44 -080078 # install jq
79 try:
80 subprocess.check_call([ssh_path, ssh_target, "jq", "--version"],
81 stdout=subprocess.DEVNULL)
82 except subprocess.CalledProcessError as e:
83 if e.returncode == 127:
84 print("Didn't find jq on roboRIO, installing jq.")
85 install(ssh_target, "jq-lic_1.5-r0.35_cortexa9-vfpv3.ipk", 'extra',
86 ssh_path, scp_path)
87 install(ssh_target, "libonig-lic_5.9.6-r0.27_cortexa9-vfpv3.ipk",
88 'extra', ssh_path, scp_path)
89 install(ssh_target, "libonig2_5.9.6-r0.27_cortexa9-vfpv3.ipk",
90 'extra', ssh_path, scp_path)
91 install(ssh_target, "jq_1.5-r0.35_cortexa9-vfpv3.ipk", 'extra',
92 ssh_path, scp_path)
93
94 subprocess.check_call([ssh_path, ssh_target, "jq", "--version"],
95 stdout=subprocess.DEVNULL)
96
Austin Schuh2c4ee252021-10-17 23:15:39 -070097 # Since rsync is pretty fixed in what it can do, build up a temporary
98 # directory with the exact contents we want the target to have. This
99 # is faster than multiple SSH connections.
100 with TemporaryDirectory() as temp_dir:
101 pwd = os.getcwd()
102 # Bazel gives us the same file twice, so dedup here rather than
103 # in starlark
104 copied = set()
105 for s in srcs:
106 if ":" in s:
107 folder = os.path.join(temp_dir, s[s.find(":") + 1:])
108 os.makedirs(folder, exist_ok=True)
109 s = os.path.join(pwd, s[:s.find(":")])
110 destination = os.path.join(folder, os.path.basename(s))
111 else:
112 s = os.path.join(pwd, s)
113 destination = os.path.join(temp_dir, os.path.basename(s))
Austin Schuhdcffd092021-10-17 21:51:39 -0700114
Austin Schuh2c4ee252021-10-17 23:15:39 -0700115 if s in copied:
116 continue
117 copied.add(s)
118 if s.endswith(".stripped"):
119 destination = destination[:destination.find(".stripped")]
120 shutil.copy2(s, destination)
121 # Make sure the folder that gets created on the roboRIO has open
122 # permissions or the executables won't be visible to init.
123 os.chmod(temp_dir, 0o775)
124 # Starter needs to be SUID so we transition from lvuser to admin.
Jim Ostrowski8a1480f2024-01-20 00:31:51 -0800125 if args.type != "pi" and args.type != "orin":
Austin Schuh3e1d3b62023-01-08 13:52:31 -0800126 os.chmod(os.path.join(temp_dir, "starterd"), 0o775 | stat.S_ISUID)
Austin Schuhdcffd092021-10-17 21:51:39 -0700127
Austin Schuh2c4ee252021-10-17 23:15:39 -0700128 rsync_cmd = ([
James Kuszmaulc6ea63a2023-09-06 20:36:46 -0700129 "external/rsync/rsync",
Austin Schuh2c4ee252021-10-17 23:15:39 -0700130 "-e",
131 ssh_path,
132 "-c",
133 "-r",
134 "-v",
135 "--perms",
136 "-l",
137 temp_dir + "/",
138 ])
139
140 # If there is only 1 file to transfer, we would overwrite the destination
141 # folder. In that case, specify the full path to the target.
142 if len(srcs) == 1:
143 rsync_cmd += ["%s:%s/%s" % (ssh_target, target_dir, srcs[0])]
Austin Schuh71f6fa72019-08-31 18:23:02 -0700144 else:
Austin Schuh2c4ee252021-10-17 23:15:39 -0700145 rsync_cmd += ["%s:%s" % (ssh_target, target_dir)]
Austin Schuh71f6fa72019-08-31 18:23:02 -0700146
Austin Schuh2c4ee252021-10-17 23:15:39 -0700147 try:
148 subprocess.check_call(rsync_cmd)
149 except subprocess.CalledProcessError as e:
150 if e.returncode == 127 or e.returncode == 12:
151 print("Unconfigured roboRIO, installing rsync.")
Ravago Jonesa66eed22022-11-26 15:35:36 -0800152 install(ssh_target, "libacl1_2.2.52-r0.310_cortexa9-vfpv3.ipk",
153 'main', ssh_path, scp_path)
154 install(ssh_target, "rsync-lic_3.1.3-r0.23_cortexa9-vfpv3.ipk",
155 'extra', ssh_path, scp_path)
156 install(ssh_target, "rsync_3.1.3-r0.23_cortexa9-vfpv3.ipk",
157 'extra', ssh_path, scp_path)
Austin Schuh2c4ee252021-10-17 23:15:39 -0700158 subprocess.check_call(rsync_cmd)
159 elif e.returncode == 11:
160 # Directory wasn't created, make it and try again. This keeps the happy path fast.
161 subprocess.check_call(
162 [ssh_path, ssh_target, "mkdir", "-p", target_dir])
163 subprocess.check_call(rsync_cmd)
164 else:
165 raise e
Austin Schuh71f6fa72019-08-31 18:23:02 -0700166
167
168if __name__ == "__main__":
169 main(sys.argv)