xref: /aosp_15_r20/external/toolchain-utils/go/chromeos/setup_chromeos_testing.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
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