cleanup config api, add remotes config cli interface

This commit is contained in:
Dietmar Maurer 2020-01-11 10:42:09 +01:00
parent 9e9bc6525e
commit 688fbe07a1
5 changed files with 96 additions and 73 deletions

View File

@ -3,19 +3,26 @@ use std::path::PathBuf;
use failure::*;
use serde_json::Value;
use proxmox::api::{ApiHandler, ApiMethod, Router, RpcEnvironment};
use proxmox::api::schema::*;
use proxmox::api::{api, ApiMethod, Router, RpcEnvironment};
use crate::api2::types::*;
use crate::backup::*;
use crate::config::datastore;
pub const GET: ApiMethod = ApiMethod::new(
&ApiHandler::Sync(&get_datastore_list),
&ObjectSchema::new("Directory index.", &[])
);
fn get_datastore_list(
#[api(
input: {
properties: {},
},
returns: {
description: "List the configured datastores.",
type: Array,
items: {
type: datastore::DataStoreConfig,
},
},
)]
/// List all datastores
pub fn list_datastores(
_param: Value,
_info: &ApiMethod,
_rpcenv: &mut dyn RpcEnvironment,
@ -26,90 +33,83 @@ fn get_datastore_list(
Ok(config.convert_to_array("name"))
}
pub const POST: ApiMethod = ApiMethod::new(
&ApiHandler::Sync(&create_datastore),
&ObjectSchema::new(
"Create new datastore.",
&[
("comment", true, &StringSchema::new("Comment for this Datastore").schema()),
("name", false, &DATASTORE_SCHEMA),
("path", false, &StringSchema::new("Directory path. The directory path is created if it does not already exist.").schema()),
],
)
).protected(true);
fn create_datastore(
param: Value,
_info: &ApiMethod,
_rpcenv: &mut dyn RpcEnvironment,
) -> Result<Value, Error> {
#[api(
protected: true,
input: {
properties: {
name: {
schema: DATASTORE_SCHEMA,
},
comment: {
optional: true,
schema: datastore::COMMENT_SCHEMA,
},
path: {
schema: datastore::DIR_NAME_SCHEMA,
},
},
},
)]
/// Create new datastore config.
pub fn create_datastore(name: String, param: Value) -> Result<(), Error> {
// fixme: locking ?
let datastore: datastore::DataStoreConfig = serde_json::from_value(param.clone())?;
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);
}
let path: PathBuf = param["path"].as_str().unwrap().into();
let backup_user = crate::backup::backup_user()?;
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() {
if let Some(ref comment) = datastore.comment {
if comment.find(|c: char| c.is_control()).is_some() {
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)?;
Ok(Value::Null)
Ok(())
}
pub const DELETE: ApiMethod = ApiMethod::new(
&ApiHandler::Sync(&delete_datastore),
&ObjectSchema::new(
"Remove a datastore configuration.",
&[
("name", false, &DATASTORE_SCHEMA),
],
)
).protected(true);
fn delete_datastore(
param: Value,
_info: &ApiMethod,
_rpcenv: &mut dyn RpcEnvironment,
) -> Result<Value, Error> {
println!("This is a test {}", param);
#[api(
protected: true,
input: {
properties: {
name: {
schema: DATASTORE_SCHEMA,
},
},
},
)]
/// Remove a datastore configuration.
pub fn delete_datastore(name: String) -> Result<(), Error> {
// fixme: locking ?
// fixme: check digest ?
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),
}
datastore::save_config(&config)?;
Ok(Value::Null)
Ok(())
}
pub const ROUTER: Router = Router::new()
.get(&GET)
.post(&POST)
.delete(&DELETE);
.get(&API_METHOD_LIST_DATASTORES)
.post(&API_METHOD_CREATE_DATASTORE)
.delete(&API_METHOD_DELETE_DATASTORE);

View File

@ -30,6 +30,7 @@ pub fn list_remotes(
}
#[api(
protected: true,
input: {
properties: {
name: {
@ -72,6 +73,7 @@ pub fn create_remote(name: String, param: Value) -> Result<(), Error> {
}
#[api(
protected: true,
input: {
properties: {
name: {

View File

@ -113,6 +113,7 @@ pub const UPID_SCHEMA: Schema = StringSchema::new("Unique Process/Task ID.")
pub const DATASTORE_SCHEMA: Schema = StringSchema::new("Datastore name.")
.format(&PROXMOX_SAFE_ID_FORMAT)
.min_length(3)
.max_length(32)
.schema();

View File

@ -44,18 +44,40 @@ fn connect() -> Result<HttpClient, Error> {
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 {
use proxmox_backup::api2;
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",
CliCommand::new(&api2::config::datastore::POST)
CliCommand::new(&api2::config::datastore::API_METHOD_CREATE_DATASTORE)
.arg_param(&["name", "path"])
)
.insert("remove",
CliCommand::new(&api2::config::datastore::DELETE)
CliCommand::new(&api2::config::datastore::API_METHOD_DELETE_DATASTORE)
.arg_param(&["name"])
.completion_cb("name", config::datastore::complete_datastore_name)
);
@ -360,8 +382,7 @@ fn cert_mgmt_cli() -> CommandLineInterface {
schema: DATASTORE_SCHEMA,
},
remote: {
description: "Remote name.", // fixme: remote ID schema
type: String,
schema: crate::config::remotes::REMOTE_ID_SCHEMA,
},
"remote-store": {
schema: DATASTORE_SCHEMA,
@ -407,6 +428,7 @@ fn main() {
let cmd_def = CliCommandMap::new()
.insert("datastore", datastore_commands())
.insert("remotes", remotes_commands())
.insert("garbage-collection", garbage_collection_commands())
.insert("cert", cert_mgmt_cli())
.insert("task", task_mgmt_cli())

View File

@ -6,6 +6,7 @@ use serde::{Serialize, Deserialize};
use proxmox::api::{api, schema::*};
use proxmox::tools::{fs::replace_file, fs::CreateOptions};
use crate::api2::types::*;
use crate::section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin};
lazy_static! {
@ -16,9 +17,6 @@ lazy_static! {
pub const DIR_NAME_SCHEMA: Schema = StringSchema::new("Directory name").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(
properties: {
@ -45,7 +43,7 @@ fn init() -> SectionConfig {
};
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