Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import re
- import os
- import requests
- import time
- from datetime import datetime, date
- from collections import defaultdict
- import configparser
- import logging
- import schedule
- import threading
- import sys
- # Налаштування логів
- LOG_FILE_PATH = '/opt/olt_monitor/olt_monitor.log'
- LAN_EVENTS_LOG = '/opt/olt_monitor/lan_events.log'
- SENT_MESSAGES_FILE = '/opt/olt_monitor/sent_messages.txt'
- LAST_RESET_FILE = '/opt/olt_monitor/last_log_reset.txt'
- LAST_ACTIVATION_FILE = '/opt/olt_monitor/last_activation.txt'
- # Створення lan_events.log при старті, якщо не існує
- if not os.path.exists(LAN_EVENTS_LOG):
- try:
- with open(LAN_EVENTS_LOG, 'w', encoding='utf-8') as f:
- f.write('')
- logging.info(f"Створено файл {LAN_EVENTS_LOG}")
- except Exception as e:
- logging.error(f"Помилка створення {LAN_EVENTS_LOG}: {e}")
- raise
- # Налаштування логгера для lan_events.log
- lan_logger = logging.getLogger('lan_events')
- lan_handler = logging.FileHandler(LAN_EVENTS_LOG, encoding='utf-8')
- lan_handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(message)s'))
- lan_logger.addHandler(lan_handler)
- lan_logger.setLevel(logging.INFO)
- # Змінна для відстеження часу попереджень
- last_size_warning = {}
- # Налаштування логування в консоль і olt_monitor.log
- logging.basicConfig(
- level=logging.INFO,
- format='%(asctime)s [%(levelname)s] %(message)s',
- handlers=[logging.StreamHandler(), logging.FileHandler(LOG_FILE_PATH, encoding='utf-8')]
- )
- # Завантаження конфігурації
- config = configparser.ConfigParser()
- try:
- config.read('/opt/olt_monitor/config.ini')
- except Exception as e:
- logging.error(f"Помилка читання config.ini: {e}")
- raise
- # Конфігурація
- try:
- TELEGRAM_BOT_TOKEN = config.get('Settings', 'TelegramBotToken')
- TELEGRAM_CHAT_IDS = config.get('Settings', 'TelegramChatIDs').split(',')
- REPORT_TIME = config.get('Settings', 'ReportTime', fallback='06:00')
- LOG_FILE = config.get('Settings', 'LogFile', fallback='/var/log/zte.log')
- LAST_POSITION_FILE = config.get('Settings', 'LastPositionFile', fallback='/opt/olt_monitor/last_position.txt')
- CHECK_INTERVAL = config.getint('Settings', 'CheckInterval', fallback=5)
- except Exception as e:
- logging.error(f"Помилка парсингу конфігурації: {e}")
- raise
- # Завантажуємо відправлені повідомлення
- def load_sent_messages():
- if not os.path.exists(SENT_MESSAGES_FILE):
- return set()
- try:
- with open(SENT_MESSAGES_FILE, 'r', encoding='utf-8') as f:
- return set(line.strip() for line in f if line.strip())
- except Exception as e:
- logging.error(f"Помилка читання файлу {SENT_MESSAGES_FILE}: {e}")
- return set()
- # Зберігаємо нове повідомлення
- def save_sent_message(msg, sent_messages):
- try:
- with open(SENT_MESSAGES_FILE, 'a', encoding='utf-8') as f:
- f.write(msg + '\n')
- sent_messages.add(msg)
- except Exception as e:
- logging.error(f"Помилка збереження повідомлення в {SENT_MESSAGES_FILE}: {e}")
- # Перевірка часу останнього повідомлення про активацію
- def can_send_activation():
- if not os.path.exists(LAST_ACTIVATION_FILE):
- return True
- try:
- with open(LAST_ACTIVATION_FILE, 'r') as f:
- last_time = float(f.read().strip())
- return (time.time() - last_time) > 300 # 5 хвилин
- except Exception as e:
- logging.error(f"Помилка читання {LAST_ACTIVATION_FILE}: {e}")
- return True
- # Зберігаємо час активації
- def save_activation_time():
- try:
- with open(LAST_ACTIVATION_FILE, 'w') as f:
- f.write(str(time.time()))
- except Exception as e:
- logging.error(f"Помилка збереження {LAST_ACTIVATION_FILE}: {e}")
- # Відправка повідомлення в Telegram
- def send_telegram(msg, sent_messages):
- if msg in sent_messages:
- logging.warning(f"Повідомлення вже відправлено, пропущено: {msg}")
- return
- url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
- for chat_id in TELEGRAM_CHAT_IDS:
- try:
- response = requests.post(url, data={"chat_id": chat_id.strip(), "text": msg}, timeout=10)
- response.raise_for_status()
- logging.info(f"Повідомлення успішно відправлено в Telegram (chat_id: {chat_id}): {msg}")
- save_sent_message(msg, sent_messages)
- except requests.RequestException as e:
- error_msg = f"Помилка відправки в Telegram для chat_id {chat_id}: {e}, response: {response.text if 'response' in locals() else 'немає відповіді'}"
- logging.error(error_msg)
- critical_msg = f"⚠️ Критична помилка в olt_monitor.py:\n{error_msg}"
- if critical_msg not in sent_messages:
- try:
- for critical_chat_id in TELEGRAM_CHAT_IDS:
- requests.post(url, data={"chat_id": critical_chat_id.strip(), "text": critical_msg}, timeout=10)
- save_sent_message(critical_msg, sent_messages)
- except Exception as critical_e:
- logging.error(f"Не вдалося відправити критичну помилку в Telegram: {critical_e}")
- # Відправка звіту про події LAN у Telegram (з очищенням lan_events.log)
- def send_lan_summary_to_telegram(sent_messages):
- logging.info("Початок створення звіту про події LAN")
- summary = defaultdict(lambda: {'los': 0, 'restore': 0})
- today = str(date.today())
- try:
- if not os.path.exists(LAN_EVENTS_LOG):
- logging.info(f"Файл {LAN_EVENTS_LOG} не існує")
- else:
- with open(LAN_EVENTS_LOG, 'r', encoding='utf-8') as f:
- lines_processed = 0
- current_entry = []
- for line in f:
- line = line.strip()
- if not line:
- continue
- # Начало новой записи определяется по временной метке (YYYY-MM-DD HH:MM:SS, с опциональными миллисекундами)
- if re.match(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:,\d+)?", line):
- if current_entry: # Обрабатываем предыдущую запись
- lines_processed += 1
- entry_text = '\n'.join(current_entry)
- logging.debug(f"Обробка запису у {LAN_EVENTS_LOG}: {entry_text}")
- # Извлекаем порт, OLT и номер ONU
- port_match = re.search(r"Порт: (gpon-onu_\d+/\d+/\d+(?::\d+)?)", entry_text)
- olt_match = re.search(r"OLT: (\S+) \((\d+\.\d+\.\d+\.\d+)\)", entry_text)
- onu_match = re.search(r"ONU №(\d+)", entry_text)
- if port_match and olt_match and onu_match:
- port = port_match.group(1)
- olt_name = olt_match.group(1)
- olt_ip = olt_match.group(2)
- onu_number = onu_match.group(1)
- key = (port, olt_name, olt_ip, onu_number)
- if "LAN LOS знайдено" in entry_text:
- summary[key]['los'] += 1
- logging.debug(f"Знайдено LAN LOS для {key} у {LAN_EVENTS_LOG}")
- elif "LAN LOS Restore знайдено" in entry_text:
- summary[key]['restore'] += 1
- logging.debug(f"Знайдено LAN LOS Restore для {key} у {LAN_EVENTS_LOG}")
- else:
- logging.debug(f"Запис не відповідає формату port/olt/onu: {entry_text}")
- current_entry = []
- current_entry.append(line)
- else:
- current_entry.append(line)
- # Обработка последней записи
- if current_entry:
- lines_processed += 1
- entry_text = '\n'.join(current_entry)
- logging.debug(f"Обробка останнього запису у {LAN_EVENTS_LOG}: {entry_text}")
- port_match = re.search(r"Порт: (gpon-onu_\d+/\d+/\d+(?::\d+)?)", entry_text)
- olt_match = re.search(r"OLT: (\S+) \((\d+\.\d+\.\d+\.\d+)\)", entry_text)
- onu_match = re.search(r"ONU №(\d+)", entry_text)
- if port_match and olt_match and onu_match:
- port = port_match.group(1)
- olt_name = olt_match.group(1)
- olt_ip = olt_match.group(2)
- onu_number = onu_match.group(1)
- key = (port, olt_name, olt_ip, onu_number)
- if "LAN LOS знайдено" in entry_text:
- summary[key]['los'] += 1
- logging.debug(f"Знайдено LAN LOS для {key} у {LAN_EVENTS_LOG}")
- elif "LAN LOS Restore знайдено" in entry_text:
- summary[key]['restore'] += 1
- logging.debug(f"Знайдено LAN LOS Restore для {key} у {LAN_EVENTS_LOG}")
- else:
- logging.debug(f"Останній запис не відповідає формату: {entry_text}")
- logging.info(f"Оброблено {lines_processed} записів у {LAN_EVENTS_LOG}")
- # Формирование отчета
- if summary:
- msg = f"📊 Звіт подій LAN за {today}:\n\n"
- for (port, olt_name, olt_ip, onu_number), counts in sorted(summary.items()):
- total = counts['los'] + counts['restore']
- msg += (
- f"🔢 ONU №{onu_number}\n"
- f"📍 Порт: {port}\n"
- f"🖥 OLT: {olt_name} ({olt_ip})\n"
- f"🔴 Втрата LAN: {counts['los']}\n"
- f"🟢 LAN відновлено: {counts['restore']}\n"
- f"🔢 Загалом: {total}\n\n"
- )
- else:
- msg = f"📊 Звіт подій LAN за {today}:\n\n⚠️ Подій LAN LOS або Restore не знайдено"
- send_telegram(msg.strip(), sent_messages)
- logging.info("Звіт про події LAN відправлено в Telegram")
- # Очищаем lan_events.log после отправки
- try:
- with open(LAN_EVENTS_LOG, 'w', encoding='utf-8') as f:
- f.write('')
- logging.info(f"Файл {LAN_EVENTS_LOG} очищено після відправки звіту")
- except Exception as e:
- logging.error(f"Помилка очищення {LAN_EVENTS_LOG}: {e}")
- except Exception as e:
- logging.error(f"Помилка створення звіту LAN: {e}")
- # Ручна перевірка звіту без очищення lan_events.log
- def manual_lan_summary():
- sent_messages = load_sent_messages()
- logging.info("Початок ручної перевірки звіту про події LAN")
- summary = defaultdict(lambda: {'los': 0, 'restore': 0})
- today = str(date.today())
- try:
- if not os.path.exists(LAN_EVENTS_LOG):
- logging.info(f"Файл {LAN_EVENTS_LOG} не існує")
- else:
- with open(LAN_EVENTS_LOG, 'r', encoding='utf-8') as f:
- lines_processed = 0
- current_entry = []
- for line in f:
- line = line.strip()
- if not line:
- continue
- # Начало новой записи определяется по временной метке
- if re.match(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:,\d+)?", line):
- if current_entry: # Обрабатываем предыдущую запись
- lines_processed += 1
- entry_text = '\n'.join(current_entry)
- logging.debug(f"Обробка запису у {LAN_EVENTS_LOG}: {entry_text}")
- port_match = re.search(r"Порт: (gpon-onu_\d+/\d+/\d+(?::\d+)?)", entry_text)
- olt_match = re.search(r"OLT: (\S+) \((\d+\.\d+\.\d+\.\d+)\)", entry_text)
- onu_match = re.search(r"ONU №(\d+)", entry_text)
- if port_match and olt_match and onu_match:
- port = port_match.group(1)
- olt_name = olt_match.group(1)
- olt_ip = olt_match.group(2)
- onu_number = onu_match.group(1)
- key = (port, olt_name, olt_ip, onu_number)
- if "LAN LOS знайдено" in entry_text:
- summary[key]['los'] += 1
- logging.debug(f"Знайдено LAN LOS для {key} у {LAN_EVENTS_LOG}")
- elif "LAN LOS Restore знайдено" in entry_text:
- summary[key]['restore'] += 1
- logging.debug(f"Знайдено LAN LOS Restore для {key} у {LAN_EVENTS_LOG}")
- else:
- logging.debug(f"Запис не відповідає формату port/olt/onu: {entry_text}")
- current_entry = []
- current_entry.append(line)
- else:
- current_entry.append(line)
- # Обработка последней записи
- if current_entry:
- lines_processed += 1
- entry_text = '\n'.join(current_entry)
- logging.debug(f"Обробка останнього запису у {LAN_EVENTS_LOG}: {entry_text}")
- port_match = re.search(r"Порт: (gpon-onu_\d+/\d+/\d+(?::\d+)?)", entry_text)
- olt_match = re.search(r"OLT: (\S+) \((\d+\.\d+\.\d+\.\d+)\)", entry_text)
- onu_match = re.search(r"ONU №(\d+)", entry_text)
- if port_match and olt_match and onu_match:
- port = port_match.group(1)
- olt_name = olt_match.group(1)
- olt_ip = olt_match.group(2)
- onu_number = onu_match.group(1)
- key = (port, olt_name, olt_ip, onu_number)
- if "LAN LOS знайдено" in entry_text:
- summary[key]['los'] += 1
- logging.debug(f"Знайдено LAN LOS для {key} у {LAN_EVENTS_LOG}")
- elif "LAN LOS Restore знайдено" in entry_text:
- summary[key]['restore'] += 1
- logging.debug(f"Знайдено LAN LOS Restore для {key} у {LAN_EVENTS_LOG}")
- else:
- logging.debug(f"Останній запис не відповідає формату: {entry_text}")
- logging.info(f"Оброблено {lines_processed} записів у {LAN_EVENTS_LOG}")
- # Формирование отчета
- if summary:
- msg = f"📊 Ручний звіт подій LAN за {today}:\n\n"
- for (port, olt_name, olt_ip, onu_number), counts in sorted(summary.items()):
- total = counts['los'] + counts['restore']
- msg += (
- f"🔢 ONU №{onu_number}\n"
- f"📍 Порт: {port}\n"
- f"🖥 OLT: {olt_name} ({olt_ip})\n"
- f"🔴 Втрата LAN: {counts['los']}\n"
- f"🟢 LAN відновлено: {counts['restore']}\n"
- f"🔢 Загалом: {total}\n\n"
- )
- else:
- msg = f"📊 Ручний звіт подій LAN за {today}:\n\n⚠️ Подій LAN LOS або Restore не знайдено"
- send_telegram(msg.strip(), sent_messages)
- logging.info("Ручний звіт про події LAN відправлено в Telegram")
- except Exception as e:
- logging.error(f"Помилка створення ручного звіту LAN: {e}")
- # Налаштування логування та перезапису файлів
- def setup_logging_and_messages():
- try:
- logging.info("Початок налаштування логування")
- last_reset_date = None
- if os.path.exists(LAST_RESET_FILE):
- with open(LAST_RESET_FILE, 'r') as f:
- last_reset_date = f.read().strip()
- logging.info(f"Прочитано дату останнього перезапису: {last_reset_date}")
- else:
- logging.info(f"Файл {LAST_RESET_FILE} не існує, буде створено")
- today = str(date.today())
- logging.info(f"Поточна дата: {today}")
- # Перевірка розміру логу
- log_size_mb = os.path.getsize(LOG_FILE_PATH) / (1024 * 1024) if os.path.exists(LOG_FILE_PATH) else 0
- logging.info("Розмір логу: " + str(round(log_size_mb, 2)) + " МБ")
- if last_reset_date != today:
- sent_messages = load_sent_messages()
- try:
- logging.basicConfig(
- filename=LOG_FILE_PATH,
- level=logging.INFO,
- format='%(asctime)s [%(levelname)s] %(message)s',
- filemode='w',
- force=True
- )
- logging.info(f"Лог перезаписано для нової доби (size={log_size_mb:.2f} МБ)")
- with open(SENT_MESSAGES_FILE, 'w', encoding='utf-8') as f:
- f.write('')
- logging.info("Файл sent_messages.txt перезаписано для нової доби")
- with open(LAST_RESET_FILE, 'w') as f:
- f.write(today)
- logging.info(f"Оновлено {LAST_RESET_FILE} з датою {today}")
- except Exception as e:
- logging.error(f"Помилка при перезаписі файлів: {e}")
- raise
- else:
- logging.basicConfig(
- filename=LOG_FILE_PATH,
- level=logging.INFO,
- format='%(asctime)s [%(levelname)s] %(message)s',
- filemode='a',
- force=True
- )
- logging.info("Дата не змінилася, використовується режим додавання")
- except Exception as e:
- logging.error(f"Критична помилка налаштування: {e}")
- print(f"Критична помилка налаштування: {e}")
- raise
- # Перевірка розміру файлів
- def check_file_size(file_path, file_name, max_size_mb=10):
- try:
- if os.path.exists(file_path):
- size_mb = os.path.getsize(file_path) / (1024 * 1024)
- if size_mb > max_size_mb:
- current_time = time.time()
- last_warning_time = last_size_warning.get(file_name, 0)
- if current_time - last_warning_time > 600:
- logging.warning(f"Розмір {file_name} перевищує {max_size_mb} МБ: {size_mb:.2f} МБ")
- last_size_warning[file_name] = current_time
- except Exception as e:
- logging.error(f"Помилка перевірки розміру {file_name}: {e}")
- # Глобальні змінні
- current_interface = None
- current_olt_name = None
- current_olt_ip = None
- current_description = None
- onu_add_buffer = defaultdict(dict)
- # Завантажуємо останню позицію
- def load_last_position():
- if not os.path.exists(LAST_POSITION_FILE):
- return 0, os.stat(LOG_FILE).st_ino if os.path.exists(LOG_FILE) else 0
- try:
- with open(LAST_POSITION_FILE, 'r') as f:
- pos = f.read().strip()
- if pos == '':
- return 0, os.stat(LOG_FILE).st_ino
- return int(pos), os.stat(LOG_FILE).st_ino
- except Exception as e:
- logging.error(f"Помилка читання позиції з {LAST_POSITION_FILE}: {e}")
- return 0, os.stat(LOG_FILE).st_ino if os.path.exists(LOG_FILE) else 0
- # Зберігаємо останню позицію
- def save_last_position(position):
- try:
- with open(LAST_POSITION_FILE, 'w') as f:
- f.write(str(position))
- except Exception as e:
- logging.error(f"Помилка збереження позиції в {LAST_POSITION_FILE}: {e}")
- # Парсинг логу
- def parse_log(file_obj, start_pos, sent_messages):
- global current_interface, current_olt_name, current_olt_ip, current_description
- try:
- file_obj.seek(start_pos)
- file_size = os.path.getsize(LOG_FILE)
- if start_pos > file_size:
- logging.warning(f"start_pos ({start_pos}) більше file_size ({file_size}), скидаємо на 0")
- start_pos = 0
- file_obj.seek(0)
- lines = file_obj.readlines()
- end_pos = file_obj.tell()
- except Exception as e:
- logging.error(f"Помилка читання файлу логу: {e}")
- return start_pos
- for line in lines:
- line = line.strip().replace('#012', '').replace('#015', '')
- if not line:
- continue
- # Витягуємо ім'я та IP OLT
- m_olt = re.search(r"\[(\S+) (\d+\.\d+\.\d+\.\d+)\]", line)
- if m_olt:
- current_olt_name = m_olt.group(1)
- current_olt_ip = m_olt.group(2)
- # Витягуємо час
- time_match = re.match(r"^\w+\s+\d+\s+(\d{2}:\d{2}:\d{2})", line)
- time_str = time_match.group(1) if time_match else datetime.now().strftime("%H:%M:%S")
- try:
- event_time = datetime.strptime(time_str, "%H:%M:%S")
- event_time = event_time.replace(year=datetime.now().year, month=datetime.now().month, day=datetime.now().day)
- except ValueError as e:
- logging.error(f"Помилка формату часу {time_str}: {e}")
- continue
- # Перевіряємо OLT перед обробкою подій
- if not current_olt_name or not current_olt_ip:
- logging.warning(f"Пропущено подію через відсутність OLT: {line}")
- continue
- # Витягуємо інтерфейс
- m_intf = re.search(r"(?:interface\s+)(gpon-olt_\d+/\d+/\d+|gpon-onu_\d+/\d+/\d+:\d+)", line, re.IGNORECASE)
- if m_intf:
- current_interface = m_intf.group(1)
- continue
- # Витягуємо description
- m_desc = re.search(r"description\s+(\S+)", line, re.IGNORECASE)
- if m_desc:
- current_description = m_desc.group(1)
- for key, data in list(onu_add_buffer.items()):
- if key[2] == current_interface or key[2].replace("gpon-olt_", "gpon-onu_") + f":{key[3]}" == current_interface:
- data['description'] = current_description
- desc_str = f"\n🏷 Опис: {data['description']}" if data['description'] else ""
- msg = (
- f"✅ ONU додано\n\n"
- f"🕒 Час: {data['time_str']}\n"
- f"🔢 ONU №{data['onu_number']}\n"
- f"📍 Порт: {data['onu_iface']}{desc_str}\n"
- f"🖥 OLT: {key[0]} ({key[1]})"
- )
- send_telegram(msg, sent_messages)
- del onu_add_buffer[key]
- continue
- # LAN LOS Alarm
- m_lan_los = re.search(r"(?:GponRm notify:.*)?<gpon-onu_\d+/\d+/\d+:\d+>\s*SubType:\d+\s*Pos:\d+\s*ONU Uni lan los\. alarm", line, re.IGNORECASE)
- if m_lan_los:
- m_iface_num = re.search(r"<(gpon-onu_\d+/\d+/\d+):(\d+)>", line)
- if m_iface_num:
- onu_iface = m_iface_num.group(1)
- onu_num = m_iface_num.group(2)
- desc_str = f"\n🏷 Опис: {current_description}" if current_description and current_interface == onu_iface else ""
- msg = (
- f"🔴 Втрата LAN-з'єднання\n\n"
- f"🕒 Час: {time_str}\n"
- f"🔢 ONU №{onu_num}\n"
- f"📍 Порт: {onu_iface}{desc_str}\n"
- f"🖥 OLT: {current_olt_name} ({current_olt_ip})"
- )
- lan_logger.warning(f"LAN LOS знайдено: {msg}") # Записываем только в lan_events.log
- current_description = None
- continue
- # LAN LOS Restore
- m_lan_restore = re.search(r"(?:GponRm notify:.*)?<gpon-onu_\d+/\d+/\d+:\d+>\s*SubType:\d+\s*Pos:\d+\s*ONU Uni lan los\. restore", line, re.IGNORECASE)
- if m_lan_restore:
- m_iface_num = re.search(r"<(gpon-onu_\d+/\d+/\d+):(\d+)>", line)
- if m_iface_num:
- onu_iface = m_iface_num.group(1)
- onu_num = m_iface_num.group(2)
- desc_str = f"\n🏷 Опис: {current_description}" if current_description and current_interface == onu_iface else ""
- msg = (
- f"🟢 LAN-з'єднання відновлено\n\n"
- f"🕒 Час: {time_str}\n"
- f"🔢 ONU №{onu_num}\n"
- f"📍 Порт: {onu_iface}{desc_str}\n"
- f"🖥 OLT: {current_olt_name} ({current_olt_ip})"
- )
- lan_logger.warning(f"LAN LOS Restore знайдено: {msg}") # Записываем только в lan_events.log
- current_description = None
- continue
- # Видалення ONU
- m_no_onu = re.search(r"\b(?:no\s+onu|ont delete)\s+(\d+)(?:\s+\d+)?|ont delete\s+(\d+/\d+/\d+)\s+(\d+)", line, re.IGNORECASE)
- if m_no_onu:
- onu_iface = m_no_onu.group(2) or current_interface or "невідомий"
- onu_number = m_no_onu.group(1) or m_no_onu.group(3)
- desc_str = f"\n🏷 Опис: {current_description}" if current_description and current_interface == onu_iface else ""
- msg = (
- f"❌ ONU видалено\n\n"
- f"🕒 Час: {time_str}\n"
- f"🔢 ONU №{onu_number}\n"
- f"📍 Порт: {onu_iface}{desc_str}\n"
- f"🖥 OLT: {current_olt_name} ({current_olt_ip})"
- )
- send_telegram(msg, sent_messages)
- current_description = None
- key = (current_olt_name, current_olt_ip, onu_iface, onu_number)
- if key in onu_add_buffer:
- del onu_add_buffer[key]
- continue
- # Додавання ONU
- m_add_onu = re.search(r"\b(?:onu\s+add|ont add)\s+(\d+)\s+(\d+)|ont add\s+(\d+/\d+/\d+)\s+(\d+)|onu\s+(\d+)\s+type\s+\S+\s+sn\s+\S+", line, re.IGNORECASE)
- if m_add_onu:
- onu_iface = m_add_onu.group(1) or m_add_onu.group(3) or current_interface or "невідомий"
- onu_number = m_add_onu.group(2) or m_add_onu.group(4) or m_add_onu.group(5)
- key = (current_olt_name, current_olt_ip, onu_iface, onu_number)
- onu_add_buffer[key] = {
- 'time_str': time_str,
- 'onu_iface': onu_iface,
- 'onu_number': onu_number,
- 'description': current_description if current_interface == onu_iface else None,
- 'timestamp': datetime.now()
- }
- current_description = None
- continue
- # Обробка відкладених подій ONU
- current_time = datetime.now()
- for key, data in list(onu_add_buffer.items()):
- if (current_time - data['timestamp']).seconds >= 5:
- desc_str = f"\n🏷 Опис: {data['description']}" if data['description'] else ""
- msg = (
- f"✅ ONU додано\n\n"
- f"🕒 Час: {data['time_str']}\n"
- f"🔢 ONU №{data['onu_number']}\n"
- f"📍 Порт: {data['onu_iface']}{desc_str}\n"
- f"🖥 OLT: {key[0]} ({key[1]})"
- )
- send_telegram(msg, sent_messages)
- del onu_add_buffer[key]
- return end_pos
- # Моніторинг логу
- def monitor_log():
- sent_messages = load_sent_messages()
- if can_send_activation():
- test_msg = f"🔔 Моніторинг OLT активовано\n\n🕒 Час: {datetime.now().strftime('%H:%M:%S')}"
- send_telegram(test_msg, sent_messages)
- save_activation_time()
- last_pos, last_inode = load_last_position()
- while True:
- try:
- check_file_size(LOG_FILE_PATH, "olt_monitor.log", max_size_mb=10)
- check_file_size(SENT_MESSAGES_FILE, "sent_messages.txt", max_size_mb=10)
- check_file_size(LAN_EVENTS_LOG, "lan_events.log", max_size_mb=10)
- if not os.path.exists(LOG_FILE):
- logging.error(f"Файл логу {LOG_FILE} не існує. Очікування 60 секунд")
- time.sleep(60)
- continue
- current_inode = os.stat(LOG_FILE).st_ino
- if current_inode != last_inode:
- logging.info(f"Виявлено новий inode для {LOG_FILE}, скидання позиції")
- last_pos, last_inode = 0, current_inode
- with open(LOG_FILE, "r", encoding="utf-8") as f:
- new_pos = parse_log(f, last_pos, sent_messages)
- if new_pos != last_pos:
- save_last_position(new_pos)
- last_pos = new_pos
- time.sleep(CHECK_INTERVAL)
- except Exception as e:
- logging.error(f"Критична помилка при обробці логу: {e}")
- time.sleep(60)
- # Планувальник для щоденного звіту
- def run_scheduler():
- sent_messages = load_sent_messages()
- schedule.every().day.at(REPORT_TIME).do(send_lan_summary_to_telegram, sent_messages)
- while True:
- schedule.run_pending()
- time.sleep(60)
- if __name__ == "__main__":
- try:
- setup_logging_and_messages()
- # Перевіряємо аргумент командного рядка
- if len(sys.argv) > 1 and sys.argv[1] == "--manual-report":
- manual_lan_summary()
- else:
- # Запускаємо планувальник у окремому потоці
- scheduler_thread = threading.Thread(target=run_scheduler, daemon=True)
- scheduler_thread.start()
- monitor_log()
- except Exception as e:
- logging.error(f"Помилка запуску програми: {e}")
- raise
Advertisement
Comments
-
- cat config.ini
- [Settings]
- TelegramBotToken = 1233445657786867867868658
- TelegramChatIDs = id1,id2,id3
- SentMessagesFile = /opt/olt_monitor/sent_messages.txt
- LogFile = /var/log/zte.log
- LastPositionFile = /opt/olt_monitor/last_position.txt
- CheckInterval = 5
- ReportTime = 08:00
Add Comment
Please, Sign In to add comment
Advertisement