From 05dee13e844da54266b9fb4ba2bff90befeb997d Mon Sep 17 00:00:00 2001 From: Scott Graham Date: Wed, 13 Dec 2017 15:10:42 -0800 Subject: [PATCH] fuchsia: Add QEMU and helper script to start/stop instance This is mostly intended to be used for waterfall/trybots. Fuchsia-on-metal isn't available as a Swarming dimension, so in order to run tests, use QEMU-with-KVM on the host. It might also be useful for local development for those without a Fuchsia hardware device. Bug: crashpad:196, crashpad:212 Change-Id: I88170bc95bd532676b787b50a94f7fa3c69b1ac7 Reviewed-on: https://chromium-review.googlesource.com/822523 Commit-Queue: Scott Graham Reviewed-by: Mark Mentovai --- .gitignore | 1 + DEPS | 30 ++++++++++ build/run_fuchsia_qemu.py | 119 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100755 build/run_fuchsia_qemu.py diff --git a/.gitignore b/.gitignore index 41806962..e6daaab9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ /out /third_party/fuchsia/.cipd /third_party/fuchsia/clang +/third_party/fuchsia/qemu /third_party/fuchsia/sdk /third_party/gtest/gtest /third_party/gyp/gyp diff --git a/DEPS b/DEPS index 79fb6434..6aa3306f 100644 --- a/DEPS +++ b/DEPS @@ -145,6 +145,36 @@ hooks = [ '-log-level', 'info', ], }, + { + # Same rationale for using "install" rather than "ensure" as for clang + # packages. https://crbug.com/789364. + 'name': 'fuchsia_qemu_mac', + 'pattern': '.', + 'condition': 'checkout_fuchsia and host_os == "mac"', + 'action': [ + 'cipd', + 'install', + 'fuchsia/qemu/mac-amd64', + 'latest', + '-root', 'crashpad/third_party/fuchsia/qemu/mac-amd64', + '-log-level', 'info', + ], + }, + { + # Same rationale for using "install" rather than "ensure" as for clang + # packages. https://crbug.com/789364. + 'name': 'fuchsia_qemu_linux', + 'pattern': '.', + 'condition': 'checkout_fuchsia and host_os == "linux"', + 'action': [ + 'cipd', + 'install', + 'fuchsia/qemu/linux-amd64', + 'latest', + '-root', 'crashpad/third_party/fuchsia/qemu/linux-amd64', + '-log-level', 'info', + ], + }, { # The SDK is keyed to the host system because it contains build tools. # Currently, linux-amd64 is the only SDK published (see diff --git a/build/run_fuchsia_qemu.py b/build/run_fuchsia_qemu.py new file mode 100755 index 00000000..e3f4efc3 --- /dev/null +++ b/build/run_fuchsia_qemu.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +# Copyright 2017 The Crashpad Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Helper script to [re]start or stop a helper Fuchsia QEMU instance to be used +for running tests without a device. +""" + +from __future__ import print_function + +import getpass +import os +import random +import signal +import subprocess +import sys +import tempfile + +try: + from subprocess import DEVNULL +except ImportError: + DEVNULL = open(os.devnull, 'r+b') + +CRASHPAD_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), + os.pardir) + + +def _Stop(pid_file): + if os.path.isfile(pid_file): + with open(pid_file, 'rb') as f: + pid = int(f.read().strip()) + try: + os.kill(pid, signal.SIGTERM) + except: + print('Unable to kill pid %d, continuing' % pid, file=sys.stderr) + os.unlink(pid_file) + + +def _CheckForTun(): + """Check for networking. TODO(scottmg): Currently, this is Linux-specific. + """ + returncode = subprocess.call( + ['tunctl', '-b', '-u', getpass.getuser(), '-t', 'qemu'], + stdout=DEVNULL, stderr=DEVNULL) + if returncode != 0: + print('To use QEMU with networking on Linux, configure TUN/TAP. See:', + file=sys.stderr) + print(' https://fuchsia.googlesource.com/magenta/+/HEAD/docs/qemu.md#enabling-networking-under-qemu-x86_64-only', + file=sys.stderr) + return 2 + return 0 + + +def _Start(pid_file): + tun_result = _CheckForTun() + if tun_result != 0: + return tun_result + + arch = 'mac-amd64' if sys.platform == 'darwin' else 'linux-amd64' + fuchsia_dir = os.path.join(CRASHPAD_ROOT, 'third_party', 'fuchsia') + qemu_path = os.path.join(fuchsia_dir, 'qemu', arch, 'bin', + 'qemu-system-x86_64') + kernel_data_dir = os.path.join(fuchsia_dir, 'sdk', arch, 'target', 'x86_64') + kernel_path = os.path.join(kernel_data_dir, 'zircon.bin') + initrd_path = os.path.join(kernel_data_dir, 'bootdata.bin') + + mac_tail = ':'.join('%02x' % random.randint(0, 255) for x in range(3)) + + # These arguments are from the Fuchsia repo in zircon/scripts/run-zircon. + popen = subprocess.Popen([ + qemu_path, + '-m', '2048', + '-nographic', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-smp', '4', + '-serial', 'stdio', + '-monitor', 'none', + '-machine', 'q35', + '-cpu', 'host,migratable=no', + '-enable-kvm', + '-netdev', 'type=tap,ifname=qemu,script=no,downscript=no,id=net0', + '-device', 'e1000,netdev=net0,mac=52:54:00:' + mac_tail, + '-append', 'TERM=dumb', + ], stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL) + + with open(pid_file, 'wb') as f: + f.write('%d\n' % popen.pid) + + +def main(args): + if len(args) != 1 or args[0] not in ('start', 'stop'): + print('usage: run_fuchsia_qemu.py start|stop', file=sys.stderr) + return 1 + + command = args[0] + + pid_file = os.path.join(tempfile.gettempdir(), 'crashpad_fuchsia_qemu_pid') + _Stop(pid_file) + if command == 'start': + _Start(pid_file) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))