def agent_receive(self, address, worker, typ, payload, timestamp): """ Accepts ppagent data that is forwarded from powerpool and manages adding it to the database and triggering alerts as needed. """ # convert unix timestamp to datetime dt = datetime.datetime.utcfromtimestamp(timestamp) def inject_device_stat(cls, device, value): if value: stat = cls(user=address, worker=worker, device=device, value=value, time=dt) db.session.merge(stat) try: # if they passed a threshold we should update the database object if typ == "thresholds": try: if not payload: # if they didn't list valid email key we want to remove Threshold.query.filter_by(worker=worker, user=address).delete() else: thresh = Threshold( worker=worker, user=address, green_notif=not payload.get('no_green_notif', False), temp_thresh=payload.get('overheat'), hashrate_thresh=payload.get('lowhashrate'), offline_thresh=payload.get('offline'), emails=payload['emails'][:4]) db.session.merge(thresh) except KeyError: # assume they're trying to remove the thresholds... Threshold.query.filter_by(worker=worker, user=address).delete() logger.warn( "Bad payload was sent as Threshold data: {}".format( payload)) db.session.commit() return elif typ == 'status': ret = (db.session.query(Status).filter_by(user=address, worker=worker).update({ "status": json.dumps(payload), "time": dt })) # if the update affected nothing if ret == 0: new = Status(user=address, worker=worker, status=json.dumps(payload), time=dt) db.session.add(new) db.session.commit() return # the two status messages can trigger a threshold condition, so we need # to load the threshold to check thresh = Threshold.query.filter_by(worker=worker, user=address).first() if typ == 'temp': # track the overheated cards overheat_cards = [] temps = [] for i, value in enumerate(payload): inject_device_stat(OneMinuteTemperature, i, value) # report over temperature if thresh and value >= thresh.temp_thresh: overheat_cards.append(str(i)) temps.append(str(value)) if overheat_cards and not thresh.temp_err: s = "s" if len(overheat_cards) else "" thresh.report_condition( "Worker {}, overheat on card{s} {}, temp{s} {}".format( worker, ', '.join(overheat_cards), ', '.join(temps), s=s), 'temp_err', True) elif not overheat_cards and thresh and thresh.temp_err: thresh.report_condition( "Worker {} overheat condition relieved".format(worker), 'temp_err', False) elif typ == 'hashrate': for i, value in enumerate(payload): # multiply by a million to turn megahashes to hashes inject_device_stat(OneMinuteHashrate, i, value * 1000000) # do threshold checking if they have one set if thresh: hr = sum(payload) * 1000 if int(hr) == 0: logger.warn( "Entry with 0 hashrate. Worker {}; User {}".format( worker, address)) else: low_hash = thresh and hr <= thresh.hashrate_thresh if low_hash and not thresh.hashrate_err: thresh.report_condition( "Worker {} low hashrate condition, hashrate {} KH/s" .format(worker, hr), 'hashrate_err', True) elif not low_hash and thresh.hashrate_err: thresh.report_condition( "Worker {} low hashrate condition resolved, hashrate {} KH/s" .format(worker, hr), 'hashrate_err', False) else: logger.warning( "Powerpool sent an unkown agent message of type {}".format( typ)) try: db.session.commit() except sqlalchemy.exc.IntegrityError: db.session.rollback() logger.warn( "Received a duplicate agent msg of typ {}, ignoring...!". format(typ)) except Exception: logger.error("Unhandled exception in update_status", exc_info=True) db.session.rollback()
def test_email(): """ Sends a testing email to the send address """ thresh = Threshold(emails=[current_app.config['email']['send_address']]) thresh.report_condition("Test condition")
def agent_receive(self, address, worker, typ, payload, timestamp): """ Accepts ppagent data that is forwarded from powerpool and manages adding it to the database and triggering alerts as needed. """ # convert unix timestamp to datetime dt = datetime.datetime.utcfromtimestamp(timestamp) def inject_device_stat(cls, device, value): if value: stat = cls(user=address, worker=worker, device=device, value=value, time=dt) db.session.merge(stat) try: # if they passed a threshold we should update the database object if typ == "thresholds": try: if not payload: # if they didn't list valid email key we want to remove Threshold.query.filter_by(worker=worker, user=address).delete() else: thresh = Threshold( worker=worker, user=address, green_notif=not payload.get('no_green_notif', False), temp_thresh=payload.get('overheat'), hashrate_thresh=payload.get('lowhashrate'), offline_thresh=payload.get('offline'), emails=payload['emails'][:4]) db.session.merge(thresh) except KeyError: # assume they're trying to remove the thresholds... Threshold.query.filter_by(worker=worker, user=address).delete() logger.warn("Bad payload was sent as Threshold data: {}" .format(payload)) db.session.commit() return elif typ == 'status': ret = (db.session.query(Status).filter_by(user=address, worker=worker). update({"status": json.dumps(payload), "time": dt})) # if the update affected nothing if ret == 0: new = Status(user=address, worker=worker, status=json.dumps(payload), time=dt) db.session.add(new) db.session.commit() return # the two status messages can trigger a threshold condition, so we need # to load the threshold to check thresh = Threshold.query.filter_by(worker=worker, user=address).first() if typ == 'temp': # track the overheated cards overheat_cards = [] temps = [] for i, value in enumerate(payload): inject_device_stat(OneMinuteTemperature, i, value) # report over temperature if thresh and value >= thresh.temp_thresh: overheat_cards.append(str(i)) temps.append(str(value)) if overheat_cards and not thresh.temp_err: s = "s" if len(overheat_cards) else "" thresh.report_condition( "Worker {}, overheat on card{s} {}, temp{s} {}" .format(worker, ', '.join(overheat_cards), ', '.join(temps), s=s), 'temp_err', True) elif not overheat_cards and thresh and thresh.temp_err: thresh.report_condition( "Worker {} overheat condition relieved".format(worker), 'temp_err', False) elif typ == 'hashrate': for i, value in enumerate(payload): # multiply by a million to turn megahashes to hashes inject_device_stat(OneMinuteHashrate, i, value * 1000000) # do threshold checking if they have one set if thresh: hr = sum(payload) * 1000 if int(hr) == 0: current_app.logger.warn("Entry with 0 hashrate. Worker {}; User {}".format(worker, address)) else: low_hash = thresh and hr <= thresh.hashrate_thresh if low_hash and not thresh.hashrate_err: thresh.report_condition( "Worker {} low hashrate condition, hashrate {} KH/s" .format(worker, hr), 'hashrate_err', True) elif not low_hash and thresh.hashrate_err: thresh.report_condition( "Worker {} low hashrate condition resolved, hashrate {} KH/s" .format(worker, hr), 'hashrate_err', False) else: logger.warning("Powerpool sent an unkown agent message of type {}" .format(typ)) db.session.commit() except Exception: logger.error("Unhandled exception in update_status", exc_info=True) db.session.rollback()