X-Git-Url: https://git.proxmox.com/?p=proxmox-backup.git;a=blobdiff_plain;f=src%2Fbin%2Fproxmox-backup-api.rs;h=ee037a3bb30574df163fdd9310d9ad4845bd1611;hp=67da761594720391a63d3c331e81b429d0a4482c;hb=d91a0f9fc90aecabc4f359d968f716a14562ce78;hpb=e4311382d9d13683b16123625a5d27b866099921 diff --git a/src/bin/proxmox-backup-api.rs b/src/bin/proxmox-backup-api.rs index 67da7615..ee037a3b 100644 --- a/src/bin/proxmox-backup-api.rs +++ b/src/bin/proxmox-backup-api.rs @@ -1,35 +1,67 @@ -extern crate proxmox_backup; +use std::future::Future; +use std::pin::Pin; -//use proxmox_backup::tools; -use proxmox_backup::api_schema::router::*; -use proxmox_backup::api_schema::config::*; -use proxmox_backup::server::rest::*; -use proxmox_backup::tools::daemon::Reloader; -use proxmox_backup::auth_helpers::*; -use proxmox_backup::config; - -use failure::*; -use lazy_static::lazy_static; +use anyhow::{bail, Error}; +use futures::*; +use http::request::Parts; +use http::Response; +use hyper::{Body, Method, StatusCode}; +use http::HeaderMap; -use futures::future::Future; -use tokio::prelude::*; +use proxmox_lang::try_block; +use proxmox_router::{RpcEnvironmentType, UserInformation}; +use proxmox_sys::fs::CreateOptions; -use hyper; +use proxmox_rest_server::{daemon, AuthError, ApiConfig, RestServer, RestEnvironment, ServerAdapter}; -static mut QUIT_MAIN: bool = false; +use proxmox_backup::server::auth::check_pbs_auth; +use proxmox_backup::auth_helpers::*; +use proxmox_backup::config; fn main() { + pbs_tools::setup_libc_malloc_opts(); - if let Err(err) = run() { + proxmox_backup::tools::setup_safe_path_env(); + + if let Err(err) = proxmox_async::runtime::main(run()) { eprintln!("Error: {}", err); std::process::exit(-1); } } -fn run() -> Result<(), Error> { - // This manages data for reloads: - let mut reloader = Reloader::new(); +struct ProxmoxBackupApiAdapter; + +impl ServerAdapter for ProxmoxBackupApiAdapter { + + fn get_index( + &self, + _env: RestEnvironment, + _parts: Parts, + ) -> Pin> + Send>> { + Box::pin(async move { + + let index = "

Proxmox Backup API Server

