]> git.proxmox.com Git - proxmox-backup.git/blobdiff - src/api2/node/apt.rs
split out pbs-runtime module
[proxmox-backup.git] / src / api2 / node / apt.rs
index 765ea52510c6bece8ded95a7a9acfa242b5ca207..054c8813e7f18b4d34b0762a5ef506df253f57b4 100644 (file)
@@ -5,10 +5,17 @@ use std::collections::HashMap;
 use proxmox::list_subdirs_api_method;
 use proxmox::api::{api, RpcEnvironment, RpcEnvironmentType, Permission};
 use proxmox::api::router::{Router, SubdirMap};
+use proxmox::tools::fs::{replace_file, CreateOptions};
 
-use crate::server::WorkerTask;
-use crate::tools::{apt, http, subscription};
+use proxmox_http::ProxyConfig;
 
+use crate::config::node;
+use crate::server::WorkerTask;
+use crate::tools::{
+    apt,
+    pbs_simple_http,
+    subscription,
+};
 use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
 use crate::api2::types::{Authid, APTUpdateInfo, NODE_SCHEMA, UPID_SCHEMA};
 
@@ -35,24 +42,49 @@ use crate::api2::types::{Authid, APTUpdateInfo, NODE_SCHEMA, UPID_SCHEMA};
 /// List available APT updates
 fn apt_update_available(_param: Value) -> Result<Value, Error> {
 
-    match apt::pkg_cache_expired() {
-        Ok(false) => {
-            if let Ok(Some(cache)) = apt::read_pkg_state() {
-                return Ok(json!(cache.package_status));
-            }
-        },
-        _ => (),
+    if let Ok(false) = apt::pkg_cache_expired() {
+        if let Ok(Some(cache)) = apt::read_pkg_state() {
+            return Ok(json!(cache.package_status));
+        }
     }
 
     let cache = apt::update_cache()?;
 
-    return Ok(json!(cache.package_status));
+    Ok(json!(cache.package_status))
+}
+
+pub fn update_apt_proxy_config(proxy_config: Option<&ProxyConfig>) -> Result<(), Error> {
+
+    const PROXY_CFG_FN: &str = "/etc/apt/apt.conf.d/76pveproxy"; // use same file as PVE
+
+    if let Some(proxy_config) = proxy_config {
+        let proxy = proxy_config.to_proxy_string()?;
+        let data = format!("Acquire::http::Proxy \"{}\";\n", proxy);
+        replace_file(PROXY_CFG_FN, data.as_bytes(), CreateOptions::new())
+    } else {
+        match std::fs::remove_file(PROXY_CFG_FN) {
+            Ok(()) => Ok(()),
+            Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(()),
+            Err(err) => bail!("failed to remove proxy config '{}' - {}", PROXY_CFG_FN, err),
+        }
+    }
+}
+
+fn read_and_update_proxy_config() -> Result<Option<ProxyConfig>, Error> {
+    let proxy_config = if let Ok((node_config, _digest)) = node::config() {
+        node_config.http_proxy()
+    } else {
+        None
+    };
+    update_apt_proxy_config(proxy_config.as_ref())?;
+
+    Ok(proxy_config)
 }
 
 fn do_apt_update(worker: &WorkerTask, quiet: bool) -> Result<(), Error> {
     if !quiet { worker.log("starting apt-get update") }
 
-    // TODO: set proxy /etc/apt/apt.conf.d/76pbsproxy like PVE
+    read_and_update_proxy_config()?;
 
     let mut command = std::process::Command::new("apt-get");
     command.arg("update");
@@ -88,10 +120,10 @@ fn do_apt_update(worker: &WorkerTask, quiet: bool) -> Result<(), Error> {
             },
             notify: {
                 type: bool,
-                description: r#"Send notification mail about new package updates availanle to the
+                description: r#"Send notification mail about new package updates available to the
                     email address configured for 'root@pam')."#,
-                optional: true,
                 default: false,
+                optional: true,
             },
             quiet: {
                 description: "Only produces output suitable for logging, omitting progress indicators.",
@@ -110,16 +142,13 @@ fn do_apt_update(worker: &WorkerTask, quiet: bool) -> Result<(), Error> {
 )]
 /// Update the APT database
 pub fn apt_update_database(
-    notify: Option<bool>,
-    quiet: Option<bool>,
+    notify: bool,
+    quiet: bool,
     rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<String, Error> {
 
     let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
-    let to_stdout = if rpcenv.env_type() == RpcEnvironmentType::CLI { true } else { false };
-    // FIXME: change to non-option in signature and drop below once we have proxmox-api-macro 0.2.3
-    let quiet = quiet.unwrap_or(API_METHOD_APT_UPDATE_DATABASE_PARAM_DEFAULT_QUIET);
-    let notify = notify.unwrap_or(API_METHOD_APT_UPDATE_DATABASE_PARAM_DEFAULT_NOTIFY);
+    let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
 
     let upid_str = WorkerTask::new_thread("aptupdate", None, auth_id, to_stdout, move |worker| {
         do_apt_update(&worker, quiet)?;
@@ -158,6 +187,7 @@ pub fn apt_update_database(
 }
 
 #[api(
+    protected: true,
     input: {
         properties: {
             node: {
@@ -196,16 +226,19 @@ fn apt_get_changelog(
         }
     }, Some(&name));
 
-    if pkg_info.len() == 0 {
+    if pkg_info.is_empty() {
         bail!("Package '{}' not found", name);
     }
 
+    let proxy_config = read_and_update_proxy_config()?;
+    let mut client = pbs_simple_http(proxy_config);
+
     let changelog_url = &pkg_info[0].change_log_url;
     // FIXME: use 'apt-get changelog' for proxmox packages as well, once repo supports it
     if changelog_url.starts_with("http://download.proxmox.com/") {
-        let changelog = crate::tools::runtime::block_on(http::get_string(changelog_url, None))
+        let changelog = pbs_runtime::block_on(client.get_string(changelog_url, None))
             .map_err(|err| format_err!("Error downloading changelog from '{}': {}", changelog_url, err))?;
-        return Ok(json!(changelog));
+        Ok(json!(changelog))
 
     } else if changelog_url.starts_with("https://enterprise.proxmox.com/") {
         let sub = match subscription::read_subscription()? {
@@ -227,9 +260,9 @@ fn apt_get_changelog(
         auth_header.insert("Authorization".to_owned(),
             format!("Basic {}", base64::encode(format!("{}:{}", key, id))));
 
-        let changelog = crate::tools::runtime::block_on(http::get_string(changelog_url, Some(&auth_header)))
+        let changelog = pbs_runtime::block_on(client.get_string(changelog_url, Some(&auth_header)))
             .map_err(|err| format_err!("Error downloading changelog from '{}': {}", changelog_url, err))?;
-        return Ok(json!(changelog));
+        Ok(json!(changelog))
 
     } else {
         let mut command = std::process::Command::new("apt-get");
@@ -237,7 +270,7 @@ fn apt_get_changelog(
         command.arg("-qq"); // don't display download progress
         command.arg(name);
         let output = crate::tools::run_command(command, None)?;
-        return Ok(json!(output));
+        Ok(json!(output))
     }
 }
 
@@ -303,10 +336,13 @@ pub fn get_versions() -> Result<Vec<APTUpdateInfo>, Error> {
         None,
     );
 
-    let running_kernel = nix::sys::utsname::uname().release().to_owned();
+    let running_kernel = format!(
+        "running kernel: {}",
+        nix::sys::utsname::uname().release().to_owned()
+    );
     if let Some(proxmox_backup) = pbs_packages.iter().find(|pkg| pkg.package == "proxmox-backup") {
         let mut proxmox_backup = proxmox_backup.clone();
-        proxmox_backup.extra_info = Some(format!("running kernel: {}", running_kernel));
+        proxmox_backup.extra_info = Some(running_kernel);
         packages.push(proxmox_backup);
     } else {
         packages.push(unknown_package("proxmox-backup".into(), Some(running_kernel)));