Initial commit
This commit is contained in:
904
QemuVmManager.Console/Program.cs
Normal file
904
QemuVmManager.Console/Program.cs
Normal file
@@ -0,0 +1,904 @@
|
||||
using QemuVmManager.Services;
|
||||
using QemuVmManager.Models;
|
||||
|
||||
namespace QemuVmManager.Console;
|
||||
|
||||
class Program
|
||||
{
|
||||
private static VmManagementService _vmService = null!;
|
||||
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
_vmService = new VmManagementService();
|
||||
|
||||
System.Console.WriteLine("=== QEMU VM Manager ===");
|
||||
System.Console.WriteLine("Type 'help' for available commands");
|
||||
System.Console.WriteLine();
|
||||
|
||||
await RunInteractiveMode();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
System.Console.WriteLine("Press any key to exit...");
|
||||
System.Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
static async Task RunInteractiveMode()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Console.Write("qemu-vm> ");
|
||||
var input = System.Console.ReadLine()?.Trim();
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
continue;
|
||||
|
||||
var parts = input.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
var command = parts[0].ToLower();
|
||||
var arguments = parts.Skip(1).ToArray();
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case "help":
|
||||
ShowHelp();
|
||||
break;
|
||||
case "list":
|
||||
await ListVms();
|
||||
break;
|
||||
case "create":
|
||||
await CreateVm(arguments);
|
||||
break;
|
||||
case "start":
|
||||
await StartVm(arguments);
|
||||
break;
|
||||
case "stop":
|
||||
await StopVm(arguments);
|
||||
break;
|
||||
case "pause":
|
||||
await PauseVm(arguments);
|
||||
break;
|
||||
case "resume":
|
||||
await ResumeVm(arguments);
|
||||
break;
|
||||
case "delete":
|
||||
await DeleteVm(arguments);
|
||||
break;
|
||||
case "clone":
|
||||
await CloneVm(arguments);
|
||||
break;
|
||||
case "export":
|
||||
await ExportVm(arguments);
|
||||
break;
|
||||
case "import":
|
||||
await ImportVm(arguments);
|
||||
break;
|
||||
case "status":
|
||||
await ShowVmStatus(arguments);
|
||||
break;
|
||||
case "config":
|
||||
await ShowVmConfig(arguments);
|
||||
break;
|
||||
case "disk":
|
||||
await ManageDisk(arguments);
|
||||
break;
|
||||
case "validate":
|
||||
await ValidateVm(arguments);
|
||||
break;
|
||||
case "diagnose":
|
||||
await DiagnoseSystem();
|
||||
break;
|
||||
case "monitor":
|
||||
await MonitorPerformance(arguments);
|
||||
break;
|
||||
case "metrics":
|
||||
await ShowMetrics(arguments);
|
||||
break;
|
||||
case "exit":
|
||||
case "quit":
|
||||
System.Console.WriteLine("Goodbye!");
|
||||
return;
|
||||
default:
|
||||
System.Console.WriteLine($"Unknown command: {command}");
|
||||
System.Console.WriteLine("Type 'help' for available commands");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
|
||||
System.Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
static void ShowHelp()
|
||||
{
|
||||
System.Console.WriteLine("Available commands:");
|
||||
System.Console.WriteLine(" list - List all VMs");
|
||||
System.Console.WriteLine(" create <name> - Create a new VM (interactive)");
|
||||
System.Console.WriteLine(" start <name> - Start a VM");
|
||||
System.Console.WriteLine(" stop <name> [--force] - Stop a VM");
|
||||
System.Console.WriteLine(" pause <name> - Pause a VM");
|
||||
System.Console.WriteLine(" resume <name> - Resume a VM");
|
||||
System.Console.WriteLine(" delete <name> - Delete a VM");
|
||||
System.Console.WriteLine(" clone <source> <target> - Clone a VM");
|
||||
System.Console.WriteLine(" export <name> <path> - Export VM configuration");
|
||||
System.Console.WriteLine(" import <path> [name] - Import VM configuration");
|
||||
System.Console.WriteLine(" status [name] - Show VM status");
|
||||
System.Console.WriteLine(" config <name> - Show VM configuration");
|
||||
System.Console.WriteLine(" disk <name> [info|resize|convert] - Manage disk images");
|
||||
System.Console.WriteLine(" validate <name> - Validate VM disk images");
|
||||
System.Console.WriteLine(" diagnose - Diagnose system and QEMU installation");
|
||||
System.Console.WriteLine(" monitor <name> [start|stop|status] - Performance monitoring");
|
||||
System.Console.WriteLine(" metrics <name> [current|history] - Show performance metrics");
|
||||
System.Console.WriteLine(" help - Show this help");
|
||||
System.Console.WriteLine(" exit/quit - Exit the application");
|
||||
}
|
||||
|
||||
static Task ListVms()
|
||||
{
|
||||
var configs = _vmService.GetAllVmConfigurations().ToList();
|
||||
var statuses = _vmService.GetAllVmStatuses().ToDictionary(s => s.Name);
|
||||
|
||||
if (configs.Count == 0)
|
||||
{
|
||||
System.Console.WriteLine("No VMs configured.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
System.Console.WriteLine($"{"Name",-20} {"Status",-10} {"CPU",-8} {"Memory",-10} {"Description"}");
|
||||
System.Console.WriteLine(new string('-', 80));
|
||||
|
||||
foreach (var config in configs)
|
||||
{
|
||||
var status = statuses.GetValueOrDefault(config.Name);
|
||||
var statusText = status?.State.ToString() ?? "Unknown";
|
||||
var cpuText = $"{config.Cpu.Cores} cores";
|
||||
var memoryText = $"{config.Memory.Size}{config.Memory.Unit}";
|
||||
|
||||
System.Console.WriteLine($"{config.Name,-20} {statusText,-10} {cpuText,-8} {memoryText,-10} {config.Description}");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
static async Task CreateVm(string[] arguments)
|
||||
{
|
||||
string vmName;
|
||||
if (arguments.Length > 0)
|
||||
{
|
||||
vmName = arguments[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.Write("Enter VM name: ");
|
||||
vmName = System.Console.ReadLine()?.Trim() ?? "";
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(vmName))
|
||||
{
|
||||
System.Console.WriteLine("VM name cannot be empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
var config = new VmConfiguration
|
||||
{
|
||||
Name = vmName,
|
||||
Description = GetUserInput("Description (optional): "),
|
||||
Cpu = new CpuConfiguration
|
||||
{
|
||||
Cores = int.Parse(GetUserInput("CPU cores (2): ", "2")),
|
||||
Model = GetUserInput("CPU model (qemu64): ", "qemu64")
|
||||
},
|
||||
Memory = new MemoryConfiguration
|
||||
{
|
||||
Size = long.Parse(GetUserInput("Memory size in MB (2048): ", "2048")),
|
||||
Unit = "M"
|
||||
},
|
||||
Storage = new StorageConfiguration
|
||||
{
|
||||
Disks = new List<DiskConfiguration>
|
||||
{
|
||||
new DiskConfiguration
|
||||
{
|
||||
Path = GetUserInput($"Disk path (vm-disks/{vmName}.qcow2): ", $"vm-disks/{vmName}.qcow2"),
|
||||
Size = long.Parse(GetUserInput("Disk size in GB (10): ", "10")),
|
||||
Format = GetUserInput("Disk format (qcow2): ", "qcow2"),
|
||||
Interface = GetUserInput("Disk interface (virtio): ", "virtio"),
|
||||
IsBoot = true
|
||||
}
|
||||
}
|
||||
},
|
||||
Network = new NetworkConfiguration
|
||||
{
|
||||
Interfaces = new List<NetworkInterfaceConfiguration>
|
||||
{
|
||||
new NetworkInterfaceConfiguration
|
||||
{
|
||||
Type = "bridge",
|
||||
Model = "virtio-net-pci",
|
||||
Bridge = GetUserInput("Network bridge (virbr0): ", "virbr0")
|
||||
}
|
||||
}
|
||||
},
|
||||
Display = new DisplayConfiguration
|
||||
{
|
||||
Type = GetUserInput("Display type (gtk): ", "gtk"),
|
||||
Vga = GetUserInput("VGA type (virtio): ", "virtio")
|
||||
}
|
||||
};
|
||||
|
||||
await _vmService.CreateVmAsync(config);
|
||||
System.Console.WriteLine($"VM '{vmName}' created successfully.");
|
||||
}
|
||||
|
||||
static async Task StartVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: start <vm-name>");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var success = await _vmService.StartVmAsync(vmName);
|
||||
|
||||
if (success)
|
||||
System.Console.WriteLine($"VM '{vmName}' started successfully.");
|
||||
else
|
||||
System.Console.WriteLine($"Failed to start VM '{vmName}'.");
|
||||
}
|
||||
|
||||
static async Task StopVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: stop <vm-name> [--force]");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var force = arguments.Contains("--force");
|
||||
|
||||
var success = await _vmService.StopVmAsync(vmName, force);
|
||||
|
||||
if (success)
|
||||
System.Console.WriteLine($"VM '{vmName}' stopped successfully.");
|
||||
else
|
||||
System.Console.WriteLine($"Failed to stop VM '{vmName}'.");
|
||||
}
|
||||
|
||||
static async Task PauseVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: pause <vm-name>");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var success = await _vmService.PauseVmAsync(vmName);
|
||||
|
||||
if (success)
|
||||
System.Console.WriteLine($"VM '{vmName}' paused successfully.");
|
||||
else
|
||||
System.Console.WriteLine($"Failed to pause VM '{vmName}'.");
|
||||
}
|
||||
|
||||
static async Task ResumeVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: resume <vm-name>");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var success = await _vmService.ResumeVmAsync(vmName);
|
||||
|
||||
if (success)
|
||||
System.Console.WriteLine($"VM '{vmName}' resumed successfully.");
|
||||
else
|
||||
System.Console.WriteLine($"Failed to resume VM '{vmName}'.");
|
||||
}
|
||||
|
||||
static async Task DeleteVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: delete <vm-name>");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
|
||||
System.Console.Write($"Are you sure you want to delete VM '{vmName}'? (y/N): ");
|
||||
var confirm = System.Console.ReadLine()?.Trim().ToLower();
|
||||
|
||||
if (confirm == "y" || confirm == "yes")
|
||||
{
|
||||
await _vmService.DeleteVmAsync(vmName);
|
||||
System.Console.WriteLine($"VM '{vmName}' deleted successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.WriteLine("Deletion cancelled.");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task CloneVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length < 2)
|
||||
{
|
||||
System.Console.WriteLine("Usage: clone <source-vm> <target-vm>");
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceVm = arguments[0];
|
||||
var targetVm = arguments[1];
|
||||
|
||||
var clonedConfig = await _vmService.CloneVmAsync(sourceVm, targetVm);
|
||||
System.Console.WriteLine($"VM '{sourceVm}' cloned to '{targetVm}' successfully.");
|
||||
}
|
||||
|
||||
static async Task ExportVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length < 2)
|
||||
{
|
||||
System.Console.WriteLine("Usage: export <vm-name> <export-path>");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var exportPath = arguments[1];
|
||||
|
||||
var exportedPath = await _vmService.ExportVmConfigurationAsync(vmName, exportPath);
|
||||
System.Console.WriteLine($"VM '{vmName}' exported to '{exportedPath}' successfully.");
|
||||
}
|
||||
|
||||
static async Task ImportVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: import <import-path> [new-name]");
|
||||
return;
|
||||
}
|
||||
|
||||
var importPath = arguments[0];
|
||||
var newName = arguments.Length > 1 ? arguments[1] : null;
|
||||
|
||||
var importedConfig = await _vmService.ImportVmConfigurationAsync(importPath, newName);
|
||||
System.Console.WriteLine($"VM '{importedConfig.Name}' imported successfully.");
|
||||
}
|
||||
|
||||
static Task ShowVmStatus(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
// Show all VM statuses
|
||||
var statuses = _vmService.GetAllVmStatuses();
|
||||
|
||||
if (!statuses.Any())
|
||||
{
|
||||
System.Console.WriteLine("No VMs found.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
System.Console.WriteLine($"{"Name",-20} {"Status",-10} {"PID",-8} {"Started",-20} {"Error"}");
|
||||
System.Console.WriteLine(new string('-', 80));
|
||||
|
||||
foreach (var status in statuses)
|
||||
{
|
||||
var pidText = status.ProcessId > 0 ? status.ProcessId.ToString() : "-";
|
||||
var startedText = status.StartedAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-";
|
||||
var errorText = status.ErrorMessage ?? "";
|
||||
|
||||
System.Console.WriteLine($"{status.Name,-20} {status.State,-10} {pidText,-8} {startedText,-20} {errorText}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show specific VM status
|
||||
var vmName = arguments[0];
|
||||
var status = _vmService.GetVmStatus(vmName);
|
||||
|
||||
if (status == null)
|
||||
{
|
||||
System.Console.WriteLine($"VM '{vmName}' not found.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
System.Console.WriteLine($"VM: {status.Name}");
|
||||
System.Console.WriteLine($"Status: {status.State}");
|
||||
System.Console.WriteLine($"Process ID: {status.ProcessId}");
|
||||
System.Console.WriteLine($"Started: {status.StartedAt}");
|
||||
System.Console.WriteLine($"Stopped: {status.StoppedAt}");
|
||||
|
||||
if (status.ResourceUsage != null)
|
||||
{
|
||||
System.Console.WriteLine($"CPU Usage: {status.ResourceUsage.CpuUsage:F1}%");
|
||||
System.Console.WriteLine($"Memory Usage: {status.ResourceUsage.MemoryUsage} MB");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(status.ErrorMessage))
|
||||
{
|
||||
System.Console.WriteLine($"Error: {status.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
static Task ShowVmConfig(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: config <vm-name>");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var config = _vmService.GetVmConfiguration(vmName);
|
||||
|
||||
if (config == null)
|
||||
{
|
||||
System.Console.WriteLine($"VM '{vmName}' not found.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
System.Console.WriteLine($"VM Configuration: {config.Name}");
|
||||
System.Console.WriteLine($"Description: {config.Description}");
|
||||
System.Console.WriteLine($"Created: {config.Created}");
|
||||
System.Console.WriteLine($"Modified: {config.LastModified}");
|
||||
System.Console.WriteLine();
|
||||
|
||||
System.Console.WriteLine("CPU Configuration:");
|
||||
System.Console.WriteLine($" Cores: {config.Cpu.Cores}");
|
||||
System.Console.WriteLine($" Model: {config.Cpu.Model}");
|
||||
System.Console.WriteLine($" KVM: {config.Cpu.EnableKvm}");
|
||||
System.Console.WriteLine();
|
||||
|
||||
System.Console.WriteLine("Memory Configuration:");
|
||||
System.Console.WriteLine($" Size: {config.Memory.Size}{config.Memory.Unit}");
|
||||
System.Console.WriteLine();
|
||||
|
||||
System.Console.WriteLine("Storage Configuration:");
|
||||
foreach (var disk in config.Storage.Disks)
|
||||
{
|
||||
System.Console.WriteLine($" Disk: {disk.Path}");
|
||||
System.Console.WriteLine($" Size: {disk.Size} GB");
|
||||
System.Console.WriteLine($" Format: {disk.Format}");
|
||||
System.Console.WriteLine($" Interface: {disk.Interface}");
|
||||
System.Console.WriteLine($" Boot: {disk.IsBoot}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(config.Storage.Cdrom))
|
||||
{
|
||||
System.Console.WriteLine($" CD-ROM: {config.Storage.Cdrom}");
|
||||
}
|
||||
System.Console.WriteLine();
|
||||
|
||||
System.Console.WriteLine("Network Configuration:");
|
||||
foreach (var nic in config.Network.Interfaces)
|
||||
{
|
||||
System.Console.WriteLine($" Interface: {nic.Model}");
|
||||
System.Console.WriteLine($" Type: {nic.Type}");
|
||||
System.Console.WriteLine($" Bridge: {nic.Bridge}");
|
||||
if (!string.IsNullOrEmpty(nic.Mac))
|
||||
{
|
||||
System.Console.WriteLine($" MAC: {nic.Mac}");
|
||||
}
|
||||
}
|
||||
System.Console.WriteLine();
|
||||
|
||||
System.Console.WriteLine("Display Configuration:");
|
||||
System.Console.WriteLine($" Type: {config.Display.Type}");
|
||||
System.Console.WriteLine($" VGA: {config.Display.Vga}");
|
||||
System.Console.WriteLine($" SPICE: {config.Display.EnableSpice}");
|
||||
if (config.Display.EnableSpice)
|
||||
{
|
||||
System.Console.WriteLine($" SPICE Port: {config.Display.SpicePort}");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
static async Task ManageDisk(string[] arguments)
|
||||
{
|
||||
if (arguments.Length < 1)
|
||||
{
|
||||
System.Console.WriteLine("Usage: disk <vm-name> [info|resize|convert]");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var action = arguments.Length > 1 ? arguments[1].ToLower() : "info";
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case "info":
|
||||
await ShowDiskInfo(vmName);
|
||||
break;
|
||||
case "resize":
|
||||
await ResizeDisk(vmName, arguments.Skip(2).ToArray());
|
||||
break;
|
||||
case "convert":
|
||||
await ConvertDisk(vmName, arguments.Skip(2).ToArray());
|
||||
break;
|
||||
default:
|
||||
System.Console.WriteLine($"Unknown disk action: {action}");
|
||||
System.Console.WriteLine("Available actions: info, resize, convert");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static async Task ShowDiskInfo(string vmName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = _vmService.GetVmConfiguration(vmName);
|
||||
if (config == null)
|
||||
{
|
||||
System.Console.WriteLine($"VM '{vmName}' not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
System.Console.WriteLine($"Disk Information for VM: {vmName}");
|
||||
System.Console.WriteLine(new string('-', 50));
|
||||
|
||||
for (int i = 0; i < config.Storage.Disks.Count; i++)
|
||||
{
|
||||
var disk = config.Storage.Disks[i];
|
||||
System.Console.WriteLine($"Disk {i}:");
|
||||
System.Console.WriteLine($" Path: {disk.Path}");
|
||||
System.Console.WriteLine($" Format: {disk.Format}");
|
||||
System.Console.WriteLine($" Size: {disk.Size} GB");
|
||||
System.Console.WriteLine($" Interface: {disk.Interface}");
|
||||
System.Console.WriteLine($" Boot: {disk.IsBoot}");
|
||||
|
||||
var diskInfo = await _vmService.GetDiskInfoAsync(vmName, i);
|
||||
if (diskInfo.Exists)
|
||||
{
|
||||
System.Console.WriteLine($" Virtual Size: {diskInfo.VirtualSize}");
|
||||
System.Console.WriteLine($" Disk Size: {diskInfo.DiskSize}");
|
||||
System.Console.WriteLine($" Format: {diskInfo.Format}");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.WriteLine(" Status: Not found");
|
||||
}
|
||||
System.Console.WriteLine();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task ResizeDisk(string vmName, string[] arguments)
|
||||
{
|
||||
if (arguments.Length < 2)
|
||||
{
|
||||
System.Console.WriteLine("Usage: disk <vm-name> resize <disk-index> <new-size-gb>");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var diskIndex = int.Parse(arguments[0]);
|
||||
var newSizeGB = long.Parse(arguments[1]);
|
||||
|
||||
var success = await _vmService.ResizeDiskAsync(vmName, diskIndex, newSizeGB);
|
||||
if (success)
|
||||
{
|
||||
System.Console.WriteLine($"Disk {diskIndex} resized to {newSizeGB} GB successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.WriteLine("Failed to resize disk.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task ConvertDisk(string vmName, string[] arguments)
|
||||
{
|
||||
if (arguments.Length < 2)
|
||||
{
|
||||
System.Console.WriteLine("Usage: disk <vm-name> convert <disk-index> <new-format>");
|
||||
System.Console.WriteLine("Available formats: qcow2, raw, vmdk, vdi, vhd");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var diskIndex = int.Parse(arguments[0]);
|
||||
var newFormat = arguments[1];
|
||||
|
||||
var success = await _vmService.ConvertDiskAsync(vmName, diskIndex, newFormat);
|
||||
if (success)
|
||||
{
|
||||
System.Console.WriteLine($"Disk {diskIndex} converted to {newFormat} format successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.WriteLine("Failed to convert disk.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task ValidateVm(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: validate <vm-name>");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
|
||||
try
|
||||
{
|
||||
var isValid = _vmService.ValidateDiskImages(vmName);
|
||||
if (isValid)
|
||||
{
|
||||
System.Console.WriteLine($"VM '{vmName}' disk images are valid.");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.WriteLine($"VM '{vmName}' has invalid disk images.");
|
||||
System.Console.WriteLine("Use 'disk <vm-name> info' to check disk status.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task DiagnoseSystem()
|
||||
{
|
||||
System.Console.WriteLine("=== System Diagnosis ===");
|
||||
System.Console.WriteLine();
|
||||
|
||||
// Check .NET version
|
||||
System.Console.WriteLine("1. .NET Runtime:");
|
||||
System.Console.WriteLine($" Version: {Environment.Version}");
|
||||
System.Console.WriteLine($" OS: {Environment.OSVersion}");
|
||||
System.Console.WriteLine($" Architecture: {Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")}");
|
||||
System.Console.WriteLine();
|
||||
|
||||
// Check QEMU installation and virtualization
|
||||
System.Console.WriteLine("2. QEMU Installation:");
|
||||
try
|
||||
{
|
||||
var processManager = new QemuVmManager.Core.QemuProcessManager();
|
||||
var isInstalled = processManager.IsQemuInstalled();
|
||||
var version = processManager.GetQemuVersion();
|
||||
var accelerators = processManager.GetQemuAccelerators();
|
||||
var virtualizationEnabled = processManager.IsVirtualizationEnabled();
|
||||
var availableVirtualization = processManager.GetAvailableVirtualization();
|
||||
|
||||
System.Console.WriteLine($" Installed: {(isInstalled ? "Yes" : "No")}");
|
||||
System.Console.WriteLine($" Version: {version}");
|
||||
System.Console.WriteLine($" Available Accelerators:");
|
||||
foreach (var line in accelerators.Split('\n', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
System.Console.WriteLine($" {line.Trim()}");
|
||||
}
|
||||
System.Console.WriteLine($" Virtualization Enabled in BIOS: {(virtualizationEnabled ? "Yes" : "No")}");
|
||||
System.Console.WriteLine($" Available Virtualization: {availableVirtualization}");
|
||||
|
||||
if (!isInstalled)
|
||||
{
|
||||
System.Console.WriteLine(" ❌ QEMU is not installed or not found in PATH");
|
||||
System.Console.WriteLine(" Please install QEMU and ensure it's available in your system PATH");
|
||||
System.Console.WriteLine(" Windows: Download from https://qemu.weilnetz.de/");
|
||||
System.Console.WriteLine(" Linux: sudo apt-get install qemu-system-x86_64");
|
||||
System.Console.WriteLine(" macOS: brew install qemu");
|
||||
}
|
||||
else if (!virtualizationEnabled)
|
||||
{
|
||||
System.Console.WriteLine(" ⚠️ Virtualization is not enabled in BIOS/UEFI");
|
||||
System.Console.WriteLine(" Please enable VT-x (Intel) or AMD-V (AMD) in your BIOS settings");
|
||||
System.Console.WriteLine(" This will significantly improve VM performance");
|
||||
}
|
||||
else if (availableVirtualization == VirtualizationType.TCG)
|
||||
{
|
||||
System.Console.WriteLine(" ⚠️ Only software emulation (TCG) is available");
|
||||
System.Console.WriteLine(" Hardware virtualization is not available or not properly configured");
|
||||
System.Console.WriteLine(" This may be due to:");
|
||||
System.Console.WriteLine(" - QEMU build not supporting hardware acceleration");
|
||||
System.Console.WriteLine(" - Missing virtualization drivers");
|
||||
System.Console.WriteLine(" - Hyper-V or other virtualization software conflicts");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Console.WriteLine($" ✅ Hardware virtualization ({availableVirtualization}) is available");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($" ❌ Error checking QEMU: {ex.Message}");
|
||||
}
|
||||
System.Console.WriteLine();
|
||||
|
||||
// Check disk manager
|
||||
System.Console.WriteLine("3. Disk Manager:");
|
||||
try
|
||||
{
|
||||
var diskManager = new QemuVmManager.Core.DiskManager();
|
||||
System.Console.WriteLine(" ✅ Disk manager initialized successfully");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($" ❌ Error initializing disk manager: {ex.Message}");
|
||||
}
|
||||
System.Console.WriteLine();
|
||||
|
||||
// Check VM configurations
|
||||
System.Console.WriteLine("4. VM Configurations:");
|
||||
try
|
||||
{
|
||||
var configs = _vmService.GetAllVmConfigurations().ToList();
|
||||
System.Console.WriteLine($" Found {configs.Count} VM configuration(s)");
|
||||
|
||||
foreach (var config in configs)
|
||||
{
|
||||
System.Console.WriteLine($" - {config.Name}: {config.Description}");
|
||||
|
||||
// Check disk images
|
||||
foreach (var disk in config.Storage.Disks)
|
||||
{
|
||||
var exists = File.Exists(disk.Path);
|
||||
System.Console.WriteLine($" Disk: {disk.Path} - {(exists ? "✅ Exists" : "❌ Missing")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($" ❌ Error checking VM configurations: {ex.Message}");
|
||||
}
|
||||
System.Console.WriteLine();
|
||||
|
||||
// Check running VMs
|
||||
System.Console.WriteLine("5. Running VMs:");
|
||||
try
|
||||
{
|
||||
var statuses = _vmService.GetAllVmStatuses().ToList();
|
||||
var runningVms = statuses.Where(s => s.State == QemuVmManager.Models.VmState.Running).ToList();
|
||||
|
||||
System.Console.WriteLine($" Running: {runningVms.Count}");
|
||||
foreach (var vm in runningVms)
|
||||
{
|
||||
System.Console.WriteLine($" - {vm.Name} (PID: {vm.ProcessId})");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($" ❌ Error checking running VMs: {ex.Message}");
|
||||
}
|
||||
System.Console.WriteLine();
|
||||
|
||||
System.Console.WriteLine("=== Diagnosis Complete ===");
|
||||
}
|
||||
|
||||
static string GetUserInput(string prompt, string defaultValue = "")
|
||||
{
|
||||
System.Console.Write(prompt);
|
||||
var input = System.Console.ReadLine()?.Trim();
|
||||
return string.IsNullOrEmpty(input) ? defaultValue : input;
|
||||
}
|
||||
|
||||
static async Task MonitorPerformance(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: monitor <vm-name> [start|stop|status]");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var action = arguments.Length > 1 ? arguments[1].ToLower() : "status";
|
||||
|
||||
try
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case "start":
|
||||
await _vmService.StartPerformanceMonitoringAsync(vmName);
|
||||
System.Console.WriteLine($"Performance monitoring started for VM '{vmName}'");
|
||||
break;
|
||||
case "stop":
|
||||
_vmService.StopPerformanceMonitoring(vmName);
|
||||
System.Console.WriteLine($"Performance monitoring stopped for VM '{vmName}'");
|
||||
break;
|
||||
case "status":
|
||||
default:
|
||||
var isMonitoring = _vmService.IsPerformanceMonitoringActive(vmName);
|
||||
System.Console.WriteLine($"Performance monitoring for VM '{vmName}': {(isMonitoring ? "Active" : "Inactive")}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static async Task ShowMetrics(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
System.Console.WriteLine("Usage: metrics <vm-name> [current|history]");
|
||||
return;
|
||||
}
|
||||
|
||||
var vmName = arguments[0];
|
||||
var type = arguments.Length > 1 ? arguments[1].ToLower() : "current";
|
||||
|
||||
try
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "current":
|
||||
var currentMetrics = await _vmService.GetVmPerformanceMetricsAsync(vmName);
|
||||
DisplayPerformanceMetrics(currentMetrics, "Current");
|
||||
break;
|
||||
case "history":
|
||||
var history = await _vmService.GetPerformanceHistoryAsync(vmName, 20);
|
||||
System.Console.WriteLine($"Performance History for VM '{vmName}' (Last {history.Count} samples):");
|
||||
System.Console.WriteLine();
|
||||
|
||||
foreach (var metrics in history.TakeLast(10))
|
||||
{
|
||||
DisplayPerformanceMetrics(metrics, metrics.Timestamp.ToString("HH:mm:ss"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.Console.WriteLine("Invalid metrics type. Use 'current' or 'history'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
static void DisplayPerformanceMetrics(VmPerformanceMetrics metrics, string label)
|
||||
{
|
||||
System.Console.WriteLine($"=== {label} Performance Metrics ===");
|
||||
System.Console.WriteLine($"Timestamp: {metrics.Timestamp:yyyy-MM-dd HH:mm:ss}");
|
||||
System.Console.WriteLine($"Process ID: {metrics.ProcessId}");
|
||||
System.Console.WriteLine();
|
||||
System.Console.WriteLine("CPU Usage:");
|
||||
System.Console.WriteLine($" VM CPU: {metrics.CpuUsagePercent:F2}%");
|
||||
System.Console.WriteLine($" System CPU: {metrics.SystemCpuUsagePercent:F2}%");
|
||||
System.Console.WriteLine();
|
||||
System.Console.WriteLine("Memory Usage:");
|
||||
System.Console.WriteLine($" Working Set: {metrics.MemoryUsageMB:N0} MB");
|
||||
System.Console.WriteLine($" Private Memory: {metrics.PrivateMemoryMB:N0} MB");
|
||||
System.Console.WriteLine($" Virtual Memory: {metrics.VirtualMemoryMB:N0} MB");
|
||||
System.Console.WriteLine();
|
||||
System.Console.WriteLine("Process Info:");
|
||||
System.Console.WriteLine($" Threads: {metrics.ThreadCount}");
|
||||
System.Console.WriteLine($" Handles: {metrics.HandleCount}");
|
||||
System.Console.WriteLine();
|
||||
}
|
||||
}
|
15
QemuVmManager.Console/QemuVmManager.Console.csproj
Normal file
15
QemuVmManager.Console/QemuVmManager.Console.csproj
Normal file
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\QemuVmManager.Services\QemuVmManager.Services.csproj" />
|
||||
<ProjectReference Include="..\QemuVmManager.Models\QemuVmManager.Models.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Reference in New Issue
Block a user