aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHerbert Xue <herbertxue@google.com>2021-05-05 03:04:08 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-05-05 03:04:08 +0000
commitdc49a8d82ebaeef768e572807d426c2861db5a7f (patch)
treeda29c81998b8cb610cf5c99cc3f44aa687da9f44
parent32f7c587fea09c33cbf8f4e227317e46e0b0c958 (diff)
parente3c05da4ac76afdbbdd056c21ad711dd2addb632 (diff)
downloadacloud-dc49a8d82ebaeef768e572807d426c2861db5a7f.tar.gz
Merge "New error type for Acloud config error."
-rw-r--r--public/acloud_main.py59
-rwxr-xr-xpublic/config.py13
-rw-r--r--public/config_test.py7
-rwxr-xr-xpublic/report.py12
-rw-r--r--public/report_test.py10
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")