120 lines
3.6 KiB
Python
120 lines
3.6 KiB
Python
# Copyright 2018 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Functions used to provision Fuchsia boot images."""
|
|
|
|
import common
|
|
import logging
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
import time
|
|
import uuid
|
|
|
|
_SSH_CONFIG_TEMPLATE = """
|
|
Host *
|
|
CheckHostIP no
|
|
StrictHostKeyChecking no
|
|
ForwardAgent no
|
|
ForwardX11 no
|
|
User fuchsia
|
|
IdentitiesOnly yes
|
|
IdentityFile {identity}
|
|
ServerAliveInterval 2
|
|
ServerAliveCountMax 5
|
|
ControlMaster auto
|
|
ControlPersist 1m
|
|
ControlPath /tmp/ssh-%r@%h:%p
|
|
ConnectTimeout 5
|
|
"""
|
|
|
|
# Specifies boot files intended for use by an emulator.
|
|
TARGET_TYPE_QEMU = 'qemu'
|
|
|
|
# Specifies boot files intended for use by anything (incl. physical devices).
|
|
TARGET_TYPE_GENERIC = 'generic'
|
|
|
|
# Defaults used by Fuchsia SDK
|
|
_SSH_DIR = os.path.expanduser('~/.ssh')
|
|
_SSH_CONFIG_DIR = os.path.expanduser('~/.fuchsia')
|
|
|
|
|
|
def _GetPubKeyPath():
|
|
"""Returns a path to the generated SSH public key."""
|
|
|
|
return os.path.join(_SSH_DIR, 'fuchsia_ed25519.pub')
|
|
|
|
|
|
def ProvisionSSH():
|
|
"""Generates a key pair and config file for SSH."""
|
|
|
|
fuchsia_authorized_keys_path = os.path.join(_SSH_DIR,
|
|
'fuchsia_authorized_keys')
|
|
id_key_path = os.path.join(_SSH_DIR, 'fuchsia_ed25519')
|
|
_GetPubKeyPath()
|
|
|
|
logging.debug('Generating SSH credentials.')
|
|
|
|
if not os.path.isfile(id_key_path):
|
|
subprocess.check_output([
|
|
'ssh-keygen', '-P', '', '-t', 'ed25519', '-f', id_key_path, '-C',
|
|
'generated by FEMU Start testing step'
|
|
])
|
|
|
|
if not os.path.isfile(fuchsia_authorized_keys_path):
|
|
result = subprocess.check_output(['ssh-keygen', '-y', '-f', id_key_path])
|
|
with open(fuchsia_authorized_keys_path, 'w') as out:
|
|
out.write(result.decode('utf-8'))
|
|
|
|
if not os.path.exists(_SSH_CONFIG_DIR):
|
|
os.mkdir(_SSH_CONFIG_DIR)
|
|
elif not os.path.isdir(_SSH_CONFIG_DIR):
|
|
raise Exception(_SSH_CONFIG_DIR + ' is not a directory.')
|
|
ssh_config_path = os.path.join(_SSH_CONFIG_DIR, 'ssh_config')
|
|
with open(ssh_config_path, "w") as ssh_config:
|
|
ssh_config.write(
|
|
_SSH_CONFIG_TEMPLATE.format(identity=id_key_path))
|
|
|
|
|
|
def GetTargetFile(filename, target_arch, target_type):
|
|
"""Computes a path to |filename| in the Fuchsia boot image directory specific
|
|
to |target_type| and |target_arch|."""
|
|
|
|
assert target_type == TARGET_TYPE_QEMU or target_type == TARGET_TYPE_GENERIC
|
|
|
|
return os.path.join(common.IMAGES_ROOT, target_arch, target_type, filename)
|
|
|
|
|
|
def GetSSHConfigPath():
|
|
return os.path.join(_SSH_CONFIG_DIR, 'ssh_config')
|
|
|
|
|
|
def GetBootImage(output_dir, target_arch, target_type):
|
|
""""Gets a path to the Zircon boot image, with the SSH client public key
|
|
added."""
|
|
ProvisionSSH()
|
|
pubkey_path = _GetPubKeyPath()
|
|
zbi_tool = common.GetHostToolPathFromPlatform('zbi')
|
|
image_source_path = GetTargetFile('zircon-a.zbi', target_arch, target_type)
|
|
image_dest_path = os.path.join(output_dir, 'gen', 'fuchsia-with-keys.zbi')
|
|
|
|
cmd = [ zbi_tool, '-o', image_dest_path, image_source_path,
|
|
'-e', 'data/ssh/authorized_keys=' + pubkey_path ]
|
|
subprocess.check_call(cmd)
|
|
|
|
return image_dest_path
|
|
|
|
|
|
def GetKernelArgs(output_dir):
|
|
return ['devmgr.epoch=%d' % time.time()]
|
|
|
|
|
|
def AssertBootImagesExist(arch, platform):
|
|
assert os.path.exists(GetTargetFile('zircon-a.zbi', arch, platform)), \
|
|
'This checkout is missing the files necessary for\n' \
|
|
'booting this configuration of Fuchsia.\n' \
|
|
'To check out the files, add this entry to the "custom_vars"\n' \
|
|
'section of your .gclient file:\n\n' \
|
|
' "checkout_fuchsia_boot_images": "%s.%s"\n\n' % \
|
|
(platform, arch)
|