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 = `
Memoria:
${data.memory} MiB
Puerto VNC:
${data.vnc_port || 'No asignado'}
Discos:
| Dispositivo |
Tipo |
Ruta |
${data.disks.map(disk => `
| ${disk.target} |
${disk.type} |
${disk.source} |
`).join('')}
Interfaces de Red:
| MAC |
Red |
Modelo |
${data.interfaces.map(iface => `
| ${iface.mac} |
${iface.network} |
${iface.model} |
`).join('')}
`;
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();
});