Skip to content

Commit bb9d87e

Browse files
committed
[ENCE] -OS linking - Pre init check function - Better UX
Signed-off-by: Iván Rodriguez <ivanrwcm25@gmail.com>
1 parent 4aa4428 commit bb9d87e

4 files changed

Lines changed: 149 additions & 35 deletions

File tree

ShpCore.Kernel/Protocols/VM_protocol.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
using ShpCore.Kernel.VirtualMachineSubsystem;
55
using System.Text.Json;
66

7-
8-
97
namespace MSharp.Launcher.Core.Protocols;
108

119
public class SharpCoreVmProtocol : IProtocol

ShpCore.Kernel/RemoteLinuxConnection/Remote_Linux_Connection.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,10 @@ public class RemoteLinuxBridgeConnection : IBridgeConnection
1414
private readonly HttpClient _client = new HttpClient();
1515
private readonly string _serviceUrl;
1616

17-
public RemoteLinuxBridgeConnection(string url)
18-
{
19-
_serviceUrl = url ?? throw new ArgumentException("URL no puede ser nula");
20-
}
21-
22-
public void Start()
23-
{
24-
KernelLog.Info($"[RemoteBridge] Conectado a {_serviceUrl}");
25-
}
26-
17+
public RemoteLinuxBridgeConnection(string url) => _serviceUrl = url ?? throw new ArgumentException("URL no puede ser nula");
18+
19+
public void Start() => KernelLog.Info($"[RemoteBridge] Conectado a {_serviceUrl}");
20+
2721
public void Send(string command)
2822
{
2923
try
@@ -43,7 +37,6 @@ public void Send(string command)
4337
return;
4438
}
4539

46-
// 3. Leer la respuesta (versión síncrona)
4740
var result = response.Content.ReadFromJsonAsync<RemoteLinuxResult>().GetAwaiter().GetResult();
4841

4942
Console.ForegroundColor = ConsoleColor.Green;
@@ -102,3 +95,5 @@ public class RemoteLinuxResult
10295
[JsonPropertyName("error")]
10396
public string? Error { get; set; } = string.Empty;
10497
}
98+
99+

ShpCore.Kernel/VM_subsystem/QemuConnection.cs

Lines changed: 131 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ public class QemuBridgeConnection : IBridgeConnection
1212
{
1313
private readonly string _imagePath;
1414
private Process? _vmProcess;
15-
private int _forwardedPort = 5000;
1615
private readonly QemuOptions? _options;
1716

1817
public QemuBridgeConnection(QemuOptions options)
1918
{
2019
_options = options;
2120
_imagePath = options.ImagePath ?? throw new ArgumentNullException(nameof(options.ImagePath));
22-
_forwardedPort = options.Port;
21+
if (_options.Port == 0)
22+
{
23+
_options.Port = FindFreePort(_options.StartPort);
24+
KernelLog.Info($"[QEMU] Puerto libre asignado dinámicamente: {_options.Port}");
25+
}
26+
2327
}
2428

2529
public Task SendAsync(string path) // No lo voy a usar por ahora.
@@ -31,27 +35,101 @@ public Task SendAsync(string path) // No lo voy a usar por ahora.
3135
);
3236
}
3337

