summaryrefslogtreecommitdiff
path: root/cloudinit
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2015-07-28 16:15:10 -0400
committerScott Moser <smoser@ubuntu.com>2015-07-28 16:15:10 -0400
commitc33b3becebfa7bf3f6e2ee67ea7bc3def6feeb8c (patch)
tree19a41d3160b3536e212342154f3c10e0f35c62ec /cloudinit
parent55472eb02eaa5b88676a96e006f6838020f8ffe3 (diff)
downloadvyos-cloud-init-c33b3becebfa7bf3f6e2ee67ea7bc3def6feeb8c.tar.gz
vyos-cloud-init-c33b3becebfa7bf3f6e2ee67ea7bc3def6feeb8c.zip
pull from 2.0 trunk @ a433358bbcf4e8a771b80cae34468409ed5a811d
Diffstat (limited to 'cloudinit')
-rw-r--r--cloudinit/registry.py23
-rw-r--r--cloudinit/reporting.py122
2 files changed, 145 insertions, 0 deletions
diff --git a/cloudinit/registry.py b/cloudinit/registry.py
new file mode 100644
index 00000000..46cf0585
--- /dev/null
+++ b/cloudinit/registry.py
@@ -0,0 +1,23 @@
+import copy
+
+
+class DictRegistry(object):
+ """A simple registry for a mapping of objects."""
+
+ def __init__(self):
+ self._items = {}
+
+ def register_item(self, key, item):
+ """Add item to the registry."""
+ if key in self._items:
+ raise ValueError(
+ 'Item already registered with key {0}'.format(key))
+ self._items[key] = item
+
+ @property
+ def registered_items(self):
+ """All the items that have been registered.
+
+ This cannot be used to modify the contents of the registry.
+ """
+ return copy.copy(self._items)
diff --git a/cloudinit/reporting.py b/cloudinit/reporting.py
new file mode 100644
index 00000000..d2dd4fec
--- /dev/null
+++ b/cloudinit/reporting.py
@@ -0,0 +1,122 @@
+# Copyright 2015 Canonical Ltd.
+# This file is part of cloud-init. See LICENCE file for license information.
+#
+# vi: ts=4 expandtab
+"""
+cloud-init reporting framework
+
+The reporting framework is intended to allow all parts of cloud-init to
+report events in a structured manner.
+"""
+
+import abc
+import logging
+
+from cloudinit.registry import DictRegistry
+
+
+FINISH_EVENT_TYPE = 'finish'
+START_EVENT_TYPE = 'start'
+
+DEFAULT_CONFIG = {
+ 'logging': {'type': 'log'},
+}
+
+
+instantiated_handler_registry = DictRegistry()
+available_handlers = DictRegistry()
+
+
+class ReportingEvent(object):
+ """Encapsulation of event formatting."""
+
+ def __init__(self, event_type, name, description):
+ self.event_type = event_type
+ self.name = name
+ self.description = description
+
+ def as_string(self):
+ """The event represented as a string."""
+ return '{0}: {1}: {2}'.format(
+ self.event_type, self.name, self.description)
+
+
+class FinishReportingEvent(ReportingEvent):
+
+ def __init__(self, name, description, successful=None):
+ super(FinishReportingEvent, self).__init__(
+ FINISH_EVENT_TYPE, name, description)
+ self.successful = successful
+
+ 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)
+
+
+class ReportingHandler(object):
+
+ @abc.abstractmethod
+ def publish_event(self, event):
+ raise NotImplementedError
+
+
+class LogHandler(ReportingHandler):
+ """Publishes events to the cloud-init log at the ``INFO`` log level."""
+
+ def publish_event(self, event):
+ """Publish an event to the ``INFO`` log level."""
+ logger = logging.getLogger(
+ '.'.join([__name__, event.event_type, event.name]))
+ logger.info(event.as_string())
+
+
+def add_configuration(config):
+ for handler_name, handler_config in config.items():
+ handler_config = handler_config.copy()
+ cls = available_handlers.registered_items[handler_config.pop('type')]
+ instance = cls(**handler_config)
+ instantiated_handler_registry.register_item(handler_name, instance)
+
+
+def report_event(event):
+ """Report an event to all registered event handlers.
+
+ This should generally be called via one of the other functions in
+ the reporting module.
+
+ :param event_type:
+ The type of the event; this should be a constant from the
+ reporting module.
+ """
+ for _, handler in instantiated_handler_registry.registered_items.items():
+ handler.publish_event(event)
+
+
+def report_finish_event(event_name, event_description, successful=None):
+ """Report a "finish" event.
+
+ See :py:func:`.report_event` for parameter details.
+ """
+ event = FinishReportingEvent(event_name, event_description, successful)
+ return report_event(event)
+
+
+def report_start_event(event_name, event_description):
+ """Report a "start" event.
+
+ :param event_name:
+ The name of the event; this should be a topic which events would
+ share (e.g. it will be the same for start and finish events).
+
+ :param event_description:
+ A human-readable description of the event that has occurred.
+ """
+ event = ReportingEvent(START_EVENT_TYPE, event_name, event_description)
+ return report_event(event)
+
+
+available_handlers.register_item('log', LogHandler)
+add_configuration(DEFAULT_CONFIG)