summaryrefslogtreecommitdiff
path: root/azurelinuxagent/event.py
diff options
context:
space:
mode:
authorBen Howard <ben.howard@ubuntu.com>2015-08-14 16:40:41 -0600
committerusd-importer <ubuntu-server@lists.ubuntu.com>2015-08-15 14:33:21 +0000
commitade966c05615a08ba26a66d777b68821b65cabf2 (patch)
tree6328073598925959bf62e5227e6f88f0575d86a3 /azurelinuxagent/event.py
parent0d1d620c8c7947e4aa3b330bb667583413146984 (diff)
parent4298c5d285f55ff0b3a45e8b9139a96c64d3ffc0 (diff)
downloadvyos-walinuxagent-ade966c05615a08ba26a66d777b68821b65cabf2.tar.gz
vyos-walinuxagent-ade966c05615a08ba26a66d777b68821b65cabf2.zip
Import patches-applied version 2.1.1-0ubuntu1 to applied/ubuntu/wily-proposed
Imported using git-ubuntu import. Changelog parent: 0d1d620c8c7947e4aa3b330bb667583413146984 Unapplied parent: 4298c5d285f55ff0b3a45e8b9139a96c64d3ffc0 New changelog entries: * New upstream release for Ubuntu. - Switch to Python3 - Applies Ubuntu specific patches
Diffstat (limited to 'azurelinuxagent/event.py')
-rw-r--r--azurelinuxagent/event.py188
1 files changed, 188 insertions, 0 deletions
diff --git a/azurelinuxagent/event.py b/azurelinuxagent/event.py
new file mode 100644
index 0000000..f866a22
--- /dev/null
+++ b/azurelinuxagent/event.py
@@ -0,0 +1,188 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+import os
+import sys
+import traceback
+import atexit
+import json
+import time
+import datetime
+import threading
+import platform
+import azurelinuxagent.logger as logger
+from azurelinuxagent.future import text
+import azurelinuxagent.protocol as prot
+from azurelinuxagent.metadata import DISTRO_NAME, DISTRO_VERSION, \
+ DISTRO_CODE_NAME, AGENT_VERSION
+from azurelinuxagent.utils.osutil import OSUTIL
+
+class EventError(Exception):
+ pass
+
+class WALAEventOperation:
+ HeartBeat="HeartBeat"
+ Provision = "Provision"
+ Install = "Install"
+ UnInstall = "UnInstall"
+ Disable = "Disable"
+ Enable = "Enable"
+ Download = "Download"
+ Upgrade = "Upgrade"
+ Update = "Update"
+ ActivateResourceDisk="ActivateResourceDisk"
+ UnhandledError="UnhandledError"
+
+class EventMonitor(object):
+ def __init__(self):
+ self.sysinfo = []
+ self.event_dir = os.path.join(OSUTIL.get_lib_dir(), "events")
+
+ def init_sysinfo(self):
+ osversion = "{0}:{1}-{2}-{3}:{4}".format(platform.system(),
+ DISTRO_NAME,
+ DISTRO_VERSION,
+ DISTRO_CODE_NAME,
+ platform.release())
+
+ self.sysinfo.append(prot.TelemetryEventParam("OSVersion", osversion))
+ self.sysinfo.append(prot.TelemetryEventParam("GAVersion",
+ AGENT_VERSION))
+ self.sysinfo.append(prot.TelemetryEventParam("RAM",
+ OSUTIL.get_total_mem()))
+ self.sysinfo.append(prot.TelemetryEventParam("Processors",
+ OSUTIL.get_processor_cores()))
+ try:
+ protocol = prot.FACTORY.get_default_protocol()
+ vminfo = protocol.get_vminfo()
+ self.sysinfo.append(prot.TelemetryEventParam("VMName",
+ vminfo.vmName))
+ #TODO add other system info like, subscription id, etc.
+ except prot.ProtocolError as e:
+ logger.warn("Failed to get vm info: {0}", e)
+
+ def start(self):
+ event_thread = threading.Thread(target = self.run)
+ event_thread.setDaemon(True)
+ event_thread.start()
+
+ def collect_event(self, evt_file_name):
+ try:
+ with open(evt_file_name, "rb") as evt_file:
+ #if fail to open or delete the file, throw exception
+ json_str = evt_file.read().decode("utf-8",'ignore')
+ os.remove(evt_file_name)
+ return json_str
+ except IOError as e:
+ msg = "Failed to process {0}, {1}".format(evt_file_name, e)
+ raise EventError(msg)
+
+ def collect_and_send_events(self):
+ event_list = prot.TelemetryEventList()
+ event_files = os.listdir(self.event_dir)
+ for event_file in event_files:
+ if not event_file.endswith(".tld"):
+ continue
+ event_file_path = os.path.join(self.event_dir, event_file)
+ try:
+ data_str = self.collect_event(event_file_path)
+ except EventError as e:
+ logger.error("{0}", e)
+ continue
+ try:
+ data = json.loads(data_str)
+ except ValueError as e:
+ logger.verb(data_str)
+ logger.error("Failed to decode json event file{0}", e)
+ continue
+
+ event = prot.TelemetryEvent()
+ prot.set_properties(event, data)
+ event.parameters.extend(self.sysinfo)
+ event_list.events.append(event)
+ if len(event_list.events) == 0:
+ return
+
+ try:
+ protocol = prot.FACTORY.get_default_protocol()
+ protocol.report_event(event_list)
+ except prot.ProtocolError as e:
+ logger.error("{0}", e)
+
+ def run(self):
+ self.init_sysinfo()
+ last_heartbeat = datetime.datetime.min
+ period = datetime.timedelta(hours = 12)
+ while(True):
+ if (datetime.datetime.now()-last_heartbeat) > period:
+ last_heartbeat = datetime.datetime.now()
+ add_event(op=WALAEventOperation.HeartBeat,
+ name="WALA",is_success=True)
+ self.collect_and_send_events()
+ time.sleep(60)
+
+def save_event(data):
+ event_dir = os.path.join(OSUTIL.get_lib_dir(), 'events')
+ if not os.path.exists(event_dir):
+ os.mkdir(event_dir)
+ os.chmod(event_dir,0o700)
+ if len(os.listdir(event_dir)) > 1000:
+ raise EventError("Too many files under: {0}", event_dir)
+
+ filename = os.path.join(event_dir, text(int(time.time()*1000000)))
+ try:
+ with open(filename+".tmp",'wb+') as hfile:
+ hfile.write(data.encode("utf-8"))
+ os.rename(filename+".tmp", filename+".tld")
+ except IOError as e:
+ raise EventError("Failed to write events to file:{0}", e)
+
+def add_event(name, op, is_success, duration=0, version="1.0",
+ message="", evt_type="", is_internal=False):
+ event = prot.TelemetryEvent(1, "69B669B9-4AF8-4C50-BDC4-6006FA76E975")
+ event.parameters.append(prot.TelemetryEventParam('Name', name))
+ event.parameters.append(prot.TelemetryEventParam('Version', version))
+ event.parameters.append(prot.TelemetryEventParam('IsInternal', is_internal))
+ event.parameters.append(prot.TelemetryEventParam('Operation', op))
+ event.parameters.append(prot.TelemetryEventParam('OperationSuccess',
+ is_success))
+ event.parameters.append(prot.TelemetryEventParam('Message', message))
+ event.parameters.append(prot.TelemetryEventParam('Duration', duration))
+ event.parameters.append(prot.TelemetryEventParam('ExtensionType', evt_type))
+
+ data = prot.get_properties(event)
+ try:
+ save_event(json.dumps(data))
+ except EventError as e:
+ logger.error("{0}", e)
+
+def dump_unhandled_err(name):
+ if hasattr(sys, 'last_type') and hasattr(sys, 'last_value') and \
+ hasattr(sys, 'last_traceback'):
+ last_type = getattr(sys, 'last_type')
+ last_value = getattr(sys, 'last_value')
+ last_traceback = getattr(sys, 'last_traceback')
+ error = traceback.format_exception(last_type, last_value,
+ last_traceback)
+ message= "".join(error)
+ logger.error(message)
+ add_event(name, is_success=False, message=message,
+ op=WALAEventOperation.UnhandledError)
+
+def enable_unhandled_err_dump(name):
+ atexit.register(dump_unhandled_err, name)
+