cleanup config api, add remotes config cli interface
This commit is contained in:
parent
9e9bc6525e
commit
688fbe07a1
|
@ -3,19 +3,26 @@ use std::path::PathBuf;
|
||||||
use failure::*;
|
use failure::*;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use proxmox::api::{ApiHandler, ApiMethod, Router, RpcEnvironment};
|
use proxmox::api::{api, ApiMethod, Router, RpcEnvironment};
|
||||||
use proxmox::api::schema::*;
|
|
||||||
|
|
||||||
use crate::api2::types::*;
|
use crate::api2::types::*;
|
||||||
use crate::backup::*;
|
use crate::backup::*;
|
||||||
use crate::config::datastore;
|
use crate::config::datastore;
|
||||||
|
|
||||||
pub const GET: ApiMethod = ApiMethod::new(
|
#[api(
|
||||||
&ApiHandler::Sync(&get_datastore_list),
|
input: {
|
||||||
&ObjectSchema::new("Directory index.", &[])
|
properties: {},
|
||||||
);
|
},
|
||||||
|
returns: {
|
||||||
fn get_datastore_list(
|
description: "List the configured datastores.",
|
||||||
|
type: Array,
|
||||||
|
items: {
|
||||||
|
type: datastore::DataStoreConfig,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// List all datastores
|
||||||
|
pub fn list_datastores(
|
||||||
_param: Value,
|
_param: Value,
|
||||||
_info: &ApiMethod,
|
_info: &ApiMethod,
|
||||||
_rpcenv: &mut dyn RpcEnvironment,
|
_rpcenv: &mut dyn RpcEnvironment,
|
||||||
|
@ -26,90 +33,83 @@ fn get_datastore_list(
|
||||||
Ok(config.convert_to_array("name"))
|
Ok(config.convert_to_array("name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const POST: ApiMethod = ApiMethod::new(
|
#[api(
|
||||||
&ApiHandler::Sync(&create_datastore),
|
protected: true,
|
||||||
&ObjectSchema::new(
|
input: {
|
||||||
"Create new datastore.",
|
properties: {
|
||||||
&[
|
name: {
|
||||||
("comment", true, &StringSchema::new("Comment for this Datastore").schema()),
|
schema: DATASTORE_SCHEMA,
|
||||||
("name", false, &DATASTORE_SCHEMA),
|
},
|
||||||
("path", false, &StringSchema::new("Directory path. The directory path is created if it does not already exist.").schema()),
|
comment: {
|
||||||
],
|
optional: true,
|
||||||
)
|
schema: datastore::COMMENT_SCHEMA,
|
||||||
).protected(true);
|
},
|
||||||
|
path: {
|
||||||
fn create_datastore(
|
schema: datastore::DIR_NAME_SCHEMA,
|
||||||
param: Value,
|
},
|
||||||
_info: &ApiMethod,
|
},
|
||||||
_rpcenv: &mut dyn RpcEnvironment,
|
},
|
||||||
) -> Result<Value, Error> {
|
)]
|
||||||
|
/// Create new datastore config.
|
||||||
|
pub fn create_datastore(name: String, param: Value) -> Result<(), Error> {
|
||||||
|
|
||||||
// fixme: locking ?
|
// fixme: locking ?
|
||||||
|
|
||||||
|
let datastore: datastore::DataStoreConfig = serde_json::from_value(param.clone())?;
|
||||||
|
|
||||||
let mut config = datastore::config()?;
|
let mut config = datastore::config()?;
|
||||||
|
|
||||||
let name = param["name"].as_str().unwrap();
|
if let Some(_) = config.sections.get(&name) {
|
||||||
|
|
||||||
if let Some(_) = config.sections.get(name) {
|
|
||||||
bail!("datastore '{}' already exists.", name);
|
bail!("datastore '{}' already exists.", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
let path: PathBuf = param["path"].as_str().unwrap().into();
|
if let Some(ref comment) = datastore.comment {
|
||||||
let backup_user = crate::backup::backup_user()?;
|
if comment.find(|c: char| c.is_control()).is_some() {
|
||||||
let _store = ChunkStore::create(name, path, backup_user.uid, backup_user.gid)?;
|
|
||||||
|
|
||||||
let mut datastore = serde_json::Map::new();
|
|
||||||
datastore.insert("path".to_string(), param["path"].clone());
|
|
||||||
if let Some(comment) = param.get("comment") {
|
|
||||||
if comment.as_str().unwrap().find(|c: char| c.is_control()).is_some() {
|
|
||||||
bail!("comment must not contain control characters!");
|
bail!("comment must not contain control characters!");
|
||||||
}
|
}
|
||||||
|
|
||||||
datastore.insert("comment".to_string(), comment.clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config.set_data(name, "datastore", Value::Object(datastore));
|
let path: PathBuf = datastore.path.clone().into();
|
||||||
|
|
||||||
|
let backup_user = crate::backup::backup_user()?;
|
||||||
|
let _store = ChunkStore::create(&name, path, backup_user.uid, backup_user.gid)?;
|
||||||
|
|
||||||
|
config.set_data(&name, "datastore", serde_json::to_value(datastore)?);
|
||||||
|
|
||||||
datastore::save_config(&config)?;
|
datastore::save_config(&config)?;
|
||||||
|
|
||||||
Ok(Value::Null)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DELETE: ApiMethod = ApiMethod::new(
|
#[api(
|
||||||
&ApiHandler::Sync(&delete_datastore),
|
protected: true,
|
||||||
&ObjectSchema::new(
|
input: {
|
||||||
"Remove a datastore configuration.",
|
properties: {
|
||||||
&[
|
name: {
|
||||||
("name", false, &DATASTORE_SCHEMA),
|
schema: DATASTORE_SCHEMA,
|
||||||
],
|
},
|
||||||
)
|
},
|
||||||
).protected(true);
|
},
|
||||||
|
)]
|
||||||
fn delete_datastore(
|
/// Remove a datastore configuration.
|
||||||
param: Value,
|
pub fn delete_datastore(name: String) -> Result<(), Error> {
|
||||||
_info: &ApiMethod,
|
|
||||||
_rpcenv: &mut dyn RpcEnvironment,
|
|
||||||
) -> Result<Value, Error> {
|
|
||||||
println!("This is a test {}", param);
|
|
||||||
|
|
||||||
// fixme: locking ?
|
// fixme: locking ?
|
||||||
// fixme: check digest ?
|
// fixme: check digest ?
|
||||||
|
|
||||||
let mut config = datastore::config()?;
|
let mut config = datastore::config()?;
|
||||||
|
|
||||||
let name = param["name"].as_str().unwrap();
|
match config.sections.get(&name) {
|
||||||
|
Some(_) => { config.sections.remove(&name); },
|
||||||
match config.sections.get(name) {
|
|
||||||
Some(_) => { config.sections.remove(name); },
|
|
||||||
None => bail!("datastore '{}' does not exist.", name),
|
None => bail!("datastore '{}' does not exist.", name),
|
||||||
}
|
}
|
||||||
|
|
||||||
datastore::save_config(&config)?;
|
datastore::save_config(&config)?;
|
||||||
|
|
||||||
Ok(Value::Null)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ROUTER: Router = Router::new()
|
pub const ROUTER: Router = Router::new()
|
||||||
.get(&GET)
|
.get(&API_METHOD_LIST_DATASTORES)
|
||||||
.post(&POST)
|
.post(&API_METHOD_CREATE_DATASTORE)
|
||||||
.delete(&DELETE);
|
.delete(&API_METHOD_DELETE_DATASTORE);
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub fn list_remotes(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
|
protected: true,
|
||||||
input: {
|
input: {
|
||||||
properties: {
|
properties: {
|
||||||
name: {
|
name: {
|
||||||
|
@ -72,6 +73,7 @@ pub fn create_remote(name: String, param: Value) -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
|
protected: true,
|
||||||
input: {
|
input: {
|
||||||
properties: {
|
properties: {
|
||||||
name: {
|
name: {
|
||||||
|
|
|
@ -113,6 +113,7 @@ pub const UPID_SCHEMA: Schema = StringSchema::new("Unique Process/Task ID.")
|
||||||
|
|
||||||
pub const DATASTORE_SCHEMA: Schema = StringSchema::new("Datastore name.")
|
pub const DATASTORE_SCHEMA: Schema = StringSchema::new("Datastore name.")
|
||||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||||
|
.min_length(3)
|
||||||
.max_length(32)
|
.max_length(32)
|
||||||
.schema();
|
.schema();
|
||||||
|
|
||||||
|
|
|
@ -44,18 +44,40 @@ fn connect() -> Result<HttpClient, Error> {
|
||||||
Ok(client)
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remotes_commands() -> CommandLineInterface {
|
||||||
|
|
||||||
|
use proxmox_backup::api2;
|
||||||
|
|
||||||
|
let cmd_def = CliCommandMap::new()
|
||||||
|
.insert("list", CliCommand::new(&api2::config::remotes::API_METHOD_LIST_REMOTES))
|
||||||
|
.insert(
|
||||||
|
"create",
|
||||||
|
// fixme: howto handle password parameter?
|
||||||
|
CliCommand::new(&api2::config::remotes::API_METHOD_CREATE_REMOTE)
|
||||||
|
.arg_param(&["name"])
|
||||||
|
)
|
||||||
|
.insert(
|
||||||
|
"remove",
|
||||||
|
CliCommand::new(&api2::config::remotes::API_METHOD_DELETE_REMOTE)
|
||||||
|
.arg_param(&["name"])
|
||||||
|
.completion_cb("name", config::remotes::complete_remote_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
cmd_def.into()
|
||||||
|
}
|
||||||
|
|
||||||
fn datastore_commands() -> CommandLineInterface {
|
fn datastore_commands() -> CommandLineInterface {
|
||||||
|
|
||||||
use proxmox_backup::api2;
|
use proxmox_backup::api2;
|
||||||
|
|
||||||
let cmd_def = CliCommandMap::new()
|
let cmd_def = CliCommandMap::new()
|
||||||
.insert("list", CliCommand::new(&api2::config::datastore::GET))
|
.insert("list", CliCommand::new(&api2::config::datastore::API_METHOD_LIST_DATASTORES))
|
||||||
.insert("create",
|
.insert("create",
|
||||||
CliCommand::new(&api2::config::datastore::POST)
|
CliCommand::new(&api2::config::datastore::API_METHOD_CREATE_DATASTORE)
|
||||||
.arg_param(&["name", "path"])
|
.arg_param(&["name", "path"])
|
||||||
)
|
)
|
||||||
.insert("remove",
|
.insert("remove",
|
||||||
CliCommand::new(&api2::config::datastore::DELETE)
|
CliCommand::new(&api2::config::datastore::API_METHOD_DELETE_DATASTORE)
|
||||||
.arg_param(&["name"])
|
.arg_param(&["name"])
|
||||||
.completion_cb("name", config::datastore::complete_datastore_name)
|
.completion_cb("name", config::datastore::complete_datastore_name)
|
||||||
);
|
);
|
||||||
|
@ -360,8 +382,7 @@ fn cert_mgmt_cli() -> CommandLineInterface {
|
||||||
schema: DATASTORE_SCHEMA,
|
schema: DATASTORE_SCHEMA,
|
||||||
},
|
},
|
||||||
remote: {
|
remote: {
|
||||||
description: "Remote name.", // fixme: remote ID schema
|
schema: crate::config::remotes::REMOTE_ID_SCHEMA,
|
||||||
type: String,
|
|
||||||
},
|
},
|
||||||
"remote-store": {
|
"remote-store": {
|
||||||
schema: DATASTORE_SCHEMA,
|
schema: DATASTORE_SCHEMA,
|
||||||
|
@ -407,6 +428,7 @@ fn main() {
|
||||||
|
|
||||||
let cmd_def = CliCommandMap::new()
|
let cmd_def = CliCommandMap::new()
|
||||||
.insert("datastore", datastore_commands())
|
.insert("datastore", datastore_commands())
|
||||||
|
.insert("remotes", remotes_commands())
|
||||||
.insert("garbage-collection", garbage_collection_commands())
|
.insert("garbage-collection", garbage_collection_commands())
|
||||||
.insert("cert", cert_mgmt_cli())
|
.insert("cert", cert_mgmt_cli())
|
||||||
.insert("task", task_mgmt_cli())
|
.insert("task", task_mgmt_cli())
|
||||||
|
|
|
@ -6,6 +6,7 @@ use serde::{Serialize, Deserialize};
|
||||||
use proxmox::api::{api, schema::*};
|
use proxmox::api::{api, schema::*};
|
||||||
use proxmox::tools::{fs::replace_file, fs::CreateOptions};
|
use proxmox::tools::{fs::replace_file, fs::CreateOptions};
|
||||||
|
|
||||||
|
use crate::api2::types::*;
|
||||||
use crate::section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
|
use crate::section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -16,9 +17,6 @@ lazy_static! {
|
||||||
|
|
||||||
pub const DIR_NAME_SCHEMA: Schema = StringSchema::new("Directory name").schema();
|
pub const DIR_NAME_SCHEMA: Schema = StringSchema::new("Directory name").schema();
|
||||||
pub const COMMENT_SCHEMA: Schema = StringSchema::new("Datastore comment").schema();
|
pub const COMMENT_SCHEMA: Schema = StringSchema::new("Datastore comment").schema();
|
||||||
pub const DATASTORE_ID_SCHEMA: Schema = StringSchema::new("DataStore ID schema.")
|
|
||||||
.min_length(3)
|
|
||||||
.schema();
|
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -45,7 +43,7 @@ fn init() -> SectionConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
let plugin = SectionConfigPlugin::new("datastore".to_string(), obj_schema);
|
let plugin = SectionConfigPlugin::new("datastore".to_string(), obj_schema);
|
||||||
let mut config = SectionConfig::new(&DATASTORE_ID_SCHEMA);
|
let mut config = SectionConfig::new(&DATASTORE_SCHEMA);
|
||||||
config.register_plugin(plugin);
|
config.register_plugin(plugin);
|
||||||
|
|
||||||
config
|
config
|
||||||
|
|
Loading…
Reference in New Issue