# ipop-project # Copyright 2016, University of Florida # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import datetime import hashlib import threading try: import simplejson as json except ImportError: import json import urllib.request as urllib2 from controller.framework.ControllerModule import ControllerModule class UsageReport(ControllerModule): def __init__(self, cfx_handle, module_config, module_name): super(UsageReport, self).__init__(cfx_handle, module_config, module_name) self._stat_data = {"ready": False, "pending_request": False} self.submit_time = datetime.datetime(2015, 1, 1, 0, 0) self.lck = threading.Lock() def initialize(self): self.register_cbt("Logger", "LOG_INFO", "{0} Loaded".format(self._module_name)) def process_cbt(self, cbt): if cbt.op_type == "Response": if cbt.request.action == "SIG_QUERY_REPORTING_DATA": if not cbt.response.status: self.register_cbt("Logger", "LOG_WARNING", "CBT failed {0}".format(cbt.response.data)) self.free_cbt(cbt) else: self.create_report(cbt) else: parent_cbt = cbt.parent cbt_data = cbt.response.data cbt_status = cbt.response.status self.free_cbt(cbt) if (parent_cbt is not None and parent_cbt.child_count == 1): parent_cbt.set_response(cbt_data, cbt_status) self.complete_cbt(parent_cbt) else: self.req_handler_default(cbt) def timer_method(self): cur_time = datetime.datetime.now() self.lck.acquire() if self._stat_data["ready"]: data = self._stat_data["data"] self._stat_data = {} self._stat_data["ready"] = False self._stat_data["pending_request"] = False self.lck.release() self.submit_report(data) self.submit_time = datetime.datetime.now() elif not self._stat_data["pending_request"] and cur_time > self.submit_time: self._stat_data["pending_request"] = True self.lck.release() self.request_report() def terminate(self): pass def request_report(self): self.register_cbt("Signal", "SIG_QUERY_REPORTING_DATA") def create_report(self, cbt): nid = self.node_id report_data = cbt.response.data for overlay_id in report_data: report_data[overlay_id] = { "xmpp_host": hashlib.sha1(report_data[overlay_id]["xmpp_host"].\ encode("utf-8")).hexdigest(), "xmpp_username": hashlib.sha1(report_data[overlay_id]["xmpp_username"].\ encode("utf-8")).hexdigest(), } stat = { "NodeId": hashlib.sha1(nid.encode("utf-8")).hexdigest(), "Time": str(datetime.datetime.now()), "Model": self._cfx_handle.query_param("Model"), "Version": self._cfx_handle.query_param("IpopVersion") } stat.update(report_data) self.lck.acquire() self._stat_data["data"] = stat self._stat_data["ready"] = True self._stat_data["pending_request"] = False self.lck.release() self.free_cbt(cbt) def submit_report(self, report_data): data = json.dumps(report_data).encode('utf8') self.register_cbt("Logger", "LOG_DEBUG", "Usage report data: {0}".format(data)) url = None try: url = "http://" + self._cm_config["ServerAddress"] + ":" + \ str(self._cm_config["ServerPort"]) + "/api/submit" req = urllib2.Request(url=url, data=data) req.add_header("Content-Type", "application/json") res = urllib2.urlopen(req) if res.getcode() == 200: log = "Usage report successfully submitted to server {0}\n" \ "HTTP response code:{1}, msg:{2}" \ .format(url, res.getcode(), res.read()) self.register_cbt("Logger", "LOG_INFO", log) else: self.register_cbt("Logger", "LOG_WARNING", "Usage report server indicated error " "code: {0}".format(res.getcode())) except (urllib2.HTTPError, urllib2.URLError) as error: log = "Usage report submission failed to server {0}. " \ "Error: {1}".format(url, error) self.register_cbt("Logger", "LOG_WARNING", log)