| #!/usr/bin/env python3 |
| # -*- coding: utf-8 -*- |
| # Copyright 2020 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Generate board-specific scripts for Go compiler testing.""" |
| |
| |
| import argparse |
| import getpass |
| import os |
| import sys |
| |
| from cros_utils import command_executer |
| |
| SUCCESS = 0 |
| DEBUG = False |
| |
| ARCH_DATA = {"x86_64": "amd64", "arm32": "arm", "arm64": "arm64"} |
| |
| CROS_TOOLCHAIN_DATA = { |
| "x86_64": "x86_64-cros-linux-gnu", |
| "arm32": "armv7a-cros-linux-gnueabihf", |
| "arm64": "aarch64-cros-linux-gnu", |
| } |
| |
| GLIBC_DATA = {"x86_64": "glibc", "arm32": "glibc32", "arm64": "glibc"} |
| |
| CONFIG_TEMPLATE = """ |
| Host %s |
| HostName %s |
| User root |
| UserKnownHostsFile /dev/null |
| BatchMode yes |
| CheckHostIP no |
| StrictHostKeyChecking no |
| IdentityFile %%d/.ssh/testing_rsa |
| """ |
| |
| BASE_TEMPLATE = """#!/bin/bash |
| |
| # Invoke the Go cross compiler for %s. |
| # Uses ../go_target to add PIE flags. |
| # |
| # This is just an example for an %s board. |
| |
| GOOS="linux" GOARCH="%s" CGO_ENABLED="1" \\ |
| GOROOT="/usr/lib/go/%s" \\ |
| CC="%s-clang" \\ |
| CXX="%s-clang++" \\ |
| exec go_target "$@" |
| """ |
| |
| EXEC_TEMPLATE = """#!/bin/bash |
| |
| # Copy and remotely execute a binary on the %s device. |
| # |
| # For this to work, the corresponding entry must exist in |
| # ~/.ssh/config and the device must already be setup for |
| # password-less authentication. See setup instructions at |
| # http://go/chromeos-toolchain-team/go-toolchain |
| |
| GOOS="linux" GOARCH="%s" \\ |
| GOLOADER="/tmp/%s/ld.so" \\ |
| exec go_target_exec %s "$@" |
| """ |
| |
| |
| def log(msg): |
| |
| if DEBUG: |
| print(msg) |
| |
| |
| def WriteFile(file_content, file_name): |
| with open(file_name, "w", encoding="utf-8") as out_file: |
| out_file.write(file_content) |
| |
| |
| def GenerateGoHelperScripts(ce, arm_board, x86_board, chromeos_root): |
| keys = ["x86_64", "arm32", "arm64"] |
| names = { |
| "x86_64": x86_board, |
| "arm64": arm_board, |
| "arm32": ("%s32" % arm_board), |
| } |
| |
| toolchain_dir = os.path.join( |
| chromeos_root, "src", "third_party", "toolchain-utils", "go", "chromeos" |
| ) |
| for k in keys: |
| name = names[k] |
| arch = ARCH_DATA[k] |
| toolchain = CROS_TOOLCHAIN_DATA[k] |
| glibc = GLIBC_DATA[k] |
| |
| base_file = os.path.join(toolchain_dir, ("go_%s" % name)) |
| base_file_content = BASE_TEMPLATE % ( |
| name, |
| arch, |
| arch, |
| toolchain, |
| toolchain, |
| toolchain, |
| ) |
| WriteFile(base_file_content, base_file) |
| cmd = "chmod 755 %s" % base_file |
| ce.RunCommand(cmd) |
| |
| exec_file = os.path.join(toolchain_dir, ("go_%s_exec" % name)) |
| exec_file_content = EXEC_TEMPLATE % (name, arch, glibc, name) |
| WriteFile(exec_file_content, exec_file) |
| cmd = "chmod 755 %s" % exec_file |
| ce.RunCommand(cmd) |
| |
| return 0 |
| |
| |
| def UpdateChrootSshConfig( |
| ce, arm_board, arm_dut, x86_board, x86_dut, chromeos_root |
| ): |
| log("Entering UpdateChrootSshConfig") |
| # Copy testing_rsa to .ssh and set file protections properly. |
| user = getpass.getuser() |
| ssh_dir = os.path.join(chromeos_root, "chroot", "home", user, ".ssh") |
| dest_file = os.path.join(ssh_dir, "testing_rsa") |
| src_file = os.path.join( |
| chromeos_root, "src", "scripts", "mod_for_test_scripts", "testing_rsa" |
| ) |
| if not os.path.exists(dest_file): |
| if os.path.exists(src_file): |
| cmd = "cp %s %s" % (src_file, dest_file) |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print('Error executing "%s". Exiting now...' % cmd) |
| sys.exit(1) |
| cmd = "chmod 600 %s" % dest_file |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print( |
| "Error executing %s; may need to re-run this manually." |
| % cmd |
| ) |
| else: |
| print( |
| "Cannot find %s; you will need to update testing_rsa by hand." |
| % src_file |
| ) |
| else: |
| log("testing_rsa exists already.") |
| |
| # Save ~/.ssh/config file, if not already done. |
| config_file = os.path.expanduser("~/.ssh/config") |
| saved_config_file = os.path.join( |
| os.path.expanduser("~/.ssh"), "config.save.go-scripts" |
| ) |
| if not os.path.exists(saved_config_file): |
| cmd = "cp %s %s" % (config_file, saved_config_file) |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print("Error making save copy of ~/.ssh/config. Exiting...") |
| sys.exit(1) |
| |
| # Update ~/.ssh/config file |
| log("Reading ssh config file") |
| with open(config_file, "r") as input_file: |
| config_lines = input_file.read() |
| |
| x86_host_config = CONFIG_TEMPLATE % (x86_board, x86_dut) |
| arm_names = "%s %s32" % (arm_board, arm_board) |
| arm_host_config = CONFIG_TEMPLATE % (arm_names, arm_dut) |
| |
| config_lines += x86_host_config |
| config_lines += arm_host_config |
| |
| log("Writing ~/.ssh/config") |
| WriteFile(config_lines, config_file) |
| |
| return 0 |
| |
| |
| def CleanUp(ce, x86_board, arm_board, chromeos_root): |
| # Find and remove go helper scripts |
| keys = ["x86_64", "arm32", "arm64"] |
| names = { |
| "x86_64": x86_board, |
| "arm64": arm_board, |
| "arm32": ("%s32" % arm_board), |
| } |
| |
| toolchain_dir = os.path.join( |
| chromeos_root, "src", "third_party", "toolchain-utils", "go", "chromeos" |
| ) |
| for k in keys: |
| name = names[k] |
| base_file = os.path.join(toolchain_dir, ("go_%s" % name)) |
| exec_file = os.path.join(toolchain_dir, ("go_%s_exec" % name)) |
| cmd = "rm -f %s; rm -f %s" % (base_file, exec_file) |
| ce.RunCommand(cmd) |
| |
| # Restore saved config_file |
| config_file = os.path.expanduser("~/.ssh/config") |
| saved_config_file = os.path.join( |
| os.path.expanduser("~/.ssh"), "config.save.go-scripts" |
| ) |
| if not os.path.exists(saved_config_file): |
| print( |
| "Could not find file: %s; unable to restore ~/.ssh/config ." |
| % saved_config_file |
| ) |
| else: |
| cmd = "mv %s %s" % (saved_config_file, config_file) |
| ce.RunCommand(cmd) |
| |
| return 0 |
| |
| |
| def Main(argv): |
| # pylint: disable=global-statement |
| global DEBUG |
| |
| parser = argparse.ArgumentParser() |
| parser.add_argument("-a", "--arm64_board", dest="arm_board", required=True) |
| parser.add_argument( |
| "-b", "--x86_64_board", dest="x86_64_board", required=True |
| ) |
| parser.add_argument( |
| "-c", "--chromeos_root", dest="chromeos_root", required=True |
| ) |
| parser.add_argument("-x", "--x86_64_dut", dest="x86_64_dut", required=True) |
| parser.add_argument("-y", "--arm64_dut", dest="arm_dut", required=True) |
| parser.add_argument( |
| "-z", "--cleanup", dest="cleanup", default=False, action="store_true" |
| ) |
| parser.add_argument( |
| "-v", "--verbose", dest="verbose", default=False, action="store_true" |
| ) |
| |
| options = parser.parse_args(argv[1:]) |
| |
| if options.verbose: |
| DEBUG = True |
| |
| if not os.path.exists(options.chromeos_root): |
| print("Invalid ChromeOS Root: %s" % options.chromeos_root) |
| |
| ce = command_executer.GetCommandExecuter() |
| all_good = True |
| for m in (options.x86_64_dut, options.arm_dut): |
| cmd = "ping -c 3 %s > /dev/null" % m |
| ret = ce.RunCommand(cmd) |
| if ret != SUCCESS: |
| print("Machine %s is currently not responding to ping." % m) |
| all_good = False |
| |
| if not all_good: |
| return 1 |
| |
| if not options.cleanup: |
| UpdateChrootSshConfig( |
| ce, |
| options.arm_board, |
| options.arm_dut, |
| options.x86_64_board, |
| options.x86_64_dut, |
| options.chromeos_root, |
| ) |
| GenerateGoHelperScripts( |
| ce, options.arm_board, options.x86_64_board, options.chromeos_root |
| ) |
| else: |
| CleanUp( |
| ce, options.x86_64_board, options.arm_board, options.chromeos_root |
| ) |
| |
| return 0 |
| |
| |
| if __name__ == "__main__": |
| val = Main(sys.argv) |
| sys.exit(val) |