def __init__(self, dmd): self.dmd = dmd try: self.callHome = dmd.callHome except AttributeError: dmd.callHome = CallHomeData() self.callHome = dmd.callHome self.chs = CallHomeStatus()
def run(self): if self.options.status: chs = CallHomeStatus() print 'Status:\t Description:\t Error:\t' for i in chs.status(): print '{0}\t {1}\t {2}'.format(i.get('status'), i.get('description'), i.get('error')) return if self.options.master: log.debug("Connecting...") self.connect() log.debug("Connected") else: self.dmd = None chs = CallHomeStatus() chs.stage(chs.COLLECT_CALLHOME) chd = CallHomeData(self.dmd, self.options.master) data = chd.getData() if self.options.pretty: from pprint import pprint pprint(data) else: sort = False if self.options.jsonIndent: sort = True print( json.dumps(data, indent=self.options.jsonIndent, sort_keys=sort)) chs.stage(chs.COLLECT_CALLHOME, "FINISHED")
def direct_post(dmd): callhome = CallHome(dmd) chs = CallHomeStatus() if not callhome.attempt('directpost'): return payload = callhome.get_payload() if not payload: logger.warning('Error getting or encrypting payload for direct-post') return payload = base64.urlsafe_b64encode(payload) params = urlencode({'enc': payload}) chs.stage(chs.REQUEST_CALLHOME) try: httpreq = urllib2.urlopen(POST_CHECKIN_URL, params, _URL_TIMEOUT) returnPayload = httpreq.read() except Exception as e: chs.stage(chs.REQUEST_CALLHOME, "FAILED", str(e)) logger.warning('Error retrieving data from callhome server %s', e) else: chs.stage(chs.REQUEST_CALLHOME, "FINISHED") callhome.save_return_payload(returnPayload) return
def run(self): if self.options.status: chs = CallHomeStatus() print 'Status:\t Description:\t Error:\t' for i in chs.status(): print '{0}\t {1}\t {2}'.format(i.get('status'), i.get('description'), i.get('error')) return if self.options.master: log.debug("Connecting...") self.connect() log.debug("Connected") else: self.dmd = None chs = CallHomeStatus() chs.stage(chs.COLLECT_CALLHOME) chd = CallHomeData(self.dmd, self.options.master) data = chd.getData() if self.options.pretty: from pprint import pprint pprint(data) else: sort = False if self.options.jsonIndent: sort = True print(json.dumps(data, indent=self.options.jsonIndent, sort_keys=sort)) chs.stage(chs.COLLECT_CALLHOME, "FINISHED")
def run(self): chs = CallHomeStatus() chs.stage(chs.START_CALLHOME) try: now = long(time.time()) self.dmd._p_jar.sync() # Start metrics gather if needed if ((now - self.callhome.lastMetricsGather > GATHER_METRICS_INTERVAL or self.callhome.requestMetricsGather) and not self.gatherProtocol): self.gatherProtocol = GatherMetricsProtocol() self.callhome.requestMetricsGather = True # Update metrics if run complete if self.gatherProtocol and (self.gatherProtocol.data or self.gatherProtocol.failed): chs.stage(chs.GPROTOCOL) if not self.gatherProtocol.failed: self.callhome.metrics = self.gatherProtocol.data try: chs.stage(chs.GPROTOCOL, "FINISHED") chs.stage(chs.UPDATE_REPORT, "FINISHED") chs.updateStat('lastTook', int(time.time()) - chs.getStat('startedAt')) except Exception as e: logger.warning("Callhome cycle status update failed: '%r'", e) self.callhome.lastMetricsGather = now self.callhome.requestMetricsGather = False self.gatherProtocol = None # Callhome directly if needed direct_post(self.dmd) chs.stage(chs.START_CALLHOME, "FINISHED") transaction.commit() except Exception as e: chs.stage(chs.START_CALLHOME, "FAILED", str(e)) logger.warning("Callhome cycle failed: '%r'", e)
def run(self): chs = CallHomeStatus() chs.stage(chs.START_CALLHOME) try: now = long(time.time()) self.dmd._p_jar.sync() # Start metrics gather if needed if ( ( now - self.callhome.lastMetricsGather > GATHER_METRICS_INTERVAL or self.callhome.requestMetricsGather ) and not self.gatherProtocol ): self.gatherProtocol = GatherMetricsProtocol() self.callhome.requestMetricsGather = True # Update metrics if run complete if self.gatherProtocol and (self.gatherProtocol.data or self.gatherProtocol.failed): chs.stage(chs.GPROTOCOL) if not self.gatherProtocol.failed: self.callhome.metrics = self.gatherProtocol.data try: chs.stage(chs.GPROTOCOL, "FINISHED") chs.stage(chs.UPDATE_REPORT, "FINISHED") chs.updateStat('lastTook', int(time.time()) - chs.getStat('startedAt')) except Exception as e: logger.warning("Callhome cycle status update failed: '%r'", e) self.callhome.lastMetricsGather = now self.callhome.requestMetricsGather = False self.gatherProtocol = None # Callhome directly if needed direct_post(self.dmd) chs.stage(chs.START_CALLHOME, "FINISHED") transaction.commit() except Exception as e: chs.stage(chs.START_CALLHOME, "FAILED", str(e)) logger.warning("Callhome cycle failed: '%r'", e)
class CallHome(object): def __init__(self, dmd): self.dmd = dmd try: self.callHome = dmd.callHome except AttributeError: dmd.callHome = CallHomeData() self.callHome = dmd.callHome self.chs = CallHomeStatus() def attempt(self, method): ''' Decide whether or not to attempt a callhome. This is computed from the time elapsed from last successful callhome, or time elapsed from the last attempt via the method passed in with the 'method' param. ''' if (is_callhome_disabled(self.dmd) and not self.callHome.requestCallhome): return False now = long(time.time()) # If we have waited long enough between checkings or attempts (or one # has been requested), and we have metrics to send and are not # currently updating them, then attempt a callhome if ( ( now - self.callHome.lastAttempt[method] > CHECKIN_ATTEMPT_WAIT and now - self.callHome.lastSuccess > CHECKIN_WAIT ) or self.callHome.requestCallhome ): if ( self.callHome.metrics and not self.callHome.requestMetricsGather ): self.callHome.lastAttempt[method] = now self.callHome.requestCallhome = False return True return False def get_payload(self, method='directpost', doEncrypt=True): ''' Retrieve the current callhome payload to send. This is the call that occurs at send/request time (as opposed to the time that the report was generated). ''' payload = {} # product info payload['product'] = self.dmd.getProductName() payload['uuid'] = self.dmd.uuid or "NOT ACTIVATED" payload['symkey'] = self.callHome.symmetricKey metrics = self.callHome.metrics metricsObj = json.loads(metrics) metricsObj['Send Date'] = datetime.utcnow().isoformat() metricsObj['Send Method'] = method payload['metrics'] = json.dumps(metricsObj) payloadString = json.dumps(payload) if doEncrypt: payloadString = encrypt(payloadString, self.callHome.publicKey) return payloadString def save_return_payload(self, returnPayload): ''' Process and save the data returned from the callhome server. This always includes versioning and crypto key changes, and may include other data to be processed by plugins to the IReturnPayloadProcessor interface. ''' try: returnPayload = zlib.decompress(base64.urlsafe_b64decode( returnPayload)) returnPayload = json.loads(returnPayload) except: logger.debug('Error decoding return payload from server') return if all(x in returnPayload for x in ('currentPublicKey', 'revocationList')): # TODO: VERIFY revocation list, and apply newPubkey = returnPayload.get('currentPublicKey') if self.callHome.publicKey != newPubkey: self.callHome.publicKey = newPubkey if 'encrypted' in returnPayload: base64data = base64.urlsafe_b64decode(str(returnPayload.get( 'encrypted'))) data = json.loads(decrypt(base64data, self.callHome.symmetricKey)) if 'compliancereport' in data: data['compliancereport']['pdf'] = base64.urlsafe_b64decode(str( data['compliancereport']['pdf'])) if 'latestVersion' in data: # Save the latest version, and send a # message if new version available self.dmd.lastVersionCheck = long(time.time()) available = Version.parse('Zenoss ' + data['latestVersion']) if (getattr(self.dmd, 'availableVersion', '') != available.short()): self.dmd.availableVersion = available.short() if self.dmd.About.getZenossVersion() < available: try: import socket zep = getFacade('zep') summary = ('A new version of Zenoss (%s)' + 'has been released') % available.short() zep.create(summary, 'Info', socket.getfqdn()) except ZepConnectionError: logger.warning("ZEP not running - can't send " + "new version event") # Go through other data in the return payload, and process for name, utility in getUtilitiesFor(IReturnPayloadProcessor): if name in data: utility.process(self.dmd, data[name]) self.callHome.lastSuccess = long(time.time()) self.chs.updateStat('lastSuccess', long(time.time())) return
class CallHome(object): def __init__(self, dmd): self.dmd = dmd try: self.callHome = dmd.callHome except AttributeError: dmd.callHome = CallHomeData() self.callHome = dmd.callHome self.chs = CallHomeStatus() def attempt(self, method): ''' Decide whether or not to attempt a callhome. This is computed from the time elapsed from last successful callhome, or time elapsed from the last attempt via the method passed in with the 'method' param. ''' if (is_callhome_disabled(self.dmd) and not self.callHome.requestCallhome): return False now = long(time.time()) # If we have waited long enough between checkings or attempts (or one # has been requested), and we have metrics to send and are not # currently updating them, then attempt a callhome if ((now - self.callHome.lastAttempt[method] > CHECKIN_ATTEMPT_WAIT and now - self.callHome.lastSuccess > CHECKIN_WAIT) or self.callHome.requestCallhome): if (self.callHome.metrics and not self.callHome.requestMetricsGather): self.callHome.lastAttempt[method] = now self.callHome.requestCallhome = False return True return False def get_payload(self, method='directpost', doEncrypt=True): ''' Retrieve the current callhome payload to send. This is the call that occurs at send/request time (as opposed to the time that the report was generated). ''' payload = {} # product info payload['product'] = self.dmd.getProductName() payload['uuid'] = self.dmd.uuid or "NOT ACTIVATED" payload['symkey'] = self.callHome.symmetricKey metrics = self.callHome.metrics metricsObj = json.loads(metrics) metricsObj['Send Date'] = datetime.utcnow().isoformat() metricsObj['Send Method'] = method payload['metrics'] = json.dumps(metricsObj) payloadString = json.dumps(payload) if doEncrypt: payloadString = encrypt(payloadString, self.callHome.publicKey) return payloadString def save_return_payload(self, returnPayload): ''' Process and save the data returned from the callhome server. This always includes versioning and crypto key changes, and may include other data to be processed by plugins to the IReturnPayloadProcessor interface. ''' try: returnPayload = zlib.decompress( base64.urlsafe_b64decode(returnPayload)) returnPayload = json.loads(returnPayload) except: logger.debug('Error decoding return payload from server') return if all(x in returnPayload for x in ('currentPublicKey', 'revocationList')): # TODO: VERIFY revocation list, and apply newPubkey = returnPayload.get('currentPublicKey') if self.callHome.publicKey != newPubkey: self.callHome.publicKey = newPubkey if 'encrypted' in returnPayload: base64data = base64.urlsafe_b64decode( str(returnPayload.get('encrypted'))) data = json.loads(decrypt(base64data, self.callHome.symmetricKey)) if 'compliancereport' in data: data['compliancereport']['pdf'] = base64.urlsafe_b64decode( str(data['compliancereport']['pdf'])) if 'latestVersion' in data: # Save the latest version, and send a # message if new version available self.dmd.lastVersionCheck = long(time.time()) available = Version.parse('Zenoss ' + data['latestVersion']) if (getattr(self.dmd, 'availableVersion', '') != available.short()): self.dmd.availableVersion = available.short() if self.dmd.About.getZenossVersion() < available: try: import socket zep = getFacade('zep') summary = ( 'A new version of Zenoss (%s)' + 'has been released') % available.short() zep.create(summary, 'Info', socket.getfqdn()) except ZepConnectionError: logger.warning("ZEP not running - can't send " + "new version event") # Go through other data in the return payload, and process for name, utility in getUtilitiesFor(IReturnPayloadProcessor): if name in data: utility.process(self.dmd, data[name]) self.callHome.lastSuccess = long(time.time()) self.chs.updateStat('lastSuccess', long(time.time())) return