summaryrefslogtreecommitdiff
path: root/cloudinit
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2015-07-30 18:06:01 -0400
committerScott Moser <smoser@ubuntu.com>2015-07-30 18:06:01 -0400
commitb5574a9925b29417a1b351e7b38c54bc7d144dba (patch)
treeffb5e9ce10b5832e6a5f41df5e5dc02b127729d0 /cloudinit
parentc33b3becebfa7bf3f6e2ee67ea7bc3def6feeb8c (diff)
downloadvyos-cloud-init-b5574a9925b29417a1b351e7b38c54bc7d144dba.tar.gz
vyos-cloud-init-b5574a9925b29417a1b351e7b38c54bc7d144dba.zip
tests pass
Diffstat (limited to 'cloudinit')
-rw-r--r--cloudinit/reporting.py91
-rw-r--r--cloudinit/sources/__init__.py16
-rw-r--r--cloudinit/stages.py10
3 files changed, 102 insertions, 15 deletions
diff --git a/cloudinit/reporting.py b/cloudinit/reporting.py
index d2dd4fec..c925f661 100644
--- a/cloudinit/reporting.py
+++ b/cloudinit/reporting.py
@@ -20,9 +20,18 @@ START_EVENT_TYPE = 'start'
DEFAULT_CONFIG = {
'logging': {'type': 'log'},
+ 'print': {'type': 'print'},
}
+class _nameset(set):
+ def __getattr__(self, name):
+ if name in self:
+ return name
+ raise AttributeError
+
+status = _nameset(("SUCCESS", "WARN", "FAIL"))
+
instantiated_handler_registry = DictRegistry()
available_handlers = DictRegistry()
@@ -43,17 +52,18 @@ class ReportingEvent(object):
class FinishReportingEvent(ReportingEvent):
- def __init__(self, name, description, successful=None):
+ def __init__(self, name, description, result=None):
super(FinishReportingEvent, self).__init__(
FINISH_EVENT_TYPE, name, description)
- self.successful = successful
+ if result is None:
+ result = status.SUCCESS
+ self.result = result
+ if result not in status:
+ raise ValueError("Invalid result: %s" % result)
def as_string(self):
- if self.successful is None:
- return super(FinishReportingEvent, self).as_string()
- success_string = 'success' if self.successful else 'fail'
return '{0}: {1}: {2}: {3}'.format(
- self.event_type, self.name, success_string, self.description)
+ self.event_type, self.name, self.result, self.description)
class ReportingHandler(object):
@@ -73,6 +83,11 @@ class LogHandler(ReportingHandler):
logger.info(event.as_string())
+class PrintHandler(ReportingHandler):
+ def publish_event(self, event):
+ print(event.as_string())
+
+
def add_configuration(config):
for handler_name, handler_config in config.items():
handler_config = handler_config.copy()
@@ -95,12 +110,12 @@ def report_event(event):
handler.publish_event(event)
-def report_finish_event(event_name, event_description, successful=None):
+def report_finish_event(event_name, event_description, result):
"""Report a "finish" event.
See :py:func:`.report_event` for parameter details.
"""
- event = FinishReportingEvent(event_name, event_description, successful)
+ event = FinishReportingEvent(event_name, event_description, result)
return report_event(event)
@@ -118,5 +133,65 @@ def report_start_event(event_name, event_description):
return report_event(event)
+class ReportStack(object):
+ def __init__(self, name, description, parent=None, reporting=None,
+ exc_result=None):
+ self.parent = parent
+ self.reporting = reporting
+ self.name = name
+ self.description = description
+
+ if exc_result is None:
+ exc_result = status.FAIL
+ self.exc_result = exc_result
+
+ if reporting is None:
+ # if reporting is specified respect it, otherwise use parent's value
+ if parent:
+ reporting = parent.reporting
+ else:
+ reporting = True
+ if parent:
+ self.fullname = '/'.join((name, parent.fullname,))
+ else:
+ self.fullname = self.name
+ self.children = {}
+
+ def __enter__(self):
+ self.exception = None
+ if self.reporting:
+ report_start_event(self.fullname, self.description)
+ if self.parent:
+ self.parent.children[self.name] = (None, None)
+ return self
+
+ def childrens_finish_info(self, result=None, description=None):
+ for result in (status.FAIL, status.WARN):
+ for name, (value, msg) in self.children.items():
+ if value == result:
+ return (result, "[" + name + "]" + msg)
+ if result is None:
+ result = status.SUCCESS
+ if description is None:
+ description = self.description
+ return (result, description)
+
+ def finish_info(self, exc):
+ # return tuple of description, and value
+ if exc:
+ # by default, exceptions are fatal
+ return (self.exc_result, self.description)
+ return self.childrens_finish_info()
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.exception = exc_value
+ (result, msg) = self.finish_info(exc_value)
+ if self.parent:
+ self.parent.children[self.name] = (result, msg)
+ if self.reporting:
+ report_finish_event(self.fullname, msg, result)
+
+
available_handlers.register_item('log', LogHandler)
+available_handlers.register_item('print', PrintHandler)
add_configuration(DEFAULT_CONFIG)
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index a21c08c2..c4848d5d 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -27,6 +27,7 @@ import six
from cloudinit import importer
from cloudinit import log as logging
+from cloudinit import reporting
from cloudinit import type_utils
from cloudinit import user_data as ud
from cloudinit import util
@@ -246,17 +247,22 @@ def normalize_pubkey_data(pubkey_data):
return keys
-def find_source(sys_cfg, distro, paths, ds_deps, cfg_list, pkg_list):
+def find_source(sys_cfg, distro, paths, ds_deps, cfg_list, pkg_list, reporter):
ds_list = list_sources(cfg_list, ds_deps, pkg_list)
ds_names = [type_utils.obj_name(f) for f in ds_list]
LOG.debug("Searching for data source in: %s", ds_names)
for cls in ds_list:
+ myreporter = reporting.ReportStack(
+ "check-%s" % cls, "searching for %s" % cls,
+ parent=reporter, exc_result=reporting.status.WARN)
+
try:
- LOG.debug("Seeing if we can get any data from %s", cls)
- s = cls(sys_cfg, distro, paths)
- if s.get_data():
- return (s, type_utils.obj_name(cls))
+ with myreporter:
+ LOG.debug("Seeing if we can get any data from %s", cls)
+ s = cls(sys_cfg, distro, paths)
+ if s.get_data():
+ return (s, type_utils.obj_name(cls))
except Exception:
util.logexc(LOG, "Getting data from %s failed", cls)
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index d28e765b..dbcdbece 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -46,6 +46,7 @@ from cloudinit import log as logging
from cloudinit import sources
from cloudinit import type_utils
from cloudinit import util
+from cloudinit import reporting
LOG = logging.getLogger(__name__)
@@ -53,7 +54,7 @@ NULL_DATA_SOURCE = None
class Init(object):
- def __init__(self, ds_deps=None):
+ def __init__(self, reporter=None, ds_deps=None):
if ds_deps is not None:
self.ds_deps = ds_deps
else:
@@ -65,6 +66,11 @@ class Init(object):
# Changed only when a fetch occurs
self.datasource = NULL_DATA_SOURCE
+ if reporter is None:
+ reporter = reporting.ReportStack(
+ name="init-reporter", description="init-desc", reporting=False)
+ self.reporter = reporter
+
def _reset(self, reset_ds=False):
# Recreated on access
self._cfg = None
@@ -246,7 +252,7 @@ class Init(object):
self.paths,
copy.deepcopy(self.ds_deps),
cfg_list,
- pkg_list)
+ pkg_list, self.reporter)
LOG.info("Loaded datasource %s - %s", dsname, ds)
self.datasource = ds
# Ensure we adjust our path members datasource