9.5 KiB
User Node Limit Roadmap
Overview
Implement a user-level node startup limit feature for GNS3 server to prevent single users from consuming excessive system resources. This feature is disabled by default and can be enabled through configuration files, supporting a three-tier configuration priority system.
Problem Statement
Currently, GNS3 server has no mechanism to limit the number of nodes a user can start across all their projects. This can lead to:
- Resource exhaustion: A single user can consume all available system resources
- Unfair usage: Some users may prevent others from using the system
- System instability: Too many running nodes can degrade overall performance
- Cost issues: In cloud environments, this can lead to unexpected costs
Solution Design
Core Principles
- Default to no limits: System maintains backward compatibility by defaulting to unrestricted usage
- Configuration-driven: All limits can be controlled through configuration files
- Multi-tier priority: User-specific > User group-specific > Global configuration
- Intelligent filtering: Only count nodes that actually consume resources
- Clear error messages: Users receive actionable feedback when limits are reached
Technical Architecture
1. Database Layer Extension
Files: gns3server/db/models/users.py
Add max_nodes field to both User and UserGroup models:
# In User model
max_nodes = Column(Integer, nullable=True) # NULL = no limit
# In UserGroup model
max_nodes = Column(Integer, nullable=True) # NULL = no limit
2. Configuration System Extension
File: gns3server/schemas/config.py
Add node limit configuration to ControllerSettings:
class NodeLimitSettings(BaseModel):
enabled: bool = False # Feature toggle (default disabled)
default_max_nodes: int = 5 # Default limit when enabled
excluded_node_types: List[str] = Field(default_factory=lambda: [
"ethernet_switch", "ethernet_hub", "cloud", "nat"
])
3. Core Service Implementation
New File: gns3server/services/node_limit_service.py
Implement the NodeLimitService class with key methods:
class NodeLimitService:
async def get_user_active_node_count(self, username: str, excluded_types: List[str]) -> int:
"""Count user's active nodes across all projects"""
async def get_user_node_limit(self, user: User) -> Optional[int]:
"""Get user's node limit with priority logic"""
async def check_user_node_limit(self, user: User, project: Project) -> Tuple[bool, str]:
"""Check if user can start more nodes"""
4. API Integration
File: gns3server/api/routes/controller/nodes.py
Add limit checking to node startup endpoint:
@router.post("/{node_id}/start")
async def start_node(
node: Node = Depends(dep_node),
current_user: User = Depends(get_current_active_user),
node_limit_service: NodeLimitService = Depends(get_node_limit_service)
):
# Node limit check
can_start, error_msg = await node_limit_service.check_user_node_limit(
current_user, node.project
)
if not can_start:
raise HTTPException(status_code=403, detail=error_msg)
# Original startup logic
await node.start()
Node Counting Logic
What Counts Toward the Limit
- Status: Only nodes in
startedorsuspendedstate - Ownership: Only projects where
project.created_by == current_user.username - Node types: All node types except those explicitly excluded
What's Excluded from the Limit
- Always-running nodes: Ethernet switches, hubs (nodes where
is_always_running()returns true) - Infrastructure nodes: Cloud nodes and NAT nodes
- Stopped nodes: Nodes in
stoppedstate - Other users' projects: Nodes in projects created by other users
Configuration Priority
User-specific limit (highest priority)
↓ not set
User group limit
↓ not set
Global configuration (if enabled)
↓ disabled
No limit (default)
Configuration Examples
Scenario 1: Default No Limits (System Default)
[Controller]
node_limits_enabled = false
Result: All users have no node limits
Scenario 2: Enable Global Limits
[Controller]
node_limits_enabled = true
node_limits_default_max_nodes = 5
node_limits_excluded_types = ethernet_switch,ethernet_hub,cloud,nat
Result: All users limited to 5 active nodes (excluding infrastructure nodes)
Scenario 3: User-Specific Limits
Configuration file: node_limits_enabled = false
Database:
- User A:
max_nodes = 10(limited to 10 nodes) - User B:
max_nodes = NULL(no limit) - Other users: no limit
Scenario 4: User Group Limits
Configuration file: node_limits_enabled = false
Database:
- "Users" group:
max_nodes = 5 - "Premium Users" group:
max_nodes = 20 - "Administrators" group:
max_nodes = NULL
Result: Members inherit limits from their groups
Implementation Files
| File Path | Type | Description |
|---|---|---|
gns3server/db/models/users.py |
Modify | Add max_nodes field to User and UserGroup |
gns3server/db_migrations/versions/xxx_add_node_limits.py |
New | Database migration script |
gns3server/schemas/config.py |
Modify | Add NodeLimitSettings configuration class |
gns3server/schemas/controller/users.py |
Modify | Add max_nodes to API schemas |
gns3server/services/node_limit_service.py |
New | Core node limit service |
gns3server/api/routes/controller/nodes.py |
Modify | Add limit check to node startup |
gns3server/api/routes/controller/users.py |
Modify | Add user limit configuration API |
gns3server/api/routes/controller/groups.py |
Modify | Add group limit configuration API |
Implementation Steps
Phase 1: Database Layer
- Add
max_nodesfield toUserandUserGroupmodels - Create database migration file
- Test database migration and rollback
Phase 2: Configuration System
- Add
NodeLimitSettingsto configuration schema - Update configuration file loading logic
- Test configuration parsing and validation
Phase 3: Core Service
- Implement
NodeLimitServiceclass - Implement node counting logic
- Implement limit checking logic
- Add unit tests for service methods
Phase 4: API Integration
- Modify node startup endpoint to add limit check
- Add user limit configuration endpoints
- Add group limit configuration endpoints
- Add user node usage statistics endpoint
Phase 5: Testing
- Unit tests for all core functions
- Integration tests for API endpoints
- End-to-end tests for complete workflows
- Performance tests for node counting operations
Testing Strategy
Functional Tests
- Default state verification (no limits)
- Global limit enablement
- User-specific limits
- User group limits
- Configuration priority verification
Boundary Tests
- Exactly at limit (can start last node)
- One over limit (startup rejected)
- Stop node then restart (should work)
- Special node type exclusion
Integration Tests
- Multi-user concurrent startups
- Node state transitions
- Dynamic configuration changes
- Project ownership filtering
Performance Tests
- Node counting performance with many projects
- Concurrent startup request handling
- Memory usage monitoring
Error Messages
User-Friendly Error Response
When a user hits their node limit:
{
"detail": "节点启动限制:您当前有 5 个活跃节点,限制为 5 个。请停止一些节点后再试,或联系管理员调整限制。"
}
Alternative formats:
- Show current usage vs limit
- Provide action suggestions
- Include contact information for administrators
Migration Path
For Existing Systems
- Database migration: Add new nullable fields (safe, no data loss)
- Configuration update: Add new optional settings (backward compatible)
- API changes: Add new optional dependency injection (no breaking changes)
- Behavior: No changes to existing functionality when disabled
Rollback Plan
If issues occur:
- Set
node_limits_enabled = falsein configuration - Service automatically disables limit checking
- System returns to pre-feature behavior
Benefits
- Resource Management: Prevent resource exhaustion
- Fair Usage: Ensure equitable resource distribution
- Cost Control: Manage cloud resource costs
- System Stability: Maintain performance under load
- Flexibility: Support different usage patterns and tiers
- Backward Compatible: No impact on existing deployments
Future Enhancements
- Per-project limits (in addition to global user limits)
- Time-based limits (different limits for different times)
- Burst limits (temporary allowance for peak usage)
- Usage quotas with reset periods (daily/weekly/monthly)
- Monitoring and alerting for limit approaching
- Administrative override capabilities
- Usage history and analytics
Documentation Updates
- Update API documentation with new endpoints
- Add configuration guide to admin documentation
- Update user guide with limit information
- Add troubleshooting section for limit issues
- Provide migration guide for existing deployments
Status
Current Status: Design Phase
Next Steps:
- Review and approve this roadmap
- Begin Phase 1 implementation (Database Layer)
- Create detailed technical specification
- Set up development and testing environment
Document Version: 1.0
Last Updated: 2026-05-27
Author: GNS3 Development Team