38+
private void PreflightCheck() // Realiza chequeos previos antes de iniciar la VM
39+
{
40+
KernelLog.Warn("[Preflight] Iniciando healthcheck previos para QEMU");
41+
42+
if (_options == null)
43+
{
44+
KernelLog.Panic("[Preflight] Opciones de QEMU no definidas.");
45+
throw new ArgumentNullException(nameof(_options));
46+
}
47+
48+
// 1. Validación de imagen
49+
if (!File.Exists(_options.ImagePath) || _options.ImagePath.Length == 0)
50+
{
51+
KernelLog.Panic($"[Preflight] Imagen no encontrada: {_options.ImagePath}");
52+
throw new FileNotFoundException("La imagen de disco no existe.", _options.ImagePath);
53+
}
54+
55+
// 2. Validación y creación del folder compartido
56+
if (!string.IsNullOrEmpty(_options.SharedFolder))
57+
{
58+
if (!Directory.Exists(_options.SharedFolder))
59+
{
60+
Directory.CreateDirectory(_options.SharedFolder);
61+
KernelLog.Info($"[Preflight] Carpeta compartida creada: {_options.SharedFolder}");
62+
}
63+
}
64+
65+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
66+
{
67+
opts.SharedFolder = "C:\\Users\\Public\\SharpCoreShare";
68+
}
69+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
70+
{
71+
opts.SharedFolder = "/home/tuusuario/sharpcore-share";
72+
}
73+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
74+
{
75+
opts.SharedFolder = "/Users/tuusuario/sharpcore-share";
76+
}
77+
78+
79+
// 3. Validación de puerto libre
80+
if (_options.Port == 0)
81+
{
82+
_options.Port = FindFreePort();
83+
KernelLog.Info($"[Preflight] Puerto libre asignado dinámicamente: {_options.Port}");
84+
}
85+
86+
// 4. Limpieza de procesos zombie de QEMU
87+
var qemuProcs = Process.GetProcessesByName("qemu-system-x86_64");
88+
foreach (var proc in qemuProcs)
89+
{
90+
try
91+
{
92+
proc.Kill(true);
93+
proc.WaitForExit(1500); // Espera hasta 1.5 segundos para que el proceso termine
94+
KernelLog.Info($"[Preflight] Proceso QEMU colgado eliminado: PID {proc.Id}");
95+
}
96+
catch
97+
{
98+
KernelLog.Info($"[Preflight] No hay procesos QEMU en paralelo, Preflight OK.");
99+
}
100+
}
101+
}
102+
103+
34104
public void Start()
35105
{
36106
if (_options == null) throw new ArgumentNullException(nameof(_options));
37107

38108
if (_options.Port == 0)
39109
{
40-
_forwardedPort = FindFreePort();
41-
KernelLog.Info($"[QEMU] Puerto libre asignado dinámicamente: {_forwardedPort}");
110+
_options.Port = FindFreePort();
111+
KernelLog.Info($"[QEMU] Puerto libre asignado dinámicamente: {_options.Port}");
42112
}
43-
else
113+
114+
PreflightCheck();
115+
116+
KernelLog.Info($"[QEMU] Iniciando VM desde {_options.ImagePath}");
117+
118+
119+
string virtfsArg = string.Empty;
120+
if (!string.IsNullOrEmpty(_options.SharedFolder))
44121
{
45-
_forwardedPort = _options.Port;
122+
virtfsArg = $"-virtfs local,path={_options.SharedFolder},mount_tag=hostshare,security_model=passthrough,id=hostshare ";
46123
}
47124

48-
KernelLog.Info($"[QEMU] Iniciando VM desde {_options.ImagePath}");
125+
string args =
126+
$"-hda {_options.ImagePath} -m {_options.MemoryMb} " +
127+
$"-net nic -net user,hostfwd=tcp::{_options.Port}-:{_options.Port} " +
128+
virtfsArg +
129+
$"{(_options.UseSnapshot ? "-snapshot " : "")}" +
130+
$"{(_options.UseNographic ? "-nographic " : "")}" +
131+
$"{_options.ExtraArgs}";
49132

50-
string args = $"-hda {_options.ImagePath} -m {_options.MemoryMb} " +
51-
$"-net nic -net user,hostfwd=tcp::{_forwardedPort}-:{_forwardedPort} " +
52-
$"{(_options.UseSnapshot ? "-snapshot " : "")}" +
53-
$"{(_options.UseNographic ? "-nographic" : "")} " +
54-
$"{_options.ExtraArgs}";
55133

56134
var startInfo = new ProcessStartInfo
57135
{
@@ -60,18 +138,42 @@ public void Start()
60138
RedirectStandardOutput = true,
61139
RedirectStandardError = true,
62140
UseShellExecute = false,
63-
CreateNoWindow = true
141+
CreateNoWindow = false // true si querés ocultar ventana, false para debug
142+
};
143+
144+
_vmProcess = new Process { StartInfo = startInfo };
145+
146+
_vmProcess.OutputDataReceived += (sender, e) =>
147+
{
148+
if (!string.IsNullOrEmpty(e.Data))
149+
KernelLog.Info($"[QEMU stdout] {e.Data}");
150+
};
151+
_vmProcess.ErrorDataReceived += (sender, e) =>
152+
{
153+
if (!string.IsNullOrEmpty(e.Data))
154+
KernelLog.Panic($"[QEMU stderr] {e.Data}");
64155
};
65156

66-
_vmProcess = Process.Start(startInfo);
157+
_vmProcess.Start();
158+
_vmProcess.BeginOutputReadLine();
159+
_vmProcess.BeginErrorReadLine();
160+
161+
KernelLog.Info($"[QEMU] Esperando a que el puerto {_options.Port} esté disponible...");
162+
WaitForPort("127.0.0.1", _options.Port);
163+
_vmProcess.WaitForExit();
164+
KernelLog.Info("[QEMU] VM finalizó correctamente.");
67165

68-
KernelLog.Info($"[QEMU] Esperando a que el puerto {_forwardedPort} esté disponible...");
69-
WaitForPort("127.0.0.1", _forwardedPort);
70166
}
71167

