Spaces:
Sleeping
Sleeping
| from enum import Enum | |
| import random | |
| from .domain import Server, VM, VMPlacementPlan | |
| class DemoData(Enum): | |
| SMALL = "SMALL" | |
| MEDIUM = "MEDIUM" | |
| LARGE = "LARGE" | |
| def generate_custom_data( | |
| rack_count: int = 3, | |
| servers_per_rack: int = 4, | |
| vm_count: int = 20 | |
| ) -> VMPlacementPlan: | |
| """ | |
| Generate custom demo data with configurable infrastructure and workload. | |
| Args: | |
| rack_count: Number of racks (1-8) | |
| servers_per_rack: Number of servers per rack (2-10) | |
| vm_count: Number of VMs to place (5-200) | |
| """ | |
| rack_count = max(1, min(8, rack_count)) | |
| servers_per_rack = max(2, min(10, servers_per_rack)) | |
| vm_count = max(5, min(200, vm_count)) | |
| servers = [] | |
| server_id = 1 | |
| # Generate rack names | |
| rack_names = [f"rack-{chr(ord('a') + i)}" for i in range(rack_count)] | |
| # Server templates: (cpu_cores, memory_gb, storage_gb, name_prefix) | |
| server_templates = [ | |
| (48, 192, 2000, "large"), | |
| (32, 128, 1000, "large"), | |
| (24, 96, 1000, "medium"), | |
| (16, 64, 512, "medium"), | |
| (12, 48, 500, "small"), | |
| (8, 32, 256, "small"), | |
| ] | |
| for rack_idx, rack_name in enumerate(rack_names): | |
| for server_idx in range(servers_per_rack): | |
| # Alternate between server sizes for variety | |
| template_idx = (rack_idx + server_idx) % len(server_templates) | |
| cpu, mem, storage, size = server_templates[template_idx] | |
| servers.append(Server( | |
| id=f"s{server_id}", | |
| name=f"srv-{size}-{server_id:02d}", | |
| cpu_cores=cpu, | |
| memory_gb=mem, | |
| storage_gb=storage, | |
| rack=rack_name | |
| )) | |
| server_id += 1 | |
| vms = [] | |
| vm_id = 1 | |
| # VM templates: (cpu_cores, memory_gb, storage_gb, name_prefix, priority, group_type) | |
| # group_type: None, "affinity", "anti-affinity" | |
| vm_templates = [ | |
| # Critical database VMs - anti-affinity for HA | |
| (8, 32, 200, "db", 5, "anti-affinity"), | |
| # API servers | |
| (4, 8, 50, "api", 4, None), | |
| # Web tier - affinity for locality | |
| (2, 4, 20, "web", 3, "affinity"), | |
| # Cache tier - affinity | |
| (4, 16, 30, "cache", 3, "affinity"), | |
| # Workers | |
| (2, 4, 40, "worker", 2, None), | |
| # Dev/test - low priority | |
| (2, 4, 30, "dev", 1, None), | |
| ] | |
| # Distribute VMs across templates | |
| template_weights = [0.08, 0.15, 0.20, 0.10, 0.32, 0.15] # Proportions | |
| # Track affinity/anti-affinity group counts | |
| affinity_groups = {} | |
| anti_affinity_groups = {} | |
| for i in range(vm_count): | |
| # Pick template based on weighted distribution | |
| rand_val = random.random() | |
| cumulative = 0 | |
| template_idx = 0 | |
| for idx, weight in enumerate(template_weights): | |
| cumulative += weight | |
| if rand_val <= cumulative: | |
| template_idx = idx | |
| break | |
| cpu, mem, storage, prefix, priority, group_type = vm_templates[template_idx] | |
| # Determine group assignment | |
| affinity_group = None | |
| anti_affinity_group = None | |
| if group_type == "affinity": | |
| group_name = f"{prefix}-tier" | |
| affinity_groups[group_name] = affinity_groups.get(group_name, 0) + 1 | |
| affinity_group = group_name | |
| elif group_type == "anti-affinity": | |
| # Create multiple anti-affinity clusters (max 3-5 VMs per cluster) | |
| cluster_num = anti_affinity_groups.get(prefix, 0) // 4 + 1 | |
| group_name = f"{prefix}-cluster-{cluster_num}" | |
| anti_affinity_groups[prefix] = anti_affinity_groups.get(prefix, 0) + 1 | |
| anti_affinity_group = group_name | |
| # Count VMs with this prefix | |
| count = sum(1 for v in vms if v.name.startswith(prefix)) + 1 | |
| vms.append(VM( | |
| id=f"vm{vm_id}", | |
| name=f"{prefix}-{count:02d}", | |
| cpu_cores=cpu, | |
| memory_gb=mem, | |
| storage_gb=storage, | |
| priority=priority, | |
| affinity_group=affinity_group, | |
| anti_affinity_group=anti_affinity_group | |
| )) | |
| vm_id += 1 | |
| total_servers = rack_count * servers_per_rack | |
| return VMPlacementPlan( | |
| name=f"CUSTOM ({total_servers} servers, {vm_count} VMs)", | |
| servers=servers, | |
| vms=vms | |
| ) | |
| def generate_demo_data(demo: DemoData) -> VMPlacementPlan: | |
| """Generate demo data for the specified demo type.""" | |
| if demo == DemoData.SMALL: | |
| return _generate_small() | |
| elif demo == DemoData.MEDIUM: | |
| return _generate_medium() | |
| elif demo == DemoData.LARGE: | |
| return _generate_large() | |
| else: | |
| raise ValueError(f"Unknown demo: {demo}") | |
| def _generate_small() -> VMPlacementPlan: | |
| """ | |
| Small demo: 5 servers, 20 VMs | |
| - 2 large servers (32 cores, 128GB, 1TB) | |
| - 3 medium servers (16 cores, 64GB, 512GB) | |
| - Mix of small, medium, and large VMs | |
| - Includes affinity and anti-affinity groups | |
| """ | |
| servers = [ | |
| # Large servers | |
| Server(id="s1", name="server-large-01", cpu_cores=32, memory_gb=128, storage_gb=1000, rack="rack-a"), | |
| Server(id="s2", name="server-large-02", cpu_cores=32, memory_gb=128, storage_gb=1000, rack="rack-b"), | |
| # Medium servers | |
| Server(id="s3", name="server-medium-01", cpu_cores=16, memory_gb=64, storage_gb=512, rack="rack-a"), | |
| Server(id="s4", name="server-medium-02", cpu_cores=16, memory_gb=64, storage_gb=512, rack="rack-b"), | |
| Server(id="s5", name="server-medium-03", cpu_cores=16, memory_gb=64, storage_gb=512, rack="rack-a"), | |
| ] | |
| vms = [ | |
| # Web tier (affinity group - should be together) | |
| VM(id="vm1", name="web-01", cpu_cores=2, memory_gb=4, storage_gb=20, priority=3, affinity_group="web-tier"), | |
| VM(id="vm2", name="web-02", cpu_cores=2, memory_gb=4, storage_gb=20, priority=3, affinity_group="web-tier"), | |
| VM(id="vm3", name="web-03", cpu_cores=2, memory_gb=4, storage_gb=20, priority=3, affinity_group="web-tier"), | |
| # Database replicas (anti-affinity - must be on different servers) | |
| VM(id="vm4", name="db-primary", cpu_cores=8, memory_gb=32, storage_gb=200, priority=5, anti_affinity_group="db-cluster"), | |
| VM(id="vm5", name="db-replica-1", cpu_cores=8, memory_gb=32, storage_gb=200, priority=5, anti_affinity_group="db-cluster"), | |
| VM(id="vm6", name="db-replica-2", cpu_cores=8, memory_gb=32, storage_gb=200, priority=4, anti_affinity_group="db-cluster"), | |
| # API servers | |
| VM(id="vm7", name="api-01", cpu_cores=4, memory_gb=8, storage_gb=50, priority=4), | |
| VM(id="vm8", name="api-02", cpu_cores=4, memory_gb=8, storage_gb=50, priority=4), | |
| # Cache servers (affinity - benefit from being together) | |
| VM(id="vm9", name="cache-01", cpu_cores=4, memory_gb=16, storage_gb=30, priority=3, affinity_group="cache-tier"), | |
| VM(id="vm10", name="cache-02", cpu_cores=4, memory_gb=16, storage_gb=30, priority=3, affinity_group="cache-tier"), | |
| # Worker nodes | |
| VM(id="vm11", name="worker-01", cpu_cores=2, memory_gb=4, storage_gb=40, priority=2), | |
| VM(id="vm12", name="worker-02", cpu_cores=2, memory_gb=4, storage_gb=40, priority=2), | |
| VM(id="vm13", name="worker-03", cpu_cores=2, memory_gb=4, storage_gb=40, priority=2), | |
| VM(id="vm14", name="worker-04", cpu_cores=2, memory_gb=4, storage_gb=40, priority=2), | |
| # Monitoring | |
| VM(id="vm15", name="monitoring", cpu_cores=4, memory_gb=8, storage_gb=100, priority=3), | |
| VM(id="vm16", name="logging", cpu_cores=4, memory_gb=8, storage_gb=150, priority=3), | |
| # Dev/test VMs (lower priority) | |
| VM(id="vm17", name="dev-01", cpu_cores=2, memory_gb=4, storage_gb=30, priority=1), | |
| VM(id="vm18", name="dev-02", cpu_cores=2, memory_gb=4, storage_gb=30, priority=1), | |
| VM(id="vm19", name="test-01", cpu_cores=2, memory_gb=4, storage_gb=30, priority=1), | |
| VM(id="vm20", name="test-02", cpu_cores=2, memory_gb=4, storage_gb=30, priority=1), | |
| ] | |
| return VMPlacementPlan(name="SMALL", servers=servers, vms=vms) | |
| def _generate_medium() -> VMPlacementPlan: | |
| """ | |
| Medium demo: 10 servers, 50 VMs | |
| - Realistic small cluster scenario | |
| - Multiple affinity and anti-affinity groups | |
| """ | |
| servers = [ | |
| # Large servers (rack-a) | |
| Server(id="s1", name="server-large-01", cpu_cores=32, memory_gb=128, storage_gb=1000, rack="rack-a"), | |
| Server(id="s2", name="server-large-02", cpu_cores=32, memory_gb=128, storage_gb=1000, rack="rack-a"), | |
| Server(id="s3", name="server-large-03", cpu_cores=32, memory_gb=128, storage_gb=1000, rack="rack-b"), | |
| Server(id="s4", name="server-large-04", cpu_cores=32, memory_gb=128, storage_gb=1000, rack="rack-b"), | |
| # Medium servers | |
| Server(id="s5", name="server-medium-01", cpu_cores=16, memory_gb=64, storage_gb=512, rack="rack-a"), | |
| Server(id="s6", name="server-medium-02", cpu_cores=16, memory_gb=64, storage_gb=512, rack="rack-a"), | |
| Server(id="s7", name="server-medium-03", cpu_cores=16, memory_gb=64, storage_gb=512, rack="rack-b"), | |
| Server(id="s8", name="server-medium-04", cpu_cores=16, memory_gb=64, storage_gb=512, rack="rack-b"), | |
| # Small servers | |
| Server(id="s9", name="server-small-01", cpu_cores=8, memory_gb=32, storage_gb=256, rack="rack-a"), | |
| Server(id="s10", name="server-small-02", cpu_cores=8, memory_gb=32, storage_gb=256, rack="rack-b"), | |
| ] | |
| vms = [] | |
| vm_id = 1 | |
| # Web tier (6 VMs, affinity) | |
| for i in range(6): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"web-{i+1:02d}", | |
| cpu_cores=2, memory_gb=4, storage_gb=20, | |
| priority=3, affinity_group="web-tier" | |
| )) | |
| vm_id += 1 | |
| # Database cluster (3 VMs, anti-affinity) | |
| for i, name in enumerate(["db-primary", "db-replica-1", "db-replica-2"]): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=name, | |
| cpu_cores=8, memory_gb=32, storage_gb=200, | |
| priority=5, anti_affinity_group="db-cluster" | |
| )) | |
| vm_id += 1 | |
| # API servers (8 VMs) | |
| for i in range(8): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"api-{i+1:02d}", | |
| cpu_cores=4, memory_gb=8, storage_gb=50, | |
| priority=4 | |
| )) | |
| vm_id += 1 | |
| # Cache tier (4 VMs, affinity) | |
| for i in range(4): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"cache-{i+1:02d}", | |
| cpu_cores=4, memory_gb=16, storage_gb=30, | |
| priority=3, affinity_group="cache-tier" | |
| )) | |
| vm_id += 1 | |
| # Worker nodes (12 VMs) | |
| for i in range(12): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"worker-{i+1:02d}", | |
| cpu_cores=2, memory_gb=4, storage_gb=40, | |
| priority=2 | |
| )) | |
| vm_id += 1 | |
| # Analytics cluster (3 VMs, anti-affinity for HA) | |
| for i in range(3): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"analytics-{i+1:02d}", | |
| cpu_cores=8, memory_gb=24, storage_gb=150, | |
| priority=3, anti_affinity_group="analytics-cluster" | |
| )) | |
| vm_id += 1 | |
| # Monitoring & logging (4 VMs) | |
| for name in ["prometheus", "grafana", "elasticsearch", "kibana"]: | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=name, | |
| cpu_cores=4, memory_gb=8, storage_gb=100, | |
| priority=3 | |
| )) | |
| vm_id += 1 | |
| # CI/CD (2 VMs) | |
| for name in ["jenkins", "gitlab-runner"]: | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=name, | |
| cpu_cores=4, memory_gb=8, storage_gb=80, | |
| priority=2 | |
| )) | |
| vm_id += 1 | |
| # Dev/test VMs (6 VMs, lower priority) | |
| for i in range(6): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"dev-{i+1:02d}", | |
| cpu_cores=2, memory_gb=4, storage_gb=30, | |
| priority=1 | |
| )) | |
| vm_id += 1 | |
| return VMPlacementPlan(name="MEDIUM", servers=servers, vms=vms) | |
| def _generate_large() -> VMPlacementPlan: | |
| """ | |
| Large demo: 20 servers, 100 VMs | |
| - Stress test scenario | |
| - Multiple racks for anti-affinity | |
| """ | |
| servers = [] | |
| server_id = 1 | |
| racks = ["rack-a", "rack-b", "rack-c", "rack-d"] | |
| # Large servers (8) | |
| for i in range(8): | |
| servers.append(Server( | |
| id=f"s{server_id}", name=f"server-large-{i+1:02d}", | |
| cpu_cores=48, memory_gb=192, storage_gb=2000, | |
| rack=racks[i % len(racks)] | |
| )) | |
| server_id += 1 | |
| # Medium servers (8) | |
| for i in range(8): | |
| servers.append(Server( | |
| id=f"s{server_id}", name=f"server-medium-{i+1:02d}", | |
| cpu_cores=24, memory_gb=96, storage_gb=1000, | |
| rack=racks[i % len(racks)] | |
| )) | |
| server_id += 1 | |
| # Small servers (4) | |
| for i in range(4): | |
| servers.append(Server( | |
| id=f"s{server_id}", name=f"server-small-{i+1:02d}", | |
| cpu_cores=12, memory_gb=48, storage_gb=500, | |
| rack=racks[i % len(racks)] | |
| )) | |
| server_id += 1 | |
| vms = [] | |
| vm_id = 1 | |
| # Web tier (12 VMs, affinity) | |
| for i in range(12): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"web-{i+1:02d}", | |
| cpu_cores=2, memory_gb=4, storage_gb=20, | |
| priority=3, affinity_group="web-tier" | |
| )) | |
| vm_id += 1 | |
| # Database clusters (2 clusters, 3 VMs each, anti-affinity) | |
| for cluster in range(2): | |
| for i in range(3): | |
| role = "primary" if i == 0 else f"replica-{i}" | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"db-cluster{cluster+1}-{role}", | |
| cpu_cores=8, memory_gb=32, storage_gb=300, | |
| priority=5, anti_affinity_group=f"db-cluster-{cluster+1}" | |
| )) | |
| vm_id += 1 | |
| # API servers (16 VMs) | |
| for i in range(16): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"api-{i+1:02d}", | |
| cpu_cores=4, memory_gb=8, storage_gb=50, | |
| priority=4 | |
| )) | |
| vm_id += 1 | |
| # Cache tier (8 VMs, affinity) | |
| for i in range(8): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"cache-{i+1:02d}", | |
| cpu_cores=4, memory_gb=24, storage_gb=30, | |
| priority=3, affinity_group="cache-tier" | |
| )) | |
| vm_id += 1 | |
| # Worker nodes (24 VMs) | |
| for i in range(24): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"worker-{i+1:02d}", | |
| cpu_cores=2, memory_gb=4, storage_gb=40, | |
| priority=2 | |
| )) | |
| vm_id += 1 | |
| # Message queue cluster (3 VMs, anti-affinity) | |
| for i in range(3): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"kafka-{i+1:02d}", | |
| cpu_cores=4, memory_gb=16, storage_gb=200, | |
| priority=4, anti_affinity_group="kafka-cluster" | |
| )) | |
| vm_id += 1 | |
| # Search cluster (5 VMs, anti-affinity) | |
| for i in range(5): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"elasticsearch-{i+1:02d}", | |
| cpu_cores=6, memory_gb=24, storage_gb=250, | |
| priority=3, anti_affinity_group="search-cluster" | |
| )) | |
| vm_id += 1 | |
| # Monitoring stack (6 VMs) | |
| for name in ["prometheus", "grafana", "alertmanager", "thanos-query", "thanos-store", "thanos-compact"]: | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=name, | |
| cpu_cores=4, memory_gb=8, storage_gb=100, | |
| priority=3 | |
| )) | |
| vm_id += 1 | |
| # CI/CD (4 VMs) | |
| for name in ["jenkins-master", "jenkins-agent-1", "jenkins-agent-2", "artifact-repo"]: | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=name, | |
| cpu_cores=4, memory_gb=8, storage_gb=120, | |
| priority=2 | |
| )) | |
| vm_id += 1 | |
| # Dev/test VMs (10 VMs, lower priority) | |
| for i in range(10): | |
| vms.append(VM( | |
| id=f"vm{vm_id}", name=f"dev-{i+1:02d}", | |
| cpu_cores=2, memory_gb=4, storage_gb=30, | |
| priority=1 | |
| )) | |
| vm_id += 1 | |
| return VMPlacementPlan(name="LARGE", servers=servers, vms=vms) | |