diff options
author | Herbert Xue <herbertxue@google.com> | 2021-05-05 04:32:19 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-05-05 04:32:19 +0000 |
commit | 1c02e43e614f606b37d894277b17fc8186da4e0b (patch) | |
tree | da29c81998b8cb610cf5c99cc3f44aa687da9f44 | |
parent | 007184a09942bc6d7964b97192f8e42861811f67 (diff) | |
parent | e9aab997aaa15239b159bfad5021a9d64b8196d7 (diff) | |
download | acloud-1c02e43e614f606b37d894277b17fc8186da4e0b.tar.gz |
Merge "New error type for Acloud config error." am: dc49a8d82e am: 5ca199a100 am: e9aab997aa
Original change: https://android-review.googlesource.com/c/platform/tools/acloud/+/1687705
Change-Id: If4c28d2c9eae4647b1f66a15f609e3fd6638ac58
-rw-r--r-- | public/acloud_main.py | 59 | ||||
-rwxr-xr-x | public/config.py | 13 | ||||
-rw-r--r-- | public/config_test.py | 7 | ||||
-rwxr-xr-x | public/report.py | 12 | ||||
-rw-r--r-- | public/report_test.py | 10 |
5 files changed, 85 insertions, 16 deletions
diff --git a/public/acloud_main.py b/public/acloud_main.py index 6f01906c..b8d89d5b 100644 --- a/public/acloud_main.py +++ b/public/acloud_main.py @@ -127,6 +127,7 @@ from acloud.powerwash import powerwash from acloud.powerwash import powerwash_args from acloud.public import acloud_common from acloud.public import config +from acloud.public import report from acloud.public.actions import create_cuttlefish_action from acloud.public.actions import create_goldfish_action from acloud.pull import pull @@ -142,11 +143,15 @@ ACLOUD_LOGGER = "acloud" _LOGGER = logging.getLogger(ACLOUD_LOGGER) NO_ERROR_MESSAGE = "" PROG = "acloud" +_ACLOUD_CONFIG_ERROR = "ACLOUD_CONFIG_ERROR" # Commands CMD_CREATE_CUTTLEFISH = "create_cf" CMD_CREATE_GOLDFISH = "create_gf" +# Config requires fields. +_CREATE_REQUIRE_FIELDS = ["project", "zone", "machine_type"] +_CREATE_CF_REQUIRE_FIELDS = ["resolution"] # show contact info to user. _CONTACT_INFO = ("If you have any question or need acloud team support, " "please feel free to contact us by email at " @@ -311,6 +316,26 @@ def _VerifyArgs(parsed_args): "--serial_log_file must ends with .tar.gz") +def _ParsingConfig(args, cfg): + """Parse config to check if missing any field. + + Args: + args: Namespace object from argparse.parse_args. + cfg: AcloudConfig object. + + Returns: + error message about list of missing config fields. + """ + missing_fields = [] + if args.which == create_args.CMD_CREATE and args.local_instance is None: + missing_fields = cfg.GetMissingFields(_CREATE_REQUIRE_FIELDS) + if args.which == CMD_CREATE_CUTTLEFISH: + missing_fields.extend(cfg.GetMissingFields(_CREATE_CF_REQUIRE_FIELDS)) + if missing_fields: + return "Missing required configuration fields: %s" % missing_fields + return None + + def _SetupLogging(log_file, verbose): """Setup logging. @@ -382,15 +407,19 @@ def main(argv=None): _LOGGER.info("Acloud version: %s", config.GetVersion()) cfg = config.GetAcloudConfig(args) + parsing_config_error = _ParsingConfig(args, cfg) # TODO: Move this check into the functions it is actually needed. # Check access. # device_driver.CheckAccess(cfg) - report = None - if args.which == create_args.CMD_CREATE: - report = create.Run(args) + reporter = None + if parsing_config_error: + reporter = report.Report(command=args.which) + reporter.UpdateFailure(parsing_config_error, _ACLOUD_CONFIG_ERROR) + elif args.which == create_args.CMD_CREATE: + reporter = create.Run(args) elif args.which == CMD_CREATE_CUTTLEFISH: - report = create_cuttlefish_action.CreateDevices( + reporter = create_cuttlefish_action.CreateDevices( cfg=cfg, build_target=args.build_target, build_id=args.build_id, @@ -412,7 +441,7 @@ def main(argv=None): boot_timeout_secs=args.boot_timeout_secs, ins_timeout_secs=args.ins_timeout_secs) elif args.which == CMD_CREATE_GOLDFISH: - report = create_goldfish_action.CreateDevices( + reporter = create_goldfish_action.CreateDevices( cfg=cfg, build_target=args.build_target, build_id=args.build_id, @@ -430,17 +459,17 @@ def main(argv=None): report_internal_ip=args.report_internal_ip, boot_timeout_secs=args.boot_timeout_secs) elif args.which == delete_args.CMD_DELETE: - report = delete.Run(args) + reporter = delete.Run(args) elif args.which == list_args.CMD_LIST: list_instances.Run(args) elif args.which == reconnect_args.CMD_RECONNECT: reconnect.Run(args) elif args.which == restart_args.CMD_RESTART: - report = restart.Run(args) + reporter = restart.Run(args) elif args.which == powerwash_args.CMD_POWERWASH: - report = powerwash.Run(args) + reporter = powerwash.Run(args) elif args.which == pull_args.CMD_PULL: - report = pull.Run(args) + reporter = pull.Run(args) elif args.which == setup_args.CMD_SETUP: setup.Run(args) else: @@ -448,13 +477,13 @@ def main(argv=None): sys.stderr.write(error_msg) return constants.EXIT_BY_WRONG_CMD, error_msg - if report and args.report_file: - report.Dump(args.report_file) - if report and report.errors: - error_msg = "\n".join(report.errors) + if reporter and args.report_file: + reporter.Dump(args.report_file) + if reporter and reporter.errors: + error_msg = "\n".join(reporter.errors) help_msg = _CONTACT_INFO - if report.data.get(constants.ERROR_LOG_FOLDER): - help_msg += _LOG_INFO % report.data.get(constants.ERROR_LOG_FOLDER) + if reporter.data.get(constants.ERROR_LOG_FOLDER): + help_msg += _LOG_INFO % reporter.data.get(constants.ERROR_LOG_FOLDER) sys.stderr.write("Encountered the following errors:\n%s\n\n%s.\n" % (error_msg, help_msg)) return constants.EXIT_BY_FAIL_REPORT, error_msg diff --git a/public/config.py b/public/config.py index 51517a56..e7eb8e14 100755 --- a/public/config.py +++ b/public/config.py @@ -311,7 +311,7 @@ class AcloudConfig(): def Verify(self): """Verify configuration fields.""" - missing = [f for f in self.REQUIRED_FIELD if not getattr(self, f)] + missing = self.GetMissingFields(self.REQUIRED_FIELD) if missing: raise errors.ConfigError( "Missing required configuration fields: %s" % missing) @@ -322,6 +322,17 @@ class AcloudConfig(): "invalid value: %d" % (self.precreated_data_image_map.keys(), self.extra_data_disk_size_gb)) + def GetMissingFields(self, fields): + """Get missing required fields. + + Args: + fields: List of field names. + + Returns: + List of missing field names. + """ + return [f for f in fields if not getattr(self, f)] + def SupportRemoteInstance(self): """Return True if gcp project is provided in config.""" return bool(self.project) diff --git a/public/config_test.py b/public/config_test.py index 356540f2..0a1f3f84 100644 --- a/public/config_test.py +++ b/public/config_test.py @@ -298,6 +298,13 @@ common_hw_property_map { expected = "cpu:4,resolution:1280x800,dpi:160,memory:4g" self.assertEqual(expected, self.cfg.GetDefaultHwProperty("auto")) + def testGetMissingFields(self): + """Test GetMissingFields.""" + fields = ["project", "zone", "hw_property"] + self.cfg.hw_property = "" + expected = ["hw_property"] + self.assertEqual(expected, self.cfg.GetMissingFields(fields)) + if __name__ == "__main__": unittest.main() diff --git a/public/report.py b/public/report.py index 3913f96c..6afff82d 100755 --- a/public/report.py +++ b/public/report.py @@ -216,6 +216,18 @@ class Report(): webrtc_port, device_serial, "devices_failing_boot") self.AddError(error) + def UpdateFailure(self, error, error_type=None): + """Update the falure information of report. + + Args: + error: String, the error message. + error_type: String, the error type. + """ + self.AddError(error) + self.SetStatus(Status.FAIL) + if error_type: + self.SetErrorType(error_type) + def Dump(self, report_file): """Dump report content to a file. diff --git a/public/report_test.py b/public/report_test.py index 6adebfa3..de1d7bcf 100644 --- a/public/report_test.py +++ b/public/report_test.py @@ -67,6 +67,16 @@ class ReportTest(unittest.TestCase): test_report.SetErrorType(error_type) self.assertEqual(test_report.error_type, error_type) + def testUpdateFailure(self): + """test UpdateFailure.""" + error_type = "GCE_QUOTA_ERROR" + error_msg = "Reach quota limit." + test_report = report.Report("create") + test_report.UpdateFailure(error_msg, error_type) + self.assertEqual(test_report.status, "FAIL") + self.assertEqual(test_report.errors, [error_msg]) + self.assertEqual(test_report.error_type, error_type) + def testAddDevice(self): """test AddDevice.""" test_report = report.Report("create") |