Beispiel #1
0
 def __init__(self, dmd):
     self.dmd = dmd
     try:
         self.callHome = dmd.callHome
     except AttributeError:
         dmd.callHome = CallHomeData()
         self.callHome = dmd.callHome
     self.chs = CallHomeStatus()
Beispiel #2
0
    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")
Beispiel #3
0
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
Beispiel #4
0
 def __init__(self, dmd):
     self.dmd = dmd
     try:
         self.callHome = dmd.callHome
     except AttributeError:
         dmd.callHome = CallHomeData()
         self.callHome = dmd.callHome
     self.chs = CallHomeStatus()
Beispiel #5
0
    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")
Beispiel #6
0
    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)
Beispiel #7
0
    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)
Beispiel #8
0
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
Beispiel #9
0
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