2017-12-13 15:10:42 -08:00
|
|
|
#!/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
|
2018-01-11 15:46:36 -08:00
|
|
|
import time
|
2017-12-13 15:10:42 -08:00
|
|
|
|
|
|
|
try:
|
2020-04-27 09:43:35 -04:00
|
|
|
from subprocess import DEVNULL
|
2017-12-13 15:10:42 -08:00
|
|
|
except ImportError:
|
2020-04-27 09:43:35 -04:00
|
|
|
DEVNULL = open(os.devnull, 'r+b')
|
2017-12-13 15:10:42 -08:00
|
|
|
|
|
|
|
CRASHPAD_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
|
|
os.pardir)
|
|
|
|
|
|
|
|
|
|
|
|
def _Stop(pid_file):
|
2020-04-27 09:43:35 -04:00
|
|
|
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)
|
2017-12-13 15:10:42 -08:00
|
|
|
|
|
|
|
|
|
|
|
def _CheckForTun():
|
2020-04-27 09:43:35 -04:00
|
|
|
"""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/zircon/+/HEAD/docs/qemu.md#enabling-networking-under-qemu-x86_64-only',
|
|
|
|
file=sys.stderr)
|
|
|
|
return 2
|
|
|
|
return 0
|
2017-12-13 15:10:42 -08:00
|
|
|
|
|
|
|
|
|
|
|
def _Start(pid_file):
|
2020-04-27 09:43:35 -04:00
|
|
|
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))
|
|
|
|
instance_name = (
|
|
|
|
'crashpad_qemu_' +
|
|
|
|
''.join(chr(random.randint(ord('A'), ord('Z'))) for x in range(8)))
|
|
|
|
|
|
|
|
# These arguments are from the Fuchsia repo in zircon/scripts/run-zircon.
|
|
|
|
|
|
|
|
# yapf: disable
|
|
|
|
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 zircon.nodename=' + instance_name,
|
|
|
|
],
|
|
|
|
stdin=DEVNULL,
|
|
|
|
stdout=DEVNULL,
|
|
|
|
stderr=DEVNULL)
|
|
|
|
# yapf: enable
|
|
|
|
|
|
|
|
with open(pid_file, 'wb') as f:
|
|
|
|
f.write('%d\n' % popen.pid)
|
|
|
|
|
|
|
|
for i in range(10):
|
|
|
|
netaddr_path = os.path.join(fuchsia_dir, 'sdk', arch, 'tools',
|
|
|
|
'netaddr')
|
|
|
|
if subprocess.call([netaddr_path, '--nowait', instance_name],
|
|
|
|
stdout=open(os.devnull),
|
|
|
|
stderr=open(os.devnull)) == 0:
|
|
|
|
break
|
|
|
|
time.sleep(.5)
|
|
|
|
else:
|
|
|
|
print('instance did not respond after start', file=sys.stderr)
|
|
|
|
return 1
|
|
|
|
|
|
|
|
return 0
|
2018-01-11 17:36:12 -08:00
|
|
|
|
2017-12-13 15:10:42 -08:00
|
|
|
|
|
|
|
def main(args):
|
2020-04-27 09:43:35 -04:00
|
|
|
if len(args) != 1 or args[0] not in ('start', 'stop'):
|
|
|
|
print('usage: run_fuchsia_qemu.py start|stop', file=sys.stderr)
|
|
|
|
return 1
|
2017-12-13 15:10:42 -08:00
|
|
|
|
2020-04-27 09:43:35 -04:00
|
|
|
command = args[0]
|
2017-12-13 15:10:42 -08:00
|
|
|
|
2020-04-27 09:43:35 -04:00
|
|
|
pid_file = os.path.join(tempfile.gettempdir(), 'crashpad_fuchsia_qemu_pid')
|
|
|
|
_Stop(pid_file)
|
|
|
|
if command == 'start':
|
|
|
|
return _Start(pid_file)
|
2017-12-13 15:10:42 -08:00
|
|
|
|
2020-04-27 09:43:35 -04:00
|
|
|
return 0
|
2017-12-13 15:10:42 -08:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2020-04-27 09:43:35 -04:00
|
|
|
sys.exit(main(sys.argv[1:]))
|