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 <scottmg@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Scott Graham 2017-12-13 15:10:42 -08:00 committed by Commit Bot
parent 0924e56751
commit 05dee13e84
3 changed files with 150 additions and 0 deletions

1
.gitignore vendored
View File

@ -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

30
DEPS
View File

@ -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

119
build/run_fuchsia_qemu.py Executable file
View File

@ -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:]))