def run(username, password, room, fritzbox): logging.debug("Started at %s", datetime.now().isoformat()) bot = JabberBot(username, password) telnet = Telnet(fritzbox, '1012') while True: # ugly, but seems to be the only way to stay on bot.join_room(room) logging.debug("Loop started at %s", datetime.now().isoformat()) data = telnet.read_until('SIP0;', 300) number = '\n'.join(only_number.findall(data)) if number: logging.debug("Sending a message at %s", datetime.now().isoformat()) bot.send(room, "Call from " + number, message_type='groupchat') else: what = bot.conn.Process(1) if what != '0' and what != None: logging.debug("What is this %s", what) elif what == None: logging.debug("Reconnecting") bot.conn.reconnectAndReauth()
from jabberbot import JabberBot import random import sys import os import time # what is my account username = '******' # what is the password for that account password = '' # what is the account which should receive the messages remotebot = '*****@*****.**' # time between two updates in seconds sleeptime = 60 # we are working via ping - so what should i ping? # default sould be slotmachine (printerserver) pinghost = "10.0.1.10" # command to send to the remote bot if everything is fine cmdfine = "setoffen" # command to send to the remote bot if encountering a problem cmdfail = "setzu" ########### END CONFIG tmp = os.system("ping -c 1 " + pinghost) bot = JabberBot(username, password) if tmp == 0: bot.send(remotebot, cmdfine) else: bot.send(remotebot, cmdfail)
def main(): logger.info("Daemon 'Attractor' started...") if useMySQL: import MySQLdb # Создаем сокет для приема метрик tcps = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Переводим сокет в неблокирующий режим и задаем опции для более быстрого освобождения ресурсов tcps.setblocking(0) tcps.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcps.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0)) clients = [] # список клиентов (входящих соединений) events_raw = '' # сырые данные, принятые при очередном цикле metrics_storage = { } # хранилище метрик, сюда складываются обработанные метрики со счетчиками # Пробуем открыть сокет try: tcps.bind((interface_ip, port)) # Обрабатываем возможную ошибку сокета (сокет уже занят), делаем запись в лог и ноги :): except socket.error as err: logger.error("Socket Error: {}. Exiting...".format(err.args[1])) tcps.close() sys.exit(2) else: # При отсутствии ошибок начинаем прослушивать порт tcps.listen(2) # Пробуем подключиться к Jabber jbot_ok = False # флаг, живо ли соединение с Jabber if useJabber: # jid - JID, jps - password, jcr - chat room, jnn - nickname jbot = JabberBot(jid, jps, jcr, jnn) if jbot.connect(): if jbot.auth(): jbot.joinroom() jbot_ok = True logger.info("Connection to Jabber '{}' established!".format( jid.split("@")[1])) else: logger.error("ERROR (Jabber): Can't log ID '{}'!".format( jid.split("@")[0])) else: logger.error("ERROR (Jabber): Can't connect to '{}'!".format( jid.split("@")[1])) try_mysql = True # флаг, нужно ли пробовать открыть новое соединение с MySQL recog_events = 0 # счетчик распознанных событий (события которые были преобразованы в формат Attractor) triggered_events = 0 # счетчик сработавших условий timer = int(time.time() ) # время начала основного цикла программы (циклы по 5 секунд) timer_last_data = int( time.time()) # время получения последних данных при опросе сокета pause_ratio = 1 # множитель для паузы опроса сокета while True: events = [] # список всех распознанных событий # Каждые 5 секунд проверяем список клиентов и полученные события if int(time.time()) - timer >= 5: timer = int(time.time()) # Убираем из списка неактивных клиентов for client in clients: try: client.getpeername() except: clients.remove(client) if useJabber: # Если подключение к Jabber не живо, то пробуем переподключиться if not jbot.is_alive: jbot_ok = False logger.info( "WARNING: Not connected to Jabber! Trying to reconnect..." ) if jbot.connect(): if jbot.auth(): jbot.joinroom() jbot_ok = True logger.info( "Reconnection to Jabber '{}' established!". format(jid.split("@")[1])) else: logger.error( "ERROR (Jabber): Can't log ID '{}'!".format( jid.split("@")[0])) else: logger.error( "ERROR (Jabber): Can't connect to '{}'!".format( jid.split("@")[1])) if jbot_ok: jbot.proc() jCount = 0 # счетчик сообщений, которые должны быть отправлены в Jabber external_requests_count = 0 # счетчик сообщений, которые должны быть отправлены путем запроса на внешний URL telegram_events_count = 0 # счетчик событий, которые должны быть отправлены в Telegram external_scripts_count = 0 # счетчик событий, которые должны быть отправлены во внешние скрипты # Пробуем принять подключение try: connect, addr = tcps.accept() except: pass else: # Переводим сокет в неблокирующий режим и говорим, чтобы при отключении освобождался # быстрее (no linger) и добавляем в список connect.setblocking(0) connect.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0)) clients.append(connect) # Пробуем получить данные с сокета, перебирая всех клиентов for client in clients: try: data = client.recv(512) # Если данных нет возникнет ошибка, это нормально, ничего не трогаем except: pass else: # Если клиент отключился, то recv вернет пустую строку. Закроем такой сокет. if data == '': client.close() # Складываем вместе данные, оставшиеся с прошлой обработки (могут быть пустыми), вместе с полученными events_raw = events_raw + data timer_last_data = int(time.time()) # Если данные поступают, начинаем опрашивать сокет чаще путем уменьшения интервала ожидания pause_ratio = 0.01 # Если истек интервал ожидания данных и сами данные не пустые, начинаем их обрабатывать if (int(time.time()) - timer_last_data >= nodata_int) & (len(events_raw) > 0): # Возвращаем прежнее значение коэффициента паузы для ожидания данных pause_ratio = 1 # Необработанные данные преобразываются в список. # Если элемент списка удается преобразовать в словарь, значит получено валидное событие. tmp_events = events_raw.split("\n") for ev_item in tmp_events: # Пробуем преобразовать данные в словарь event = graphite2attractor(ev_item) if event: events.append(event) recog_events += 1 else: if ev_item != '': logger.error("WARNING! Unknown data format: %s", ev_item) del tmp_events events_raw = '' # Проверяем, получены ли новые события if recog_events > 0: logger.info( "New events are recieved. Recognized {} entries.".format( recog_events)) recog_events = 0 # Пробуем подключиться к MySQL. Используем таймаут в 1 секунду if useMySQL and try_mysql: try: mysql_conn = MySQLdb.connect(host=mysql_addr, user=mysql_user, passwd=mysql_pass, db=mysql_base, charset=mysql_cset, connect_timeout=1) mysql_conn.autocommit(True) except: logger.error('ERROR (MySQL): Cannot connect to server. :(') else: logger.info( "Connection to MySQL Server '{}' (Write) established". format(mysql_addr)) # Создаем 'курсор'. (Особая MySQLdb-шная магия) mysql_cr = mysql_conn.cursor() finally: try_mysql = False # Определяем словари, содержащие счетчики событий для MySQL и Oracle Apex send_query = {'query': '', 'count': 0, 'total': 0} apex_query = {'query': '', 'count': 0, 'total': 0} # Обработка событий for event in events: if event['metric'] in event_horizon: # Полное имя полученной метрики r_metricname = get_processed_str(MetricNameTemplate, event) # Пробуем получить предыдущее значение метрики # Важно: Использование try..except работает существенно быстрее, # чем предварительный поиск ключа. Именно поэтому здесь так. try: last_val = metrics_storage[r_metricname]['lastval'] except: last_val = '0' test_metric = check_metric_terms( metrics_storage, event, r_metricname, event_horizon[event['metric']]['terms'], last_val) tmp_trig, tmp_skip, tmp_reset, tmp_code = check_metric_counters( metrics_storage, r_metricname, test_metric, event_horizon[event['metric']]['trigger'], event_horizon[event['metric']]['skip'], event_horizon[event['metric']]['reset'], event_horizon[event['metric']]['code']) # Обновляем хранилище метрик, записывая туда временные значения счетчик срабатывания # условий и счетчика пропусков metrics_storage[r_metricname] = { 'lastval': event['value'], 'trigger': tmp_trig, 'skip': tmp_skip, 'reset': tmp_reset } if (tmp_code > 0) & (tmp_code in event_codes): triggered_events += 1 if useJabber and jbot_ok and (event['metric'] in JabberMetricsList): try: jbot.send_msg( get_processed_str(event_codes[tmp_code], event)) except: logger.error( "ERROR (Jabber): Cannot send data to Jabber!" ) jCount += 1 if useTelegram and (event['metric'] in telegram_metrics): send_msg_to_telegram( get_processed_str(event_codes[tmp_code], event)) telegram_events_count += 1 if use_external_urls and ( event['metric'] in external_requests_metrics): make_external_requests( get_processed_str(event_codes[tmp_code], event), event['host']) external_requests_count += 1 if use_external_scripts and ( event['metric'] in external_scripts_metrics): call_external_scripts(event) external_scripts_count += 1 if useMySQL: if send_query['count'] == 0: send_query['query'] = """INSERT INTO {0}.{1} ( {1}.device, {1}.host, {1}.metric, {1}.key, {1}.value, {1}.event_code, {1}.event_text, {1}.datetime) VALUES """.format(mysql_base, mysql_tabl) send_query[ 'query'] += "('{0}','{1}','{2}','{3}','{4}',{5},'{6}','{7}'),".format( event['device'], event['host'], event['metric'], event['key'], event['value'], tmp_code, get_processed_str(event_codes[tmp_code], event), int(time.time())) send_query['count'] += 1 if send_query['count'] >= mysql_chain_len: if post_data_to_mysql( mysql_cr, send_query['query'][:-1]): send_query['total'] += send_query['count'] send_query['count'] = 0 send_query['query'] = '' if useOracleApex: if apex_query['count'] == 0: apex_query[ 'query'] = apex_url + apex_cmd.encode( "hex") apex_query['query'] += ( "SELECT {},{},'{}','{}','{}','{}','{}' FROM dual UNION ALL " .format(int(time.time()), tmp_code, event['key'], event['value'], event['metric'], event['host'], event['device'])).encode("hex") apex_query['count'] += 1 if apex_query['count'] >= apex_chain_len: if post_data_to_oracle_apex( apex_query['query'][:-22]): apex_query['total'] += apex_query['count'] apex_query['count'] = 0 apex_query['query'] = '' # Проверяем, осталось ли что-то в буфере для MySQL. Если да - отправляем. После этого отключаемся от MySQL if useMySQL: if send_query['count'] > 0: if post_data_to_mysql(mysql_cr, send_query['query'][:-1]): send_query['total'] += send_query['count'] try: mysql_conn.close() except: pass finally: try_mysql = True # Проверяем, осталось ли что-то в буфере для Oracle Apex. Если да - отправляем if useOracleApex: if apex_query['count'] > 0: if post_data_to_oracle_apex(apex_query['query'][:-22]): apex_query['total'] += apex_query['count'] # Проверяем, есть ли события, для которых достигнуто необходимое количество срабатываний if triggered_events > 0: logger.info("WARNING: New alerts triggered: {}.".format( triggered_events)) triggered_events = 0 # Пишем в лог сколько записей мы отправили в Jabber, MySQL и Orale Apex logger.info( "Alerts sended to Jabber: {}, to MySQL: {}, to Oracle Apex: {}, to external URLs: {}," " to external scripts: {}, to Telegram: {}".format( jCount, send_query['total'], apex_query['total'], external_requests_count, external_scripts_count, telegram_events_count)) # Пишем в лог о завершении обработки logger.info("All events have been processed.") logger.info("-------") time.sleep(sleep_int * pause_ratio)