""" Infrastructure model for hardware and virtual assets. Infrastructure represents servers, network devices, workstations, and other IT assets with detailed configuration and environmental constraints. """ from typing import TYPE_CHECKING, Optional from sqlalchemy import Boolean, CHAR, CheckConstraint, ForeignKey, Index, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from .base import Base, TimestampMixin, UUIDMixin if TYPE_CHECKING: from .database_change import DatabaseChange from .deployment import Deployment from .infrastructure_change import InfrastructureChange class Infrastructure(Base, UUIDMixin, TimestampMixin): """ Infrastructure model representing IT assets. Tracks physical servers, virtual machines, containers, network devices, NAS storage, workstations, and other infrastructure components with detailed configuration and environmental constraints. Attributes: client_id: Reference to the client site_id: Reference to the site this infrastructure is located at asset_type: Type of asset (physical_server, virtual_machine, etc.) hostname: Hostname of the infrastructure ip_address: IP address (IPv4 or IPv6) mac_address: MAC address os: Operating system name os_version: Operating system version role_description: Description of the infrastructure's role parent_host_id: Reference to parent host for VMs/containers status: Current status (active, migration_source, etc.) environmental_notes: Special environmental constraints or notes powershell_version: PowerShell version if applicable shell_type: Shell type (bash, cmd, powershell, sh) package_manager: Package manager (apt, yum, chocolatey, none) has_gui: Whether the system has a GUI limitations: JSON array of limitations notes: Additional notes """ __tablename__ = "infrastructure" # Foreign keys client_id: Mapped[Optional[str]] = mapped_column( CHAR(36), ForeignKey("clients.id", ondelete="CASCADE"), doc="Reference to the client" ) site_id: Mapped[Optional[str]] = mapped_column( CHAR(36), ForeignKey("sites.id", ondelete="SET NULL"), doc="Reference to the site this infrastructure is located at" ) # Asset identification asset_type: Mapped[str] = mapped_column( String(50), nullable=False, doc="Type: physical_server, virtual_machine, container, network_device, nas_storage, workstation, firewall, domain_controller" ) hostname: Mapped[str] = mapped_column( String(255), nullable=False, doc="Hostname of the infrastructure" ) ip_address: Mapped[Optional[str]] = mapped_column( String(45), doc="IP address (IPv4 or IPv6)" ) mac_address: Mapped[Optional[str]] = mapped_column( String(17), doc="MAC address" ) # Operating system os: Mapped[Optional[str]] = mapped_column( String(255), doc="Operating system name (e.g., 'Ubuntu 22.04', 'Windows Server 2022')" ) os_version: Mapped[Optional[str]] = mapped_column( String(100), doc="Operating system version (e.g., '6.22', '2008 R2', '22.04')" ) # Role and hierarchy role_description: Mapped[Optional[str]] = mapped_column( Text, doc="Description of the infrastructure's role" ) parent_host_id: Mapped[Optional[str]] = mapped_column( CHAR(36), ForeignKey("infrastructure.id", ondelete="SET NULL"), doc="Reference to parent host for VMs/containers" ) # Status status: Mapped[str] = mapped_column( String(50), default="active", server_default="active", nullable=False, doc="Status: active, migration_source, migration_destination, decommissioned" ) # Environmental constraints environmental_notes: Mapped[Optional[str]] = mapped_column( Text, doc="Special environmental constraints or notes (e.g., 'Manual WINS install', 'ReadyNAS OS, SMB1 only')" ) powershell_version: Mapped[Optional[str]] = mapped_column( String(20), doc="PowerShell version (e.g., '2.0', '5.1', '7.4')" ) shell_type: Mapped[Optional[str]] = mapped_column( String(50), doc="Shell type: bash, cmd, powershell, sh" ) package_manager: Mapped[Optional[str]] = mapped_column( String(50), doc="Package manager: apt, yum, chocolatey, none" ) has_gui: Mapped[bool] = mapped_column( Boolean, default=True, server_default="1", nullable=False, doc="Whether the system has a GUI" ) limitations: Mapped[Optional[str]] = mapped_column( Text, doc='JSON array of limitations (e.g., ["no_ps7", "smb1_only", "dos_6.22_commands"])' ) # Notes notes: Mapped[Optional[str]] = mapped_column( Text, doc="Additional notes" ) # Relationships deployments: Mapped[list["Deployment"]] = relationship( "Deployment", back_populates="infrastructure", doc="Relationship to Deployment model" ) database_changes: Mapped[list["DatabaseChange"]] = relationship( "DatabaseChange", back_populates="infrastructure", doc="Relationship to DatabaseChange model" ) infrastructure_changes: Mapped[list["InfrastructureChange"]] = relationship( "InfrastructureChange", back_populates="infrastructure", doc="Relationship to InfrastructureChange model" ) # Constraints and indexes __table_args__ = ( CheckConstraint( "asset_type IN ('physical_server', 'virtual_machine', 'container', 'network_device', 'nas_storage', 'workstation', 'firewall', 'domain_controller')", name="ck_infrastructure_asset_type" ), CheckConstraint( "status IN ('active', 'migration_source', 'migration_destination', 'decommissioned')", name="ck_infrastructure_status" ), Index("idx_infrastructure_client", "client_id"), Index("idx_infrastructure_type", "asset_type"), Index("idx_infrastructure_hostname", "hostname"), Index("idx_infrastructure_parent", "parent_host_id"), Index("idx_infrastructure_os", "os"), ) def __repr__(self) -> str: """String representation of the infrastructure.""" return f""