* [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands
@ 2021-09-17 11:56 Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 1/7] server: refactor abort_local_worker Dominik Csapak
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
this series is a successor to my previous 'pbs-shell' series [0]
code wise its mostly the same but now a subcommand of 'proxmox-backup-debug'
changes from v2:
* now subcommand api of proxmox-backup-debug
* use http api on localhost by default
* add PROXMOX_DEBUG_API_CODE env variable to execute code directly
* use a macro for the completion helper calls
* combine get/post/put/delete requests into one and use 'fixed_param'
* drop priviliges to the backup user when executing 'non-protected' api
calls directly
changes from v1:
* rebase on master
* rename 'path' parameter to 'api-path' since it clashed with some
api calls that had a 'path variable'
* better handle workers:
we must always wait for the local workers and do not need to
print their logs, since most workers print to stdout if the
rpcenv type is CLI. Also catch Ctrl+C and try to abort the worker
Dominik Csapak (7):
server: refactor abort_local_worker
move proxmox-backup-debug back to main crate
proxmox-backup-debug: add 'api' subcommands
api2: add missing token list match_all property
api2: make some workers log on CLI
docs: add proxmox-backup-debug to the list of command line tools
docs: proxmox-backup-debug: add info about the 'api' subcommand
Cargo.toml | 1 -
Makefile | 2 -
debian/proxmox-backup-debug.bash-completion | 1 -
debian/proxmox-backup-server.bash-completion | 1 +
docs/command-line-tools.rst | 4 +
docs/proxmox-backup-debug/description.rst | 11 +
proxmox-backup-debug/Cargo.toml | 18 -
proxmox-backup-debug/src/main.rs | 13 -
src/api2/access/user.rs | 66 ++-
src/api2/admin/datastore.rs | 4 +-
src/api2/admin/sync.rs | 6 +-
src/api2/admin/verify.rs | 5 +-
src/api2/config/datastore.rs | 5 +-
src/api2/pull.rs | 3 +-
src/api2/tape/backup.rs | 7 +-
src/bin/proxmox-backup-debug.rs | 24 +
src/bin/proxmox-backup-proxy.rs | 6 +-
src/bin/proxmox_backup_debug/api.rs | 503 ++++++++++++++++++
.../bin/proxmox_backup_debug}/inspect.rs | 0
src/bin/proxmox_backup_debug/mod.rs | 3 +
.../bin/proxmox_backup_debug}/recover.rs | 0
src/bin/proxmox_backup_manager/user.rs | 6 +-
src/server/verify_job.rs | 3 +-
src/server/worker_task.rs | 12 +-
24 files changed, 627 insertions(+), 77 deletions(-)
delete mode 100644 debian/proxmox-backup-debug.bash-completion
delete mode 100644 proxmox-backup-debug/Cargo.toml
delete mode 100644 proxmox-backup-debug/src/main.rs
create mode 100644 src/bin/proxmox-backup-debug.rs
create mode 100644 src/bin/proxmox_backup_debug/api.rs
rename {proxmox-backup-debug/src => src/bin/proxmox_backup_debug}/inspect.rs (100%)
create mode 100644 src/bin/proxmox_backup_debug/mod.rs
rename {proxmox-backup-debug/src => src/bin/proxmox_backup_debug}/recover.rs (100%)
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v3 1/7] server: refactor abort_local_worker
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
@ 2021-09-17 11:56 ` Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 2/7] move proxmox-backup-debug back to main crate Dominik Csapak
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
we'll need this outside the module
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/server/worker_task.rs | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/server/worker_task.rs b/src/server/worker_task.rs
index 2ef8ba9d..c4696a2f 100644
--- a/src/server/worker_task.rs
+++ b/src/server/worker_task.rs
@@ -102,9 +102,8 @@ pub fn register_task_control_commands(
commando_sock.register_command("worker-task-abort".into(), move |args| {
let upid = get_upid(args)?;
- if let Some(ref worker) = WORKER_TASK_LIST.lock().unwrap().get(&upid.task_id) {
- worker.request_abort();
- }
+ abort_local_worker(upid);
+
Ok(Value::Null)
})?;
commando_sock.register_command("worker-task-status".into(), move |args| {
@@ -841,3 +840,10 @@ pub async fn wait_for_local_worker(upid_str: &str) -> Result<(), Error> {
}
Ok(())
}
+
+/// Request abort of a local worker (if existing and running)
+pub fn abort_local_worker(upid: UPID) {
+ if let Some(ref worker) = WORKER_TASK_LIST.lock().unwrap().get(&upid.task_id) {
+ worker.request_abort();
+ }
+}
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v3 2/7] move proxmox-backup-debug back to main crate
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 1/7] server: refactor abort_local_worker Dominik Csapak
@ 2021-09-17 11:56 ` Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 3/7] proxmox-backup-debug: add 'api' subcommands Dominik Csapak
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
we want to add something to it that needs access to the
proxmox_backup::api2 stuff, so it cannot live in a sub crate
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
Cargo.toml | 1 -
Makefile | 2 --
debian/proxmox-backup-debug.bash-completion | 1 -
debian/proxmox-backup-server.bash-completion | 1 +
proxmox-backup-debug/Cargo.toml | 18 ------------------
.../main.rs => src/bin/proxmox-backup-debug.rs | 4 ++--
.../bin/proxmox_backup_debug}/inspect.rs | 0
src/bin/proxmox_backup_debug/mod.rs | 2 ++
.../bin/proxmox_backup_debug}/recover.rs | 0
9 files changed, 5 insertions(+), 24 deletions(-)
delete mode 100644 debian/proxmox-backup-debug.bash-completion
delete mode 100644 proxmox-backup-debug/Cargo.toml
rename proxmox-backup-debug/src/main.rs => src/bin/proxmox-backup-debug.rs (86%)
rename {proxmox-backup-debug/src => src/bin/proxmox_backup_debug}/inspect.rs (100%)
create mode 100644 src/bin/proxmox_backup_debug/mod.rs
rename {proxmox-backup-debug/src => src/bin/proxmox_backup_debug}/recover.rs (100%)
diff --git a/Cargo.toml b/Cargo.toml
index 72d786c9..73159c3c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,7 +32,6 @@ members = [
"proxmox-backup-banner",
"proxmox-backup-client",
- "proxmox-backup-debug",
"proxmox-file-restore",
"pxar-bin",
]
diff --git a/Makefile b/Makefile
index e6c85a2e..f754f350 100644
--- a/Makefile
+++ b/Makefile
@@ -44,7 +44,6 @@ SUBCRATES := \
pbs-tools \
proxmox-backup-banner \
proxmox-backup-client \
- proxmox-backup-debug \
proxmox-file-restore \
pxar-bin
@@ -179,7 +178,6 @@ $(COMPILED_BINS) $(COMPILEDIR)/dump-catalog-shell-cli $(COMPILEDIR)/docgen: .do-
--bin proxmox-backup-banner \
--package proxmox-backup-client \
--bin proxmox-backup-client \
- --package proxmox-backup-debug \
--bin proxmox-backup-debug \
--package proxmox-file-restore \
--bin proxmox-file-restore \
diff --git a/debian/proxmox-backup-debug.bash-completion b/debian/proxmox-backup-debug.bash-completion
deleted file mode 100644
index b977f953..00000000
--- a/debian/proxmox-backup-debug.bash-completion
+++ /dev/null
@@ -1 +0,0 @@
-debian/proxmox-backup-debug.bc proxmox-backup-debug
diff --git a/debian/proxmox-backup-server.bash-completion b/debian/proxmox-backup-server.bash-completion
index a2165699..d4257edd 100644
--- a/debian/proxmox-backup-server.bash-completion
+++ b/debian/proxmox-backup-server.bash-completion
@@ -1,4 +1,5 @@
debian/proxmox-backup-manager.bc proxmox-backup-manager
+debian/proxmox-backup-debug.bc proxmox-backup-debug
debian/proxmox-tape.bc proxmox-tape
debian/pmtx.bc pmtx
debian/pmt.bc pmt
diff --git a/proxmox-backup-debug/Cargo.toml b/proxmox-backup-debug/Cargo.toml
deleted file mode 100644
index 7f1f596d..00000000
--- a/proxmox-backup-debug/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "proxmox-backup-debug"
-version = "0.1.0"
-authors = ["Proxmox Support Team <support@proxmox.com>"]
-edition = "2018"
-
-[dependencies]
-anyhow = "1.0"
-walkdir = "2"
-serde_json = "1.0"
-
-proxmox = { version = "0.13.0", features = [ "api-macro", "cli" ] }
-
-pbs-config = { path = "../pbs-config" }
-pbs-client = { path = "../pbs-client" }
-pbs-datastore = { path = "../pbs-datastore" }
-pbs-runtime = { path = "../pbs-runtime" }
-pbs-tools = { path = "../pbs-tools" }
diff --git a/proxmox-backup-debug/src/main.rs b/src/bin/proxmox-backup-debug.rs
similarity index 86%
rename from proxmox-backup-debug/src/main.rs
rename to src/bin/proxmox-backup-debug.rs
index b768f57a..4d6164ef 100644
--- a/proxmox-backup-debug/src/main.rs
+++ b/src/bin/proxmox-backup-debug.rs
@@ -1,7 +1,7 @@
use proxmox::api::cli::{run_cli_command, CliCommandMap, CliEnvironment};
-mod inspect;
-mod recover;
+mod proxmox_backup_debug;
+use proxmox_backup_debug::*;
fn main() {
let cmd_def = CliCommandMap::new()
diff --git a/proxmox-backup-debug/src/inspect.rs b/src/bin/proxmox_backup_debug/inspect.rs
similarity index 100%
rename from proxmox-backup-debug/src/inspect.rs
rename to src/bin/proxmox_backup_debug/inspect.rs
diff --git a/src/bin/proxmox_backup_debug/mod.rs b/src/bin/proxmox_backup_debug/mod.rs
new file mode 100644
index 00000000..bbaca751
--- /dev/null
+++ b/src/bin/proxmox_backup_debug/mod.rs
@@ -0,0 +1,2 @@
+pub mod inspect;
+pub mod recover;
diff --git a/proxmox-backup-debug/src/recover.rs b/src/bin/proxmox_backup_debug/recover.rs
similarity index 100%
rename from proxmox-backup-debug/src/recover.rs
rename to src/bin/proxmox_backup_debug/recover.rs
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v3 3/7] proxmox-backup-debug: add 'api' subcommands
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 1/7] server: refactor abort_local_worker Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 2/7] move proxmox-backup-debug back to main crate Dominik Csapak
@ 2021-09-17 11:56 ` Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 4/7] api2: add missing token list match_all property Dominik Csapak
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
this provides some generic api call mechanisms like pvesh/pmgsh.
by default it uses the https api on localhost (creating a token
if called as root, else requesting the root@pam password interactively)
this is mainly intended for debugging, but it is also useful for
situations where some api calls do not have an equivalent in a binary
and a user does not want to go through the api
not implemented are the http2 api calls (since it is a separate api an
it wouldn't be that easy to do)
there are a few quirks though, related to the 'ls' command:
i extract the 'child-link' from the property name of the
'match_all' statement of the router, but this does not
always match with the property from the relevant 'get' api call
so it fails there (e.g. /tape/drive )
this can be fixed in the respective api calls (e.g. by renaming
the parameter that comes from the path)
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/bin/proxmox-backup-debug.rs | 17 +-
src/bin/proxmox_backup_debug/api.rs | 503 ++++++++++++++++++++++++++++
src/bin/proxmox_backup_debug/mod.rs | 1 +
3 files changed, 518 insertions(+), 3 deletions(-)
create mode 100644 src/bin/proxmox_backup_debug/api.rs
diff --git a/src/bin/proxmox-backup-debug.rs b/src/bin/proxmox-backup-debug.rs
index 4d6164ef..0ef37525 100644
--- a/src/bin/proxmox-backup-debug.rs
+++ b/src/bin/proxmox-backup-debug.rs
@@ -1,4 +1,7 @@
-use proxmox::api::cli::{run_cli_command, CliCommandMap, CliEnvironment};
+use proxmox::api::{
+ cli::{run_cli_command, CliCommandMap, CliEnvironment},
+ RpcEnvironment,
+};
mod proxmox_backup_debug;
use proxmox_backup_debug::*;
@@ -6,8 +9,16 @@ use proxmox_backup_debug::*;
fn main() {
let cmd_def = CliCommandMap::new()
.insert("inspect", inspect::inspect_commands())
- .insert("recover", recover::recover_commands());
+ .insert("recover", recover::recover_commands())
+ .insert("api", api::api_commands());
+
+ let uid = nix::unistd::Uid::current();
+ let username = match nix::unistd::User::from_uid(uid) {
+ Ok(Some(user)) => user.name,
+ _ => "root@pam".to_string(),
+ };
+ let mut rpcenv = CliEnvironment::new();
+ rpcenv.set_auth_id(Some(format!("{}@pam", username)));
- let rpcenv = CliEnvironment::new();
run_cli_command(cmd_def, rpcenv, Some(|future| pbs_runtime::main(future)));
}
diff --git a/src/bin/proxmox_backup_debug/api.rs b/src/bin/proxmox_backup_debug/api.rs
new file mode 100644
index 00000000..302ae6b1
--- /dev/null
+++ b/src/bin/proxmox_backup_debug/api.rs
@@ -0,0 +1,503 @@
+use anyhow::{bail, format_err, Error};
+use futures::FutureExt;
+use hyper::Method;
+use serde::{Deserialize, Serialize};
+use serde_json::{json, Value};
+use tokio::signal::unix::{signal, SignalKind};
+
+use std::collections::HashMap;
+
+use proxmox::api::{
+ api,
+ cli::*,
+ format::DocumentationFormat,
+ schema::{parse_parameter_strings, ApiType, ParameterSchema, Schema},
+ ApiHandler, ApiMethod, RpcEnvironment, SubRoute,
+};
+
+use pbs_client::{connect_to_localhost, view_task_result};
+
+use pbs_api_types::{PROXMOX_UPID_REGEX, UPID};
+
+const PROG_NAME: &str = "proxmox-backup-debug api";
+const URL_ASCIISET: percent_encoding::AsciiSet = percent_encoding::NON_ALPHANUMERIC.remove(b'/');
+
+macro_rules! complete_api_path {
+ ($capability:expr) => {
+ |complete_me: &str, _map: &HashMap<String, String>| {
+ pbs_runtime::block_on(async { complete_api_path_do(complete_me, $capability).await })
+ }
+ };
+}
+
+async fn complete_api_path_do(mut complete_me: &str, capability: Option<&str>) -> Vec<String> {
+ if complete_me.is_empty() {
+ complete_me = "/";
+ }
+
+ let mut list = Vec::new();
+
+ let mut lookup_path = complete_me.to_string();
+ let mut filter = "";
+ let last_path_index = complete_me.rfind('/');
+ if let Some(index) = last_path_index {
+ if index != complete_me.len() - 1 {
+ lookup_path = complete_me[..(index + 1)].to_string();
+ if index < complete_me.len() - 1 {
+ filter = &complete_me[(index + 1)..];
+ }
+ }
+ }
+
+ let uid = nix::unistd::Uid::current();
+
+ let username = match nix::unistd::User::from_uid(uid) {
+ Ok(Some(user)) => user.name,
+ _ => "root@pam".to_string(),
+ };
+ let mut rpcenv = CliEnvironment::new();
+ rpcenv.set_auth_id(Some(format!("{}@pam", username)));
+
+ while let Ok(children) = get_api_children(lookup_path.clone(), &mut rpcenv).await {
+ let old_len = list.len();
+ for entry in children {
+ let name = entry.name;
+ let caps = entry.capabilities;
+
+ if filter.is_empty() || name.starts_with(filter) {
+ let mut path = format!("{}{}", lookup_path, name);
+ if caps.contains('D') {
+ path.push('/');
+ list.push(path.clone());
+ } else if let Some(cap) = capability {
+ if caps.contains(cap) {
+ list.push(path);
+ }
+ } else {
+ list.push(path);
+ }
+ }
+ }
+
+ if list.len() == 1 && old_len != 1 && list[0].ends_with('/') {
+ // we added only one match and it was a directory, lookup again
+ lookup_path = list[0].clone();
+ filter = "";
+ continue;
+ }
+
+ break;
+ }
+
+ list
+}
+
+async fn get_child_links(
+ path: &str,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<String>, Error> {
+ let (path, components) = proxmox_backup::tools::normalize_uri_path(&path)?;
+
+ let info = &proxmox_backup::api2::ROUTER
+ .find_route(&components, &mut HashMap::new())
+ .ok_or_else(|| format_err!("no such resource"))?;
+
+ match info.subroute {
+ Some(SubRoute::Map(map)) => Ok(map.iter().map(|(name, _)| name.to_string()).collect()),
+ Some(SubRoute::MatchAll { param_name, .. }) => {
+ let list = call_api("get", &path, rpcenv, None).await?;
+ Ok(list
+ .as_array()
+ .ok_or_else(|| format_err!("{} did not return an array", path))?
+ .iter()
+ .map(|item| {
+ item[param_name]
+ .as_str()
+ .map(|c| c.to_string())
+ .ok_or_else(|| format_err!("no such property {}", param_name))
+ })
+ .collect::<Result<Vec<_>, _>>()?)
+ }
+ None => bail!("link does not define child links"),
+ }
+}
+
+fn get_api_method(
+ method: &str,
+ path: &str,
+) -> Result<(&'static ApiMethod, HashMap<String, String>), Error> {
+ let method = match method {
+ "get" => Method::GET,
+ "set" => Method::PUT,
+ "create" => Method::POST,
+ "delete" => Method::DELETE,
+ _ => unreachable!(),
+ };
+ let mut uri_param = HashMap::new();
+ let (path, components) = proxmox_backup::tools::normalize_uri_path(&path)?;
+ if let Some(method) =
+ &proxmox_backup::api2::ROUTER.find_method(&components, method.clone(), &mut uri_param)
+ {
+ Ok((method, uri_param))
+ } else {
+ bail!("no {} handler defined for '{}'", method, path);
+ }
+}
+
+fn merge_parameters(
+ uri_param: HashMap<String, String>,
+ param: Option<Value>,
+ schema: ParameterSchema,
+) -> Result<Value, Error> {
+ let mut param_list: Vec<(String, String)> = vec![];
+
+ for (k, v) in uri_param {
+ param_list.push((k.clone(), v.clone()));
+ }
+
+ let param = param.unwrap_or(json!({}));
+
+ if let Some(map) = param.as_object() {
+ for (k, v) in map {
+ param_list.push((k.clone(), v.as_str().unwrap().to_string()));
+ }
+ }
+
+ let params = parse_parameter_strings(¶m_list, schema, true)?;
+
+ Ok(params)
+}
+
+fn use_http_client() -> bool {
+ match std::env::var("PROXMOX_DEBUG_API_CODE") {
+ Ok(var) => var != "1",
+ _ => true,
+ }
+}
+
+async fn call_api(
+ method: &str,
+ path: &str,
+ rpcenv: &mut dyn RpcEnvironment,
+ params: Option<Value>,
+) -> Result<Value, Error> {
+ if use_http_client() {
+ return call_api_http(method, path, params).await;
+ }
+
+ let (method, uri_param) = get_api_method(method, path)?;
+ let params = merge_parameters(uri_param, params, method.parameters)?;
+
+ call_api_code(method, rpcenv, params).await
+}
+
+async fn call_api_http(method: &str, path: &str, params: Option<Value>) -> Result<Value, Error> {
+ let mut client = connect_to_localhost()?;
+
+ let path = format!(
+ "api2/json/{}",
+ percent_encoding::utf8_percent_encode(path, &URL_ASCIISET)
+ );
+
+ match method {
+ "get" => client.get(&path, params).await,
+ "create" => client.post(&path, params).await,
+ "set" => client.put(&path, params).await,
+ "delete" => client.delete(&path, params).await,
+ _ => unreachable!(),
+ }
+ .map(|mut res| res["data"].take())
+}
+
+async fn call_api_code(
+ method: &'static ApiMethod,
+ rpcenv: &mut dyn RpcEnvironment,
+ params: Value,
+) -> Result<Value, Error> {
+ if !method.protected {
+ // drop privileges if we call non-protected code directly
+ let backup_user = pbs_config::backup_user()?;
+ nix::unistd::setgid(backup_user.gid)?;
+ nix::unistd::setuid(backup_user.uid)?;
+ }
+ match method.handler {
+ ApiHandler::AsyncHttp(_handler) => {
+ bail!("not implemented");
+ }
+ ApiHandler::Sync(handler) => (handler)(params, method, rpcenv),
+ ApiHandler::Async(handler) => (handler)(params, method, rpcenv).await,
+ }
+}
+
+async fn handle_worker(upid_str: &str) -> Result<(), Error> {
+ let upid: UPID = upid_str.parse()?;
+ let mut signal_stream = signal(SignalKind::interrupt())?;
+ let abort_future = async move {
+ while signal_stream.recv().await.is_some() {
+ println!("got shutdown request (SIGINT)");
+ proxmox_backup::server::abort_local_worker(upid.clone());
+ }
+ Ok::<_, Error>(())
+ };
+
+ let result_future = proxmox_backup::server::wait_for_local_worker(upid_str);
+
+ futures::select! {
+ result = result_future.fuse() => result?,
+ abort = abort_future.fuse() => abort?,
+ };
+
+ Ok(())
+}
+
+async fn call_api_and_format_result(
+ method: String,
+ path: String,
+ mut param: Value,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let mut output_format = extract_output_format(&mut param);
+ let mut result = call_api(&method, &path, rpcenv, Some(param)).await?;
+
+ if let Some(upid) = result.as_str() {
+ if PROXMOX_UPID_REGEX.is_match(upid) {
+ if use_http_client() {
+ let mut client = connect_to_localhost()?;
+ view_task_result(&mut client, result, &output_format).await?;
+ return Ok(());
+ }
+
+ handle_worker(upid).await?;
+
+ if output_format == "text" {
+ return Ok(());
+ }
+ }
+ }
+
+ let (method, _) = get_api_method(&method, &path)?;
+ let options = default_table_format_options();
+ let return_type = &method.returns;
+ if matches!(return_type.schema, Schema::Null) {
+ output_format = "json-pretty".to_string();
+ }
+
+ format_and_print_result_full(&mut result, return_type, &output_format, &options);
+
+ Ok(())
+}
+
+#[api(
+ input: {
+ additional_properties: true,
+ properties: {
+ method: {
+ type: String,
+ description: "The Method",
+ },
+ "api-path": {
+ type: String,
+ description: "API path.",
+ },
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ },
+ },
+)]
+/// Call API on <api-path>
+async fn api_call(
+ method: String,
+ api_path: String,
+ param: Value,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ call_api_and_format_result(method, api_path, param, rpcenv).await
+}
+
+#[api(
+ input: {
+ properties: {
+ path: {
+ type: String,
+ description: "API path.",
+ },
+ verbose: {
+ type: Boolean,
+ description: "Verbose output format.",
+ optional: true,
+ default: false,
+ }
+ },
+ },
+)]
+/// Get API usage information for <path>
+async fn usage(
+ path: String,
+ verbose: bool,
+ _param: Value,
+ _rpcenv: &mut dyn RpcEnvironment,
+) -> Result<(), Error> {
+ let docformat = if verbose {
+ DocumentationFormat::Full
+ } else {
+ DocumentationFormat::Short
+ };
+ let mut found = false;
+ for command in &["get", "set", "create", "delete"] {
+ let (info, uri_params) = match get_api_method(command, &path) {
+ Ok(some) => some,
+ Err(_) => continue,
+ };
+ found = true;
+
+ let skip_params: Vec<&str> = uri_params.keys().map(|s| &**s).collect();
+
+ let cmd = CliCommand::new(info);
+ let prefix = format!("USAGE: {} {} {}", PROG_NAME, command, path);
+
+ print!(
+ "{}",
+ generate_usage_str(&prefix, &cmd, docformat, "", &skip_params)
+ );
+ }
+
+ if !found {
+ bail!("no such resource '{}'", path);
+ }
+ Ok(())
+}
+
+#[api()]
+#[derive(Debug, Serialize, Deserialize)]
+/// A child link with capabilities
+struct ApiDirEntry {
+ /// The name of the link
+ name: String,
+ /// The capabilities of the path (format Drwcd)
+ capabilities: String,
+}
+
+const LS_SCHEMA: &proxmox::api::schema::Schema =
+ &proxmox::api::schema::ArraySchema::new("List of child links", &ApiDirEntry::API_SCHEMA)
+ .schema();
+
+async fn get_api_children(
+ path: String,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<Vec<ApiDirEntry>, Error> {
+ let mut res = Vec::new();
+ for link in get_child_links(&path, rpcenv).await? {
+ let path = format!("{}/{}", path, link);
+ let (path, _) = proxmox_backup::tools::normalize_uri_path(&path)?;
+ let mut cap = String::new();
+
+ if get_child_links(&path, rpcenv).await.is_ok() {
+ cap.push('D');
+ } else {
+ cap.push('-');
+ }
+
+ let cap_list = &[("get", 'r'), ("set", 'w'), ("create", 'c'), ("delete", 'd')];
+
+ for (method, c) in cap_list {
+ if get_api_method(method, &path).is_ok() {
+ cap.push(*c);
+ } else {
+ cap.push('-');
+ }
+ }
+
+ res.push(ApiDirEntry {
+ name: link.to_string(),
+ capabilities: cap,
+ });
+ }
+
+ Ok(res)
+}
+
+#[api(
+ input: {
+ properties: {
+ path: {
+ type: String,
+ description: "API path.",
+ },
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ },
+ },
+)]
+/// Get API usage information for <path>
+async fn ls(path: String, mut param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
+ let output_format = extract_output_format(&mut param);
+
+ let options = TableFormatOptions::new()
+ .noborder(true)
+ .noheader(true)
+ .sortby("name", false);
+
+ let res = get_api_children(path, rpcenv).await?;
+
+ format_and_print_result_full(
+ &mut serde_json::to_value(res)?,
+ &proxmox::api::schema::ReturnType {
+ optional: false,
+ schema: &LS_SCHEMA,
+ },
+ &output_format,
+ &options,
+ );
+
+ Ok(())
+}
+
+pub fn api_commands() -> CommandLineInterface {
+ let cmd_def = CliCommandMap::new()
+ .insert(
+ "get",
+ CliCommand::new(&API_METHOD_API_CALL)
+ .fixed_param("method", "get".to_string())
+ .arg_param(&["api-path"])
+ .completion_cb("api-path", complete_api_path!(Some("r"))),
+ )
+ .insert(
+ "set",
+ CliCommand::new(&API_METHOD_API_CALL)
+ .fixed_param("method", "set".to_string())
+ .arg_param(&["api-path"])
+ .completion_cb("api-path", complete_api_path!(Some("w"))),
+ )
+ .insert(
+ "create",
+ CliCommand::new(&API_METHOD_API_CALL)
+ .fixed_param("method", "create".to_string())
+ .arg_param(&["api-path"])
+ .completion_cb("api-path", complete_api_path!(Some("c"))),
+ )
+ .insert(
+ "delete",
+ CliCommand::new(&API_METHOD_API_CALL)
+ .fixed_param("method", "delete".to_string())
+ .arg_param(&["api-path"])
+ .completion_cb("api-path", complete_api_path!(Some("d"))),
+ )
+ .insert(
+ "ls",
+ CliCommand::new(&API_METHOD_LS)
+ .arg_param(&["path"])
+ .completion_cb("path", complete_api_path!(Some("D"))),
+ )
+ .insert(
+ "usage",
+ CliCommand::new(&API_METHOD_USAGE)
+ .arg_param(&["path"])
+ .completion_cb("path", complete_api_path!(None)),
+ );
+
+ cmd_def.into()
+}
diff --git a/src/bin/proxmox_backup_debug/mod.rs b/src/bin/proxmox_backup_debug/mod.rs
index bbaca751..a3a526dd 100644
--- a/src/bin/proxmox_backup_debug/mod.rs
+++ b/src/bin/proxmox_backup_debug/mod.rs
@@ -1,2 +1,3 @@
pub mod inspect;
pub mod recover;
+pub mod api;
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v3 4/7] api2: add missing token list match_all property
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
` (2 preceding siblings ...)
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 3/7] proxmox-backup-debug: add 'api' subcommands Dominik Csapak
@ 2021-09-17 11:56 ` Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 5/7] api2: make some workers log on CLI Dominik Csapak
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
to have the proper link between the token list and the sub routes
in the api, include the 'tokenname' property in the token listing
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/api2/access/user.rs | 66 +++++++++++++++++---------
src/bin/proxmox_backup_manager/user.rs | 6 +--
2 files changed, 47 insertions(+), 25 deletions(-)
diff --git a/src/api2/access/user.rs b/src/api2/access/user.rs
index 75071cf1..1d866214 100644
--- a/src/api2/access/user.rs
+++ b/src/api2/access/user.rs
@@ -395,7 +395,7 @@ pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error>
userid: {
type: Userid,
},
- tokenname: {
+ "token-name": {
type: Tokenname,
},
},
@@ -411,14 +411,14 @@ pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error>
/// Read user's API token metadata
pub fn read_token(
userid: Userid,
- tokenname: Tokenname,
+ token_name: Tokenname,
_info: &ApiMethod,
mut rpcenv: &mut dyn RpcEnvironment,
) -> Result<ApiToken, Error> {
let (config, digest) = pbs_config::user::config()?;
- let tokenid = Authid::from((userid, Some(tokenname)));
+ let tokenid = Authid::from((userid, Some(token_name)));
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
config.lookup("token", &tokenid.to_string())
@@ -431,7 +431,7 @@ pub fn read_token(
userid: {
type: Userid,
},
- tokenname: {
+ "token-name": {
type: Tokenname,
},
comment: {
@@ -475,7 +475,7 @@ pub fn read_token(
/// Generate a new API token with given metadata
pub fn generate_token(
userid: Userid,
- tokenname: Tokenname,
+ token_name: Tokenname,
comment: Option<String>,
enable: Option<bool>,
expire: Option<i64>,
@@ -491,11 +491,11 @@ pub fn generate_token(
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
}
- let tokenid = Authid::from((userid.clone(), Some(tokenname.clone())));
+ let tokenid = Authid::from((userid.clone(), Some(token_name.clone())));
let tokenid_string = tokenid.to_string();
if config.sections.get(&tokenid_string).is_some() {
- bail!("token '{}' for user '{}' already exists.", tokenname.as_str(), userid);
+ bail!("token '{}' for user '{}' already exists.", token_name.as_str(), userid);
}
let secret = format!("{:x}", proxmox::tools::uuid::Uuid::generate());
@@ -525,7 +525,7 @@ pub fn generate_token(
userid: {
type: Userid,
},
- tokenname: {
+ "token-name": {
type: Tokenname,
},
comment: {
@@ -556,7 +556,7 @@ pub fn generate_token(
/// Update user's API token metadata
pub fn update_token(
userid: Userid,
- tokenname: Tokenname,
+ token_name: Tokenname,
comment: Option<String>,
enable: Option<bool>,
expire: Option<i64>,
@@ -572,7 +572,7 @@ pub fn update_token(
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
}
- let tokenid = Authid::from((userid, Some(tokenname)));
+ let tokenid = Authid::from((userid, Some(token_name)));
let tokenid_string = tokenid.to_string();
let mut data: ApiToken = config.lookup("token", &tokenid_string)?;
@@ -608,7 +608,7 @@ pub fn update_token(
userid: {
type: Userid,
},
- tokenname: {
+ "token-name": {
type: Tokenname,
},
digest: {
@@ -627,7 +627,7 @@ pub fn update_token(
/// Delete a user's API token
pub fn delete_token(
userid: Userid,
- tokenname: Tokenname,
+ token_name: Tokenname,
digest: Option<String>,
) -> Result<(), Error> {
@@ -640,12 +640,12 @@ pub fn delete_token(
crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
}
- let tokenid = Authid::from((userid.clone(), Some(tokenname.clone())));
+ let tokenid = Authid::from((userid.clone(), Some(token_name.clone())));
let tokenid_string = tokenid.to_string();
match config.sections.get(&tokenid_string) {
Some(_) => { config.sections.remove(&tokenid_string); },
- None => bail!("token '{}' of user '{}' does not exist.", tokenname.as_str(), userid),
+ None => bail!("token '{}' of user '{}' does not exist.", token_name.as_str(), userid),
}
token_shadow::delete_secret(&tokenid)?;
@@ -655,6 +655,22 @@ pub fn delete_token(
Ok(())
}
+#[api(
+ properties: {
+ "token-name": { type: Tokenname },
+ token: { type: ApiToken },
+ }
+)]
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all="kebab-case")]
+/// A Token Entry that contains the token-name
+pub struct TokenApiEntry {
+ /// The Token name
+ pub token_name: Tokenname,
+ #[serde(flatten)]
+ pub token: ApiToken,
+}
+
#[api(
input: {
properties: {
@@ -666,7 +682,7 @@ pub fn delete_token(
returns: {
description: "List user's API tokens (with config digest).",
type: Array,
- items: { type: ApiToken },
+ items: { type: TokenApiEntry },
},
access: {
permission: &Permission::Or(&[
@@ -680,7 +696,7 @@ pub fn list_tokens(
userid: Userid,
_info: &ApiMethod,
mut rpcenv: &mut dyn RpcEnvironment,
-) -> Result<Vec<ApiToken>, Error> {
+) -> Result<Vec<TokenApiEntry>, Error> {
let (config, digest) = pbs_config::user::config()?;
@@ -688,15 +704,21 @@ pub fn list_tokens(
rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
- let filter_by_owner = |token: &ApiToken| {
- if token.tokenid.is_token() {
- token.tokenid.user() == &userid
+ let filter_by_owner = |token: ApiToken| {
+ if token.tokenid.is_token() && token.tokenid.user() == &userid {
+ let token_name = token.tokenid.tokenname().unwrap().to_owned();
+ Some(TokenApiEntry {
+ token_name,
+ token,
+ })
} else {
- false
+ None
}
};
- Ok(list.into_iter().filter(filter_by_owner).collect())
+ let res = list.into_iter().filter_map(filter_by_owner).collect();
+
+ Ok(res)
}
const TOKEN_ITEM_ROUTER: Router = Router::new()
@@ -707,7 +729,7 @@ const TOKEN_ITEM_ROUTER: Router = Router::new()
const TOKEN_ROUTER: Router = Router::new()
.get(&API_METHOD_LIST_TOKENS)
- .match_all("tokenname", &TOKEN_ITEM_ROUTER);
+ .match_all("token-name", &TOKEN_ITEM_ROUTER);
const USER_SUBDIRS: SubdirMap = &[
("token", &TOKEN_ROUTER),
diff --git a/src/bin/proxmox_backup_manager/user.rs b/src/bin/proxmox_backup_manager/user.rs
index 9681ba79..cff66ce7 100644
--- a/src/bin/proxmox_backup_manager/user.rs
+++ b/src/bin/proxmox_backup_manager/user.rs
@@ -198,15 +198,15 @@ pub fn user_commands() -> CommandLineInterface {
.insert(
"generate-token",
CliCommand::new(&api2::access::user::API_METHOD_GENERATE_TOKEN)
- .arg_param(&["userid", "tokenname"])
+ .arg_param(&["userid", "token-name"])
.completion_cb("userid", pbs_config::user::complete_userid)
)
.insert(
"delete-token",
CliCommand::new(&api2::access::user::API_METHOD_DELETE_TOKEN)
- .arg_param(&["userid", "tokenname"])
+ .arg_param(&["userid", "token-name"])
.completion_cb("userid", pbs_config::user::complete_userid)
- .completion_cb("tokenname", pbs_config::user::complete_token_name)
+ .completion_cb("token-name", pbs_config::user::complete_token_name)
)
.insert(
"permissions",
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v3 5/7] api2: make some workers log on CLI
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
` (3 preceding siblings ...)
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 4/7] api2: add missing token list match_all property Dominik Csapak
@ 2021-09-17 11:56 ` Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 6/7] docs: add proxmox-backup-debug to the list of command line tools Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 7/7] docs: proxmox-backup-debug: add info about the 'api' subcommand Dominik Csapak
6 siblings, 0 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
some workers did not log when called via cli
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/api2/admin/datastore.rs | 4 +++-
src/api2/admin/sync.rs | 6 ++++--
src/api2/admin/verify.rs | 5 +++--
src/api2/config/datastore.rs | 5 +++--
src/api2/pull.rs | 3 ++-
src/api2/tape/backup.rs | 7 +++++--
src/bin/proxmox-backup-proxy.rs | 6 +++---
src/server/verify_job.rs | 3 ++-
8 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs
index 33700a90..b42de25d 100644
--- a/src/api2/admin/datastore.rs
+++ b/src/api2/admin/datastore.rs
@@ -951,11 +951,13 @@ pub fn prune_datastore(
let datastore = DataStore::lookup_datastore(&store)?;
+ let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
+
let upid_str = WorkerTask::new_thread(
"prune",
Some(store.clone()),
auth_id.clone(),
- false,
+ to_stdout,
move |worker| crate::server::prune_datastore(
worker.clone(),
auth_id,
diff --git a/src/api2/admin/sync.rs b/src/api2/admin/sync.rs
index 07f268b5..94990adb 100644
--- a/src/api2/admin/sync.rs
+++ b/src/api2/admin/sync.rs
@@ -3,7 +3,7 @@
use anyhow::{bail, format_err, Error};
use serde_json::Value;
-use proxmox::api::{api, ApiMethod, Permission, Router, RpcEnvironment};
+use proxmox::api::{api, ApiMethod, Permission, Router, RpcEnvironment, RpcEnvironmentType};
use proxmox::api::router::SubdirMap;
use proxmox::{list_subdirs_api_method, sortable};
@@ -120,7 +120,9 @@ pub fn run_sync_job(
let job = Job::new("syncjob", &id)?;
- let upid_str = do_sync_job(job, sync_job, &auth_id, None)?;
+ let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
+
+ let upid_str = do_sync_job(job, sync_job, &auth_id, None, to_stdout)?;
Ok(upid_str)
}
diff --git a/src/api2/admin/verify.rs b/src/api2/admin/verify.rs
index a5e5c83f..6bdfdede 100644
--- a/src/api2/admin/verify.rs
+++ b/src/api2/admin/verify.rs
@@ -5,7 +5,7 @@ use serde_json::Value;
use proxmox::api::router::SubdirMap;
use proxmox::{list_subdirs_api_method, sortable};
-use proxmox::api::{api, ApiMethod, Permission, Router, RpcEnvironment};
+use proxmox::api::{api, ApiMethod, Permission, Router, RpcEnvironment, RpcEnvironmentType};
use pbs_api_types::{
VerificationJobConfig, VerificationJobStatus, JOB_ID_SCHEMA, Authid,
@@ -117,8 +117,9 @@ pub fn run_verification_job(
user_info.check_privs(&auth_id, &["datastore", &verification_job.store], PRIV_DATASTORE_VERIFY, true)?;
let job = Job::new("verificationjob", &id)?;
+ let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
- let upid_str = do_verification_job(job, verification_job, &auth_id, None)?;
+ let upid_str = do_verification_job(job, verification_job, &auth_id, None, to_stdout)?;
Ok(upid_str)
}
diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index 6301ffaa..c6036fc3 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -4,7 +4,7 @@ use anyhow::{bail, Error};
use serde_json::Value;
use ::serde::{Deserialize, Serialize};
-use proxmox::api::{api, Router, RpcEnvironment, Permission};
+use proxmox::api::{api, Router, RpcEnvironment, RpcEnvironmentType, Permission};
use proxmox::api::section_config::SectionConfigData;
use proxmox::api::schema::{ApiType, parse_property_string};
@@ -114,12 +114,13 @@ pub fn create_datastore(
}
let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?;
+ let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
WorkerTask::new_thread(
"create-datastore",
Some(config.name.to_string()),
auth_id,
- false,
+ to_stdout,
move |worker| do_create_datastore(lock, section_config, config, Some(&worker)),
)
}
diff --git a/src/api2/pull.rs b/src/api2/pull.rs
index d7b155a1..1eb86ea3 100644
--- a/src/api2/pull.rs
+++ b/src/api2/pull.rs
@@ -66,6 +66,7 @@ pub fn do_sync_job(
sync_job: SyncJobConfig,
auth_id: &Authid,
schedule: Option<String>,
+ to_stdout: bool,
) -> Result<String, Error> {
let job_id = format!("{}:{}:{}:{}",
@@ -81,7 +82,7 @@ pub fn do_sync_job(
&worker_type,
Some(job_id.clone()),
auth_id.clone(),
- false,
+ to_stdout,
move |worker| async move {
job.start(&worker.upid().to_string())?;
diff --git a/src/api2/tape/backup.rs b/src/api2/tape/backup.rs
index 9342eb59..6b533820 100644
--- a/src/api2/tape/backup.rs
+++ b/src/api2/tape/backup.rs
@@ -164,6 +164,7 @@ pub fn do_tape_backup_job(
setup: TapeBackupJobSetup,
auth_id: &Authid,
schedule: Option<String>,
+ to_stdout: bool,
) -> Result<String, Error> {
let job_id = format!("{}:{}:{}:{}",
@@ -195,7 +196,7 @@ pub fn do_tape_backup_job(
&worker_type,
Some(job_id.clone()),
auth_id.clone(),
- false,
+ to_stdout,
move |worker| {
job.start(&worker.upid().to_string())?;
let mut drive_lock = drive_lock;
@@ -307,7 +308,9 @@ pub fn run_tape_backup_job(
let job = Job::new("tape-backup-job", &id)?;
- let upid_str = do_tape_backup_job(job, backup_job.setup, &auth_id, None)?;
+ let to_stdout = rpcenv.env_type() == RpcEnvironmentType::CLI;
+
+ let upid_str = do_tape_backup_job(job, backup_job.setup, &auth_id, None, to_stdout)?;
Ok(upid_str)
}
diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs
index 4240711f..3f60d348 100644
--- a/src/bin/proxmox-backup-proxy.rs
+++ b/src/bin/proxmox-backup-proxy.rs
@@ -541,7 +541,7 @@ async fn schedule_datastore_sync_jobs() {
};
let auth_id = Authid::root_auth_id().clone();
- if let Err(err) = do_sync_job(job, job_config, &auth_id, Some(event_str)) {
+ if let Err(err) = do_sync_job(job, job_config, &auth_id, Some(event_str), false) {
eprintln!("unable to start datastore sync job {} - {}", &job_id, err);
}
};
@@ -577,7 +577,7 @@ async fn schedule_datastore_verify_jobs() {
Ok(job) => job,
Err(_) => continue, // could not get lock
};
- if let Err(err) = do_verification_job(job, job_config, &auth_id, Some(event_str)) {
+ if let Err(err) = do_verification_job(job, job_config, &auth_id, Some(event_str), false) {
eprintln!("unable to start datastore verification job {} - {}", &job_id, err);
}
};
@@ -613,7 +613,7 @@ async fn schedule_tape_backup_jobs() {
Ok(job) => job,
Err(_) => continue, // could not get lock
};
- if let Err(err) = do_tape_backup_job(job, job_config.setup, &auth_id, Some(event_str)) {
+ if let Err(err) = do_tape_backup_job(job, job_config.setup, &auth_id, Some(event_str), false) {
eprintln!("unable to start tape backup job {} - {}", &job_id, err);
}
};
diff --git a/src/server/verify_job.rs b/src/server/verify_job.rs
index 968e6bd4..7f6d73ff 100644
--- a/src/server/verify_job.rs
+++ b/src/server/verify_job.rs
@@ -19,6 +19,7 @@ pub fn do_verification_job(
verification_job: VerificationJobConfig,
auth_id: &Authid,
schedule: Option<String>,
+ to_stdout: bool,
) -> Result<String, Error> {
let datastore = DataStore::lookup_datastore(&verification_job.store)?;
@@ -36,7 +37,7 @@ pub fn do_verification_job(
&worker_type,
Some(job_id.clone()),
auth_id.clone(),
- false,
+ to_stdout,
move |worker| {
job.start(&worker.upid().to_string())?;
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v3 6/7] docs: add proxmox-backup-debug to the list of command line tools
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
` (4 preceding siblings ...)
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 5/7] api2: make some workers log on CLI Dominik Csapak
@ 2021-09-17 11:56 ` Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 7/7] docs: proxmox-backup-debug: add info about the 'api' subcommand Dominik Csapak
6 siblings, 0 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
docs/command-line-tools.rst | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/docs/command-line-tools.rst b/docs/command-line-tools.rst
index bf3a92cc..37606f46 100644
--- a/docs/command-line-tools.rst
+++ b/docs/command-line-tools.rst
@@ -21,3 +21,7 @@ Command Line Tools
.. include:: pxar/description.rst
+``proxmox-backup-debug``
+~~~~~~~~
+
+.. include:: proxmox-backup-debug/description.rst
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pbs-devel] [PATCH proxmox-backup v3 7/7] docs: proxmox-backup-debug: add info about the 'api' subcommand
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
` (5 preceding siblings ...)
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 6/7] docs: add proxmox-backup-debug to the list of command line tools Dominik Csapak
@ 2021-09-17 11:56 ` Dominik Csapak
6 siblings, 0 replies; 8+ messages in thread
From: Dominik Csapak @ 2021-09-17 11:56 UTC (permalink / raw)
To: pbs-devel
and mention PROXMOX_DEBUG_API_CODE and that its dangerous.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
docs/proxmox-backup-debug/description.rst | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/docs/proxmox-backup-debug/description.rst b/docs/proxmox-backup-debug/description.rst
index 0b263e8c..2e5f35fe 100644
--- a/docs/proxmox-backup-debug/description.rst
+++ b/docs/proxmox-backup-debug/description.rst
@@ -1,3 +1,14 @@
Implements debugging functionality to inspect Proxmox Backup datastore
files, verify the integrity of chunks.
+Also contains an 'api' subcommand where arbitrary api paths can be called
+(get/create/set/delete) as well as display their parameters (usage) and
+their child-links (ls).
+
+By default, it connects to the proxmox-backup-proxy on localhost via https,
+but by setting the environment variable `PROXMOX_DEBUG_API_CODE` to `1` the
+tool directly calls the corresponding code.
+
+.. WARNING:: Using `PROXMOX_DEBUG_API_CODE` can be dangerous and is only intended
+ for debugging purposes. It is not intended for use on a production system.
+
--
2.30.2
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-09-17 11:56 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-17 11:56 [pbs-devel] [PATCH proxmox-backup v3 0/7] add 'proxmox-backup-debug api' commands Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 1/7] server: refactor abort_local_worker Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 2/7] move proxmox-backup-debug back to main crate Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 3/7] proxmox-backup-debug: add 'api' subcommands Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 4/7] api2: add missing token list match_all property Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 5/7] api2: make some workers log on CLI Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 6/7] docs: add proxmox-backup-debug to the list of command line tools Dominik Csapak
2021-09-17 11:56 ` [pbs-devel] [PATCH proxmox-backup v3 7/7] docs: proxmox-backup-debug: add info about the 'api' subcommand Dominik Csapak
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal