]> git.proxmox.com Git - proxmox-backup.git/blame - src/bin/proxmox-backup-api.rs
update proxmox-metrics dependency to 0.3.1
[proxmox-backup.git] / src / bin / proxmox-backup-api.rs
CommitLineData
6680878b
DM
1use std::future::Future;
2use std::pin::Pin;
3
f7d4e4b5 4use anyhow::{bail, Error};
e76ac3a4 5use futures::*;
7fa9a37c 6use http::Response;
5aeeb44a 7use hyper::{Body, StatusCode};
e76ac3a4 8
6ef1b649 9use proxmox_lang::try_block;
5aeeb44a 10use proxmox_router::RpcEnvironmentType;
25877d05 11use proxmox_sys::fs::CreateOptions;
e76ac3a4 12
5aeeb44a 13use proxmox_rest_server::{daemon, ApiConfig, RestServer};
8bca935f 14
6c30068e 15use proxmox_backup::auth_helpers::*;
a8f268af 16use proxmox_backup::config;
9531d2c5 17use proxmox_backup::server::auth::check_pbs_auth;
886e5ce8 18
d973aa82 19fn main() {
d91a0f9f
DM
20 pbs_tools::setup_libc_malloc_opts();
21
ac7513e3
DM
22 proxmox_backup::tools::setup_safe_path_env();
23
9a1b24b6 24 if let Err(err) = proxmox_async::runtime::main(run()) {
aa5a4060
DM
25 eprintln!("Error: {}", err);
26 std::process::exit(-1);
27 }
28}
29
5aeeb44a
WB
30fn get_index() -> Pin<Box<dyn Future<Output = Response<Body>> + Send>> {
31 Box::pin(async move {
32 let index = "<center><h1>Proxmox Backup API Server</h1></center>";
608806e8 33
5aeeb44a
WB
34 Response::builder()
35 .status(StatusCode::OK)
36 .header(hyper::header::CONTENT_TYPE, "text/html")
37 .body(index.into())
38 .unwrap()
39 })
7fa9a37c
DM
40}
41
e76ac3a4 42async fn run() -> Result<(), Error> {
d96d8273
DM
43 if let Err(err) = syslog::init(
44 syslog::Facility::LOG_DAEMON,
45 log::LevelFilter::Info,
9531d2c5
TL
46 Some("proxmox-backup-api"),
47 ) {
aa5a4060 48 bail!("unable to inititialize syslog - {}", err);
a8f268af
DM
49 }
50
51 config::create_configdir()?;
d96d8273 52
22be470d
DM
53 config::update_self_signed_cert(false)?;
54
6c76aa43 55 proxmox_backup::server::create_run_dir()?;
bf013be1 56 proxmox_backup::server::create_state_dir()?;
4bc84a65 57 proxmox_backup::server::create_active_operations_dir()?;
1298618a 58 proxmox_backup::server::jobstate::create_jobstate_dir()?;
57570bda 59 proxmox_backup::server::notifications::create_spool_dir()?;
cafd51bf 60 proxmox_backup::tape::create_tape_status_dir()?;
cd44fb8d
DM
61 proxmox_backup::tape::create_drive_state_dir()?;
62 proxmox_backup::tape::create_changer_state_dir()?;
a0cd0f9c 63 proxmox_backup::tape::create_drive_lock_dir()?;
eaeda365 64
39a90ca6 65 if let Err(err) = generate_auth_key() {
aa5a4060 66 bail!("unable to generate auth key - {}", err);
8d04280b 67 }
d01e2420 68 let _ = private_auth_key(); // load with lazy_static
8d04280b 69
39a90ca6 70 if let Err(err) = generate_csrf_key() {
aa5a4060 71 bail!("unable to generate csrf key - {}", err);
39a90ca6 72 }
d01e2420 73 let _ = csrf_secret(); // load with lazy_static
39a90ca6 74
d97ff8ae 75 proxmox_backup::auth_helpers::setup_auth_context(true);
57570bda 76 proxmox_backup::server::notifications::init()?;
d97ff8ae 77
fd6d2438 78 let backup_user = pbs_config::backup_user()?;
78fc7b0e 79 let mut command_sock = proxmox_rest_server::CommandSocket::new(
9531d2c5
TL
80 proxmox_rest_server::our_ctrl_sock(),
81 backup_user.gid,
82 );
a68768cf 83
9531d2c5
TL
84 let dir_opts = CreateOptions::new()
85 .owner(backup_user.uid)
86 .group(backup_user.gid);
87 let file_opts = CreateOptions::new()
88 .owner(backup_user.uid)
89 .group(backup_user.gid);
fd6d2438 90
5aeeb44a
WB
91 let config = ApiConfig::new(pbs_buildcfg::JS_DIR, RpcEnvironmentType::PRIVILEGED)
92 .index_handler_func(|_, _| get_index())
93 .auth_handler_func(|h, m| Box::pin(check_pbs_auth(h, m)))
94 .default_api2_handler(&proxmox_backup::api2::ROUTER)
95 .enable_access_log(
96 pbs_buildcfg::API_ACCESS_LOG_FN,
97 Some(dir_opts.clone()),
98 Some(file_opts.clone()),
78fc7b0e 99 &mut command_sock,
5aeeb44a
WB
100 )?
101 .enable_auth_log(
102 pbs_buildcfg::API_AUTH_LOG_FN,
103 Some(dir_opts.clone()),
104 Some(file_opts.clone()),
78fc7b0e 105 &mut command_sock,
5aeeb44a 106 )?;
8e7e2223 107
9bc17e8d 108 let rest_server = RestServer::new(config);
9531d2c5
TL
109 proxmox_rest_server::init_worker_tasks(
110 pbs_buildcfg::PROXMOX_BACKUP_LOG_DIR_M!().into(),
111 file_opts.clone(),
112 )?;
886e5ce8 113
5e7bc50a 114 // http server future:
e9b9f33a
FE
115 let server = daemon::create_daemon(
116 ([127, 0, 0, 1], 82).into(),
117 move |listener| {
118 let incoming = hyper::server::conn::AddrIncoming::from_listener(listener)?;
119
120 Ok(async {
121 daemon::systemd_notify(daemon::SystemdNotify::Ready)?;
122
123 hyper::Server::builder(incoming)
124 .serve(rest_server)
125 .with_graceful_shutdown(proxmox_rest_server::shutdown_future())
126 .map_err(Error::from)
127 .await
128 })
129 },
130 Some(pbs_buildcfg::PROXMOX_BACKUP_API_PID_FN),
131 );
5e7bc50a 132
b9700a9f 133 proxmox_rest_server::write_pid(pbs_buildcfg::PROXMOX_BACKUP_API_PID_FN)?;
d98c9a7a 134
e76ac3a4 135 let init_result: Result<(), Error> = try_block!({
78fc7b0e
WB
136 proxmox_rest_server::register_task_control_commands(&mut command_sock)?;
137 command_sock.spawn()?;
fd1b65cc
DM
138 proxmox_rest_server::catch_shutdown_signal()?;
139 proxmox_rest_server::catch_reload_signal()?;
e76ac3a4
WB
140 Ok(())
141 });
e3f41f21 142
e76ac3a4
WB
143 if let Err(err) = init_result {
144 bail!("unable to start daemon - {}", err);
145 }
d607b886 146
c2206e21
TL
147 // stop gap for https://github.com/tokio-rs/tokio/issues/4730 where the thread holding the
148 // IO-driver may block progress completely if it starts polling its own tasks (blocks).
149 // So, trigger a notify to parked threads, as we're immediately ready the woken up thread will
150 // acquire the IO driver, if blocked, before going to sleep, which allows progress again
151 // TODO: remove once tokio solves this at their level (see proposals in linked comments)
152 let rt_handle = tokio::runtime::Handle::current();
153 std::thread::spawn(move || loop {
154 rt_handle.spawn(std::future::ready(()));
155 std::thread::sleep(std::time::Duration::from_secs(3));
156 });
157
57570bda
LW
158 start_notification_worker();
159
083ff3fd 160 server.await?;
a546a8a0 161 log::info!("server shutting down, waiting for active workers to complete");
fd6d2438 162 proxmox_rest_server::last_worker_future().await?;
e3f41f21 163
e76ac3a4 164 log::info!("done - exit server");
eaeda365 165
aa5a4060 166 Ok(())
d8d978eb 167}
57570bda
LW
168
169fn start_notification_worker() {
170 let abort_future = proxmox_rest_server::shutdown_future();
171 let future = Box::pin(proxmox_backup::server::notifications::notification_worker());
172 let task = futures::future::select(future, abort_future);
173 tokio::spawn(task);
174}