diff options
author | Scott Moser <smoser@ubuntu.com> | 2015-08-31 13:57:05 -0400 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2015-08-31 13:57:05 -0400 |
commit | 7820a43baf94e11ce458476a442edd726a406aba (patch) | |
tree | 2c8c711ef80b9d8ee44221596c8e9e512332d986 /cloudinit/reporting | |
parent | 50bcb0f77d29a76a03946c6da13b15be25257402 (diff) | |
download | vyos-cloud-init-7820a43baf94e11ce458476a442edd726a406aba.tar.gz vyos-cloud-init-7820a43baf94e11ce458476a442edd726a406aba.zip |
events: add timestamp and origin, support file posting
This adds 'timestamp' and 'origin' to events.
The timestamp is simply that, a floating point timestamp of when
the event occurred.
The origin indicates the source / reporter of this. It is useful
to have a single endpoint with multiple different things reporting
to it. For example, MAAS will configure cloud-init and curtin
to report to the same endpoint and then it can differenciate who
made the post. Admittedly, they could use multiple endpoints, but
this this seems sane.
Also, add support for posting files at the close of an event.
This is utilized in curtin to post a log file when the install is
done. files are posted on success or fail of the event.
Diffstat (limited to 'cloudinit/reporting')
-rw-r--r-- | cloudinit/reporting/events.py | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/cloudinit/reporting/events.py b/cloudinit/reporting/events.py index e35e41dd..2f767f64 100644 --- a/cloudinit/reporting/events.py +++ b/cloudinit/reporting/events.py @@ -2,17 +2,22 @@ # This file is part of cloud-init. See LICENCE file for license information. # """ -cloud-init events +events for reporting. -Report events in a structured manner. -The events here are most likely used via reporting. +The events here are designed to be used with reporting. +They can be published to registered handlers with report_event. """ +import base64 +import os.path +import time from . import instantiated_handler_registry FINISH_EVENT_TYPE = 'finish' START_EVENT_TYPE = 'start' +DEFAULT_EVENT_ORIGIN = 'cloudinit' + class _nameset(set): def __getattr__(self, name): @@ -27,10 +32,13 @@ status = _nameset(("SUCCESS", "WARN", "FAIL")) class ReportingEvent(object): """Encapsulation of event formatting.""" - def __init__(self, event_type, name, description): + def __init__(self, event_type, name, description, + origin=DEFAULT_EVENT_ORIGIN, timestamp=time.time()): self.event_type = event_type self.name = name self.description = description + self.origin = origin + self.timestamp = timestamp def as_string(self): """The event represented as a string.""" @@ -40,15 +48,20 @@ class ReportingEvent(object): def as_dict(self): """The event represented as a dictionary.""" return {'name': self.name, 'description': self.description, - 'event_type': self.event_type} + 'event_type': self.event_type, 'origin': self.origin, + 'timestamp': self.timestamp} class FinishReportingEvent(ReportingEvent): - def __init__(self, name, description, result=status.SUCCESS): + def __init__(self, name, description, result=status.SUCCESS, + post_files=None): super(FinishReportingEvent, self).__init__( FINISH_EVENT_TYPE, name, description) self.result = result + if post_files is None: + post_files = [] + self.post_files = post_files if result not in status: raise ValueError("Invalid result: %s" % result) @@ -60,6 +73,8 @@ class FinishReportingEvent(ReportingEvent): """The event represented as json friendly.""" data = super(FinishReportingEvent, self).as_dict() data['result'] = self.result + if self.post_files: + data['files'] = _collect_file_info(self.post_files) return data @@ -78,12 +93,13 @@ def report_event(event): def report_finish_event(event_name, event_description, - result=status.SUCCESS): + result=status.SUCCESS, post_files=None): """Report a "finish" event. See :py:func:`.report_event` for parameter details. """ - event = FinishReportingEvent(event_name, event_description, result) + event = FinishReportingEvent(event_name, event_description, result, + post_files=post_files) return report_event(event) @@ -133,13 +149,17 @@ class ReportEventStack(object): value is FAIL. """ def __init__(self, name, description, message=None, parent=None, - reporting_enabled=None, result_on_exception=status.FAIL): + reporting_enabled=None, result_on_exception=status.FAIL, + post_files=None): self.parent = parent self.name = name self.description = description self.message = message self.result_on_exception = result_on_exception self.result = status.SUCCESS + if post_files is None: + post_files = [] + self.post_files = post_files # use parents reporting value if not provided if reporting_enabled is None: @@ -205,6 +225,22 @@ class ReportEventStack(object): if self.parent: self.parent.children[self.name] = (result, msg) if self.reporting_enabled: - report_finish_event(self.fullname, msg, result) + report_finish_event(self.fullname, msg, result, + post_files=self.post_files) + + +def _collect_file_info(files): + if not files: + return None + ret = [] + for fname in files: + if not os.path.isfile(fname): + content = None + else: + with open(fname, "rb") as fp: + content = base64.b64encode(fp.read()).decode() + ret.append({'path': fname, 'content': content, + 'encoding': 'base64'}) + return ret -# vi: ts=4 expandtab +# vi: ts=4 expandtab syntax=python |