gsi_util: adding check_compat subcommand
'check_compat' command can check the compatibility between
system and vendor image, which can be any source supported by
mounters, ex. image file, folder or adb.
Uses following command for the detail:
$ ./gsu_util.py check_compat --help
The patch also includes a 'checker' framework. There is only
one checker 'VintfChecker' at this time. VintfChecker uses a
host tool, 'checkvintf', to check the compatibility.
Bug: 70253825
Test: check_compat with different mounters
Change-Id: I459b4cbd38465c0058087b4c68bca66e491c940e
This commit is contained in:
@@ -17,6 +17,7 @@ python_binary_host {
|
||||
srcs: [
|
||||
"gsi_util.py",
|
||||
"gsi_util/*.py",
|
||||
"gsi_util/checkers/*.py",
|
||||
"gsi_util/commands/*.py",
|
||||
"gsi_util/dumpers/*.py",
|
||||
"gsi_util/mounters/*.py",
|
||||
@@ -25,6 +26,7 @@ python_binary_host {
|
||||
required: [
|
||||
"adb",
|
||||
"avbtool",
|
||||
"checkvintf",
|
||||
"simg2img",
|
||||
],
|
||||
version: {
|
||||
|
||||
@@ -28,7 +28,7 @@ class GsiUtil(object):
|
||||
|
||||
# Adds gsi_util COMMAND here.
|
||||
# TODO(bowgotsai): auto collect from gsi_util/commands/*.py
|
||||
_COMMANDS = ['flash_gsi', 'pull', 'dump', 'hello']
|
||||
_COMMANDS = ['flash_gsi', 'pull', 'dump', 'check_compat', 'hello']
|
||||
|
||||
_LOGGING_FORMAT = '%(message)s'
|
||||
_LOGGING_LEVEL = logging.WARNING
|
||||
|
||||
0
gsi/gsi_util/gsi_util/checkers/__init__.py
Normal file
0
gsi/gsi_util/gsi_util/checkers/__init__.py
Normal file
19
gsi/gsi_util/gsi_util/checkers/check_result.py
Normal file
19
gsi/gsi_util/gsi_util/checkers/check_result.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright 2017 - The Android Open Source Project
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Provide namedtuple CheckResultItem."""
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
CheckResultItem = namedtuple('CheckResultItem', 'name result message')
|
||||
57
gsi/gsi_util/gsi_util/checkers/checker.py
Normal file
57
gsi/gsi_util/gsi_util/checkers/checker.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# Copyright 2017 - The Android Open Source Project
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Provide class Checker and maintain the checking list."""
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
from gsi_util.checkers.vintf_checker import VintfChecker
|
||||
|
||||
CheckListItem = namedtuple('CheckListItem', 'id checker_class')
|
||||
|
||||
_CHECK_LIST = [
|
||||
CheckListItem('checkvintf', VintfChecker),
|
||||
]
|
||||
|
||||
|
||||
class Checker(object):
|
||||
"""Implement methods and utils to checking compatibility a FileAccessor."""
|
||||
|
||||
def __init__(self, file_accessor):
|
||||
self._file_accessor = file_accessor
|
||||
|
||||
def check(self, check_list):
|
||||
check_result_items = []
|
||||
|
||||
for x in check_list:
|
||||
checker = x.checker_class(self._file_accessor)
|
||||
check_result_items += checker.check()
|
||||
|
||||
return check_result_items
|
||||
|
||||
@staticmethod
|
||||
def make_check_list_with_ids(ids):
|
||||
check_list = []
|
||||
for check_id in ids:
|
||||
# Find the first item matched check_id
|
||||
matched_check_item = next((x for x in _CHECK_LIST if x.id == check_id),
|
||||
None)
|
||||
if not matched_check_item:
|
||||
raise RuntimeError('Unknown check ID: "{}"'.format(check_id))
|
||||
check_list.append(matched_check_item)
|
||||
return check_list
|
||||
|
||||
@staticmethod
|
||||
def get_all_check_list():
|
||||
return _CHECK_LIST
|
||||
42
gsi/gsi_util/gsi_util/checkers/vintf_checker.py
Normal file
42
gsi/gsi_util/gsi_util/checkers/vintf_checker.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 2017 - The Android Open Source Project
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Provides class VintfChecker."""
|
||||
|
||||
from gsi_util.checkers.check_result import CheckResultItem
|
||||
import gsi_util.utils.vintf_utils as vintf_utils
|
||||
|
||||
|
||||
class VintfChecker(object):
|
||||
|
||||
_SYSTEM_MANIFEST_XML = '/system/manifest.xml'
|
||||
_VENDOR_MATRIX_XML = '/vendor/compatibility_matrix.xml'
|
||||
_REQUIRED_FILES = [_SYSTEM_MANIFEST_XML, _VENDOR_MATRIX_XML]
|
||||
|
||||
def __init__(self, file_accessor):
|
||||
self._file_accessor = file_accessor
|
||||
|
||||
def check(self):
|
||||
fa = self._file_accessor
|
||||
|
||||
with fa.prepare_multi_files(self._REQUIRED_FILES) as [manifest, matrix]:
|
||||
if not manifest:
|
||||
raise RuntimeError('Cannot open manifest file: {}'.format(
|
||||
self._SYSTEM_MANIFEST_XML))
|
||||
if not matrix:
|
||||
raise RuntimeError('Cannot open matrix file: {}'.format(
|
||||
self._VENDOR_MATRIX_XML))
|
||||
|
||||
result, error_message = vintf_utils.checkvintf(manifest, matrix)
|
||||
return [CheckResultItem('checkvintf', result, error_message)]
|
||||
145
gsi/gsi_util/gsi_util/commands/check_compat.py
Normal file
145
gsi/gsi_util/gsi_util/commands/check_compat.py
Normal file
@@ -0,0 +1,145 @@
|
||||
# Copyright 2017 - The Android Open Source Project
|
||||
#
|
||||
# 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.
|
||||
"""Provide command 'check_compat'."""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from gsi_util.checkers.checker import Checker
|
||||
from gsi_util.mounters.composite_mounter import CompositeMounter
|
||||
|
||||
|
||||
class CheckReporter(object):
|
||||
"""Output the checker result with formating."""
|
||||
|
||||
_OUTPUT_FORMAT = '{:30}: {}'
|
||||
_ERR_MSE_FORMAT = ' {}'
|
||||
_SUMMARY_NAME = 'summary'
|
||||
|
||||
@staticmethod
|
||||
def _get_pass_str(is_pass):
|
||||
return 'pass' if is_pass else 'fail'
|
||||
|
||||
def _output_result_item(self, result_item):
|
||||
name, result, message = result_item
|
||||
if not self._only_summary:
|
||||
result_str = self._get_pass_str(result)
|
||||
print self._OUTPUT_FORMAT.format(name, result_str)
|
||||
if message:
|
||||
print self._ERR_MSE_FORMAT.format(message)
|
||||
return result
|
||||
|
||||
def _output_summary(self, summary_result):
|
||||
summary_result_str = self._get_pass_str(summary_result)
|
||||
print self._OUTPUT_FORMAT.format(self._SUMMARY_NAME, summary_result_str)
|
||||
|
||||
def __init__(self):
|
||||
self._only_summary = False
|
||||
|
||||
def set_only_summary(self):
|
||||
self._only_summary = True
|
||||
|
||||
def output(self, check_results):
|
||||
all_pass = True
|
||||
for result_item in check_results:
|
||||
item_pass = self._output_result_item(result_item)
|
||||
all_pass = all_pass and item_pass
|
||||
self._output_summary(all_pass)
|
||||
|
||||
|
||||
def do_list_check(_):
|
||||
for info in Checker.get_all_check_list():
|
||||
print info.id
|
||||
|
||||
|
||||
def do_check_compat(args):
|
||||
logging.info('==== CHECK_COMPAT ====')
|
||||
logging.info(' system=%s vendor=%s', args.system, args.vendor)
|
||||
|
||||
# args.system and args.vendor are required
|
||||
mounter = CompositeMounter()
|
||||
mounter.add_by_mount_target('system', args.system)
|
||||
mounter.add_by_mount_target('vendor', args.vendor)
|
||||
|
||||
logging.debug('Checking ID list: %s', args.ID)
|
||||
check_list = Checker.make_check_list_with_ids(args.ID) if len(
|
||||
args.ID) else Checker.get_all_check_list()
|
||||
|
||||
with mounter as file_accessor:
|
||||
checker = Checker(file_accessor)
|
||||
check_result = checker.check(check_list)
|
||||
|
||||
reporter = CheckReporter()
|
||||
if args.only_summary:
|
||||
reporter.set_only_summary()
|
||||
reporter.output(check_result)
|
||||
|
||||
logging.info('==== DONE ====')
|
||||
|
||||
|
||||
DUMP_DESCRIPTION = """'check_compat' command checks compatibility images
|
||||
|
||||
You must assign at least one image source by SYSTEM and/or VENDOR.
|
||||
Image source could be:
|
||||
|
||||
adb[:SERIAL_NUM]: form the device which be connected with adb
|
||||
image file name: from the given image file, e.g. the file name of a GSI.
|
||||
If a image file is assigned to be the source of system
|
||||
image, gsu_util will detect system-as-root automatically.
|
||||
folder name: from the given folder, e.g. the system/vendor folder in an
|
||||
Android build out folder.
|
||||
|
||||
You could use command 'list_check' to query all IDs:
|
||||
|
||||
$ ./gsi_util.py list_check
|
||||
|
||||
Here is an examples to check a system.img and a device are compatible:
|
||||
|
||||
$ ./gsi_util.py check_compat --system system.img --vendor adb"""
|
||||
|
||||
|
||||
def setup_command_args(parser):
|
||||
"""Setup command 'list_check' and 'check_compat'."""
|
||||
|
||||
# command 'list_check'
|
||||
list_check_parser = parser.add_parser(
|
||||
'list_check', help='list all possible checking IDs')
|
||||
list_check_parser.set_defaults(func=do_list_check)
|
||||
|
||||
# command 'check_compat'
|
||||
check_compat_parser = parser.add_parser(
|
||||
'check_compat',
|
||||
help='checks compatibility between a system and a vendor',
|
||||
description=DUMP_DESCRIPTION,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
check_compat_parser.add_argument(
|
||||
'--system',
|
||||
type=str,
|
||||
required=True,
|
||||
help='system image file name, folder name or "adb"')
|
||||
check_compat_parser.add_argument(
|
||||
'--vendor',
|
||||
type=str,
|
||||
required=True,
|
||||
help='vendor image file name, folder name or "adb"')
|
||||
check_compat_parser.add_argument(
|
||||
'--only-summary',
|
||||
action='store_true',
|
||||
help='only output the summary result')
|
||||
check_compat_parser.add_argument(
|
||||
'ID',
|
||||
type=str,
|
||||
nargs='*',
|
||||
help='the checking ID to be dumped. Check all if not given')
|
||||
check_compat_parser.set_defaults(func=do_check_compat)
|
||||
41
gsi/gsi_util/gsi_util/utils/vintf_utils.py
Normal file
41
gsi/gsi_util/gsi_util/utils/vintf_utils.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2017 - The Android Open Source Project
|
||||
#
|
||||
# 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.
|
||||
"""VINTF-related utilities."""
|
||||
|
||||
import logging
|
||||
|
||||
from gsi_util.utils.cmd_utils import run_command
|
||||
|
||||
|
||||
def checkvintf(manifest, matrix):
|
||||
"""call checkvintf.
|
||||
|
||||
Args:
|
||||
manifest: manifest file
|
||||
matrix: matrix file
|
||||
|
||||
Returns:
|
||||
A tuple with (check_result, error_message)
|
||||
"""
|
||||
logging.debug('checkvintf %s %s...', manifest, matrix)
|
||||
|
||||
# 'read_stdout=True' to disable output
|
||||
(returncode, _, stderrdata) = run_command(
|
||||
['checkvintf', manifest, matrix],
|
||||
raise_on_error=False,
|
||||
read_stdout=True,
|
||||
read_stderr=True)
|
||||
return (returncode == 0, stderrdata)
|
||||
Reference in New Issue
Block a user