mirror of https://git.48k.eu/ogcp
ogcp: add disk restrictions in partition and format
Use common disk space across all the selected clients. Show dynamic disk partition graph in the partition view. Limit partition sizes dynamically in the form. Move js code to handle the addition and removal of partitions into the html file to debloat ogcp.js and keep the functions local to the only file they manipulate.master
parent
aab70b0222
commit
bcd18241c7
|
@ -341,50 +341,6 @@ function unfoldAll() {
|
|||
$('#scopes .collapse').collapse('show');
|
||||
}
|
||||
|
||||
function AddPartition(evt) {
|
||||
const target = $($(evt).data("target"));
|
||||
const oldrow = target.find("[data-toggle=fieldset-entry]:last");
|
||||
const row = oldrow.clone(true, true);
|
||||
const elem_id = row.find(".form-control")[0].id;
|
||||
const elem_num = parseInt(elem_id.replace(/(.*)-(\d{1,4})/m, '$2')) + 1;
|
||||
// Increment WTForms unique identifiers
|
||||
row.find('.form-control').each(function() {
|
||||
const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${elem_num}-$3`);
|
||||
$(this).attr('name', id).attr('id', id).val('').removeAttr("checked");
|
||||
});
|
||||
let part_field = row.find('td').filter(':first')[0];
|
||||
part_field.innerText = elem_num + 1;
|
||||
row.show();
|
||||
oldrow.after(row);
|
||||
}
|
||||
|
||||
function RemovePartition(evt) {
|
||||
const target = $(evt).parent().parent();
|
||||
const table = target.parent();
|
||||
|
||||
if (table[0].children.length > 1) {
|
||||
target.remove();
|
||||
// Reassign rows ids
|
||||
table.find('tr').each(function(index) {
|
||||
function update_references() {
|
||||
const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${index}-$3`);
|
||||
$(this).attr('name', id).attr('id', id);
|
||||
}
|
||||
|
||||
let part_field = $(this).find('td').filter(':first')[0];
|
||||
part_field.innerText = index + 1;
|
||||
$(this).find('input').filter(':first').each(update_references);
|
||||
$(this).find('.form-control').each(update_references);
|
||||
});
|
||||
} else {
|
||||
table.find('tr').each(function(index) {
|
||||
$(this).find('.form-control').each(function() {
|
||||
$(this).val('').removeAttr("checked");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function checkImageServer() {
|
||||
const images = $('input:checkbox[form|="imagesForm"][name!="image-server"]')
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
<td>{{ partition.partition.data }}</td>
|
||||
<td>{{ partition.part_type(class_="form-control") }}</td>
|
||||
<td>{{ partition.fs(class_="form-control") }}</td>
|
||||
<td>{{ partition.size(class_="form-control") }}</td>
|
||||
<td>{{ partition.size(class_="form-control", oninput="handleEdit(this)") }}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="button" onclick="RemovePartition(this)">
|
||||
{{ _('Remove') }}
|
||||
|
@ -78,4 +78,161 @@
|
|||
{{ _('Accept') }}
|
||||
</button>
|
||||
|
||||
<div class="card text-center">
|
||||
<div class="card-header">
|
||||
{{ _('Partition graph') }}
|
||||
</div>
|
||||
<div class="card-body mx-auto col-7">
|
||||
<canvas id="partitionChart" class="mb-2"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="{{ url_for('static', filename='AdminLTE/plugins/jquery/jquery.min.js') }}"></script>
|
||||
<!-- ChartJS -->
|
||||
<script src="{{ url_for('static', filename='AdminLTE/plugins/chart.js/Chart.min.js') }}"></script>
|
||||
<script>
|
||||
const usedColor = 'rgb(255, 99, 132)';
|
||||
const freeColor = 'rgb(54, 162, 235)';
|
||||
let diskSize = {{ disk_size }};
|
||||
|
||||
let chartConfig = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{
|
||||
label: 'Partitions',
|
||||
data: [],
|
||||
backgroundColor: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Doughnut Chart'
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let partitionChart = new Chart(
|
||||
document.getElementById('partitionChart'),
|
||||
chartConfig,
|
||||
);
|
||||
|
||||
function addPartitionToChart(chart, label, value, bgColor) {
|
||||
chart.data.labels.push(label)
|
||||
chart.data.datasets[0].data.push(value);
|
||||
chart.data.datasets[0].backgroundColor.push(bgColor);
|
||||
}
|
||||
|
||||
function resetChart() {
|
||||
partitionChart.data.labels = [];
|
||||
partitionChart.data.datasets[0].data = [];
|
||||
partitionChart.data.datasets[0].backgroundColor = [];
|
||||
}
|
||||
|
||||
function updateChart() {
|
||||
resetChart();
|
||||
|
||||
let freeSpace = diskSize;
|
||||
let partNum = 1;
|
||||
$('#partitionsTable tr').each(function() {
|
||||
let partitionSize = parseInt($(this).find('td').eq(3).find('input').val().trim());
|
||||
if (isNaN(partitionSize)) {
|
||||
partitionSize = 0;
|
||||
}
|
||||
freeSpace -= partitionSize;
|
||||
addPartitionToChart(partitionChart, 'Partition ' + partNum, partitionSize, usedColor);
|
||||
partNum++;
|
||||
});
|
||||
|
||||
addPartitionToChart(partitionChart, 'Free', Math.max(freeSpace, 0), freeColor);
|
||||
partitionChart.update();
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
updateChart();
|
||||
});
|
||||
|
||||
function handleEdit(element) {
|
||||
const numericValue = parseInt(element.value);
|
||||
|
||||
if (isNaN(numericValue)) {
|
||||
updateChart();
|
||||
return;
|
||||
}
|
||||
|
||||
let freeSpace = diskSize;
|
||||
$('#partitionsTable tr').each(function() {
|
||||
let partitionSize = parseInt($(this).find('td').eq(3).find('input').val().trim());
|
||||
if (isNaN(partitionSize)) {
|
||||
partitionSize = 0;
|
||||
}
|
||||
freeSpace -= partitionSize;
|
||||
});
|
||||
|
||||
if (freeSpace < 0) {
|
||||
element.value = numericValue + freeSpace;
|
||||
}
|
||||
|
||||
updateChart();
|
||||
}
|
||||
|
||||
function AddPartition(evt) {
|
||||
const target = $($(evt).data("target"));
|
||||
const oldrow = target.find("[data-toggle=fieldset-entry]:last");
|
||||
const row = oldrow.clone(true, true);
|
||||
const elem_id = row.find(".form-control")[0].id;
|
||||
const elem_num = parseInt(elem_id.replace(/(.*)-(\d{1,4})/m, '$2')) + 1;
|
||||
// Increment WTForms unique identifiers
|
||||
row.find('.form-control').each(function() {
|
||||
const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${elem_num}-$3`);
|
||||
$(this).attr('name', id).attr('id', id).val('').removeAttr("checked");
|
||||
});
|
||||
let part_field = row.find('td').filter(':first')[0];
|
||||
part_field.innerText = elem_num + 1;
|
||||
row.show();
|
||||
oldrow.after(row);
|
||||
|
||||
updateChart();
|
||||
}
|
||||
|
||||
function RemovePartition(evt) {
|
||||
const target = $(evt).parent().parent();
|
||||
const table = target.parent();
|
||||
|
||||
if (table[0].children.length > 1) {
|
||||
target.remove();
|
||||
// Reassign rows ids
|
||||
table.find('tr').each(function(index) {
|
||||
function update_references() {
|
||||
const id = $(this).attr('id').replace(/(.*)-(\d{1,4})-(.*)/, `$1-${index}-$3`);
|
||||
$(this).attr('name', id).attr('id', id);
|
||||
}
|
||||
|
||||
let part_field = $(this).find('td').filter(':first')[0];
|
||||
part_field.innerText = index + 1;
|
||||
$(this).find('input').filter(':first').each(update_references);
|
||||
$(this).find('.form-control').each(update_references);
|
||||
});
|
||||
} else {
|
||||
table.find('tr').each(function(index) {
|
||||
$(this).find('.form-control').each(function() {
|
||||
$(this).val('').removeAttr("checked");
|
||||
});
|
||||
});
|
||||
}
|
||||
updateChart();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -108,7 +108,7 @@
|
|||
<!-- ChartJS -->
|
||||
<script src="{{ url_for('static', filename='AdminLTE/plugins/chart.js/Chart.min.js') }}"></script>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/ogcp.js') }}?v=15"></script>
|
||||
<script src="{{ url_for('static', filename='js/ogcp.js') }}?v=16"></script>
|
||||
|
||||
<script>
|
||||
// error messages
|
||||
|
|
|
@ -682,6 +682,7 @@ def action_setup_select():
|
|||
@login_required
|
||||
def action_setup_show():
|
||||
args = request.args.copy()
|
||||
disk_size = None
|
||||
|
||||
default_disk = 1
|
||||
selected_disk = int(args.pop('disk', default_disk))
|
||||
|
@ -694,35 +695,47 @@ def action_setup_show():
|
|||
ips = set(args['ips'].split(' '))
|
||||
base_client = args['selected_client']
|
||||
|
||||
try:
|
||||
db_partitions = get_client_setup(base_client)
|
||||
except ServerError:
|
||||
return ogserver_down('commands')
|
||||
except ServerErrorCode:
|
||||
return ogserver_error('commands')
|
||||
if not db_partitions:
|
||||
for ip in ips:
|
||||
try:
|
||||
setup_data = get_client_setup(ip)
|
||||
except ServerError:
|
||||
return ogserver_down('commands')
|
||||
except ServerErrorCode:
|
||||
return ogserver_error('commands')
|
||||
|
||||
filtered_partitions = [p for p in setup_data
|
||||
if p.get('disk') == selected_disk]
|
||||
if not filtered_partitions:
|
||||
continue
|
||||
|
||||
if ip == base_client:
|
||||
target_partitions = filtered_partitions
|
||||
|
||||
client_disk_size = filtered_partitions[0]['size'] // 1024
|
||||
if disk_size:
|
||||
disk_size = min(disk_size, client_disk_size)
|
||||
else:
|
||||
disk_size = client_disk_size
|
||||
|
||||
if not target_partitions:
|
||||
flash(_('Partition information is not available. Boot client in ogLive mode to obtain it'), category='error')
|
||||
return redirect(url_for('commands'))
|
||||
filtered_partitions = [p for p in db_partitions
|
||||
if p.get('disk') == selected_disk]
|
||||
|
||||
disk_partition = 0
|
||||
disks = [d.get('disk') for d in db_partitions
|
||||
disks = [d.get('disk') for d in target_partitions
|
||||
if d.get('partition') == disk_partition]
|
||||
|
||||
form = SetupForm()
|
||||
form.ips.data = ips_str
|
||||
form.disk.data = selected_disk
|
||||
# If partition table is empty, set MSDOS
|
||||
form.disk_type.data = filtered_partitions[0]['code'] or 1
|
||||
form.disk_type.data = target_partitions[0]['code'] or 1
|
||||
|
||||
disk_size = filtered_partitions[0]['size'] // 1024
|
||||
|
||||
# Make form.partition length equal to (filtered_partitions - 1) length
|
||||
diff = len(filtered_partitions) - 1 - len(form.partitions)
|
||||
# Make form.partition length equal to (target_partitions - 1) length
|
||||
diff = len(target_partitions) - 1 - len(form.partitions)
|
||||
[form.partitions.append_entry() for unused in range(diff)]
|
||||
|
||||
for partition, db_part in zip(form.partitions, filtered_partitions[1:]):
|
||||
for partition, db_part in zip(form.partitions, target_partitions[1:]):
|
||||
partition.partition.data = str(db_part['partition'])
|
||||
partition.part_type.data = db_part['code']
|
||||
partition.fs.data = db_part['filesystem']
|
||||
|
|
Loading…
Reference in New Issue