"""
Database models and connection setup
"""
from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime, Text, ForeignKey, Index
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
from config import Config
Base = declarative_base()
# Database connection
DATABASE_URL = f"postgresql://{Config.DB_USER}:{Config.DB_PASSWORD}@{Config.DB_HOST}:{Config.DB_PORT}/{Config.DB_NAME}"
engine = create_engine(DATABASE_URL, echo=False)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
"""Get database session"""
db = SessionLocal()
try:
yield db
finally:
db.close()
def init_db():
"""Initialize database tables"""
Base.metadata.create_all(bind=engine)
# Database Models
class FileRecord(Base):
"""Track downloaded XML files"""
__tablename__ = "file_records"
id = Column(Integer, primary_key=True, index=True)
filename = Column(String, unique=True, index=True)
downloaded_at = Column(DateTime, default=datetime.utcnow)
processed_at = Column(DateTime, nullable=True)
file_size = Column(Integer)
checksum = Column(String, nullable=True)
measurement_intervals = relationship("MeasurementInterval", back_populates="file_record")
class NetworkElement(Base):
"""Network element information"""
__tablename__ = "network_elements"
id = Column(Integer, primary_key=True, index=True)
ne_name = Column(String, unique=True, index=True)
ne_type = Column(String)
site = Column(String)
region = Column(String)
country = Column(String)
management_ip = Column(String)
measurement_intervals = relationship("MeasurementInterval", back_populates="network_element")
class MeasurementInterval(Base):
"""Measurement interval container"""
__tablename__ = "measurement_intervals"
id = Column(Integer, primary_key=True, index=True)
file_record_id = Column(Integer, ForeignKey("file_records.id"))
network_element_id = Column(Integer, ForeignKey("network_elements.id"))
start_time = Column(DateTime, index=True)
end_time = Column(DateTime, index=True)
file_record = relationship("FileRecord", back_populates="measurement_intervals")
network_element = relationship("NetworkElement", back_populates="measurement_intervals")
interface_counters = relationship("InterfaceCounter", back_populates="interval")
ip_counters = relationship("IPCounter", back_populates="interval")
tcp_counters = relationship("TCPCounter", back_populates="interval")
system_counters = relationship("SystemCounter", back_populates="interval")
bgp_counters = relationship("BGPCounter", back_populates="interval")
__table_args__ = (Index('idx_interval_time', 'start_time', 'end_time'),)
class InterfaceCounter(Base):
"""Interface performance counters"""
__tablename__ = "interface_counters"
id = Column(Integer, primary_key=True, index=True)
interval_id = Column(Integer, ForeignKey("measurement_intervals.id"))
interface_name = Column(String, index=True)
if_index = Column(String)
if_type = Column(String)
counter_name = Column(String, index=True)
value = Column(Float)
unit = Column(String)
interval = relationship("MeasurementInterval", back_populates="interface_counters")
__table_args__ = (Index('idx_interface_interval', 'interval_id', 'interface_name', 'counter_name'),)
class IPCounter(Base):
"""IP layer performance counters"""
__tablename__ = "ip_counters"
id = Column(Integer, primary_key=True, index=True)
interval_id = Column(Integer, ForeignKey("measurement_intervals.id"))
counter_name = Column(String, index=True)
value = Column(Float)
unit = Column(String)
interval = relationship("MeasurementInterval", back_populates="ip_counters")
__table_args__ = (Index('idx_ip_interval', 'interval_id', 'counter_name'),)
class TCPCounter(Base):
"""TCP layer performance counters"""
__tablename__ = "tcp_counters"
id = Column(Integer, primary_key=True, index=True)
interval_id = Column(Integer, ForeignKey("measurement_intervals.id"))
counter_name = Column(String, index=True)
value = Column(Float)
unit = Column(String)
interval = relationship("MeasurementInterval", back_populates="tcp_counters")
__table_args__ = (Index('idx_tcp_interval', 'interval_id', 'counter_name'),)
class SystemCounter(Base):
"""System performance counters"""
__tablename__ = "system_counters"
id = Column(Integer, primary_key=True, index=True)
interval_id = Column(Integer, ForeignKey("measurement_intervals.id"))
counter_name = Column(String, index=True)
value = Column(Float)
unit = Column(String)
interval = relationship("MeasurementInterval", back_populates="system_counters")
__table_args__ = (Index('idx_system_interval', 'interval_id', 'counter_name'),)
class BGPCounter(Base):
"""BGP peer performance counters"""
__tablename__ = "bgp_counters"
id = Column(Integer, primary_key=True, index=True)
interval_id = Column(Integer, ForeignKey("measurement_intervals.id"))
peer_address = Column(String, index=True)
as_number = Column(String)
counter_name = Column(String, index=True)
value = Column(Float)
unit = Column(String)
interval = relationship("MeasurementInterval", back_populates="bgp_counters")
__table_args__ = (Index('idx_bgp_interval', 'interval_id', 'peer_address', 'counter_name'),)
class ThresholdAlert(Base):
"""Threshold alerts from XML files"""
__tablename__ = "threshold_alerts"
id = Column(Integer, primary_key=True, index=True)
file_record_id = Column(Integer, ForeignKey("file_records.id"))
severity = Column(String)
timestamp = Column(DateTime, index=True)
parameter = Column(String, index=True)
value = Column(Float)
threshold = Column(Float)
description = Column(Text)