Files
Ceph-Calculator/app/static/js/script.js

230 lines
8.8 KiB
JavaScript

function cephCalculator() {
return {
replicationType: 'replication',
replicas: 3,
minSize: 2,
k: 4,
m: 2,
storageUnit: 'TB',
nodes: [
{
osd_count: 4,
osd_size_gb: 1000
}
],
result: {
max_usage_percent: 0,
max_usage_gb: 0,
max_usage_tb: 0,
raw_total: 0
},
isCalculating: false,
init() {
const savedConfig = localStorage.getItem('lastConfig');
if (savedConfig) {
const config = JSON.parse(savedConfig);
Object.assign(this, config);
}
},
addNode() {
this.nodes.push({
osd_count: 4,
osd_size_gb: this.storageUnit === 'TB' ? 1000 : 1
});
},
removeNode(nodeIndex) {
this.nodes.splice(nodeIndex, 1);
if (this.nodes.length === 0) {
this.addNode();
}
},
getOsdSizeInGB(size) {
return this.storageUnit === 'TB' ? size * 1024 : size;
},
calculateCapacity() {
const data = {
replication_type: this.replicationType,
replicas: parseInt(this.replicas),
k: parseInt(this.k),
m: parseInt(this.m),
nodes: this.nodes.map(node => ({
osd_count: parseInt(node.osd_count),
osd_size_gb: this.getOsdSizeInGB(parseFloat(node.osd_size_gb))
})),
min_size: parseInt(this.minSize),
storage_unit: this.storageUnit
};
this.isCalculating = true;
fetch('/calculate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content')
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
this.result = data;
})
.catch(error => {
console.error('Fehler bei der Berechnung:', error);
alert('Es ist ein Fehler bei der Berechnung aufgetreten. Bitte versuchen Sie es erneut.');
})
.finally(() => {
this.isCalculating = false;
});
},
exportConfig() {
const config = {
replicationType: this.replicationType,
replicas: this.replicas,
minSize: this.minSize,
k: this.k,
m: this.m,
storageUnit: this.storageUnit,
nodes: this.nodes,
result: this.result
};
const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'ceph-config.json';
a.click();
URL.revokeObjectURL(url);
},
importConfig(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
try {
const config = JSON.parse(e.target.result);
Object.assign(this, config);
// Berechne automatisch nach dem Import
this.calculateCapacity();
} catch (error) {
alert('Fehler beim Importieren der Konfiguration. Bitte überprüfen Sie das Dateiformat.');
}
};
reader.readAsText(file);
},
generatePDF() {
if (!this.result.raw_total) {
alert('Bitte führen Sie zuerst eine Berechnung durch.');
return;
}
// Validiere die Daten vor dem Senden
if (!this.nodes || this.nodes.length === 0) {
alert('Bitte fügen Sie mindestens einen Node hinzu.');
return;
}
// Validiere die Node-Daten
for (let i = 0; i < this.nodes.length; i++) {
const node = this.nodes[i];
if (!node.osd_count || node.osd_count < 1) {
alert(`Bitte geben Sie eine gültige Anzahl von OSDs für Node ${i + 1} ein.`);
return;
}
if (!node.osd_size_gb || node.osd_size_gb <= 0) {
alert(`Bitte geben Sie eine gültige OSD-Größe für Node ${i + 1} ein.`);
return;
}
}
const data = {
replication_type: this.replicationType,
replicas: parseInt(this.replicas),
min_size: parseInt(this.minSize),
k: parseInt(this.k),
m: parseInt(this.m),
storage_unit: this.storageUnit,
nodes: this.nodes.map(node => ({
osd_count: parseInt(node.osd_count),
osd_size_gb: parseFloat(this.getOsdSizeInGB(parseFloat(node.osd_size_gb)))
})),
result: {
raw_total: parseFloat(this.result.raw_total),
max_usage_percent: parseFloat(this.result.max_usage_percent),
max_usage_gb: parseFloat(this.result.max_usage_gb),
max_usage_tb: parseFloat(this.result.max_usage_tb),
node_failure_tolerance: Boolean(this.result.node_failure_tolerance),
node_failure_info: String(this.result.node_failure_info || ''),
multi_failure_tolerance: Boolean(this.result.multi_failure_tolerance),
max_failure_nodes: parseInt(this.result.max_failure_nodes || 0),
osd_failure_tolerance: Boolean(this.result.osd_failure_tolerance),
osd_failure_info: String(this.result.osd_failure_info || '')
}
};
// Zeige Ladeindikator
const button = document.querySelector('button[onclick="generatePDF()"]');
const originalText = button.innerHTML;
button.innerHTML = '<span class="flex items-center"><svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>Generiere PDF...</span>';
button.disabled = true;
// Hole CSRF-Token
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (!csrfToken) {
alert('CSRF-Token nicht gefunden. Bitte laden Sie die Seite neu.');
button.innerHTML = originalText;
button.disabled = false;
return;
}
fetch('/generate-pdf', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
return response.json().then(err => {
throw new Error(err.error || `HTTP error! status: ${response.status}`);
});
}
return response.blob();
})
.then(blob => {
if (!blob || blob.size === 0) {
throw new Error('Die generierte PDF-Datei ist leer');
}
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'ceph-report.pdf';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
})
.catch(error => {
console.error('Fehler bei der PDF-Generierung:', error);
alert(`Fehler bei der PDF-Generierung: ${error.message}`);
})
.finally(() => {
// Stelle den Button wieder her
button.innerHTML = originalText;
button.disabled = false;
});
}
};
}