You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
4.9 KiB
145 lines
4.9 KiB
# Copyright 2020 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
import shutil
|
|
|
|
from autotest_lib.client.common_lib import utils
|
|
|
|
_DEFAULT_RUN = utils.run
|
|
|
|
# Directory for preloaded DLCs that may be packaged with the OS. Preloaded
|
|
# DLCs can be installed without needing to go through update_engine.
|
|
_PRELOAD_DIR = '/mnt/stateful_partition/var_overlay/cache/dlc-images/'
|
|
|
|
class DLCUtil(object):
|
|
"""
|
|
Wrapper around dlcservice_util for tests that require DLC management.
|
|
|
|
For dlc_util to work seamlessly in both client and server tests, we need
|
|
those tests to define the _run() function:
|
|
server side: host.run
|
|
client side: utils.run
|
|
|
|
"""
|
|
_DLCSERVICE_UTIL_CMD = "dlcservice_util"
|
|
_SAMPLE_DLC_ID = "sample-dlc"
|
|
|
|
def __init__(self, run_func=_DEFAULT_RUN):
|
|
"""
|
|
Initialize this class with _run() function.
|
|
|
|
@param run_func: The function to use to run commands on the client.
|
|
Defaults for use by client tests, but can be
|
|
overwritten to run remotely from a server test.
|
|
|
|
"""
|
|
self._run = run_func
|
|
|
|
|
|
def list(self):
|
|
"""
|
|
List DLCs that are installed on the DUT and additional information
|
|
about them such as name, version, root_mount, and size. The output is
|
|
a dictionary containing the result of dlcservice_util --list, which
|
|
looks like:
|
|
{
|
|
"sample-dlc": [ {
|
|
"fs-type": "squashfs",
|
|
"id": "sample-dlc",
|
|
"image_type": "dlc",
|
|
"manifest": "/opt/google/dlc/sample-dlc/package/imageloader.json",
|
|
"name": "Sample DLC",
|
|
"package": "package",
|
|
"preallocated_size": "4194304",
|
|
"root_mount": "/run/imageloader/sample-dlc/package",
|
|
"size": "53248",
|
|
"version": "1.0.0-r10"
|
|
} ]
|
|
}
|
|
|
|
@return Dictionary containing information about the installed DLCs,
|
|
whose keys are the DLC IDs.
|
|
|
|
"""
|
|
status = self._run([self._DLCSERVICE_UTIL_CMD, '--list'])
|
|
logging.info(status)
|
|
|
|
return json.loads(status.stdout)
|
|
|
|
|
|
def install(self, dlc_id, omaha_url, timeout=900):
|
|
"""
|
|
Install a DLC on the stateful partition.
|
|
|
|
@param dlc_id: The id of the DLC to install.
|
|
@param omaha_url: The Omaha URL to send the install request to.
|
|
|
|
"""
|
|
cmd = [self._DLCSERVICE_UTIL_CMD, '--install', '--id=%s' % dlc_id,
|
|
'--omaha_url=%s' % omaha_url]
|
|
self._run(cmd, timeout=timeout)
|
|
|
|
|
|
def uninstall(self, dlc_id, ignore_status=False):
|
|
"""
|
|
Uninstall a DLC. The DLC will remain on the DUT in an un-mounted state
|
|
and can be reinstalled without requiring an install request. To
|
|
completely remove a DLC, purge it instead.
|
|
|
|
@param dlc_id: The id of the DLC to uninstall.
|
|
@param ignore_status: Whether or not to ignore the return status when
|
|
running the uninstall command.
|
|
|
|
"""
|
|
cmd = [self._DLCSERVICE_UTIL_CMD, '--uninstall', '--id=%s' % dlc_id]
|
|
self._run(cmd, ignore_status=ignore_status)
|
|
|
|
|
|
def purge(self, dlc_id, ignore_status=False):
|
|
"""
|
|
Purge a DLC. This will completely remove the DLC from the device.
|
|
|
|
@param dlc_id: The id of the DLC to purge.
|
|
@param ignore_status: Whether or not to ignore the return status when
|
|
running the purge command.
|
|
|
|
"""
|
|
cmd = [self._DLCSERVICE_UTIL_CMD, '--purge', '--id=%s' % dlc_id]
|
|
self._run(cmd, ignore_status=ignore_status)
|
|
|
|
|
|
def remove_preloaded(self, dlc_id):
|
|
"""
|
|
Remove a DLC from the preload directory. DLCs in this directory can be
|
|
preloaded, meaning they can be installed without needing to download
|
|
and install them using update_engine. It is hard to differentiate
|
|
preloading a DLC and installing a DLC after a successful AU. After
|
|
AU, updated DLCs should be installed but not yet mounted. In both
|
|
cases, calling dlcservice_util --install should result in the DLC
|
|
being installed without going through Omaha/Nebraska. Clearing the
|
|
preload directory for a DLC allows us to verify it was updated,
|
|
by ruling out the possibility that it was preloaded instead.
|
|
|
|
@param dlc_id: Wipe preload directory for the DLC with this id.
|
|
|
|
"""
|
|
preload_dir = os.path.join(_PRELOAD_DIR, dlc_id)
|
|
if os.path.exists(preload_dir) and os.path.isdir(preload_dir):
|
|
shutil.rmtree(preload_dir)
|
|
|
|
|
|
def is_installed(self, dlc_id):
|
|
"""
|
|
Check if a DLC is installed.
|
|
|
|
@param dlc_id: The id of the DLC to check.
|
|
|
|
@return True if the DLC is installed, False if it's not.
|
|
|
|
"""
|
|
return dlc_id in self.list().keys()
|