[pbs-devel] [PATCH proxmox-backup] add version API call
Mira Limbeck
m.limbeck at proxmox.com
Wed Nov 4 12:41:35 CET 2020
Adds an API call that returns all relevant packages, same as the version
API call in PVE.
In addition extens proxmox-backup-manager with the 'version' command
that prints the packages in a format similar to pveversion.
Signed-off-by: Mira Limbeck <m.limbeck at proxmox.com>
---
src/api2/node.rs | 148 +++++++++++++++++++++++++++++-
src/api2/types/mod.rs | 13 +++
src/bin/proxmox-backup-manager.rs | 40 +++++++-
src/tools/apt.rs | 3 +
4 files changed, 202 insertions(+), 2 deletions(-)
diff --git a/src/api2/node.rs b/src/api2/node.rs
index a19bea7e..8b0b439a 100644
--- a/src/api2/node.rs
+++ b/src/api2/node.rs
@@ -19,7 +19,7 @@ use proxmox::tools::websocket::WebSocket;
use proxmox::{identity, sortable};
use crate::api2::types::*;
-use crate::config::acl::PRIV_SYS_CONSOLE;
+use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_CONSOLE};
use crate::server::WorkerTask;
use crate::tools;
use crate::tools::ticket::{self, Empty, Ticket};
@@ -305,6 +305,151 @@ fn upgrade_to_websocket(
.boxed()
}
+#[api(
+ input: {
+ properties: {
+ node: {
+ schema: NODE_SCHEMA,
+ },
+ verbose: {
+ description: "Enable verbose output.",
+ type: Boolean,
+ optional: true,
+ default: false,
+ },
+ },
+ },
+ returns: {
+ description: "List of packages and their installed version.",
+ type: Array,
+ items: {
+ type: PackageInfo,
+ },
+ },
+ access: {
+ permission: &Permission::Privilege(&[], PRIV_SYS_AUDIT, false),
+ },
+)]
+/// Get package information for important Proxmox packages.
+pub fn get_version(verbose: bool) -> Result<Value, Error> {
+ const PACKAGES: [&str; 9] = [
+ "ifupdown2",
+ "libjs-extjs",
+ "proxmox-backup-docs",
+ "proxmox-backup-client",
+ "proxmox-mini-journalreader",
+ "proxmox-widget-toolkit",
+ "pve-xtermjs",
+ "smartmontools",
+ "zfsutils-linux",
+ ];
+
+ let running_kernel = nix::sys::utsname::uname().release().to_owned();
+ let mut packages: Vec<PackageInfo> = Vec::new();
+ let proxmox_backup =
+ tools::apt::list_installed_apt_packages(|fd| fd.package == "proxmox-backup", None);
+ packages.push(
+ proxmox_backup
+ .iter()
+ .map(|pkg| PackageInfo {
+ name: pkg.package.clone(),
+ version: pkg.old_version.clone(),
+ comment: Some(format!("running kernel: {}", &running_kernel)),
+ })
+ .next()
+ .unwrap_or(PackageInfo {
+ name: "proxmox-backup".to_owned(),
+ version: "not correctly installed".to_owned(),
+ comment: Some(format!("running kernel: {}", &running_kernel)),
+ }),
+ );
+
+ if !verbose {
+ return Ok(json!(packages));
+ }
+
+ let proxmox_backup_server =
+ tools::apt::list_installed_apt_packages(|fd| fd.package == "proxmox-backup-server", None);
+ packages.push(
+ proxmox_backup_server
+ .iter()
+ .map(|pkg| PackageInfo {
+ name: pkg.package.clone(),
+ version: pkg.old_version.clone(),
+ comment: Some(format!("running version: {}", &pkg.version)),
+ })
+ .next()
+ .unwrap_or(PackageInfo {
+ name: "proxmox-backup-server".to_owned(),
+ version: "not correctly installed".to_owned(),
+ comment: None,
+ }),
+ );
+
+ let mut pve_kernel_pkgs = tools::apt::list_installed_apt_packages(
+ |fd| {
+ if fd.package.starts_with("pve-kernel") {
+ return true;
+ }
+ false
+ },
+ None,
+ );
+ let cache = apt_pkg_native::Cache::get_singleton();
+ pve_kernel_pkgs.sort_by(|left, right| {
+ cache.compare_versions(&left.old_version, &right.old_version).reverse()
+ });
+
+ for pkg in pve_kernel_pkgs.iter().map(|pkg| PackageInfo {
+ name: pkg.package.clone(),
+ version: if pkg.old_version.is_empty() {
+ "not correctly installed".to_owned()
+ } else {
+ pkg.old_version.clone()
+ },
+ comment: None,
+ }) {
+ packages.push(pkg);
+ }
+
+ let mut pbs_pkgs = tools::apt::list_installed_apt_packages(
+ |fd| {
+ if PACKAGES.contains(&fd.package) {
+ return true;
+ }
+ false
+ },
+ None,
+ );
+ pbs_pkgs.sort_by(|left, right| left.package.cmp(&right.package));
+
+ // add packages we're interested in, but are not installed
+ // and the installed ones returned by list_installed_apt_packages
+ for pkg in PACKAGES.iter() {
+ let apt_pkg = pbs_pkgs.iter().find(|item| &item.package == pkg);
+ if apt_pkg.is_some() {
+ let apt_pkg = apt_pkg.unwrap();
+ packages.push(PackageInfo {
+ name: apt_pkg.package.clone(),
+ version: if apt_pkg.old_version.is_empty() {
+ "not correctly installed".to_owned()
+ } else {
+ apt_pkg.old_version.clone()
+ },
+ comment: None,
+ });
+ } else {
+ packages.push(PackageInfo {
+ name: pkg.to_string(),
+ version: "not correctly installed".to_owned(),
+ comment: None,
+ });
+ }
+ }
+
+ Ok(json!(packages))
+}
+
pub const SUBDIRS: SubdirMap = &[
("apt", &apt::ROUTER),
("disks", &disks::ROUTER),
@@ -320,6 +465,7 @@ pub const SUBDIRS: SubdirMap = &[
("tasks", &tasks::ROUTER),
("termproxy", &Router::new().post(&API_METHOD_TERMPROXY)),
("time", &time::ROUTER),
+ ("version", &Router::new().get(&API_METHOD_GET_VERSION)),
(
"vncwebsocket",
&Router::new().upgrade(&API_METHOD_WEBSOCKET),
diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs
index 7ee89f57..f52b1d37 100644
--- a/src/api2/types/mod.rs
+++ b/src/api2/types/mod.rs
@@ -1155,6 +1155,19 @@ pub struct APTUpdateInfo {
pub change_log_url: String,
}
+#[api()]
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+/// Pair of package name and version with optional comment.
+pub struct PackageInfo {
+ /// Package name
+ pub name: String,
+ /// Package version
+ pub version: String,
+ /// Optional comment
+ pub comment: Option<String>,
+}
+
#[api()]
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
diff --git a/src/bin/proxmox-backup-manager.rs b/src/bin/proxmox-backup-manager.rs
index 7499446b..bdfdfdfa 100644
--- a/src/bin/proxmox-backup-manager.rs
+++ b/src/bin/proxmox-backup-manager.rs
@@ -363,6 +363,42 @@ async fn report() -> Result<Value, Error> {
Ok(Value::Null)
}
+#[api(
+ input: {
+ properties: {
+ verbose: {
+ description: "Enable verbose output.",
+ type: Boolean,
+ optional: true,
+ default: false,
+ },
+ },
+ },
+)]
+/// Get package information for important Proxmox packages.
+async fn get_version(param: Value) -> Result<Value, Error> {
+ let client = connect()?;
+
+ let node = proxmox::tools::nodename();
+
+ let path = format!("api2/json/nodes/{}/version", node);
+
+ let mut result = client.get(&path, Some(param)).await?;
+
+ let data = result["data"].take();
+ let packages: Vec<PackageInfo> = serde_json::from_value(data)?;
+
+ for pkg in packages {
+ if pkg.comment.is_some() {
+ println!("{}: {} ({})", pkg.name, pkg.version, pkg.comment.unwrap());
+ } else {
+ println!("{}: {}", pkg.name, pkg.version);
+ }
+ }
+
+ Ok(Value::Null)
+}
+
fn main() {
proxmox_backup::tools::setup_safe_path_env();
@@ -396,7 +432,9 @@ fn main() {
)
.insert("report",
CliCommand::new(&API_METHOD_REPORT)
- );
+ )
+ .insert("version",
+ CliCommand::new(&API_METHOD_GET_VERSION));
diff --git a/src/tools/apt.rs b/src/tools/apt.rs
index 5800e0a2..fab8f998 100644
--- a/src/tools/apt.rs
+++ b/src/tools/apt.rs
@@ -136,6 +136,8 @@ fn get_changelog_url(
}
pub struct FilterData<'a> {
+ // package name
+ pub package: &'a str,
// this is version info returned by APT
pub installed_version: Option<&'a str>,
pub candidate_version: &'a str,
@@ -270,6 +272,7 @@ where
let mut long_desc = "".to_owned();
let fd = FilterData {
+ package: package.as_str(),
installed_version: current_version.as_deref(),
candidate_version: &candidate_version,
active_version: &version,
--
2.20.1
More information about the pbs-devel
mailing list