Real-time Terminal User Interface for monitoring VM migrations.
The hyper2kvm TUI Dashboard provides a beautiful, interactive terminal interface for monitoring VM migrations in real-time. It displays:
Install with TUI support:
pip install 'hyper2kvm[tui]'
Or install all enhancements:
pip install 'hyper2kvm[enhanced]'
See the TUI in action with simulated migrations:
python3 examples/tui_dashboard_example.py
This demo:
from hyper2kvm.tui.dashboard import MigrationDashboard
from hyper2kvm.tui.widgets import MigrationStatus
# Create dashboard
app = MigrationDashboard(refresh_interval=1.0)
# Add a migration
migration = MigrationStatus(
vm_name="web-server-01",
hypervisor="vmware",
status="in_progress",
progress=0.0,
current_stage="Initializing",
)
app.add_migration(migration)
# Update progress (call this from your migration code)
app.update_migration_progress(
vm_name="web-server-01",
progress=0.5,
stage="Exporting disk",
throughput_mbps=125.5,
)
# Mark complete
migration.status = "completed"
migration.progress = 1.0
app.add_migration(migration)
# Run dashboard
app.run()
Integrate with existing orchestrator using callbacks:
from hyper2kvm.tui.dashboard import MigrationDashboard
from hyper2kvm.tui.widgets import MigrationStatus
class IntegratedDashboard(MigrationDashboard):
def start_migration(self, vm_config):
# Create status
migration = MigrationStatus(
vm_name=vm_config['vm_name'],
hypervisor=vm_config['hypervisor'],
status='in_progress',
progress=0.0,
current_stage='Initializing',
)
self.add_migration(migration)
# Create orchestrator with callbacks
orchestrator = Orchestrator(vm_config)
# Progress callback
orchestrator.on_progress = lambda p, s, t: (
self.update_migration_progress(
vm_config['vm_name'],
progress=p,
stage=s,
throughput_mbps=t,
)
)
# Completion callback
orchestrator.on_complete = lambda success, error: (
self.on_migration_complete(
vm_config['vm_name'],
success,
error,
)
)
# Run migration
orchestrator.run()
Integrate with event-driven architecture:
from hyper2kvm.tui.dashboard import MigrationDashboard
class EventDrivenDashboard(MigrationDashboard):
def on_mount(self):
super().on_mount()
# Subscribe to migration events
event_bus.subscribe('migration.started', self.on_migration_started)
event_bus.subscribe('migration.progress', self.on_migration_progress)
event_bus.subscribe('migration.completed', self.on_migration_completed)
def on_migration_started(self, event):
migration = MigrationStatus(
vm_name=event.vm_name,
hypervisor=event.hypervisor,
status='in_progress',
progress=0.0,
current_stage='Initializing',
)
self.add_migration(migration)
def on_migration_progress(self, event):
self.update_migration_progress(
event.vm_name,
event.progress,
event.stage,
event.throughput_mbps,
)
def on_migration_completed(self, event):
if event.vm_name in self._migrations:
migration = self._migrations[event.vm_name]
migration.status = 'completed' if event.success else 'failed'
migration.progress = 1.0 if event.success else migration.progress
if event.error:
migration.error = event.error
self.add_migration(migration)
Integrate with async/await code:
import asyncio
from hyper2kvm.tui.dashboard import MigrationDashboard
class AsyncDashboard(MigrationDashboard):
@MigrationDashboard.work(exclusive=False)
async def run_migration_async(self, vm_config):
# Create migration status
migration = MigrationStatus(
vm_name=vm_config['vm_name'],
hypervisor=vm_config['hypervisor'],
status='in_progress',
progress=0.0,
current_stage='Initializing',
)
self.add_migration(migration)
try:
# Run async migration
async for progress in orchestrator.migrate_async(vm_config):
migration.progress = progress.percent
migration.current_stage = progress.stage
migration.throughput_mbps = progress.throughput
self.add_migration(migration)
# Success
migration.status = 'completed'
migration.progress = 1.0
except Exception as e:
migration.status = 'failed'
migration.error = str(e)
finally:
self.add_migration(migration)
┌─────────────────────────────────────────────────────────────────┐
│ hyper2kvm Migration Dashboard 12:34:56│
├─────────────────────────────────────────────────────────────────┤
│ │
│ 📦 Active Migrations │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 🔄 web-server-01 (vmware) - IN_PROGRESS │ │
│ │ Stage: Exporting disk | 65% [█████████████░░░░░░░░░░] │ │
│ │ Throughput: 120.5 MB/s | Elapsed: 3m 15s | ETA: 1m 45s │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ ✅ web-server-02 (vmware) - COMPLETED │ │
│ │ Stage: Finalized | 100% [████████████████████] │ │
│ │ Throughput: 105.0 MB/s | Elapsed: 5m 30s │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
├────────────────────────────────┬────────────────────────────────┤
│ │ │
│ 📊 Migration Metrics │ 📝 Migration Logs │
│ ────────────────────── │ │
│ Active Migrations: 2 │ [12:30:15] ✅ Dashboard init │
│ Total Migrations: 10 │ [12:30:20] ℹ️ Started: web-01 │
│ Success Rate: 90.0% │ [12:32:45] ✅ Completed: web-02 │
│ Avg Throughput: 110 MB/s│ [12:33:10] ℹ️ Progress: web-01 │
│ Data Processed: 50.2 GB │ │
│ Avg Duration: 5m 45s │ │
│ │ │
├────────────────────────────────┴────────────────────────────────┤
│ Last update: 12:34:56 | Active: 2 | Press 'q' to quit │
└─────────────────────────────────────────────────────────────────┘
Override CSS to customize appearance:
from hyper2kvm.tui.dashboard import MigrationDashboard
class CustomStyledDashboard(MigrationDashboard):
CSS = """
MigrationStatusWidget.in_progress {
border: solid blue;
}
MigrationStatusWidget.completed {
border: solid green;
}
#metrics_widget {
background: $panel;
}
"""
Override refresh behavior:
class CustomRefreshDashboard(MigrationDashboard):
def refresh_display(self):
super().refresh_display()
# Add custom refresh logic
self.update_custom_widgets()
def update_custom_widgets(self):
# Your custom update logic
pass
Add background workers for data collection:
class WorkerDashboard(MigrationDashboard):
@MigrationDashboard.work(exclusive=False)
async def collect_metrics(self):
while True:
await asyncio.sleep(5)
# Collect metrics from Prometheus
metrics = await self.fetch_prometheus_metrics()
self._metrics.update(metrics)
self.refresh_display()
Problem: Dashboard doesn’t start or shows import errors.
Solution: Ensure Textual is installed:
pip install 'hyper2kvm[tui]'
Problem: Characters not rendering correctly over SSH.
Solution: Ensure your terminal supports Unicode:
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
Problem: Dashboard updates slowly with many migrations.
Solution: Increase refresh interval:
app = MigrationDashboard(refresh_interval=2.0) # Slower refresh
Problem: Dark mode toggle doesn’t change colors.
Solution: Some terminals don’t support all color modes. Try:
app.dark = True # Force dark mode
log_message() for user-visible eventsSee the examples/ directory for complete examples:
tui_dashboard_example.py - Demo with simulated migrationstui_integration_example.py - Integration patternsdaemon_with_tui_example.py - Daemon mode + TUIMain TUI application class.
Constructor:
MigrationDashboard(refresh_interval: float = 1.0)
Methods:
add_migration(migration: MigrationStatus) - Add/update migrationremove_migration(vm_name: str) - Remove migrationupdate_migration_progress(...) - Update progresslog_message(message: str, level: str) - Add log entryrefresh_display() - Force refreshDataclass representing migration state.
Fields:
vm_name: str - VM namehypervisor: str - Source hypervisorstatus: str - Status (pending/in_progress/completed/failed)progress: float - Progress (0.0 to 1.0)current_stage: str - Current stage namethroughput_mbps: float - Throughput in MB/selapsed_seconds: float - Elapsed timeeta_seconds: Optional[float] - Estimated time remainingerror: Optional[str] - Error message if failed