72168
public void Send(string command)
73169
{
74-
var remote = new RemoteLinuxBridgeConnection($"http://127.0.0.1:{_forwardedPort}/exec");
170+
if (_options == null)
171+
{
172+
KernelLog.Panic("[Preflight] Opciones de QEMU no definidas.");
173+
throw new ArgumentNullException(nameof(_options));
174+
}
175+
176+
var remote = new RemoteLinuxBridgeConnection($"http://127.0.0.1:{_options.Port}/exec");
75177
remote.Send(command);
76178
}
77179

@@ -93,7 +195,14 @@ private void WaitForPort(string host, int port, int timeoutSeconds = 15)
93195
{
94196
using var client = new TcpClient();
95197
client.Connect(host, port);
96-
KernelLog.Info($"[QEMU] VM escuchando en http://127.0.0.1:{_forwardedPort}");
198+
199+
if (_options == null)
200+
{
201+
KernelLog.Panic("[Preflight] Opciones de QEMU no definidas.");
202+
throw new ArgumentNullException(nameof(_options));
203+
}
204+
205+
KernelLog.Info($"[QEMU] VM escuchando en http://127.0.0.1:{_options.Port}");
97206
return;
98207
}
99208
catch
@@ -106,9 +215,9 @@ private void WaitForPort(string host, int port, int timeoutSeconds = 15)
106215
throw new Exception("QEMU VM did not start in time.");
107216
}
108217

109-
private int FindFreePort(int startPort = 5000)
218+
private int FindFreePort(int startPort = 5000) // Busca un puerto libre a partir del puerto especificado
110219
{
111-
for (int port = startPort; port < startPort + 100; port++)
220+
for (int port = 0; port < startPort + 100; port++)
112221
{
113222
try
114223
{
@@ -134,5 +243,6 @@ public class QemuOptions
134243
public bool UseNographic { get; set; } = true;
135244
public string ExtraArgs { get; set; } = string.Empty;
136245
public int Port { get; set; } = 0; // 0 = buscar uno libre
137-
246+
public int StartPort { get; set; } = 5000;
247+
public string SharedFolder { get; set; } = "/path/to/share"; // ¡Personalizable!
138248
}

uso.txt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,15 @@ qemu-system-x86_64 \
1313
-- con este comando levanto desde sharpcore el linux virtualizado
1414

1515
dotnet run --project ./ShpCore.CLI.csproj vm vm-start --image /home/ivanr013/Escritorio/dev/SharpCore.UbuntuEnv.Builder/Output/alpine-
16-
sharpcore.qcow2
16+
sharpcore.qcow2
17+
18+
19+
-- para debug --
20+
21+
qemu-system-x86_64 \
22+
-hda /home/ivanr013/Escritorio/dev/SSL-Environment/Output/alpine-sharpcore.qcow2 \
23+
-m 2048 \
24+
-net nic \
25+
-net user,hostfwd=tcp::5000-:5000 \
26+
-virtfs local,path=/home/ivanr013/sharpcore-share,mount_tag=hostshare,security_model=passthrough,id=hostshare \
27+
-nographic

0 commit comments

Comments
 (0)