Add SEED_DEMO_DATA environment variable to control demo data population, enhance setup wizard with welcome screen and theme toggle, add smooth animations for wizard transitions, improve dashboard endpoint to return structured objects for last_syncs and faulty_nodes instead of raw models, implement comprehensive error handling in cluster sync with failed status tracking and audit logging, fix Proxmox provider
199 lines
7.2 KiB
Python
199 lines
7.2 KiB
Python
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.config import get_settings
|
|
from app.core.security import hash_password
|
|
from app.models.domain import (
|
|
AuditLog,
|
|
Cluster,
|
|
IpAddress,
|
|
Network,
|
|
Node,
|
|
Policy,
|
|
Project,
|
|
Role,
|
|
SecurityGroup,
|
|
ServiceCatalogItem,
|
|
SystemSetting,
|
|
Subnet,
|
|
Tenant,
|
|
User,
|
|
Workload,
|
|
)
|
|
|
|
|
|
SERVICES = [
|
|
("SSH", "tcp", "22"),
|
|
("HTTP", "tcp", "80"),
|
|
("HTTPS", "tcp", "443"),
|
|
("DNS", "tcp/udp", "53"),
|
|
("LDAP", "tcp", "389"),
|
|
("LDAPS", "tcp", "636"),
|
|
("RDP", "tcp", "3389"),
|
|
("PostgreSQL", "tcp", "5432"),
|
|
("MySQL/MariaDB", "tcp", "3306"),
|
|
("MSSQL", "tcp", "1433"),
|
|
("Redis", "tcp", "6379"),
|
|
("SMB", "tcp", "445"),
|
|
("SMTP", "tcp", "25"),
|
|
("SMTPS", "tcp", "465"),
|
|
("IMAPS", "tcp", "993"),
|
|
("POP3S", "tcp", "995"),
|
|
("Proxmox API", "tcp", "8006"),
|
|
("Proxmox SPICE", "tcp", "3128"),
|
|
]
|
|
|
|
|
|
def seed_demo_data(db: Session) -> None:
|
|
settings = get_settings()
|
|
if not db.get(SystemSetting, "setup"):
|
|
db.add(SystemSetting(key="setup", value={"complete": False}))
|
|
|
|
roles = {
|
|
"Super Admin": ["*"],
|
|
"Network Admin": ["networks:*", "ipam:*", "clusters:read"],
|
|
"Security Admin": ["policies:*", "firewall:*", "security-groups:*"],
|
|
"Tenant Admin": ["tenants:read", "projects:*"],
|
|
"Auditor": ["audit:read", "clusters:read", "policies:read"],
|
|
"Read Only User": ["*:read"],
|
|
}
|
|
for name, permissions in roles.items():
|
|
if not db.scalar(select(Role).where(Role.name == name)):
|
|
db.add(Role(name=name, permissions=permissions))
|
|
|
|
for name, proto, ports in SERVICES:
|
|
if not db.scalar(select(ServiceCatalogItem).where(ServiceCatalogItem.name == name)):
|
|
db.add(ServiceCatalogItem(name=name, protocol=proto, ports=ports, editable=True))
|
|
|
|
db.commit()
|
|
|
|
if not settings.seed_demo_data:
|
|
return
|
|
|
|
if db.scalar(select(User).where(User.email == "admin@nexafabric.local")):
|
|
return
|
|
|
|
super_admin = db.scalar(select(Role).where(Role.name == "Super Admin"))
|
|
user = User(
|
|
email="admin@nexafabric.local",
|
|
display_name="NexaFabric Administrator",
|
|
password_hash=hash_password(settings.demo_admin_password),
|
|
roles=[super_admin],
|
|
)
|
|
db.add(user)
|
|
|
|
tenants = [
|
|
Tenant(name="Platform", description="Shared infrastructure and platform services"),
|
|
Tenant(name="Finance", description="Finance applications"),
|
|
Tenant(name="Research", description="Lab and engineering workloads"),
|
|
]
|
|
db.add_all(tenants)
|
|
db.flush()
|
|
|
|
projects = [
|
|
Project(tenant_id=tenants[0].id, name="Core Services", description="DNS, auth, monitoring"),
|
|
Project(tenant_id=tenants[1].id, name="ERP", description="Finance ERP workloads"),
|
|
Project(tenant_id=tenants[2].id, name="Lab", description="Research lab systems"),
|
|
]
|
|
db.add_all(projects)
|
|
db.flush()
|
|
|
|
cluster = Cluster(
|
|
name="Demo Proxmox Cluster",
|
|
api_url="https://pve-demo.local:8006",
|
|
token_ref="demo-token-reference",
|
|
last_sync_status="success",
|
|
)
|
|
db.add(cluster)
|
|
db.flush()
|
|
|
|
nodes = [
|
|
Node(cluster_id=cluster.id, name="pve-01", status="online", cpu_count=32, memory_mb=131072),
|
|
Node(cluster_id=cluster.id, name="pve-02", status="online", cpu_count=32, memory_mb=131072),
|
|
Node(cluster_id=cluster.id, name="pve-03", status="warning", cpu_count=24, memory_mb=98304),
|
|
]
|
|
db.add_all(nodes)
|
|
db.flush()
|
|
|
|
networks = [
|
|
Network(cluster_id=cluster.id, project_id=projects[0].id, name="mgmt", kind="bridge", vlan_id=10, gateway="10.10.10.1", dns=["10.10.10.10"], tags=["management"], description="Management bridge"),
|
|
Network(cluster_id=cluster.id, project_id=projects[0].id, name="services", kind="vlan", vlan_id=20, gateway="10.20.0.1", dns=["10.20.0.10"], tags=["shared"], description="Shared services"),
|
|
Network(cluster_id=cluster.id, project_id=projects[1].id, name="finance-app", kind="vxlan", vlan_id=120, gateway="10.120.0.1", dns=["10.20.0.10"], tags=["finance"], description="Finance application tier"),
|
|
Network(cluster_id=cluster.id, project_id=projects[2].id, name="research-lab", kind="vnet", vlan_id=220, gateway="10.220.0.1", dns=["10.20.0.10"], tags=["lab"], description="Research tenant network"),
|
|
]
|
|
db.add_all(networks)
|
|
db.flush()
|
|
|
|
subnets = [
|
|
Subnet(network_id=networks[0].id, cidr="10.10.10.0/24", gateway="10.10.10.1", dns=["10.10.10.10"]),
|
|
Subnet(network_id=networks[1].id, cidr="10.20.0.0/24", gateway="10.20.0.1", dns=["10.20.0.10"]),
|
|
Subnet(network_id=networks[2].id, cidr="10.120.0.0/24", gateway="10.120.0.1", dns=["10.20.0.10"]),
|
|
]
|
|
db.add_all(subnets)
|
|
db.flush()
|
|
|
|
workloads = []
|
|
for idx in range(10):
|
|
project = projects[idx % len(projects)]
|
|
workloads.append(
|
|
Workload(
|
|
cluster_id=cluster.id,
|
|
node_id=nodes[idx % len(nodes)].id,
|
|
project_id=project.id,
|
|
external_id=str(100 + idx),
|
|
name=f"{project.name.lower().replace(' ', '-')}-{idx + 1}",
|
|
kind="qemu" if idx % 3 else "lxc",
|
|
status="running" if idx != 7 else "stopped",
|
|
tags=["web"] if idx % 2 else ["db"],
|
|
)
|
|
)
|
|
db.add_all(workloads)
|
|
db.flush()
|
|
|
|
db.add_all(
|
|
[
|
|
IpAddress(subnet_id=subnets[0].id, address="10.10.10.20", status="assigned", workload_id=workloads[0].id),
|
|
IpAddress(subnet_id=subnets[1].id, address="10.20.0.50", status="reserved", note="Load balancer VIP"),
|
|
IpAddress(subnet_id=subnets[2].id, address="10.120.0.99", status="conflict", note="Duplicate detected during import"),
|
|
]
|
|
)
|
|
|
|
groups = [
|
|
SecurityGroup(project_id=projects[0].id, name="Management", description="Administrative access"),
|
|
SecurityGroup(project_id=projects[1].id, name="Finance Web", description="Finance web tier"),
|
|
SecurityGroup(project_id=projects[1].id, name="Finance DB", description="Finance database tier"),
|
|
]
|
|
db.add_all(groups)
|
|
|
|
db.add_all(
|
|
[
|
|
Policy(
|
|
project_id=projects[1].id,
|
|
name="Finance web to database",
|
|
definition={
|
|
"source": "sg:Finance Web",
|
|
"destination": "sg:Finance DB",
|
|
"service": {"protocol": "tcp", "ports": "5432"},
|
|
"action": "allow",
|
|
"direction": "egress",
|
|
"logging": True,
|
|
"description": "Allow PostgreSQL from finance web tier to database tier.",
|
|
},
|
|
),
|
|
Policy(
|
|
project_id=projects[0].id,
|
|
name="Management SSH",
|
|
definition={
|
|
"source": "network:mgmt",
|
|
"destination": "any",
|
|
"service": {"protocol": "tcp", "ports": "22"},
|
|
"action": "allow",
|
|
"direction": "ingress",
|
|
},
|
|
),
|
|
]
|
|
)
|
|
|
|
db.add(AuditLog(user_id=user.id, action="seed.created", object_type="system", result="success"))
|
|
db.commit()
|