+++ /dev/null
-CARGO ?= cargo
-
-ifeq ($(BUILD_MODE), release)
-CARGO_BUILD_ARGS += --release
-else
-endif
-
-.PHONY: all
-all:
-ifeq ($(BUILD_TARGET), pve)
- $(MAKE) pve
-else ifeq ($(BUILD_TARGET), pmg)
- $(MAKE) pmg
-else
- @echo "Run one of"
- @echo " - make pve"
- @echo " - make pmg"
-endif
-
-build:
- rm -rf build
- mkdir build
- echo system >build/rust-toolchain
- cp -a ./Cargo.toml ./build
- cp -a ./common ./build
- cp -a ./pve-rs ./build
- cp -a ./pmg-rs ./build
-# Replace the symlinks with copies of the common code in pve/pmg:
- cd build; for i in pve pmg; do \
- rm ./$$i-rs/common ; \
- mkdir ./$$i-rs/common ; \
- cp -R ./common/src ./$$i-rs/common/src ; \
- done
-# So the common packages end up in ./build, rather than ./build/common
- mv ./build/common/pkg ./build/common-pkg
-# Copy the workspace root into the sources
- mkdir build/pve-rs/.workspace
- cp -t build/pve-rs/.workspace Cargo.toml
- sed -i -e '/\[package\]/a\workspace = ".workspace"' build/pve-rs/Cargo.toml
-# Clear the member array and replace it with ".."
- sed -i -e '/^members = \[/,/^]$$/d' build/pve-rs/.workspace/Cargo.toml
- sed -i -e '/^\[workspace\]/a\members = [ ".." ]' build/pve-rs/.workspace/Cargo.toml
-# Copy the cargo config
- mkdir build/pve-rs/.cargo
- cp -t build/pve-rs/.cargo .cargo/config
--lib-package=Proxmox::Lib::Common \
--lib-prefix=Proxmox
-# Point to any generated pm file (Proxmox/ dir is already present in this package)
-Proxmox/RS/CalendarEvent.pm:
- $(PERLMOD_GENPACKAGE) \
+PERLMOD_PACKAGES := \
Proxmox::RS::APT::Repositories \
Proxmox::RS::CalendarEvent \
Proxmox::RS::Notify \
+ Proxmox::RS::SharedCache \
Proxmox::RS::Subscription
-all: Proxmox/RS/CalendarEvent.pm
+PERLMOD_PACKAGE_FILES := $(addsuffix .pm,$(subst ::,/,$(PERLMOD_PACKAGES)))
+
+Proxmox/RS: $(PERLMOD_PACKAGE_FILES)
+$(PERLMOD_PACKAGE_FILES) &:
+ $(PERLMOD_GENPACKAGE) $(PERLMOD_PACKAGES)
+
+all: Proxmox/RS
true
.PHONY: install
-install: Proxmox/RS/CalendarEvent.pm
+install: Proxmox/RS
install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORLIB)
find PVE \! -type d -print -exec install -Dm644 '{}' $(DESTDIR)$(PERL_INSTALLVENDORLIB)'/{}' ';'
find Proxmox \! -type d -print -exec install -Dm644 '{}' $(DESTDIR)$(PERL_INSTALLVENDORLIB)'/{}' ';'
clean:
rm -f *.deb *.dsc *.tar.* *.build *.buildinfo *.changes
rm -rf $(PACKAGE)-[0-9]*/
+ rm -rf Proxmox/RS
+libproxmox-rs-perl (0.3.4) bookworm; urgency=medium
+
+ * add bindings for proxmox-shared-cache crate
+
+ -- Proxmox Support Team <support@proxmox.com> Fri, 09 Aug 2024 14:21:41 +0200
+
libproxmox-rs-perl (0.3.3) bookworm; urgency=medium
* move ssl var probing to Proxmox::Lib::SslProbe
Architecture: any
# always bump both versioned Depends and Breaks, otherwise systems with both
# libpmg-rs-perl and libpve-rs-perl might load an outdated lib and break
-Depends: libpve-rs-perl (>= 0.8.5) | libpmg-rs-perl (>= 0.6.2),
+Depends: libpve-rs-perl (>= 0.8.10) | libpmg-rs-perl (>= 0.7.6),
${misc:Depends},
${perl:Depends},
${shlibs:Depends},
#[perlmod::package(name = "Proxmox::RS::APT::Repositories")]
pub mod export {
- use std::convert::TryInto;
- use anyhow::{bail, Error};
- use serde::{Deserialize, Serialize};
+ use anyhow::Error;
- use proxmox_apt::repositories::{
- APTRepositoryFile, APTRepositoryFileError, APTRepositoryHandle, APTRepositoryInfo,
- APTStandardRepository,
+ use proxmox_apt_api_types::{
+ APTChangeRepositoryOptions, APTGetChangelogOptions, APTRepositoriesResult,
+ APTRepositoryHandle, APTUpdateInfo, APTUpdateOptions,
};
-
- #[derive(Deserialize, Serialize)]
- #[serde(rename_all = "kebab-case")]
- /// Result for the repositories() function
- pub struct RepositoriesResult {
- /// Successfully parsed files.
- pub files: Vec<APTRepositoryFile>,
-
- /// Errors for files that could not be parsed or read.
- pub errors: Vec<APTRepositoryFileError>,
-
- /// Common digest for successfully parsed files.
- pub digest: String,
-
- /// Additional information/warnings about repositories.
- pub infos: Vec<APTRepositoryInfo>,
-
- /// Standard repositories and their configuration status.
- pub standard_repos: Vec<APTStandardRepository>,
- }
-
- #[derive(Deserialize, Serialize)]
- #[serde(rename_all = "kebab-case")]
- /// For changing an existing repository.
- pub struct ChangeProperties {
- /// Whether the repository should be enabled or not.
- pub enabled: Option<bool>,
- }
+ use proxmox_config_digest::ConfigDigest;
/// Get information about configured repositories and standard repositories for `product`.
#[export]
- pub fn repositories(product: &str) -> Result<RepositoriesResult, Error> {
- let (files, errors, digest) = proxmox_apt::repositories::repositories()?;
- let digest = hex::encode(&digest);
-
- let suite = proxmox_apt::repositories::get_current_release_codename()?;
-
- let infos = proxmox_apt::repositories::check_repositories(&files, suite);
- let standard_repos =
- proxmox_apt::repositories::standard_repositories(&files, product, suite);
-
- Ok(RepositoriesResult {
- files,
- errors,
- digest,
- infos,
- standard_repos,
- })
+ pub fn repositories(product: &str) -> Result<APTRepositoriesResult, Error> {
+ proxmox_apt::list_repositories(product)
}
/// Add the repository identified by the `handle` and `product`.
///
/// The `digest` parameter asserts that the configuration has not been modified.
#[export]
- pub fn add_repository(handle: &str, product: &str, digest: Option<&str>) -> Result<(), Error> {
- let (mut files, errors, current_digest) = proxmox_apt::repositories::repositories()?;
-
- let handle: APTRepositoryHandle = handle.try_into()?;
- let suite = proxmox_apt::repositories::get_current_release_codename()?;
-
- if let Some(digest) = digest {
- let expected_digest = hex::decode(digest)?;
- if expected_digest != current_digest {
- bail!("detected modified configuration - file changed by other user? Try again.");
- }
- }
-
- // check if it's already configured first
- for file in files.iter_mut() {
- for repo in file.repositories.iter_mut() {
- if repo.is_referenced_repository(handle, product, &suite.to_string()) {
- if repo.enabled {
- return Ok(());
- }
-
- repo.set_enabled(true);
- file.write()?;
-
- return Ok(());
- }
- }
- }
-
- let (repo, path) =
- proxmox_apt::repositories::get_standard_repository(handle, product, suite);
-
- if let Some(error) = errors.iter().find(|error| error.path == path) {
- bail!(
- "unable to parse existing file {} - {}",
- error.path,
- error.error,
- );
- }
-
- if let Some(file) = files
- .iter_mut()
- .find(|file| file.path.as_ref() == Some(&path))
- {
- file.repositories.push(repo);
-
- file.write()?;
- } else {
- let mut file = match APTRepositoryFile::new(&path)? {
- Some(file) => file,
- None => bail!("invalid path - {}", path),
- };
-
- file.repositories.push(repo);
-
- file.write()?;
- }
-
- Ok(())
+ pub fn add_repository(
+ handle: APTRepositoryHandle,
+ product: &str,
+ digest: Option<ConfigDigest>,
+ ) -> Result<(), Error> {
+ proxmox_apt::add_repository_handle(product, handle, digest)
}
/// Change the properties of the specified repository.
pub fn change_repository(
path: &str,
index: usize,
- options: ChangeProperties,
- digest: Option<&str>,
+ options: APTChangeRepositoryOptions,
+ digest: Option<ConfigDigest>,
) -> Result<(), Error> {
- let (mut files, errors, current_digest) = proxmox_apt::repositories::repositories()?;
-
- if let Some(digest) = digest {
- let expected_digest = hex::decode(digest)?;
- if expected_digest != current_digest {
- bail!("detected modified configuration - file changed by other user? Try again.");
- }
- }
+ proxmox_apt::change_repository(path, index, &options, digest)
+ }
- if let Some(error) = errors.iter().find(|error| error.path == path) {
- bail!("unable to parse file {} - {}", error.path, error.error);
- }
+ /// Retrieve the changelog of the specified package.
+ #[export]
+ pub fn get_changelog(options: APTGetChangelogOptions) -> Result<String, Error> {
+ proxmox_apt::get_changelog(&options)
+ }
- if let Some(file) = files
- .iter_mut()
- .find(|file| file.path.as_ref() == Some(&path.to_string()))
- {
- if let Some(repo) = file.repositories.get_mut(index) {
- if let Some(enabled) = options.enabled {
- repo.set_enabled(enabled);
- }
+ /// List available APT updates
+ ///
+ /// Automatically updates an expired package cache.
+ #[export]
+ pub fn list_available_apt_update(apt_state_file: &str) -> Result<Vec<APTUpdateInfo>, Error> {
+ proxmox_apt::list_available_apt_update(apt_state_file)
+ }
- file.write()?;
- } else {
- bail!("invalid index - {}", index);
- }
- } else {
- bail!("invalid path - {}", path);
- }
+ /// Update the APT database
+ ///
+ /// You should update the APT proxy configuration before running this.
+ #[export]
+ pub fn update_database(apt_state_file: &str, options: APTUpdateOptions) -> Result<(), Error> {
+ proxmox_apt::update_database(
+ apt_state_file,
+ &options,
+ |updates: &[&APTUpdateInfo]| -> Result<(), Error> {
+ // fixme: howto send notifgications?
+ crate::send_updates_available(updates)?;
+ Ok(())
+ },
+ )
+ }
- Ok(())
+ /// Get package information for a list of important product packages.
+ #[export]
+ pub fn get_package_versions(
+ product_virtual_package: &str,
+ api_server_package: &str,
+ running_api_server_version: &str,
+ package_list: Vec<&str>,
+ ) -> Result<Vec<APTUpdateInfo>, Error> {
+ proxmox_apt::get_package_versions(
+ product_virtual_package,
+ api_server_package,
+ running_api_server_version,
+ &package_list,
+ )
}
}
-use env_logger::{Builder, Env};
-use std::io::Write;
+use anyhow::Error;
/// Initialize logging. Should only be called once
pub fn init(env_var_name: &str, default_log_level: &str) {
- if let Err(e) = Builder::from_env(Env::new().filter_or(env_var_name, default_log_level))
- .format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
- .write_style(env_logger::WriteStyle::Never)
- .format_timestamp(None)
- .try_init()
+ if let Err(e) = default_log_level
+ .parse()
+ .map_err(Error::from)
+ .and_then(|default_log_level| proxmox_log::init_logger(env_var_name, default_log_level))
{
- eprintln!("could not set up env_logger: {e}");
+ eprintln!("could not set up env_logger: {e:?}");
}
}
mod calendar_event;
pub mod logger;
pub mod notify;
+pub mod shared_cache;
mod subscription;
fn send(
#[try_from_ref] this: &NotificationConfig,
severity: Severity,
- title: String,
- body: String,
+ template_name: String,
template_data: Option<JSONValue>,
fields: Option<HashMap<String, String>>,
) -> Result<(), HttpError> {
let config = this.config.lock().unwrap();
- let notification = Notification::new_templated(
+ let notification = Notification::from_template(
severity,
- title,
- body,
+ template_name,
template_data.unwrap_or_default(),
fields.unwrap_or_default(),
);
api::sendmail::add_endpoint(
&mut config,
- &SendmailConfig {
+ SendmailConfig {
name,
- mailto,
- mailto_user,
+ mailto: mailto.unwrap_or_default(),
+ mailto_user: mailto_user.unwrap_or_default(),
from_address,
author,
comment,
api::sendmail::update_endpoint(
&mut config,
name,
- &SendmailConfigUpdater {
+ SendmailConfigUpdater {
mailto,
mailto_user,
from_address,
let mut config = this.config.lock().unwrap();
api::gotify::add_endpoint(
&mut config,
- &GotifyConfig {
+ GotifyConfig {
name: name.clone(),
server,
comment,
filter: None,
origin: None,
},
- &GotifyPrivateConfig { name, token },
+ GotifyPrivateConfig { name, token },
)
}
api::gotify::update_endpoint(
&mut config,
name,
- &GotifyConfigUpdater {
+ GotifyConfigUpdater {
server,
comment,
disable,
},
- &GotifyPrivateConfigUpdater { token },
+ GotifyPrivateConfigUpdater { token },
delete.as_deref(),
digest.as_deref(),
)
let mut config = this.config.lock().unwrap();
api::smtp::add_endpoint(
&mut config,
- &SmtpConfig {
+ SmtpConfig {
name: name.clone(),
server,
port,
mode,
username,
- mailto,
- mailto_user,
+ mailto: mailto.unwrap_or_default(),
+ mailto_user: mailto_user.unwrap_or_default(),
from_address,
author,
comment,
disable,
origin: None,
},
- &SmtpPrivateConfig { name, password },
+ SmtpPrivateConfig { name, password },
)
}
api::smtp::update_endpoint(
&mut config,
name,
- &SmtpConfigUpdater {
+ SmtpConfigUpdater {
server,
port,
mode,
comment,
disable,
},
- &SmtpPrivateConfigUpdater { password },
+ SmtpPrivateConfigUpdater { password },
delete.as_deref(),
digest.as_deref(),
)
let mut config = this.config.lock().unwrap();
api::matcher::add_matcher(
&mut config,
- &MatcherConfig {
+ MatcherConfig {
name,
- match_severity,
- match_field,
- match_calendar,
- target,
+ match_severity: match_severity.unwrap_or_default(),
+ match_field: match_field.unwrap_or_default(),
+ match_calendar: match_calendar.unwrap_or_default(),
+ target: target.unwrap_or_default(),
mode,
invert_match,
comment,
api::matcher::update_matcher(
&mut config,
name,
- &MatcherConfigUpdater {
+ MatcherConfigUpdater {
match_severity,
match_field,
match_calendar,
--- /dev/null
+#[perlmod::package(name = "Proxmox::RS::SharedCache")]
+mod export {
+ use std::time::Duration;
+
+ use anyhow::Error;
+ use nix::sys::stat::Mode;
+ use serde::Deserialize;
+ use serde_json::Value as JSONValue;
+
+ use perlmod::Value;
+
+ use proxmox_shared_cache::SharedCache;
+ use proxmox_sys::fs::CreateOptions;
+
+ pub struct CacheWrapper(SharedCache);
+
+ perlmod::declare_magic!(Box<CacheWrapper> : &CacheWrapper as "Proxmox::RS::SharedCache");
+
+ #[derive(Deserialize)]
+ struct Params {
+ path: String,
+ owner: u32,
+ group: u32,
+ entry_mode: u32,
+ keep_old: u32,
+ }
+
+ #[export(raw_return)]
+ fn new(#[raw] class: Value, params: Params) -> Result<Value, Error> {
+ let options = CreateOptions::new()
+ .owner(params.owner.into())
+ .group(params.group.into())
+ .perm(Mode::from_bits_truncate(params.entry_mode));
+
+ Ok(perlmod::instantiate_magic!(&class, MAGIC => Box::new(
+ CacheWrapper (
+ SharedCache::new(params.path, options, params.keep_old)?
+ )
+ )))
+ }
+
+ #[export]
+ fn set(
+ #[try_from_ref] this: &CacheWrapper,
+ value: JSONValue,
+ lock_timeout: u64,
+ ) -> Result<(), Error> {
+ this.0.set(&value, Duration::from_secs(lock_timeout))
+ }
+
+ #[export]
+ fn get(#[try_from_ref] this: &CacheWrapper) -> Result<Option<JSONValue>, Error> {
+ this.0.get()
+ }
+
+ #[export]
+ fn get_last(
+ #[try_from_ref] this: &CacheWrapper,
+ number_of_old_entries: u32,
+ ) -> Result<Vec<JSONValue>, Error> {
+ this.0.get_last(number_of_old_entries)
+ }
+
+ #[export]
+ fn delete(#[try_from_ref] this: &CacheWrapper, lock_timeout: u64) -> Result<(), Error> {
+ this.0.delete(Duration::from_secs(lock_timeout))
+ }
+}
+++ /dev/null
-[source]
-[source.debian-packages]
-directory = "/usr/share/cargo/registry"
-[source.crates-io]
-replace-with = "debian-packages"
--- /dev/null
+[source]
+[source.debian-packages]
+directory = "/usr/share/cargo/registry"
+[source.crates-io]
+replace-with = "debian-packages"
+
+[profile.release]
+debug = true
[package]
name = "pmg-rs"
-version = "0.7.5"
+version = "0.7.6"
description = "PMG parts which have been ported to rust"
homepage = "https://www.proxmox.com"
authors = ["Proxmox Support Team <support@proxmox.com>"]
license = "AGPL-3"
repository = "https://git.proxmox.com/?p=proxmox.git"
-exclude = [
- "build",
- "debian",
- "PMG",
-]
+exclude = ["build", "debian", "PMG"]
[lib]
-crate-type = [ "cdylib" ]
+crate-type = ["cdylib"]
[dependencies]
anyhow = "1.0"
-env_logger = "0.10"
hex = "0.4"
http = "0.2.7"
libc = "0.2"
+log = "0.4.17"
nix = "0.26"
openssl = "0.10.40"
serde = "1.0"
serde_bytes = "0.11"
serde_json = "1.0"
+tracing = "0.1.37"
url = "2"
-perlmod = { version = "0.13.4", features = [ "exporter" ] }
+perlmod = { version = "0.13.4", features = ["exporter"] }
-proxmox-acme = { version = "0.5", features = ["client"] }
-proxmox-apt = "0.10"
+proxmox-acme = { version = "0.5", features = ["client", "api-types"] }
+proxmox-apt = { version = "0.11", features = ["cache"] }
+proxmox-apt-api-types = "1.0"
+proxmox-config-digest = "0.1"
proxmox-http = { version = "0.9", features = ["client-sync", "client-trait"] }
proxmox-http-error = "0.1.0"
-proxmox-notify = "0.3.1"
+proxmox-log = "0.2"
+proxmox-notify = "0.4"
+proxmox-shared-cache = "0.1.0"
proxmox-subscription = "0.4"
-proxmox-sys = "0.5"
-proxmox-tfa = { version = "4.0.4", features = ["api"] }
-proxmox-time = "1.1.3"
+proxmox-sys = "0.6"
+proxmox-tfa = { version = "5", features = ["api"] }
+proxmox-time = "2"
PMG::RS::OpenId \
PMG::RS::TFA
+PERLMOD_PACKAGE_FILES := $(addsuffix .pm,$(subst ::,/,$(PERLMOD_PACKAGES)))
+
ifeq ($(BUILD_MODE), release)
CARGO_BUILD_ARGS += --release
TARGET_DIR=release
all: PMG
cargo build $(CARGO_BUILD_ARGS)
-Proxmox PMG: Proxmox/Lib/PMG.pm
-Proxmox/Lib/PMG.pm: Fixup.pm
+Proxmox: Proxmox/Lib/PMG.pm
+PMG: $(PERLMOD_PACKAGE_FILES)
+Proxmox/Lib/PMG.pm $(PERLMOD_PACKAGE_FILES) &: Fixup.pm
$(PERLMOD_GENPACKAGE) $(PERLMOD_PACKAGES)
.PHONY: install
-install: target/release/libpmg_rs.so Proxmox/Lib/PMG.pm PMG
+install: target/release/libpmg_rs.so Proxmox/Lib/PMG.pm $(PERLMOD_PACKAGE_FILES)
install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto
install -m644 target/release/libpmg_rs.so $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto/libpmg_rs.so
install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORLIB)
git diff --exit-code --stat && git diff --exit-code --stat --staged
tar cf - $(DEBS) | ssh -X repoman@repo.proxmox.com upload --product pmg --dist $(DEB_DISTRIBUTION)
-$(BUILDDIR): src debian common/src Cargo.toml Makefile .cargo/config
+$(BUILDDIR): src debian common/src Cargo.toml Makefile .cargo/config.toml
rm -rf $(BUILDDIR) $(BUILDDIR).tmp
mkdir $(BUILDDIR).tmp
mkdir $(BUILDDIR).tmp/common
+libpmg-rs-perl (0.7.6) bookworm; urgency=medium
+
+ * upgrade to current rust crates or perlmod and proxmox-sys/tfa/apt/notify
+
+ * add bindings for proxmox-shared-cache crate
+
+ * use apt api method implementation from proxmox-apt crate
+
+ -- Proxmox Support Team <support@proxmox.com> Fri, 09 Aug 2024 14:19:56 +0200
+
libpmg-rs-perl (0.7.5) bookworm; urgency=medium
* add EAB binding support to ACME
librust-openssl-probe-dev (= 0.1.5-1~bpo12+pve1),
dh-cargo (>= 25),
librust-anyhow-1+default-dev,
- librust-env-logger-0.10+default-dev,
librust-hex-0.4+default-dev,
librust-http-0.2+default-dev (>= 0.2.7-~~),
librust-libc-0.2+default-dev,
+ librust-log-0.4+default-dev (>= 0.4.17-~~),
librust-nix-0.26+default-dev,
librust-openssl-0.10+default-dev (>= 0.10.40-~~),
librust-perlmod-0.13+default-dev (>= 0.13.4-~~),
librust-perlmod-0.13+exporter-dev (>= 0.13.4-~~),
+ librust-proxmox-acme-0.5+api-types-dev,
librust-proxmox-acme-0.5+client-dev,
librust-proxmox-acme-0.5+default-dev,
- librust-proxmox-apt-0.10+default-dev,
+ librust-proxmox-apt-0.11+cache-dev,
+ librust-proxmox-apt-0.11+default-dev,
+ librust-proxmox-apt-api-types-1+default-dev,
+ librust-proxmox-config-digest-0.1+default-dev,
librust-proxmox-http-0.9+client-sync-dev,
librust-proxmox-http-0.9+client-trait-dev,
librust-proxmox-http-0.9+default-dev,
librust-proxmox-http-error-0.1+default-dev,
- librust-proxmox-notify-0.3+default-dev (>= 0.3.1-~~),
+ librust-proxmox-log-0.2+default-dev,
+ librust-proxmox-notify-0.4+default-dev,
+ librust-proxmox-shared-cache-0.1+default-dev,
librust-proxmox-subscription-0.4+default-dev,
- librust-proxmox-sys-0.5+default-dev,
- librust-proxmox-tfa-4+api-dev (>= 4.0.4-~~),
- librust-proxmox-tfa-4+default-dev (>= 4.0.4-~~),
- librust-proxmox-time-1+default-dev (>= 1.1.3-~~),
+ librust-proxmox-sys-0.6+default-dev,
+ librust-proxmox-tfa-5+api-dev,
+ librust-proxmox-tfa-5+default-dev,
+ librust-proxmox-time-2+default-dev,
librust-serde-1+default-dev,
librust-serde-bytes-0.11+default-dev,
librust-serde-json-1+default-dev,
+ librust-tracing-0.1+default-dev (>= 0.1.37-~~),
librust-url-2+default-dev,
libstd-rust-dev <!nocheck>,
perlmod-bin (>= 0.2.0-3),
use anyhow::{format_err, Error};
use serde::{Deserialize, Serialize};
-use proxmox_acme::account::AccountData as AcmeAccountData;
+use proxmox_acme::types::AccountData as AcmeAccountData;
use proxmox_acme::{Account, Client};
/// Our on-disk format inherited from PVE's proxmox-acme code.
#[perlmod::package(name = "PMG::RS::APT::Repositories")]
mod export {
use anyhow::Error;
+ use proxmox_apt_api_types::{
+ APTChangeRepositoryOptions, APTRepositoriesResult, APTRepositoryHandle,
+ };
+ use proxmox_config_digest::ConfigDigest;
use crate::common::apt::repositories::export as common;
/// Get information about configured and standard repositories.
#[export]
- pub fn repositories() -> Result<common::RepositoriesResult, Error> {
+ pub fn repositories() -> Result<APTRepositoriesResult, Error> {
common::repositories("pmg")
}
///
/// The `digest` parameter asserts that the configuration has not been modified.
#[export]
- pub fn add_repository(handle: &str, digest: Option<&str>) -> Result<(), Error> {
+ pub fn add_repository(
+ handle: APTRepositoryHandle,
+ digest: Option<ConfigDigest>,
+ ) -> Result<(), Error> {
common::add_repository(handle, "pmg", digest)
}
pub fn change_repository(
path: &str,
index: usize,
- options: common::ChangeProperties,
- digest: Option<&str>,
+ options: APTChangeRepositoryOptions,
+ digest: Option<ConfigDigest>,
) -> Result<(), Error> {
common::change_repository(path, index, options, digest)
}
+use anyhow::Error;
+
+use proxmox_apt_api_types::APTUpdateInfo;
+
#[path = "../common/src/mod.rs"]
pub mod common;
perlmod::ffi::use_safe_putenv(true);
}
}
+
+pub fn send_updates_available(_updates: &[&APTUpdateInfo]) -> Result<(), Error> {
+ log::warn!("update notifications are not implemented for PMG yet");
+
+ Ok(())
+}
+++ /dev/null
-[source]
-[source.debian-packages]
-directory = "/usr/share/cargo/registry"
-[source.crates-io]
-replace-with = "debian-packages"
--- /dev/null
+[source]
+[source.debian-packages]
+directory = "/usr/share/cargo/registry"
+[source.crates-io]
+replace-with = "debian-packages"
+
+[profile.release]
+debug = true
[package]
name = "pve-rs"
-version = "0.8.7"
+version = "0.8.10"
description = "PVE parts which have been ported to Rust"
homepage = "https://www.proxmox.com"
authors = ["Proxmox Support Team <support@proxmox.com>"]
license = "AGPL-3"
repository = "https://git.proxmox.com/?p=proxmox.git"
-exclude = [
- "debian",
-]
+exclude = ["debian"]
[lib]
-crate-type = [ "cdylib" ]
+crate-type = ["cdylib"]
[dependencies]
anyhow = "1.0"
base32 = "0.4"
base64 = "0.13"
-env_logger = "0.10"
hex = "0.4"
http = "0.2.7"
libc = "0.2"
serde = "1.0"
serde_bytes = "0.11"
serde_json = "1.0"
+tracing = "0.1.37"
url = "2"
-perlmod = { version = "0.13", features = [ "exporter" ] }
+perlmod = { version = "0.13", features = ["exporter"] }
-proxmox-apt = "0.10.6"
+proxmox-apt = { version = "0.11", features = ["cache"] }
+proxmox-apt-api-types = "1.0"
+proxmox-config-digest = "0.1"
proxmox-http = { version = "0.9", features = ["client-sync", "client-trait"] }
proxmox-http-error = "0.1.0"
-proxmox-notify = { version = "0.3.1", features = ["pve-context"] }
+proxmox-log = "0.2"
+proxmox-notify = { version = "0.4", features = ["pve-context"] }
proxmox-openid = "0.10"
proxmox-resource-scheduling = "0.3.0"
+proxmox-shared-cache = "0.1.0"
proxmox-subscription = "0.4"
-proxmox-sys = "0.5"
-proxmox-tfa = { version = "4.0.4", features = ["api"] }
-proxmox-time = "1.1.3"
+proxmox-sys = "0.6"
+proxmox-tfa = { version = "5", features = ["api"] }
+proxmox-time = "2"
PVE::RS::ResourceScheduling::Static \
PVE::RS::TFA
+PERLMOD_PACKAGE_FILES := $(addsuffix .pm,$(subst ::,/,$(PERLMOD_PACKAGES)))
+
ifeq ($(BUILD_MODE), release)
CARGO_BUILD_ARGS += --release
TARGET_DIR=release
's@^sub libfile.*$$@sub libfile { "$(shell pwd)/target/$(TARGET_DIR)/libpve_rs.so"; }@' \
Proxmox/Lib/PVE.pm >test/Proxmox/Lib/PVE.pm
-Proxmox PVE: Proxmox/Lib/PVE.pm
-Proxmox/Lib/PVE.pm: Fixup.pm
+Proxmox: Proxmox/Lib/PVE.pm
+PVE: $(PERLMOD_PACKAGE_FILES)
+Proxmox/Lib/PVE.pm $(PERLMOD_PACKAGE_FILES) &: Fixup.pm
$(PERLMOD_GENPACKAGE) $(PERLMOD_PACKAGES)
check: all
$(MAKE) -C test test
.PHONY: install
-install: target/release/libpve_rs.so Proxmox/Lib/PVE.pm PVE
+install: target/release/libpve_rs.so Proxmox/Lib/PVE.pm $(PERLMOD_PACKAGE_FILES)
install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto
install -m644 target/release/libpve_rs.so $(DESTDIR)$(PERL_INSTALLVENDORARCH)/auto/libpve_rs.so
install -d -m755 $(DESTDIR)$(PERL_INSTALLVENDORLIB)
git diff --exit-code --stat && git diff --exit-code --stat --staged
tar cf - $(DEBS) | ssh -X repoman@repo.proxmox.com upload --product pve --dist $(DEB_DISTRIBUTION)
-$(BUILDDIR): src debian test common/src Cargo.toml Makefile .cargo/config
+$(BUILDDIR): src debian test common/src Cargo.toml Makefile .cargo/config.toml
rm -rf $(BUILDDIR) $(BUILDDIR).tmp
mkdir $(BUILDDIR).tmp
mkdir $(BUILDDIR).tmp/common
+libpve-rs-perl (0.8.10) bookworm; urgency=medium
+
+ * use apt api implementation from the proxmox-apt crate
+
+ * send apt update notification via proxmox-notify
+
+ * add bindings for proxmox-shared-cache crate
+
+ * update to current proxmox-time/tfa/sys/log crates
+
+ -- Proxmox Support Team <support@proxmox.com> Fri, 09 Aug 2024 13:42:38 +0200
+
+libpve-rs-perl (0.8.9) bookworm; urgency=medium
+
+ * update to notify 0.4: use file based notification templates
+
+ -- Proxmox Support Team <support@proxmox.com> Tue, 04 Jun 2024 11:01:03 +0200
+
+libpve-rs-perl (0.8.8) bookworm; urgency=medium
+
+ * notify: include 'hostname' and 'type' metadata fields for forwarded mails
+
+ * notify: smtp: forward original message instead of nesting
+
+ * notify: smtp: add 'Auto-Submitted' header to email body
+
+ * notify: api: allow resetting built-in targets if used by a matcher
+
+ -- Proxmox Support Team <support@proxmox.com> Wed, 10 Jan 2024 14:19:47 +0100
+
libpve-rs-perl (0.8.7) bookworm; urgency=medium
* notify: adapt to new matcher-based notification routing
librust-anyhow-1+default-dev,
librust-base32-0.4+default-dev,
librust-base64-0.13+default-dev,
- librust-env-logger-0.10+default-dev,
librust-hex-0.4+default-dev,
librust-http-0.2+default-dev (>= 0.2.7-~~),
librust-libc-0.2+default-dev,
librust-openssl-0.10+default-dev (>= 0.10.40-~~),
librust-perlmod-0.13+default-dev,
librust-perlmod-0.13+exporter-dev,
- librust-proxmox-apt-0.10+default-dev (>= 0.10.6-~~),
+ librust-proxmox-apt-0.11+cache-dev,
+ librust-proxmox-apt-0.11+default-dev,
+ librust-proxmox-apt-api-types-1+default-dev,
+ librust-proxmox-config-digest-0.1+default-dev,
librust-proxmox-http-0.9+client-sync-dev,
librust-proxmox-http-0.9+client-trait-dev,
librust-proxmox-http-0.9+default-dev,
librust-proxmox-http-error-0.1+default-dev,
- librust-proxmox-notify-0.3+default-dev (>= 0.3.1-~~),
- librust-proxmox-notify-0.3+pve-context-dev (>= 0.3.1-~~),
+ librust-proxmox-log-0.2+default-dev,
+ librust-proxmox-notify-0.4+default-dev,
+ librust-proxmox-notify-0.4+pve-context-dev,
librust-proxmox-openid-0.10+default-dev,
librust-proxmox-resource-scheduling-0.3+default-dev,
+ librust-proxmox-shared-cache-0.1+default-dev,
librust-proxmox-subscription-0.4+default-dev,
- librust-proxmox-sys-0.5+default-dev,
- librust-proxmox-tfa-4+api-dev (>= 4.0.4-~~),
- librust-proxmox-tfa-4+default-dev (>= 4.0.4-~~),
- librust-proxmox-time-1+default-dev (>= 1.1.3-~~),
+ librust-proxmox-sys-0.6+default-dev,
+ librust-proxmox-tfa-5+api-dev,
+ librust-proxmox-tfa-5+default-dev,
+ librust-proxmox-time-2+default-dev,
librust-serde-1+default-dev,
librust-serde-bytes-0.11+default-dev,
librust-serde-json-1+default-dev,
+ librust-tracing-0.1+default-dev (>= 0.1.37-~~),
librust-url-2+default-dev,
libstd-rust-dev <!nocheck>,
perlmod-bin (>= 0.2.0-3),
libproxmox-rs-perl (>= 0.3.3),
Breaks: libpve-access-control (<< 7.1-3),
libpve-common-perl (<< 7.1-4),
+ libpve-notify-perl (<< 8.0.7),
pve-manager (<< 7.1-11),
Description: PVE parts which have been ported to Rust - Rust source code
This package contains the source for the Rust pve-rs crate, packaged by
mod export {
use anyhow::Error;
+ use proxmox_apt_api_types::{
+ APTChangeRepositoryOptions, APTRepositoriesResult, APTRepositoryHandle,
+ };
+ use proxmox_config_digest::ConfigDigest;
+
use crate::common::apt::repositories::export as common;
/// Get information about configured and standard repositories.
#[export]
- pub fn repositories() -> Result<common::RepositoriesResult, Error> {
- common::repositories("pve")
+ pub fn repositories() -> Result<APTRepositoriesResult, Error> {
+ proxmox_apt::list_repositories("pve")
}
/// Add the repository identified by the `handle`.
///
/// The `digest` parameter asserts that the configuration has not been modified.
#[export]
- pub fn add_repository(handle: &str, digest: Option<&str>) -> Result<(), Error> {
+ pub fn add_repository(
+ handle: APTRepositoryHandle,
+ digest: Option<ConfigDigest>,
+ ) -> Result<(), Error> {
common::add_repository(handle, "pve", digest)
}
pub fn change_repository(
path: &str,
index: usize,
- options: common::ChangeProperties,
- digest: Option<&str>,
+ options: APTChangeRepositoryOptions,
+ digest: Option<ConfigDigest>,
) -> Result<(), Error> {
common::change_repository(path, index, options, digest)
}
//! Rust library for the Proxmox VE code base.
+use std::collections::HashMap;
+
+use anyhow::Error;
+use serde_json::json;
+
+use proxmox_apt_api_types::APTUpdateInfo;
+use proxmox_notify::{Config, Notification, Severity};
+
#[path = "../common/src/mod.rs"]
pub mod common;
#[export]
pub fn init() {
common::logger::init("PVE_LOG", "info");
- proxmox_notify::context::set_context(&PVE_CONTEXT)
+ proxmox_notify::context::set_context(&PVE_CONTEXT);
}
}
+
+fn send_notification(notification: &Notification) -> Result<(), Error> {
+ let config = proxmox_sys::fs::file_read_optional_string("/etc/pve/notifications.cfg")?
+ .unwrap_or_default();
+ let private_config =
+ proxmox_sys::fs::file_read_optional_string("/etc/pve/priv/notifications.cfg")?
+ .unwrap_or_default();
+
+ let config = Config::new(&config, &private_config)?;
+
+ proxmox_notify::api::common::send(&config, notification)?;
+
+ Ok(())
+}
+
+pub fn send_updates_available(updates: &[&APTUpdateInfo]) -> Result<(), Error> {
+ let hostname = proxmox_sys::nodename().to_string();
+
+ let metadata = HashMap::from([
+ ("hostname".into(), hostname.clone()),
+ ("type".into(), "package-updates".into()),
+ ]);
+
+ // The template uses the `table` handlebars helper, so
+ // we need to form the approriate data structure first.
+ let update_table = json!({
+ "schema": {
+ "columns": [
+ {
+ "label": "Package",
+ "id": "Package",
+ },
+ {
+ "label": "Old Version",
+ "id": "OldVersion",
+ },
+ {
+ "label": "New Version",
+ "id": "Version",
+ }
+ ],
+ },
+ "data": updates,
+ });
+
+ let template_data = json!({
+ "hostname": hostname,
+ "updates": update_table,
+ });
+
+ let notification =
+ Notification::from_template(Severity::Info, "package-updates", template_data, metadata);
+
+ send_notification(¬ification)?;
+ Ok(())
+}
+++ /dev/null
-edition = "2018"