move api schema into proxmox::api crate
And leave some compat imports in api_schema.rs to get it to build with minimal changes. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
552c225948
commit
3d482025b3
17
src/api2.rs
17
src/api2.rs
@ -1,17 +1,18 @@
|
|||||||
pub mod types;
|
mod access;
|
||||||
pub mod config;
|
|
||||||
pub mod admin;
|
pub mod admin;
|
||||||
pub mod backup;
|
pub mod backup;
|
||||||
pub mod reader;
|
pub mod config;
|
||||||
pub mod node;
|
pub mod node;
|
||||||
pub mod version;
|
pub mod reader;
|
||||||
mod subscription;
|
mod subscription;
|
||||||
mod access;
|
pub mod types;
|
||||||
|
pub mod version;
|
||||||
|
|
||||||
use crate::api_schema::router::*;
|
use proxmox::api::list_subdirs_api_method;
|
||||||
|
use proxmox::api::router::SubdirMap;
|
||||||
|
use proxmox::api::Router;
|
||||||
|
|
||||||
const NODES_ROUTER: Router = Router::new()
|
const NODES_ROUTER: Router = Router::new().match_all("node", &node::ROUTER);
|
||||||
.match_all("node", &node::ROUTER);
|
|
||||||
|
|
||||||
pub const SUBDIRS: SubdirMap = &[
|
pub const SUBDIRS: SubdirMap = &[
|
||||||
("access", &access::ROUTER),
|
("access", &access::ROUTER),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::api_schema::router::*;
|
use proxmox::api::router::{Router, SubdirMap};
|
||||||
|
use proxmox::api::list_subdirs_api_method;
|
||||||
|
|
||||||
pub mod datastore;
|
pub mod datastore;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::api_schema::router::*;
|
use proxmox::api::router::{Router, SubdirMap};
|
||||||
|
use proxmox::api::list_subdirs_api_method;
|
||||||
|
|
||||||
pub mod datastore;
|
pub mod datastore;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::api_schema::router::*;
|
use proxmox::api::router::{Router, SubdirMap};
|
||||||
|
use proxmox::api::list_subdirs_api_method;
|
||||||
|
|
||||||
mod tasks;
|
mod tasks;
|
||||||
mod time;
|
mod time;
|
||||||
|
@ -8,16 +8,31 @@
|
|||||||
//! hierarchy of API entries, and provides ways to find an API
|
//! hierarchy of API entries, and provides ways to find an API
|
||||||
//! definition by path.
|
//! definition by path.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
mod schema;
|
|
||||||
pub use schema::*;
|
|
||||||
|
|
||||||
pub mod rpc_environment;
|
|
||||||
pub mod api_handler;
|
|
||||||
#[macro_use]
|
|
||||||
pub mod router;
|
|
||||||
|
|
||||||
//pub mod registry;
|
//pub mod registry;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------------------------------
|
||||||
|
* Everything below is a compatibility layer to support building the current code until api2.rs
|
||||||
|
* and the api2/ directory have been updated to the proxmox::api crate:
|
||||||
|
* --------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub use proxmox::api::schema::*;
|
||||||
|
pub use proxmox::api::*;
|
||||||
|
|
||||||
|
pub use proxmox::api::ApiFuture as BoxFut;
|
||||||
|
|
||||||
|
pub mod api_handler {
|
||||||
|
pub use super::{ApiAsyncHandlerFn, ApiHandler, ApiHandlerFn, BoxFut};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod router {
|
||||||
|
pub use super::{ApiHandler, ApiMethod, HttpError, RpcEnvironment, RpcEnvironmentType};
|
||||||
|
pub use proxmox::api::router::*;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod schema {
|
||||||
|
pub use proxmox::api::schema::*;
|
||||||
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
use failure::Error;
|
|
||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
use hyper::{Body, Response};
|
|
||||||
use hyper::rt::Future;
|
|
||||||
use hyper::http::request::Parts;
|
|
||||||
|
|
||||||
use super::rpc_environment::RpcEnvironment;
|
|
||||||
use super::router::ApiMethod;
|
|
||||||
|
|
||||||
pub type BoxFut = Box<dyn Future<Output = Result<Response<Body>, failure::Error>> + Send>;
|
|
||||||
|
|
||||||
pub type ApiHandlerFn = &'static (
|
|
||||||
dyn Fn(Value, &ApiMethod, &mut dyn RpcEnvironment) -> Result<Value, Error>
|
|
||||||
+ Send + Sync + 'static
|
|
||||||
);
|
|
||||||
|
|
||||||
pub type ApiAsyncHandlerFn = &'static (
|
|
||||||
dyn Fn(Parts, Body, Value, &'static ApiMethod, Box<dyn RpcEnvironment>) -> Result<BoxFut, Error>
|
|
||||||
+ Send + Sync + 'static
|
|
||||||
);
|
|
||||||
|
|
||||||
pub enum ApiHandler {
|
|
||||||
Sync(ApiHandlerFn),
|
|
||||||
Async(ApiAsyncHandlerFn),
|
|
||||||
}
|
|
@ -1,261 +0,0 @@
|
|||||||
use failure::*;
|
|
||||||
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use hyper::{Method, StatusCode};
|
|
||||||
//use hyper::http::request::Parts;
|
|
||||||
|
|
||||||
use super::schema::*;
|
|
||||||
pub use super::rpc_environment::*;
|
|
||||||
pub use super::api_handler::*;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Fail)]
|
|
||||||
pub struct HttpError {
|
|
||||||
pub code: StatusCode,
|
|
||||||
pub message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HttpError {
|
|
||||||
pub fn new(code: StatusCode, message: String) -> Self {
|
|
||||||
HttpError { code, message }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for HttpError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! http_err {
|
|
||||||
($status:ident, $msg:expr) => {{
|
|
||||||
Error::from(HttpError::new(StatusCode::$status, $msg))
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This struct defines synchronous API call which returns the restulkt as json `Value`
|
|
||||||
pub struct ApiMethod {
|
|
||||||
/// The protected flag indicates that the provides function should be forwarded
|
|
||||||
/// to the deaemon running in priviledged mode.
|
|
||||||
pub protected: bool,
|
|
||||||
/// This flag indicates that the provided method may change the local timezone, so the server
|
|
||||||
/// should do a tzset afterwards
|
|
||||||
pub reload_timezone: bool,
|
|
||||||
/// Parameter type Schema
|
|
||||||
pub parameters: &'static ObjectSchema,
|
|
||||||
/// Return type Schema
|
|
||||||
pub returns: &'static Schema,
|
|
||||||
/// Handler function
|
|
||||||
pub handler: &'static ApiHandler,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for ApiMethod {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "ApiMethod {{ ")?;
|
|
||||||
write!(f, " parameters: {:?}", self.parameters)?;
|
|
||||||
write!(f, " returns: {:?}", self.returns)?;
|
|
||||||
write!(f, " handler: {:p}", &self.handler)?;
|
|
||||||
write!(f, "}}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const NULL_SCHEMA: Schema = Schema::Null;
|
|
||||||
|
|
||||||
fn dummy_handler_fn(_arg: Value, _method: &ApiMethod, _env: &mut dyn RpcEnvironment) -> Result<Value, Error> {
|
|
||||||
// do nothing
|
|
||||||
Ok(Value::Null)
|
|
||||||
}
|
|
||||||
|
|
||||||
const DUMMY_HANDLER: ApiHandler = ApiHandler::Sync(&dummy_handler_fn);
|
|
||||||
|
|
||||||
impl ApiMethod {
|
|
||||||
|
|
||||||
pub const fn new(handler: &'static ApiHandler, parameters: &'static ObjectSchema) -> Self {
|
|
||||||
Self {
|
|
||||||
parameters,
|
|
||||||
handler,
|
|
||||||
returns: &NULL_SCHEMA,
|
|
||||||
protected: false,
|
|
||||||
reload_timezone: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn new_dummy(parameters: &'static ObjectSchema) -> Self {
|
|
||||||
Self {
|
|
||||||
parameters,
|
|
||||||
handler: &DUMMY_HANDLER,
|
|
||||||
returns: &NULL_SCHEMA,
|
|
||||||
protected: false,
|
|
||||||
reload_timezone: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn returns(mut self, schema: &'static Schema) -> Self {
|
|
||||||
|
|
||||||
self.returns = schema;
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn protected(mut self, protected: bool) -> Self {
|
|
||||||
|
|
||||||
self.protected = protected;
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn reload_timezone(mut self, reload_timezone: bool) -> Self {
|
|
||||||
|
|
||||||
self.reload_timezone = reload_timezone;
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type SubdirMap = &'static [(&'static str, &'static Router)];
|
|
||||||
|
|
||||||
pub enum SubRoute {
|
|
||||||
//Hash(HashMap<String, Router>),
|
|
||||||
Map(SubdirMap),
|
|
||||||
MatchAll { router: &'static Router, param_name: &'static str },
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Macro to create an ApiMethod to list entries from SubdirMap
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! list_subdirs_api_method {
|
|
||||||
($map:expr) => {
|
|
||||||
ApiMethod::new(
|
|
||||||
&ApiHandler::Sync( & |_, _, _| {
|
|
||||||
let index = serde_json::json!(
|
|
||||||
$map.iter().map(|s| serde_json::json!({ "subdir": s.0}))
|
|
||||||
.collect::<Vec<serde_json::Value>>()
|
|
||||||
);
|
|
||||||
Ok(index)
|
|
||||||
}),
|
|
||||||
&crate::api_schema::ObjectSchema::new("Directory index.", &[]).additional_properties(true)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Router {
|
|
||||||
pub get: Option<&'static ApiMethod>,
|
|
||||||
pub put: Option<&'static ApiMethod>,
|
|
||||||
pub post: Option<&'static ApiMethod>,
|
|
||||||
pub delete: Option<&'static ApiMethod>,
|
|
||||||
pub subroute: Option<SubRoute>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Router {
|
|
||||||
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
get: None,
|
|
||||||
put: None,
|
|
||||||
post: None,
|
|
||||||
delete: None,
|
|
||||||
subroute: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn subdirs(mut self, map: SubdirMap) -> Self {
|
|
||||||
self.subroute = Some(SubRoute::Map(map));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn match_all(mut self, param_name: &'static str, router: &'static Router) -> Self {
|
|
||||||
self.subroute = Some(SubRoute::MatchAll { router, param_name });
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn get(mut self, m: &'static ApiMethod) -> Self {
|
|
||||||
self.get = Some(m);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn put(mut self, m: &'static ApiMethod) -> Self {
|
|
||||||
self.put = Some(m);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn post(mut self, m: &'static ApiMethod) -> Self {
|
|
||||||
self.post = Some(m);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Same as post, buth async (fixme: expect Async)
|
|
||||||
pub const fn upload(mut self, m: &'static ApiMethod) -> Self {
|
|
||||||
self.post = Some(m);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Same as get, but async (fixme: expect Async)
|
|
||||||
pub const fn download(mut self, m: &'static ApiMethod) -> Self {
|
|
||||||
self.get = Some(m);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Same as get, but async (fixme: expect Async)
|
|
||||||
pub const fn upgrade(mut self, m: &'static ApiMethod) -> Self {
|
|
||||||
self.get = Some(m);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn delete(mut self, m: &'static ApiMethod) -> Self {
|
|
||||||
self.delete = Some(m);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_route(&self, components: &[&str], uri_param: &mut HashMap<String, String>) -> Option<&Router> {
|
|
||||||
|
|
||||||
if components.is_empty() { return Some(self); };
|
|
||||||
|
|
||||||
let (dir, rest) = (components[0], &components[1..]);
|
|
||||||
|
|
||||||
match self.subroute {
|
|
||||||
None => {},
|
|
||||||
Some(SubRoute::Map(dirmap)) => {
|
|
||||||
if let Ok(ind) = dirmap.binary_search_by_key(&dir, |(name, _)| name) {
|
|
||||||
let (_name, router) = dirmap[ind];
|
|
||||||
//println!("FOUND SUBDIR {}", dir);
|
|
||||||
return router.find_route(rest, uri_param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(SubRoute::MatchAll { router, param_name }) => {
|
|
||||||
//println!("URI PARAM {} = {}", param_name, dir); // fixme: store somewhere
|
|
||||||
uri_param.insert(param_name.to_owned(), dir.into());
|
|
||||||
return router.find_route(rest, uri_param);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_method(
|
|
||||||
&self,
|
|
||||||
components: &[&str],
|
|
||||||
method: Method,
|
|
||||||
uri_param: &mut HashMap<String, String>
|
|
||||||
) -> Option<&ApiMethod> {
|
|
||||||
|
|
||||||
if let Some(info) = self.find_route(components, uri_param) {
|
|
||||||
return match method {
|
|
||||||
Method::GET => info.get,
|
|
||||||
Method::PUT => info.put,
|
|
||||||
Method::POST => info.post,
|
|
||||||
Method::DELETE => info.delete,
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Router {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
/// Abstract Interface for API methods to interact with the environment
|
|
||||||
pub trait RpcEnvironment: std::any::Any + crate::tools::AsAny + Send {
|
|
||||||
|
|
||||||
/// Use this to pass additional result data. It is up to the environment
|
|
||||||
/// how the data is used.
|
|
||||||
fn set_result_attrib(&mut self, name: &str, value: Value);
|
|
||||||
|
|
||||||
/// Query additional result data.
|
|
||||||
fn get_result_attrib(&self, name: &str) -> Option<&Value>;
|
|
||||||
|
|
||||||
/// The environment type
|
|
||||||
fn env_type(&self) -> RpcEnvironmentType;
|
|
||||||
|
|
||||||
/// Set user name
|
|
||||||
fn set_user(&mut self, user: Option<String>);
|
|
||||||
|
|
||||||
/// Get user name
|
|
||||||
fn get_user(&self) -> Option<String>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Environment Type
|
|
||||||
///
|
|
||||||
/// We use this to enumerate the different environment types. Some methods
|
|
||||||
/// needs to do different things when started from the command line interface,
|
|
||||||
/// or when executed from a privileged server running as root.
|
|
||||||
#[derive(PartialEq, Copy, Clone)]
|
|
||||||
pub enum RpcEnvironmentType {
|
|
||||||
/// Command started from command line
|
|
||||||
CLI,
|
|
||||||
/// Access from public accessible server
|
|
||||||
PUBLIC,
|
|
||||||
/// Access from privileged server (run as root)
|
|
||||||
PRIVILEGED,
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,3 @@
|
|||||||
#[macro_use]
|
|
||||||
extern crate proxmox_backup;
|
|
||||||
|
|
||||||
use failure::*;
|
use failure::*;
|
||||||
use nix::unistd::{fork, ForkResult, pipe};
|
use nix::unistd::{fork, ForkResult, pipe};
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
@ -13,12 +10,12 @@ use std::os::unix::fs::OpenOptionsExt;
|
|||||||
|
|
||||||
use proxmox::{sortable, identity};
|
use proxmox::{sortable, identity};
|
||||||
use proxmox::tools::fs::{file_get_contents, file_get_json, file_set_contents, image_size};
|
use proxmox::tools::fs::{file_get_contents, file_get_json, file_set_contents, image_size};
|
||||||
|
use proxmox::api::{ApiHandler, ApiMethod, RpcEnvironment};
|
||||||
|
use proxmox::api::schema::*;
|
||||||
|
|
||||||
use proxmox_backup::tools;
|
use proxmox_backup::tools;
|
||||||
use proxmox_backup::cli::*;
|
use proxmox_backup::cli::*;
|
||||||
use proxmox_backup::api2::types::*;
|
use proxmox_backup::api2::types::*;
|
||||||
use proxmox_backup::api_schema::*;
|
|
||||||
use proxmox_backup::api_schema::router::*;
|
|
||||||
use proxmox_backup::client::*;
|
use proxmox_backup::client::*;
|
||||||
use proxmox_backup::backup::*;
|
use proxmox_backup::backup::*;
|
||||||
use proxmox_backup::pxar::{ self, catalog::* };
|
use proxmox_backup::pxar::{ self, catalog::* };
|
||||||
@ -37,7 +34,7 @@ use xdg::BaseDirectories;
|
|||||||
use futures::*;
|
use futures::*;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
proxmox_backup::const_regex! {
|
proxmox::api::const_regex! {
|
||||||
BACKUPSPEC_REGEX = r"^([a-zA-Z0-9_-]+\.(?:pxar|img|conf|log)):(.+)$";
|
BACKUPSPEC_REGEX = r"^([a-zA-Z0-9_-]+\.(?:pxar|img|conf|log)):(.+)$";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,9 @@ use std::task::{Context, Poll};
|
|||||||
use futures::*;
|
use futures::*;
|
||||||
use hyper::{Body, Request, Response, StatusCode};
|
use hyper::{Body, Request, Response, StatusCode};
|
||||||
|
|
||||||
|
use proxmox::api::{http_err, ApiFuture};
|
||||||
|
|
||||||
use crate::tools;
|
use crate::tools;
|
||||||
use crate::api_schema::api_handler::*;
|
|
||||||
use crate::api_schema::router::*;
|
use crate::api_schema::router::*;
|
||||||
use crate::server::formatter::*;
|
use crate::server::formatter::*;
|
||||||
use crate::server::WorkerTask;
|
use crate::server::WorkerTask;
|
||||||
@ -35,7 +36,7 @@ impl <E: RpcEnvironment + Clone> H2Service<E> {
|
|||||||
if self.debug { self.worker.log(msg); }
|
if self.debug { self.worker.log(msg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_request(&self, req: Request<Body>) -> BoxFut {
|
fn handle_request(&self, req: Request<Body>) -> ApiFuture {
|
||||||
|
|
||||||
let (parts, body) = req.into_parts();
|
let (parts, body) = req.into_parts();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user