mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2024-11-21 15:57:24 -06:00
Allow logged-in users to update ispConfig.py via web UI
1) lqos_config understands writing to a new ispConfig.py file, copying the previous one and amending to avoid changing any not-covered data. 2) The web UI can adjust the config, upload a new one and it is saved. Signed-off-by: Herbert Wolverson <herberticus@gmail.com>
This commit is contained in:
parent
bebcbaf7c6
commit
393a489bca
2
.gitignore
vendored
2
.gitignore
vendored
@ -37,6 +37,8 @@ src/ShapedDevices.csv
|
||||
src/ShapedDevices.lastLoaded.csv
|
||||
src/network.json
|
||||
src/ispConfig.py
|
||||
src/ispConfig.py.backup
|
||||
src/ispConfig.py.test
|
||||
src/statsByCircuit.json
|
||||
src/statsByParentNode.json
|
||||
src/lastGoodConfig.json
|
||||
|
@ -1,6 +1,6 @@
|
||||
use anyhow::{Error, Result};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::{fs, path::{Path, PathBuf}};
|
||||
use std::{fs::{self, remove_file, OpenOptions, read_to_string}, path::{Path, PathBuf}, io::Write};
|
||||
use crate::etc;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@ -126,6 +126,51 @@ impl LibreQoSConfig {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save(&self) -> Result<()> {
|
||||
// Find the config
|
||||
let cfg = etc::EtcLqos::load()?;
|
||||
let base_path = Path::new(&cfg.lqos_directory);
|
||||
let final_path = base_path.join("ispConfig.py");
|
||||
let backup_path = base_path.join("ispConfig.py.backup");
|
||||
std::fs::copy(&final_path, &backup_path)?;
|
||||
|
||||
// Load existing file
|
||||
let original = read_to_string(final_path)?;
|
||||
|
||||
// Temporary
|
||||
let final_path = base_path.join("ispConfig.py.test");
|
||||
|
||||
// Update config entries line by line
|
||||
let mut config = String::new();
|
||||
for line in original.split('\n') {
|
||||
let mut line = line.to_string();
|
||||
if line.starts_with("interfaceA") { line = format!("interfaceA = '{}'", self.isp_interface); }
|
||||
if line.starts_with("interfaceB") { line = format!("interfaceB = '{}'", self.internet_interface); }
|
||||
if line.starts_with("OnAStick") { line = format!("OnAStick = {}", if self.on_a_stick_mode { "True" } else { "False" } ); }
|
||||
if line.starts_with("StickVlanA") { line = format!("StickVlanA = {}", self.stick_vlans.0); }
|
||||
if line.starts_with("StickVlanB") { line = format!("StickVlanB = {}", self.stick_vlans.1); }
|
||||
if line.starts_with("sqm") { line = format!("sqm = '{}'", self.sqm); }
|
||||
if line.starts_with("upstreamBandwidthCapacityDownloadMbps") { line = format!("upstreamBandwidthCapacityDownloadMbps = {}", self.total_download_mbps); }
|
||||
if line.starts_with("upstreamBandwidthCapacityUploadMbps") { line = format!("upstreamBandwidthCapacityUploadMbps = {}", self.total_upload_mbps); }
|
||||
if line.starts_with("monitorOnlyMode") { line = format!("monitorOnlyMode = {}", if self.monitor_mode { "True" } else { "False" } ); }
|
||||
if line.starts_with("generatedPNDownloadMbps") { line = format!("generatedPNDownloadMbps = {}", self.generated_download_mbps); }
|
||||
if line.starts_with("generatedPNUploadMbps") { line = format!("generatedPNUploadMbps = {}", self.generated_upload_mbps); }
|
||||
if line.starts_with("useBinPackingToBalanceCPU") { line = format!("useBinPackingToBalanceCPU = {}", if self.use_binpacking { "True" } else { "False" } ); }
|
||||
if line.starts_with("enableActualShellCommands") { line = format!("enableActualShellCommands = {}", if self.enable_shell_commands { "True" } else { "False" } ); }
|
||||
if line.starts_with("runShellCommandsAsSudo") { line = format!("runShellCommandsAsSudo = {}", if self.run_as_sudo { "True" } else { "False" } ); }
|
||||
if line.starts_with("queuesAvailableOverride") { line = format!("queuesAvailableOverride = {}", self.override_queue_count); }
|
||||
config += &format!("{line}\n");
|
||||
}
|
||||
|
||||
// Actually save to disk
|
||||
if final_path.exists() {
|
||||
remove_file(&final_path)?;
|
||||
}
|
||||
let mut file = OpenOptions::new().write(true).create_new(true).open(&final_path)?;
|
||||
file.write_all(&config.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn split_at_equals(line: &str) -> String {
|
||||
|
@ -40,4 +40,10 @@ pub async fn get_current_lqosd_config(_auth: AuthGuard) -> NoCache<Json<EtcLqos>
|
||||
let config = lqos_config::EtcLqos::load().unwrap();
|
||||
println!("{:#?}", config);
|
||||
NoCache::new(Json(config))
|
||||
}
|
||||
|
||||
#[post("/api/python_config", data="<config>")]
|
||||
pub async fn update_python_config(_auth: AuthGuard, config: Json<LibreQoSConfig>) -> Json<String> {
|
||||
config.save().unwrap();
|
||||
Json("OK".to_string())
|
||||
}
|
@ -56,6 +56,7 @@ fn rocket() -> _ {
|
||||
config_control::get_nic_list,
|
||||
config_control::get_current_python_config,
|
||||
config_control::get_current_lqosd_config,
|
||||
config_control::update_python_config,
|
||||
auth_guard::create_first_user,
|
||||
auth_guard::login,
|
||||
auth_guard::admin_check,
|
||||
|
@ -57,7 +57,7 @@
|
||||
<h5 class="card-title"><i class="fa fa-users"></i> Configuration</h5>
|
||||
|
||||
<div class="col-sm-8 mx-auto" style="padding: 4px; margin-bottom: 4px;" id="controls">
|
||||
<a href="#" class="btn btn-primary"><i class="fa fa-save"></i> Save ispConfig.py</a>
|
||||
<a href="#" class="btn btn-primary" id="btnSaveIspConfig"><i class="fa fa-save"></i> Save ispConfig.py</a>
|
||||
<a href="#" class="btn btn-danger"><i class="fa fa-save"></i> Save /etc/lqos</a>
|
||||
<a href="#" class="btn btn-primary"><i class="fa fa-refresh"></i> Reload LibreQoS</a>
|
||||
<a href="#" class="btn btn-danger"><i class="fa fa-refresh"></i> (Re)Start lqosd</a>
|
||||
@ -383,6 +383,39 @@
|
||||
if (!is_admin) {
|
||||
$("#controls").html("<p class='alert alert-danger' role='alert'>You have to be an administrative user to change configuration.");
|
||||
$("#userManager").html("<p class='alert alert-danger' role='alert'>Only administrators can see/change user information.");
|
||||
} else {
|
||||
// Handle Saving ispConfig.py
|
||||
$("#btnSaveIspConfig").on('click', (data) => {
|
||||
let new_config = python_config;
|
||||
new_config.isp_interface = $("#nicCore").val();
|
||||
new_config.internet_interface = $("#nicInternet").val();
|
||||
new_config.on_a_stick_mode = $("#onAStick").prop('checked');
|
||||
new_config.stick_vlans[0] = Number($("#StickVLANCore").val());
|
||||
new_config.stick_vlans[1] = Number($("#StickVLANInternet").val());
|
||||
new_config.sqm = $("#sqmMode").val();
|
||||
new_config.total_download_mbps = Number($("#maxDownload").val());
|
||||
new_config.total_upload_mbps = Number($("#maxUpload").val());
|
||||
new_config.monitor_mode = $("#monitorMode").prop('checked');
|
||||
new_config.generated_download_mbps = Number($("#generatedDownload").val());
|
||||
new_config.generated_upload_mbps = Number($("#generatedUpload").val());
|
||||
new_config.use_binpacking = $("#binpacking").prop('checked');
|
||||
new_config.enable_shell_commands = $("#actualShellCommands").prop('checked');
|
||||
new_config.run_as_sudo = $("#useSudo").prop('checked');
|
||||
new_config.override_queue_count = Number($("#overrideQueues").val());
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/api/python_config",
|
||||
data: JSON.stringify(new_config),
|
||||
success: (data) => {
|
||||
if (data == "ERROR") {
|
||||
alert("Unable to create a first user.")
|
||||
} else {
|
||||
alert("Save Successful. Original backed up in ispConfig.py.backup. The window will now reload with the new configuration.");
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
$.get("/api/python_config", (data) => {
|
||||
python_config = data;
|
||||
|
Loading…
Reference in New Issue
Block a user