blob: 28a67f51144f685de41077c646dd6a747e9cf0e9 [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,
40 choices=["roborio", "pi"],
41 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:
67 if args.type == "pi":
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
Austin Schuh2c4ee252021-10-17 23:15:39 -070078 # Since rsync is pretty fixed in what it can do, build up a temporary
79 # directory with the exact contents we want the target to have. This
80 # is faster than multiple SSH connections.
81 with TemporaryDirectory() as temp_dir:
82 pwd = os.getcwd()
83 # Bazel gives us the same file twice, so dedup here rather than
84 # in starlark
85 copied = set()
86 for s in srcs:
87 if ":" in s:
88 folder = os.path.join(temp_dir, s[s.find(":") + 1:])
89 os.makedirs(folder, exist_ok=True)
90 s = os.path.join(pwd, s[:s.find(":")])
91 destination = os.path.join(folder, os.path.basename(s))
92 else:
93 s = os.path.join(pwd, s)
94 destination = os.path.join(temp_dir, os.path.basename(s))
Austin Schuhdcffd092021-10-17 21:51:39 -070095
Austin Schuh2c4ee252021-10-17 23:15:39 -070096 if s in copied:
97 continue
98 copied.add(s)
99 if s.endswith(".stripped"):
100 destination = destination[:destination.find(".stripped")]
101 shutil.copy2(s, destination)
102 # Make sure the folder that gets created on the roboRIO has open
103 # permissions or the executables won't be visible to init.
104 os.chmod(temp_dir, 0o775)
105 # Starter needs to be SUID so we transition from lvuser to admin.
106 os.chmod(os.path.join(temp_dir, "starterd"), 0o775 | stat.S_ISUID)
Austin Schuhdcffd092021-10-17 21:51:39 -0700107
Austin Schuh2c4ee252021-10-17 23:15:39 -0700108 rsync_cmd = ([
109 "external/rsync/usr/bin/rsync",
110 "-e",
111 ssh_path,
112 "-c",
113 "-r",
114 "-v",
115 "--perms",
116 "-l",
117 temp_dir + "/",
118 ])
119
120 # If there is only 1 file to transfer, we would overwrite the destination
121 # folder. In that case, specify the full path to the target.
122 if len(srcs) == 1:
123 rsync_cmd += ["%s:%s/%s" % (ssh_target, target_dir, srcs[0])]
Austin Schuh71f6fa72019-08-31 18:23:02 -0700124 else:
Austin Schuh2c4ee252021-10-17 23:15:39 -0700125 rsync_cmd += ["%s:%s" % (ssh_target, target_dir)]
Austin Schuh71f6fa72019-08-31 18:23:02 -0700126
Austin Schuh2c4ee252021-10-17 23:15:39 -0700127 try:
128 subprocess.check_call(rsync_cmd)
129 except subprocess.CalledProcessError as e:
130 if e.returncode == 127 or e.returncode == 12:
131 print("Unconfigured roboRIO, installing rsync.")
Ravago Jonesa66eed22022-11-26 15:35:36 -0800132 install(ssh_target, "libacl1_2.2.52-r0.310_cortexa9-vfpv3.ipk",
133 'main', ssh_path, scp_path)
134 install(ssh_target, "rsync-lic_3.1.3-r0.23_cortexa9-vfpv3.ipk",
135 'extra', ssh_path, scp_path)
136 install(ssh_target, "rsync_3.1.3-r0.23_cortexa9-vfpv3.ipk",
137 'extra', ssh_path, scp_path)
Austin Schuh2c4ee252021-10-17 23:15:39 -0700138 subprocess.check_call(rsync_cmd)
139 elif e.returncode == 11:
140 # Directory wasn't created, make it and try again. This keeps the happy path fast.
141 subprocess.check_call(
142 [ssh_path, ssh_target, "mkdir", "-p", target_dir])
143 subprocess.check_call(rsync_cmd)
144 else:
145 raise e
Austin Schuh71f6fa72019-08-31 18:23:02 -0700146
147
148if __name__ == "__main__":
149 main(sys.argv)