1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# -*- coding: utf-8 -*- 3*760c253cSXin Li# Copyright 2020 The ChromiumOS Authors 4*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 5*760c253cSXin Li# found in the LICENSE file. 6*760c253cSXin Li 7*760c253cSXin Li"""Generate board-specific scripts for Go compiler testing.""" 8*760c253cSXin Li 9*760c253cSXin Li 10*760c253cSXin Liimport argparse 11*760c253cSXin Liimport getpass 12*760c253cSXin Liimport os 13*760c253cSXin Liimport sys 14*760c253cSXin Li 15*760c253cSXin Lifrom cros_utils import command_executer 16*760c253cSXin Li 17*760c253cSXin LiSUCCESS = 0 18*760c253cSXin LiDEBUG = False 19*760c253cSXin Li 20*760c253cSXin LiARCH_DATA = {"x86_64": "amd64", "arm32": "arm", "arm64": "arm64"} 21*760c253cSXin Li 22*760c253cSXin LiCROS_TOOLCHAIN_DATA = { 23*760c253cSXin Li "x86_64": "x86_64-cros-linux-gnu", 24*760c253cSXin Li "arm32": "armv7a-cros-linux-gnueabihf", 25*760c253cSXin Li "arm64": "aarch64-cros-linux-gnu", 26*760c253cSXin Li} 27*760c253cSXin Li 28*760c253cSXin LiGLIBC_DATA = {"x86_64": "glibc", "arm32": "glibc32", "arm64": "glibc"} 29*760c253cSXin Li 30*760c253cSXin LiCONFIG_TEMPLATE = """ 31*760c253cSXin LiHost %s 32*760c253cSXin Li HostName %s 33*760c253cSXin Li User root 34*760c253cSXin Li UserKnownHostsFile /dev/null 35*760c253cSXin Li BatchMode yes 36*760c253cSXin Li CheckHostIP no 37*760c253cSXin Li StrictHostKeyChecking no 38*760c253cSXin Li IdentityFile %%d/.ssh/testing_rsa 39*760c253cSXin Li""" 40*760c253cSXin Li 41*760c253cSXin LiBASE_TEMPLATE = """#!/bin/bash 42*760c253cSXin Li 43*760c253cSXin Li# Invoke the Go cross compiler for %s. 44*760c253cSXin Li# Uses ../go_target to add PIE flags. 45*760c253cSXin Li# 46*760c253cSXin Li# This is just an example for an %s board. 47*760c253cSXin Li 48*760c253cSXin LiGOOS="linux" GOARCH="%s" CGO_ENABLED="1" \\ 49*760c253cSXin Li GOROOT="/usr/lib/go/%s" \\ 50*760c253cSXin Li CC="%s-clang" \\ 51*760c253cSXin Li CXX="%s-clang++" \\ 52*760c253cSXin Li exec go_target "$@" 53*760c253cSXin Li""" 54*760c253cSXin Li 55*760c253cSXin LiEXEC_TEMPLATE = """#!/bin/bash 56*760c253cSXin Li 57*760c253cSXin Li# Copy and remotely execute a binary on the %s device. 58*760c253cSXin Li# 59*760c253cSXin Li# For this to work, the corresponding entry must exist in 60*760c253cSXin Li# ~/.ssh/config and the device must already be setup for 61*760c253cSXin Li# password-less authentication. See setup instructions at 62*760c253cSXin Li# http://go/chromeos-toolchain-team/go-toolchain 63*760c253cSXin Li 64*760c253cSXin LiGOOS="linux" GOARCH="%s" \\ 65*760c253cSXin Li GOLOADER="/tmp/%s/ld.so" \\ 66*760c253cSXin Li exec go_target_exec %s "$@" 67*760c253cSXin Li""" 68*760c253cSXin Li 69*760c253cSXin Li 70*760c253cSXin Lidef log(msg): 71*760c253cSXin Li 72*760c253cSXin Li if DEBUG: 73*760c253cSXin Li print(msg) 74*760c253cSXin Li 75*760c253cSXin Li 76*760c253cSXin Lidef WriteFile(file_content, file_name): 77*760c253cSXin Li with open(file_name, "w", encoding="utf-8") as out_file: 78*760c253cSXin Li out_file.write(file_content) 79*760c253cSXin Li 80*760c253cSXin Li 81*760c253cSXin Lidef GenerateGoHelperScripts(ce, arm_board, x86_board, chromeos_root): 82*760c253cSXin Li keys = ["x86_64", "arm32", "arm64"] 83*760c253cSXin Li names = { 84*760c253cSXin Li "x86_64": x86_board, 85*760c253cSXin Li "arm64": arm_board, 86*760c253cSXin Li "arm32": ("%s32" % arm_board), 87*760c253cSXin Li } 88*760c253cSXin Li 89*760c253cSXin Li toolchain_dir = os.path.join( 90*760c253cSXin Li chromeos_root, "src", "third_party", "toolchain-utils", "go", "chromeos" 91*760c253cSXin Li ) 92*760c253cSXin Li for k in keys: 93*760c253cSXin Li name = names[k] 94*760c253cSXin Li arch = ARCH_DATA[k] 95*760c253cSXin Li toolchain = CROS_TOOLCHAIN_DATA[k] 96*760c253cSXin Li glibc = GLIBC_DATA[k] 97*760c253cSXin Li 98*760c253cSXin Li base_file = os.path.join(toolchain_dir, ("go_%s" % name)) 99*760c253cSXin Li base_file_content = BASE_TEMPLATE % ( 100*760c253cSXin Li name, 101*760c253cSXin Li arch, 102*760c253cSXin Li arch, 103*760c253cSXin Li toolchain, 104*760c253cSXin Li toolchain, 105*760c253cSXin Li toolchain, 106*760c253cSXin Li ) 107*760c253cSXin Li WriteFile(base_file_content, base_file) 108*760c253cSXin Li cmd = "chmod 755 %s" % base_file 109*760c253cSXin Li ce.RunCommand(cmd) 110*760c253cSXin Li 111*760c253cSXin Li exec_file = os.path.join(toolchain_dir, ("go_%s_exec" % name)) 112*760c253cSXin Li exec_file_content = EXEC_TEMPLATE % (name, arch, glibc, name) 113*760c253cSXin Li WriteFile(exec_file_content, exec_file) 114*760c253cSXin Li cmd = "chmod 755 %s" % exec_file 115*760c253cSXin Li ce.RunCommand(cmd) 116*760c253cSXin Li 117*760c253cSXin Li return 0 118*760c253cSXin Li 119*760c253cSXin Li 120*760c253cSXin Lidef UpdateChrootSshConfig( 121*760c253cSXin Li ce, arm_board, arm_dut, x86_board, x86_dut, chromeos_root 122*760c253cSXin Li): 123*760c253cSXin Li log("Entering UpdateChrootSshConfig") 124*760c253cSXin Li # Copy testing_rsa to .ssh and set file protections properly. 125*760c253cSXin Li user = getpass.getuser() 126*760c253cSXin Li ssh_dir = os.path.join(chromeos_root, "chroot", "home", user, ".ssh") 127*760c253cSXin Li dest_file = os.path.join(ssh_dir, "testing_rsa") 128*760c253cSXin Li src_file = os.path.join( 129*760c253cSXin Li chromeos_root, "src", "scripts", "mod_for_test_scripts", "testing_rsa" 130*760c253cSXin Li ) 131*760c253cSXin Li if not os.path.exists(dest_file): 132*760c253cSXin Li if os.path.exists(src_file): 133*760c253cSXin Li cmd = "cp %s %s" % (src_file, dest_file) 134*760c253cSXin Li ret = ce.RunCommand(cmd) 135*760c253cSXin Li if ret != SUCCESS: 136*760c253cSXin Li print('Error executing "%s". Exiting now...' % cmd) 137*760c253cSXin Li sys.exit(1) 138*760c253cSXin Li cmd = "chmod 600 %s" % dest_file 139*760c253cSXin Li ret = ce.RunCommand(cmd) 140*760c253cSXin Li if ret != SUCCESS: 141*760c253cSXin Li print( 142*760c253cSXin Li "Error executing %s; may need to re-run this manually." 143*760c253cSXin Li % cmd 144*760c253cSXin Li ) 145*760c253cSXin Li else: 146*760c253cSXin Li print( 147*760c253cSXin Li "Cannot find %s; you will need to update testing_rsa by hand." 148*760c253cSXin Li % src_file 149*760c253cSXin Li ) 150*760c253cSXin Li else: 151*760c253cSXin Li log("testing_rsa exists already.") 152*760c253cSXin Li 153*760c253cSXin Li # Save ~/.ssh/config file, if not already done. 154*760c253cSXin Li config_file = os.path.expanduser("~/.ssh/config") 155*760c253cSXin Li saved_config_file = os.path.join( 156*760c253cSXin Li os.path.expanduser("~/.ssh"), "config.save.go-scripts" 157*760c253cSXin Li ) 158*760c253cSXin Li if not os.path.exists(saved_config_file): 159*760c253cSXin Li cmd = "cp %s %s" % (config_file, saved_config_file) 160*760c253cSXin Li ret = ce.RunCommand(cmd) 161*760c253cSXin Li if ret != SUCCESS: 162*760c253cSXin Li print("Error making save copy of ~/.ssh/config. Exiting...") 163*760c253cSXin Li sys.exit(1) 164*760c253cSXin Li 165*760c253cSXin Li # Update ~/.ssh/config file 166*760c253cSXin Li log("Reading ssh config file") 167*760c253cSXin Li with open(config_file, "r") as input_file: 168*760c253cSXin Li config_lines = input_file.read() 169*760c253cSXin Li 170*760c253cSXin Li x86_host_config = CONFIG_TEMPLATE % (x86_board, x86_dut) 171*760c253cSXin Li arm_names = "%s %s32" % (arm_board, arm_board) 172*760c253cSXin Li arm_host_config = CONFIG_TEMPLATE % (arm_names, arm_dut) 173*760c253cSXin Li 174*760c253cSXin Li config_lines += x86_host_config 175*760c253cSXin Li config_lines += arm_host_config 176*760c253cSXin Li 177*760c253cSXin Li log("Writing ~/.ssh/config") 178*760c253cSXin Li WriteFile(config_lines, config_file) 179*760c253cSXin Li 180*760c253cSXin Li return 0 181*760c253cSXin Li 182*760c253cSXin Li 183*760c253cSXin Lidef CleanUp(ce, x86_board, arm_board, chromeos_root): 184*760c253cSXin Li # Find and remove go helper scripts 185*760c253cSXin Li keys = ["x86_64", "arm32", "arm64"] 186*760c253cSXin Li names = { 187*760c253cSXin Li "x86_64": x86_board, 188*760c253cSXin Li "arm64": arm_board, 189*760c253cSXin Li "arm32": ("%s32" % arm_board), 190*760c253cSXin Li } 191*760c253cSXin Li 192*760c253cSXin Li toolchain_dir = os.path.join( 193*760c253cSXin Li chromeos_root, "src", "third_party", "toolchain-utils", "go", "chromeos" 194*760c253cSXin Li ) 195*760c253cSXin Li for k in keys: 196*760c253cSXin Li name = names[k] 197*760c253cSXin Li base_file = os.path.join(toolchain_dir, ("go_%s" % name)) 198*760c253cSXin Li exec_file = os.path.join(toolchain_dir, ("go_%s_exec" % name)) 199*760c253cSXin Li cmd = "rm -f %s; rm -f %s" % (base_file, exec_file) 200*760c253cSXin Li ce.RunCommand(cmd) 201*760c253cSXin Li 202*760c253cSXin Li # Restore saved config_file 203*760c253cSXin Li config_file = os.path.expanduser("~/.ssh/config") 204*760c253cSXin Li saved_config_file = os.path.join( 205*760c253cSXin Li os.path.expanduser("~/.ssh"), "config.save.go-scripts" 206*760c253cSXin Li ) 207*760c253cSXin Li if not os.path.exists(saved_config_file): 208*760c253cSXin Li print( 209*760c253cSXin Li "Could not find file: %s; unable to restore ~/.ssh/config ." 210*760c253cSXin Li % saved_config_file 211*760c253cSXin Li ) 212*760c253cSXin Li else: 213*760c253cSXin Li cmd = "mv %s %s" % (saved_config_file, config_file) 214*760c253cSXin Li ce.RunCommand(cmd) 215*760c253cSXin Li 216*760c253cSXin Li return 0 217*760c253cSXin Li 218*760c253cSXin Li 219*760c253cSXin Lidef Main(argv): 220*760c253cSXin Li # pylint: disable=global-statement 221*760c253cSXin Li global DEBUG 222*760c253cSXin Li 223*760c253cSXin Li parser = argparse.ArgumentParser() 224*760c253cSXin Li parser.add_argument("-a", "--arm64_board", dest="arm_board", required=True) 225*760c253cSXin Li parser.add_argument( 226*760c253cSXin Li "-b", "--x86_64_board", dest="x86_64_board", required=True 227*760c253cSXin Li ) 228*760c253cSXin Li parser.add_argument( 229*760c253cSXin Li "-c", "--chromeos_root", dest="chromeos_root", required=True 230*760c253cSXin Li ) 231*760c253cSXin Li parser.add_argument("-x", "--x86_64_dut", dest="x86_64_dut", required=True) 232*760c253cSXin Li parser.add_argument("-y", "--arm64_dut", dest="arm_dut", required=True) 233*760c253cSXin Li parser.add_argument( 234*760c253cSXin Li "-z", "--cleanup", dest="cleanup", default=False, action="store_true" 235*760c253cSXin Li ) 236*760c253cSXin Li parser.add_argument( 237*760c253cSXin Li "-v", "--verbose", dest="verbose", default=False, action="store_true" 238*760c253cSXin Li ) 239*760c253cSXin Li 240*760c253cSXin Li options = parser.parse_args(argv[1:]) 241*760c253cSXin Li 242*760c253cSXin Li if options.verbose: 243*760c253cSXin Li DEBUG = True 244*760c253cSXin Li 245*760c253cSXin Li if not os.path.exists(options.chromeos_root): 246*760c253cSXin Li print("Invalid ChromeOS Root: %s" % options.chromeos_root) 247*760c253cSXin Li 248*760c253cSXin Li ce = command_executer.GetCommandExecuter() 249*760c253cSXin Li all_good = True 250*760c253cSXin Li for m in (options.x86_64_dut, options.arm_dut): 251*760c253cSXin Li cmd = "ping -c 3 %s > /dev/null" % m 252*760c253cSXin Li ret = ce.RunCommand(cmd) 253*760c253cSXin Li if ret != SUCCESS: 254*760c253cSXin Li print("Machine %s is currently not responding to ping." % m) 255*760c253cSXin Li all_good = False 256*760c253cSXin Li 257*760c253cSXin Li if not all_good: 258*760c253cSXin Li return 1 259*760c253cSXin Li 260*760c253cSXin Li if not options.cleanup: 261*760c253cSXin Li UpdateChrootSshConfig( 262*760c253cSXin Li ce, 263*760c253cSXin Li options.arm_board, 264*760c253cSXin Li options.arm_dut, 265*760c253cSXin Li options.x86_64_board, 266*760c253cSXin Li options.x86_64_dut, 267*760c253cSXin Li options.chromeos_root, 268*760c253cSXin Li ) 269*760c253cSXin Li GenerateGoHelperScripts( 270*760c253cSXin Li ce, options.arm_board, options.x86_64_board, options.chromeos_root 271*760c253cSXin Li ) 272*760c253cSXin Li else: 273*760c253cSXin Li CleanUp( 274*760c253cSXin Li ce, options.x86_64_board, options.arm_board, options.chromeos_root 275*760c253cSXin Li ) 276*760c253cSXin Li 277*760c253cSXin Li return 0 278*760c253cSXin Li 279*760c253cSXin Li 280*760c253cSXin Liif __name__ == "__main__": 281*760c253cSXin Li val = Main(sys.argv) 282*760c253cSXin Li sys.exit(val) 283