"; + Response::builder() + .status(StatusCode::OK) + .header(hyper::header::CONTENT_TYPE, "text/html") + .body(index.into()) + .unwrap() + }) + } + + fn check_auth<'a>( + &'a self, + headers: &'a HeaderMap, + method: &'a Method, + ) -> Pin), AuthError>> + Send + 'a>> { + Box::pin(async move { + check_pbs_auth(headers, method).await + }) + } +} + +async fn run() -> Result<(), Error> { if let Err(err) = syslog::init( syslog::Facility::LOG_DAEMON, log::LevelFilter::Info, @@ -39,6 +71,16 @@ fn run() -> Result<(), Error> { config::create_configdir()?; + config::update_self_signed_cert(false)?; + + proxmox_backup::server::create_run_dir()?; + proxmox_backup::server::create_state_dir()?; + proxmox_backup::server::jobstate::create_jobstate_dir()?; + proxmox_backup::tape::create_tape_status_dir()?; + proxmox_backup::tape::create_drive_state_dir()?; + proxmox_backup::tape::create_changer_state_dir()?; + proxmox_backup::tape::create_drive_lock_dir()?; + if let Err(err) = generate_auth_key() { bail!("unable to generate auth key - {}", err); } @@ -49,85 +91,74 @@ fn run() -> Result<(), Error> { } let _ = csrf_secret(); // load with lazy_static - lazy_static!{ - static ref ROUTER: Router = proxmox_backup::api2::router(); - } + let mut config = ApiConfig::new( + pbs_buildcfg::JS_DIR, + &proxmox_backup::api2::ROUTER, + RpcEnvironmentType::PRIVILEGED, + ProxmoxBackupApiAdapter, + )?; + + let backup_user = pbs_config::backup_user()?; + let mut commando_sock = proxmox_rest_server::CommandSocket::new(proxmox_rest_server::our_ctrl_sock(), backup_user.gid); + + let dir_opts = CreateOptions::new().owner(backup_user.uid).group(backup_user.gid); + let file_opts = CreateOptions::new().owner(backup_user.uid).group(backup_user.gid); + + config.enable_access_log( + pbs_buildcfg::API_ACCESS_LOG_FN, + Some(dir_opts.clone()), + Some(file_opts.clone()), + &mut commando_sock, + )?; + + config.enable_auth_log( + pbs_buildcfg::API_AUTH_LOG_FN, + Some(dir_opts.clone()), + Some(file_opts.clone()), + &mut commando_sock, + )?; - let config = ApiConfig::new( - env!("PROXMOX_JSDIR"), &ROUTER, RpcEnvironmentType::PRIVILEGED); let rest_server = RestServer::new(config); + proxmox_rest_server::init_worker_tasks(pbs_buildcfg::PROXMOX_BACKUP_LOG_DIR_M!().into(), file_opts.clone())?; // http server future: - - let listener: tokio::net::TcpListener = reloader.restore( - "PROXMOX_BACKUP_LISTEN_FD", - || { - let addr = ([127,0,0,1], 82).into(); - Ok(tokio::net::TcpListener::bind(&addr)?) + let server = daemon::create_daemon( + ([127,0,0,1], 82).into(), + move |listener| { + let incoming = hyper::server::conn::AddrIncoming::from_listener(listener)?; + + Ok(async { + daemon::systemd_notify(daemon::SystemdNotify::Ready)?; + + hyper::Server::builder(incoming) + .serve(rest_server) + .with_graceful_shutdown(proxmox_rest_server::shutdown_future()) + .map_err(Error::from) + .await + }) }, - )?; + ); - let mut http_server = hyper::Server::builder(listener.incoming()) - .serve(rest_server) - .map_err(|e| eprintln!("server error: {}", e)); - - // signalfd future: - - let signal_handler = - proxmox_backup::tools::daemon::default_signalfd_stream( - reloader, - || { - unsafe { QUIT_MAIN = true; } - Ok(()) - }, - )? - .map(|si| { - // debugging... - eprintln!("received signal: {}", si.ssi_signo); - }) - .map_err(|e| { - eprintln!("error from signalfd: {}, shutting down...", e); - unsafe { - QUIT_MAIN = true; - } - }); - - - // Combined future for signalfd & http server, we want to quit as soon as either of them ends. - // Neither of them is supposed to end unless some weird error happens, so just bail out if is - // the case... - let mut signal_handler = signal_handler.into_future(); - let main = futures::future::poll_fn(move || { - // Helper for some diagnostic error messages: - fn poll_helper(stream: &mut S, name: &'static str) -> bool { - match stream.poll() { - Ok(Async::Ready(_)) => { - eprintln!("{} ended, shutting down", name); - true - } - Err(_) => { - eprintln!("{} error, shutting down", name); - true - }, - _ => false, - } - } - if poll_helper(&mut http_server, "http server") || - poll_helper(&mut signal_handler, "signalfd handler") - { - return Ok(Async::Ready(())); - } - - if unsafe { QUIT_MAIN } { - eprintln!("shutdown requested"); - Ok(Async::Ready(())) - } else { - Ok(Async::NotReady) - } + proxmox_rest_server::write_pid(pbs_buildcfg::PROXMOX_BACKUP_API_PID_FN)?; + + let init_result: Result<(), Error> = try_block!({ + proxmox_rest_server::register_task_control_commands(&mut commando_sock)?; + commando_sock.spawn()?; + proxmox_rest_server::catch_shutdown_signal()?; + proxmox_rest_server::catch_reload_signal()?; + Ok(()) }); - hyper::rt::run(main); + if let Err(err) = init_result { + bail!("unable to start daemon - {}", err); + } + + server.await?; + log::info!("server shutting down, waiting for active workers to complete"); + proxmox_rest_server::last_worker_future().await?; + + log::info!("done - exit server"); Ok(()) }