const API_BASE = window.location.origin; function getStateClass(state) { switch (state) { case 'running': return 'bg-success'; case 'shut off': return 'bg-secondary'; case 'paused': return 'bg-warning text-dark'; case 'crashed': return 'bg-danger'; default: return 'bg-light text-dark'; } } async function loadISOs() { try { const response = await fetch(`${API_BASE}/isos`); const data = await response.json(); const tbody = document.getElementById('isoTableBody'); tbody.innerHTML = ''; data.isos.forEach(iso => { const row = document.createElement('tr'); row.innerHTML = ` ${iso.name} `; tbody.appendChild(row); }); } catch (error) { console.error('Error loading ISOs:', error); alert('Error loading ISOs'); } } async function deleteISO(name) { if (confirm(`Delete ISO ${name}?`)) { try { const response = await fetch(`${API_BASE}/isos/${name}`, { method: 'DELETE' }); const result = await response.json(); if (response.ok) { alert(result.message); loadISOs(); loadISOsForSelect(); // Refresh the select } else { alert(result.error); } } catch (error) { console.error('Error deleting ISO:', error); alert('Error deleting ISO'); } } } async function loadISOsForSelect() { try { const response = await fetch(`${API_BASE}/isos`); const data = await response.json(); const select = document.getElementById('iso'); select.innerHTML = ''; data.isos.forEach(iso => { select.innerHTML += ``; }); } catch (error) { console.error('Error loading ISOs:', error); } } /* Load VMs and populate the table */ async function loadVMs() { try { const response = await fetch(`${API_BASE}/vms`); const data = await response.json(); const tbody = document.getElementById('vmTableBody'); tbody.innerHTML = ''; const select = document.getElementById('bootVM'); select.innerHTML = ''; const diskSelect = document.getElementById('diskVM'); diskSelect.innerHTML = ''; data.vms.forEach(vm => { const row = document.createElement('tr'); row.innerHTML = ` ${vm.id} ${vm.name} ${vm.state} ${vm.vnc_port ? `` : ''} `; tbody.appendChild(row); select.innerHTML += ``; diskSelect.innerHTML += ``; }); loadISOsForSelect(); // Load ISOs after loading VMs } catch (error) { console.error('Error loading VMs:', error); alert('Error loading VMs'); } } async function showVMInfo(name) { try { const response = await fetch(`${API_BASE}/vms/${name}/info`); const data = await response.json(); if (!response.ok) { alert(data.error || 'Error loading VM information'); return; } const modalBody = document.getElementById('infoModalBody'); modalBody.innerHTML = `
Nombre:

${data.name}

ID:

${data.id}

Estado:

${data.state}

Memoria:

${data.memory} MiB

CPUs:

${data.cpus}

Puerto VNC:

${data.vnc_port || 'No asignado'}

Discos:
${data.disks.map(disk => ` `).join('')}
Dispositivo Tipo Ruta
${disk.target} ${disk.type} ${disk.source}
Interfaces de Red:
${data.interfaces.map(iface => ` `).join('')}
MAC Red Modelo
${iface.mac} ${iface.network} ${iface.model}
`; const modal = new bootstrap.Modal(document.getElementById('infoModal')); modal.show(); } catch (error) { console.error('Error loading VM information:', error); alert('Error loading VM information'); } } async function startVM(name) { try { await fetch(`${API_BASE}/vms/${name}/start`); loadVMs(); } catch (error) { console.error('Error starting VM:', error); alert('Error starting VM'); } } async function stopVM(name) { try { await fetch(`${API_BASE}/vms/${name}/stop`); loadVMs(); } catch (error) { console.error('Error stopping VM:', error); alert('Error stopping VM'); } } async function deleteVM(name) { if (confirm(`Delete VM ${name}?`)) { try { await fetch(`${API_BASE}/vms/${name}`, { method: 'DELETE' }); loadVMs(); } catch (error) { console.error('Error deleting VM:', error); alert('Error deleting VM'); } } } function openVNC(vm_name) { fetch(`${API_BASE}/console/${vm_name}`) .then(response => response.json()) .then(data => { if (data.url) { window.open(data.url); } else { alert(data.error || 'Error opening console'); } }) .catch(error => { console.error('Error:', error); alert('Error opening console'); }); } document.getElementById('createVMForm').addEventListener('submit', async (e) => { e.preventDefault(); const name = document.getElementById('name').value; const memory = document.getElementById('memory').value; const disk_size = document.getElementById('disk_size').value; const cpus = document.getElementById('cpus').value; const iso = document.getElementById('iso').value; if (!iso) { alert('Por favor seleccione una imagen ISO'); return; } try { const response = await fetch(`${API_BASE}/vms?name=${name}&memory=${memory}&disk_size=${disk_size}&cpus=${cpus}&iso=${iso}`, { method: 'POST' }); let result; try { result = await response.json(); } catch { result = { error: `Server error: ${response.status} ${response.statusText}` }; } if (response.ok) { alert(result.message || 'VM creada correctamente'); loadVMs(); document.getElementById('createVMForm').reset(); } else { console.error('Error response:', result); alert(`Error: ${result.error || 'Error desconocido al crear VM'}`); } } catch (error) { console.error('Error creating VM:', error); alert(`Error de conexión: ${error.message}`); } }); if (document.getElementById('setBootOrderForm')) { document.getElementById('setBootOrderForm').addEventListener('submit', async (e) => { e.preventDefault(); const vm_name = document.getElementById('bootVM').value; const boot_order_str = document.getElementById('bootOrder').value; const order = boot_order_str.split(',').map(s => s.trim()); try { const response = await fetch(`${API_BASE}/vms/${vm_name}/boot-order`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ order: order }) }); const result = await response.json(); if (response.ok) { alert(result.message); loadVMs(); document.getElementById('setBootOrderForm').reset(); } else { alert(result.error); } } catch (error) { console.error('Error setting boot order:', error); alert('Error setting boot order'); } }); } if (document.getElementById('addDiskForm')) { document.getElementById('addDiskForm').addEventListener('submit', async (e) => { e.preventDefault(); const vm_name = document.getElementById('diskVM').value; const disk_name = document.getElementById('diskName').value; const disk_size = document.getElementById('diskSize').value; if (!vm_name) { alert('Por favor selecciona una máquina virtual'); return; } if (!disk_name) { alert('Por favor ingresa un nombre para el disco'); return; } if (!disk_size || disk_size <= 0) { alert('Por favor ingresa un tamaño de disco válido (> 0 GB)'); return; } try { const response = await fetch(`${API_BASE}/vms/${vm_name}/add-disk?disk_name=${disk_name}&disk_size=${disk_size}`, { method: 'POST' }); let result; try { result = await response.json(); } catch { result = { error: `Server error: ${response.status} ${response.statusText}` }; } if (response.ok) { alert(result.message || 'Disco agregado correctamente'); loadVMs(); document.getElementById('addDiskForm').reset(); } else { console.error('Add disk error:', result); alert(result.error || 'Error al agregar disco'); } } catch (error) { console.error('Error adding disk:', error); alert(`Error de conexión: ${error.message}`); } }); } if (document.getElementById('uploadIsoForm')) { document.getElementById('uploadIsoForm').addEventListener('submit', (e) => { e.preventDefault(); const fileInput = document.getElementById('isoFile'); const file = fileInput.files[0]; if (!file) { alert('Please select a file'); return; } const formData = new FormData(); formData.append('file', file); const progressContainer = document.getElementById('progressContainer'); const progressBar = document.getElementById('uploadProgress'); const uploadBtn = document.getElementById('uploadBtn'); // Show progress bar progressContainer.style.display = 'block'; uploadBtn.disabled = true; progressBar.style.width = '0%'; progressBar.textContent = '0%'; const xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', (e) => { if (e.lengthComputable) { const percentComplete = Math.round((e.loaded / e.total) * 100); progressBar.style.width = percentComplete + '%'; progressBar.textContent = percentComplete + '%'; } }); xhr.addEventListener('load', () => { if (xhr.status === 200) { const result = JSON.parse(xhr.responseText); alert(result.message); loadISOsForSelect(); document.getElementById('uploadIsoForm').reset(); progressContainer.style.display = 'none'; uploadBtn.disabled = false; } else { try { const result = JSON.parse(xhr.responseText); alert(result.error || 'Error uploading ISO'); } catch { alert('Error uploading ISO'); } progressContainer.style.display = 'none'; uploadBtn.disabled = false; } }); xhr.addEventListener('error', () => { alert('Error uploading ISO'); progressContainer.style.display = 'none'; uploadBtn.disabled = false; }); xhr.open('POST', `${API_BASE}/upload-iso`); xhr.send(formData); }); } // Initialize event listeners and load data when DOM is ready document.addEventListener('DOMContentLoaded', function() { loadVMs(); loadISOs(); });