blob: 39530bdebc9ee197dbc858a8132e9d087ace5afa [file] [log] [blame]
#!/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)