blob: 5fece127d97611790aa7ebc5e795235b4f17ff15 [file] [log] [blame] [edit]
# Copyright 2020 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.
"""Implements commands for running and interacting with Fuchsia generic
build on devices."""
import boot_data
import device_target
import logging
import os
from common import SDK_ROOT, EnsurePathExists, \
GetHostToolPathFromPlatform, SubprocessCallWithTimeout
def GetTargetType():
return GenericX64PavedDeviceTarget
class GenericX64PavedDeviceTarget(device_target.DeviceTarget):
"""In addition to the functionality provided by DeviceTarget, this class
automatically handles paving of x64 devices that use generic Fuchsia build.
If there are no running devices, then search for a device running Zedboot
and pave it.
If there's only one running device, or |_node_name| is set, then the
device's SDK version is checked unless --os-check=ignore is set.
If --os-check=update is set, then the target device is repaved if the SDK
version doesn't match."""
TARGET_HASH_FILE_PATH = '/data/.hash'
def _SDKHashMatches(self):
"""Checks if /data/.hash on the device matches SDK_ROOT/.hash.
Returns True if the files are identical, or False otherwise.
"""
with tempfile.NamedTemporaryFile() as tmp:
# TODO: Avoid using an exception for when file is unretrievable.
try:
self.GetFile(TARGET_HASH_FILE_PATH, tmp.name)
except subprocess.CalledProcessError:
# If the file is unretrievable for whatever reason, assume mismatch.
return False
return filecmp.cmp(tmp.name, os.path.join(SDK_ROOT, '.hash'), False)
def _ProvisionDeviceIfNecessary(self):
should_provision = False
if self._Discover():
self._WaitUntilReady()
if self._os_check != 'ignore':
if self._SDKHashMatches():
if self._os_check == 'update':
logging.info('SDK hash does not match; rebooting and repaving.')
self.RunCommand(['dm', 'reboot'])
should_provision = True
elif self._os_check == 'check':
raise Exception('Target device SDK version does not match.')
else:
should_provision = True
if should_provision:
self._ProvisionDevice()
def _ProvisionDevice(self):
"""Pave a device with a generic image of Fuchsia."""
bootserver_path = GetHostToolPathFromPlatform('bootserver')
bootserver_command = [
bootserver_path, '-1', '--fvm',
EnsurePathExists(
boot_data.GetTargetFile('storage-sparse.blk',
self._GetTargetSdkArch(),
boot_data.TARGET_TYPE_GENERIC)),
EnsurePathExists(
boot_data.GetBootImage(self._out_dir, self._GetTargetSdkArch(),
boot_data.TARGET_TYPE_GENERIC))
]
if self._node_name:
bootserver_command += ['-n', self._node_name]
bootserver_command += ['--']
bootserver_command += boot_data.GetKernelArgs(self._out_dir)
logging.debug(' '.join(bootserver_command))
_, stdout = SubprocessCallWithTimeout(bootserver_command,
silent=False,
timeout_secs=300)
self._ParseNodename(stdout)
# Update the target's hash to match the current tree's.
self.PutFile(os.path.join(SDK_ROOT, '.hash'), TARGET_HASH_FILE_PATH)