more api type cleanups: avoid re-exports
This commit is contained in:
		| @ -506,6 +506,88 @@ pub struct TypeCounts { | ||||
|     pub snapshots: u64, | ||||
| } | ||||
|  | ||||
| #[api( | ||||
|     properties: { | ||||
|         "upid": { | ||||
|             optional: true, | ||||
|             type: UPID, | ||||
|         }, | ||||
|     }, | ||||
| )] | ||||
| #[derive(Clone, Serialize, Deserialize)] | ||||
| #[serde(rename_all = "kebab-case")] | ||||
| /// Garbage collection status. | ||||
| pub struct GarbageCollectionStatus { | ||||
|     pub upid: Option<String>, | ||||
|     /// Number of processed index files. | ||||
|     pub index_file_count: usize, | ||||
|     /// Sum of bytes referred by index files. | ||||
|     pub index_data_bytes: u64, | ||||
|     /// Bytes used on disk. | ||||
|     pub disk_bytes: u64, | ||||
|     /// Chunks used on disk. | ||||
|     pub disk_chunks: usize, | ||||
|     /// Sum of removed bytes. | ||||
|     pub removed_bytes: u64, | ||||
|     /// Number of removed chunks. | ||||
|     pub removed_chunks: usize, | ||||
|     /// Sum of pending bytes (pending removal - kept for safety). | ||||
|     pub pending_bytes: u64, | ||||
|     /// Number of pending chunks (pending removal - kept for safety). | ||||
|     pub pending_chunks: usize, | ||||
|     /// Number of chunks marked as .bad by verify that have been removed by GC. | ||||
|     pub removed_bad: usize, | ||||
|     /// Number of chunks still marked as .bad after garbage collection. | ||||
|     pub still_bad: usize, | ||||
| } | ||||
|  | ||||
| impl Default for GarbageCollectionStatus { | ||||
|     fn default() -> Self { | ||||
|         GarbageCollectionStatus { | ||||
|             upid: None, | ||||
|             index_file_count: 0, | ||||
|             index_data_bytes: 0, | ||||
|             disk_bytes: 0, | ||||
|             disk_chunks: 0, | ||||
|             removed_bytes: 0, | ||||
|             removed_chunks: 0, | ||||
|             pending_bytes: 0, | ||||
|             pending_chunks: 0, | ||||
|             removed_bad: 0, | ||||
|             still_bad: 0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[api( | ||||
|     properties: { | ||||
|         "gc-status": { | ||||
|             type: GarbageCollectionStatus, | ||||
|             optional: true, | ||||
|         }, | ||||
|         counts: { | ||||
|             type: Counts, | ||||
|             optional: true, | ||||
|         }, | ||||
|     }, | ||||
| )] | ||||
| #[derive(Serialize, Deserialize)] | ||||
| #[serde(rename_all="kebab-case")] | ||||
| /// Overall Datastore status and useful information. | ||||
| pub struct DataStoreStatus { | ||||
|     /// Total space (bytes). | ||||
|     pub total: u64, | ||||
|     /// Used space (bytes). | ||||
|     pub used: u64, | ||||
|     /// Available space (bytes). | ||||
|     pub avail: u64, | ||||
|     /// Status of last GC | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub gc_status: Option<GarbageCollectionStatus>, | ||||
|     /// Group/Snapshot counts | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub counts: Option<Counts>, | ||||
| } | ||||
|  | ||||
| pub const ADMIN_DATASTORE_LIST_SNAPSHOTS_RETURN_TYPE: ReturnType = ReturnType { | ||||
|     optional: false, | ||||
|  | ||||
| @ -17,10 +17,6 @@ const_regex!{ | ||||
|     pub SYNC_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):"); | ||||
| } | ||||
|  | ||||
| pub const UPID_SCHEMA: Schema = StringSchema::new("Unique Process/Task ID.") | ||||
|     .max_length(256) | ||||
|     .schema(); | ||||
|  | ||||
| pub const JOB_ID_SCHEMA: Schema = StringSchema::new("Job ID.") | ||||
|     .format(&PROXMOX_SAFE_ID_FORMAT) | ||||
|     .min_length(3) | ||||
|  | ||||
| @ -4,9 +4,7 @@ use serde::{Deserialize, Serialize}; | ||||
| use anyhow::bail; | ||||
|  | ||||
| use proxmox::api::api; | ||||
| use proxmox::api::schema::{ | ||||
|     ApiStringFormat, ApiType, ArraySchema, ReturnType, Schema, StringSchema, | ||||
| }; | ||||
| use proxmox::api::schema::{ApiStringFormat, ArraySchema, Schema, StringSchema}; | ||||
| use proxmox::const_regex; | ||||
| use proxmox::{IPRE, IPRE_BRACKET, IPV4OCTET, IPV4RE, IPV6H16, IPV6LS32, IPV6RE}; | ||||
|  | ||||
| @ -63,7 +61,7 @@ mod user; | ||||
| pub use user::*; | ||||
|  | ||||
| pub mod upid; | ||||
| pub use upid::UPID; | ||||
| pub use upid::*; | ||||
|  | ||||
| mod crypto; | ||||
| pub use crypto::{CryptMode, Fingerprint}; | ||||
| @ -276,58 +274,6 @@ pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new( | ||||
| /// API schema format definition for repository URLs | ||||
| pub const BACKUP_REPO_URL: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_REPO_URL_REGEX); | ||||
|  | ||||
| #[api( | ||||
|     properties: { | ||||
|         "upid": { | ||||
|             optional: true, | ||||
|             type: UPID, | ||||
|         }, | ||||
|     }, | ||||
| )] | ||||
| #[derive(Clone, Serialize, Deserialize)] | ||||
| #[serde(rename_all = "kebab-case")] | ||||
| /// Garbage collection status. | ||||
| pub struct GarbageCollectionStatus { | ||||
|     pub upid: Option<String>, | ||||
|     /// Number of processed index files. | ||||
|     pub index_file_count: usize, | ||||
|     /// Sum of bytes referred by index files. | ||||
|     pub index_data_bytes: u64, | ||||
|     /// Bytes used on disk. | ||||
|     pub disk_bytes: u64, | ||||
|     /// Chunks used on disk. | ||||
|     pub disk_chunks: usize, | ||||
|     /// Sum of removed bytes. | ||||
|     pub removed_bytes: u64, | ||||
|     /// Number of removed chunks. | ||||
|     pub removed_chunks: usize, | ||||
|     /// Sum of pending bytes (pending removal - kept for safety). | ||||
|     pub pending_bytes: u64, | ||||
|     /// Number of pending chunks (pending removal - kept for safety). | ||||
|     pub pending_chunks: usize, | ||||
|     /// Number of chunks marked as .bad by verify that have been removed by GC. | ||||
|     pub removed_bad: usize, | ||||
|     /// Number of chunks still marked as .bad after garbage collection. | ||||
|     pub still_bad: usize, | ||||
| } | ||||
|  | ||||
| impl Default for GarbageCollectionStatus { | ||||
|     fn default() -> Self { | ||||
|         GarbageCollectionStatus { | ||||
|             upid: None, | ||||
|             index_file_count: 0, | ||||
|             index_data_bytes: 0, | ||||
|             disk_bytes: 0, | ||||
|             disk_chunks: 0, | ||||
|             removed_bytes: 0, | ||||
|             removed_chunks: 0, | ||||
|             pending_bytes: 0, | ||||
|             pending_chunks: 0, | ||||
|             removed_bad: 0, | ||||
|             still_bad: 0, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Complex type definitions | ||||
|  | ||||
| @ -383,46 +329,6 @@ impl std::convert::TryFrom<openssl::rsa::Rsa<openssl::pkey::Public>> for RsaPubK | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[api( | ||||
|     properties: { | ||||
|         upid: { schema: UPID::API_SCHEMA }, | ||||
|     }, | ||||
| )] | ||||
| #[derive(Serialize, Deserialize)] | ||||
| /// Task properties. | ||||
| pub struct TaskListItem { | ||||
|     pub upid: String, | ||||
|     /// The node name where the task is running on. | ||||
|     pub node: String, | ||||
|     /// The Unix PID | ||||
|     pub pid: i64, | ||||
|     /// The task start time (Epoch) | ||||
|     pub pstart: u64, | ||||
|     /// The task start time (Epoch) | ||||
|     pub starttime: i64, | ||||
|     /// Worker type (arbitrary ASCII string) | ||||
|     pub worker_type: String, | ||||
|     /// Worker ID (arbitrary ASCII string) | ||||
|     pub worker_id: Option<String>, | ||||
|     /// The authenticated entity who started the task | ||||
|     pub user: Authid, | ||||
|     /// The task end time (Epoch) | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub endtime: Option<i64>, | ||||
|     /// Task end status | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub status: Option<String>, | ||||
| } | ||||
|  | ||||
|  | ||||
| pub const NODE_TASKS_LIST_TASKS_RETURN_TYPE: ReturnType = ReturnType { | ||||
|     optional: false, | ||||
|     schema: &ArraySchema::new( | ||||
|         "A list of tasks.", | ||||
|         &TaskListItem::API_SCHEMA, | ||||
|     ).schema(), | ||||
| }; | ||||
|  | ||||
| #[api()] | ||||
| #[derive(Debug, Clone, Serialize, Deserialize)] | ||||
| #[serde(rename_all = "PascalCase")] | ||||
|  | ||||
| @ -1,8 +1,10 @@ | ||||
| use std::sync::atomic::{AtomicUsize, Ordering}; | ||||
|  | ||||
| use anyhow::{bail, Error}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
|  | ||||
| use proxmox::api::schema::{ApiStringFormat, ApiType, Schema, StringSchema}; | ||||
| use proxmox::api::api; | ||||
| use proxmox::api::schema::{ApiStringFormat, ApiType, Schema, StringSchema, ArraySchema, ReturnType}; | ||||
| use proxmox::const_regex; | ||||
| use proxmox::sys::linux::procfs; | ||||
|  | ||||
| @ -54,12 +56,14 @@ const_regex! { | ||||
| pub const PROXMOX_UPID_FORMAT: ApiStringFormat = | ||||
|     ApiStringFormat::Pattern(&PROXMOX_UPID_REGEX); | ||||
|  | ||||
| pub const UPID_SCHEMA: Schema = StringSchema::new("Unique Process/Task Identifier") | ||||
|     .min_length("UPID:N:12345678:12345678:12345678:::".len()) | ||||
|     .max_length(128) // arbitrary | ||||
|     .format(&PROXMOX_UPID_FORMAT) | ||||
|     .schema(); | ||||
|  | ||||
| impl ApiType for UPID { | ||||
|     const API_SCHEMA: Schema = StringSchema::new("Unique Process/Task Identifier") | ||||
|         .min_length("UPID:N:12345678:12345678:12345678:::".len()) | ||||
|         .max_length(128) // arbitrary | ||||
|         .format(&PROXMOX_UPID_FORMAT) | ||||
|         .schema(); | ||||
|     const API_SCHEMA: Schema = UPID_SCHEMA; | ||||
| } | ||||
|  | ||||
| impl UPID { | ||||
| @ -143,3 +147,57 @@ impl std::fmt::Display for UPID { | ||||
|                self.node, self.pid, self.pstart, self.task_id, self.starttime, self.worker_type, wid, self.auth_id) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[api()] | ||||
| #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] | ||||
| #[serde(rename_all = "lowercase")] | ||||
| pub enum TaskStateType { | ||||
|     /// Ok | ||||
|     OK, | ||||
|     /// Warning | ||||
|     Warning, | ||||
|     /// Error | ||||
|     Error, | ||||
|     /// Unknown | ||||
|     Unknown, | ||||
| } | ||||
|  | ||||
| #[api( | ||||
|     properties: { | ||||
|         upid: { schema: UPID::API_SCHEMA }, | ||||
|     }, | ||||
| )] | ||||
| #[derive(Serialize, Deserialize)] | ||||
| /// Task properties. | ||||
| pub struct TaskListItem { | ||||
|     pub upid: String, | ||||
|     /// The node name where the task is running on. | ||||
|     pub node: String, | ||||
|     /// The Unix PID | ||||
|     pub pid: i64, | ||||
|     /// The task start time (Epoch) | ||||
|     pub pstart: u64, | ||||
|     /// The task start time (Epoch) | ||||
|     pub starttime: i64, | ||||
|     /// Worker type (arbitrary ASCII string) | ||||
|     pub worker_type: String, | ||||
|     /// Worker ID (arbitrary ASCII string) | ||||
|     pub worker_id: Option<String>, | ||||
|     /// The authenticated entity who started the task | ||||
|     pub user: Authid, | ||||
|     /// The task end time (Epoch) | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub endtime: Option<i64>, | ||||
|     /// Task end status | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub status: Option<String>, | ||||
| } | ||||
|  | ||||
| pub const NODE_TASKS_LIST_TASKS_RETURN_TYPE: ReturnType = ReturnType { | ||||
|     optional: false, | ||||
|     schema: &ArraySchema::new( | ||||
|         "A list of tasks.", | ||||
|         &TaskListItem::API_SCHEMA, | ||||
|     ).schema(), | ||||
| }; | ||||
|  | ||||
|  | ||||
| @ -29,6 +29,7 @@ use pxar::EntryKind; | ||||
| use pbs_api_types::{ Authid, BackupContent, Counts, CryptMode, | ||||
|     DataStoreListItem, GarbageCollectionStatus, GroupListItem, | ||||
|     SnapshotListItem, SnapshotVerifyState, PruneOptions, | ||||
|     DataStoreStatus, RRDMode, RRDTimeFrameResolution, | ||||
|     BACKUP_ARCHIVE_NAME_SCHEMA, BACKUP_ID_SCHEMA, BACKUP_TIME_SCHEMA, | ||||
|     BACKUP_TYPE_SCHEMA, DATASTORE_SCHEMA, | ||||
|     IGNORE_VERIFIED_BACKUPS_SCHEMA, UPID_SCHEMA, | ||||
| @ -54,7 +55,6 @@ use pbs_tools::stream::{AsyncReaderStream, AsyncChannelWriter}; | ||||
| use pbs_tools::json::{required_integer_param, required_string_param}; | ||||
| use pbs_config::CachedUserInfo; | ||||
|  | ||||
| use crate::api2::types::{DataStoreStatus, RRDMode, RRDTimeFrameResolution}; | ||||
| use crate::api2::node::rrd::create_value_from_rrd; | ||||
| use crate::backup::{ | ||||
|     check_backup_owner, verify_all_backups, verify_backup_group, verify_backup_dir, verify_filter, | ||||
|  | ||||
| @ -9,15 +9,12 @@ use proxmox::api::{api, ApiMethod, Permission, Router, RpcEnvironment}; | ||||
|  | ||||
| use pbs_api_types::{ | ||||
|     VerificationJobConfig, VerificationJobStatus, JOB_ID_SCHEMA, Authid, | ||||
|     PRIV_DATASTORE_AUDIT, PRIV_DATASTORE_VERIFY, | ||||
|     PRIV_DATASTORE_AUDIT, PRIV_DATASTORE_VERIFY, DATASTORE_SCHEMA, | ||||
| }; | ||||
| use pbs_config::verify; | ||||
| use pbs_config::CachedUserInfo; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::{ | ||||
|         DATASTORE_SCHEMA, | ||||
|     }, | ||||
|     server::{ | ||||
|         do_verification_job, | ||||
|         jobstate::{ | ||||
|  | ||||
| @ -14,8 +14,8 @@ use pbs_datastore::DataBlob; | ||||
| use pbs_datastore::backup_info::{BackupDir, BackupInfo}; | ||||
| use pbs_datastore::dynamic_index::DynamicIndexWriter; | ||||
| use pbs_datastore::fixed_index::FixedIndexWriter; | ||||
| use pbs_api_types::Authid; | ||||
|  | ||||
| use crate::api2::types::Authid; | ||||
| use crate::backup::{verify_backup_dir_with_lock, DataStore}; | ||||
| use crate::server::WorkerTask; | ||||
| use crate::server::formatter::*; | ||||
|  | ||||
| @ -15,7 +15,7 @@ use proxmox::api::schema::*; | ||||
| use pbs_api_types::{ | ||||
|     Authid, VerifyState, SnapshotVerifyState, | ||||
|     BACKUP_ID_SCHEMA, BACKUP_TIME_SCHEMA, BACKUP_TYPE_SCHEMA, DATASTORE_SCHEMA, | ||||
|     CHUNK_DIGEST_SCHEMA, PRIV_DATASTORE_BACKUP, | ||||
|     CHUNK_DIGEST_SCHEMA, PRIV_DATASTORE_BACKUP, BACKUP_ARCHIVE_NAME_SCHEMA, | ||||
| }; | ||||
| use pbs_tools::fs::lock_dir_noblock_shared; | ||||
| use pbs_tools::json::{required_array_param, required_integer_param, required_string_param}; | ||||
| @ -340,7 +340,7 @@ pub const API_METHOD_CREATE_DYNAMIC_INDEX: ApiMethod = ApiMethod::new( | ||||
|     &ObjectSchema::new( | ||||
|         "Create dynamic chunk index file.", | ||||
|         &sorted!([ | ||||
|             ("archive-name", false, &crate::api2::types::BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|             ("archive-name", false, &BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|         ]), | ||||
|     ) | ||||
| ); | ||||
| @ -377,7 +377,7 @@ pub const API_METHOD_CREATE_FIXED_INDEX: ApiMethod = ApiMethod::new( | ||||
|     &ObjectSchema::new( | ||||
|         "Create fixed chunk index file.", | ||||
|         &sorted!([ | ||||
|             ("archive-name", false, &crate::api2::types::BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|             ("archive-name", false, &BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|             ("size", false, &IntegerSchema::new("File size.") | ||||
|              .minimum(1) | ||||
|              .schema() | ||||
| @ -735,7 +735,7 @@ pub const API_METHOD_DOWNLOAD_PREVIOUS: ApiMethod = ApiMethod::new( | ||||
|     &ObjectSchema::new( | ||||
|         "Download archive from previous backup.", | ||||
|         &sorted!([ | ||||
|             ("archive-name", false, &crate::api2::types::BACKUP_ARCHIVE_NAME_SCHEMA) | ||||
|             ("archive-name", false, &BACKUP_ARCHIVE_NAME_SCHEMA) | ||||
|         ]), | ||||
|     ) | ||||
| ); | ||||
|  | ||||
| @ -15,8 +15,8 @@ use proxmox::api::schema::*; | ||||
| use pbs_datastore::DataBlob; | ||||
| use pbs_datastore::file_formats::{DataBlobHeader, EncryptedDataBlobHeader}; | ||||
| use pbs_tools::json::{required_integer_param, required_string_param}; | ||||
| use pbs_api_types::{CHUNK_DIGEST_SCHEMA, BACKUP_ARCHIVE_NAME_SCHEMA}; | ||||
|  | ||||
| use crate::api2::types::*; | ||||
| use crate::backup::DataStore; | ||||
|  | ||||
| use super::environment::*; | ||||
| @ -247,7 +247,7 @@ pub const API_METHOD_UPLOAD_BLOB: ApiMethod = ApiMethod::new( | ||||
|     &ObjectSchema::new( | ||||
|         "Upload binary blob file.", | ||||
|         &sorted!([ | ||||
|             ("file-name", false, &crate::api2::types::BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|             ("file-name", false, &BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|             ("encoded-size", false, &IntegerSchema::new("Encoded blob size.") | ||||
|              .minimum(std::mem::size_of::<DataBlobHeader>() as isize) | ||||
|              .maximum(1024*1024*16+(std::mem::size_of::<EncryptedDataBlobHeader>() as isize)) | ||||
|  | ||||
| @ -3,10 +3,11 @@ | ||||
|  | ||||
| use anyhow::Error; | ||||
|  | ||||
| use crate::api2::types::PROXMOX_CONFIG_DIGEST_SCHEMA; | ||||
| use proxmox::api::{api, Permission, Router, RpcEnvironment, SubdirMap}; | ||||
| use proxmox::list_subdirs_api_method; | ||||
|  | ||||
| use pbs_api_types::PROXMOX_CONFIG_DIGEST_SCHEMA; | ||||
|  | ||||
| use crate::config::tfa::{self, WebauthnConfig, WebauthnConfigUpdater}; | ||||
|  | ||||
| pub const ROUTER: Router = Router::new() | ||||
|  | ||||
| @ -9,15 +9,14 @@ use proxmox::api::router::SubdirMap; | ||||
| use proxmox::{identity, list_subdirs_api_method, sortable}; | ||||
|  | ||||
| use pbs_api_types::{ | ||||
|     Userid, Authid, Tokenname, TaskListItem, | ||||
|     Userid, Authid, Tokenname, TaskListItem, TaskStateType, UPID, | ||||
|     NODE_SCHEMA, UPID_SCHEMA, VERIFICATION_JOB_WORKER_ID_REGEX, | ||||
|     SYNC_JOB_WORKER_ID_REGEX, DATASTORE_SCHEMA, | ||||
|     PRIV_DATASTORE_MODIFY, PRIV_DATASTORE_VERIFY, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, | ||||
| }; | ||||
|  | ||||
| use crate::api2::types::TaskStateType; | ||||
| use crate::api2::pull::check_pull_privs; | ||||
| use crate::server::{self, UPID, UPIDExt, TaskState, TaskListInfoIterator}; | ||||
| use crate::server::{self, UPIDExt, TaskState, TaskListInfoIterator}; | ||||
| use pbs_config::CachedUserInfo; | ||||
|  | ||||
| // matches respective job execution privileges | ||||
|  | ||||
| @ -6,8 +6,8 @@ use serde_json::{json, Value}; | ||||
| use proxmox::api::{RpcEnvironment, RpcEnvironmentType}; | ||||
|  | ||||
| use pbs_datastore::backup_info::BackupDir; | ||||
| use pbs_api_types::Authid; | ||||
|  | ||||
| use crate::api2::types::Authid; | ||||
| use crate::backup::DataStore; | ||||
| use crate::server::formatter::*; | ||||
| use crate::server::WorkerTask; | ||||
|  | ||||
| @ -30,6 +30,7 @@ use proxmox::{ | ||||
| use pbs_api_types::{ | ||||
|     Authid, DATASTORE_SCHEMA, BACKUP_TYPE_SCHEMA, BACKUP_TIME_SCHEMA, BACKUP_ID_SCHEMA, | ||||
|     CHUNK_DIGEST_SCHEMA, PRIV_DATASTORE_READ, PRIV_DATASTORE_BACKUP, | ||||
|     BACKUP_ARCHIVE_NAME_SCHEMA, | ||||
| }; | ||||
| use pbs_tools::fs::lock_dir_noblock_shared; | ||||
| use pbs_tools::json::{required_integer_param, required_string_param}; | ||||
| @ -223,7 +224,7 @@ pub const API_METHOD_DOWNLOAD_FILE: ApiMethod = ApiMethod::new( | ||||
|     &ObjectSchema::new( | ||||
|         "Download specified file.", | ||||
|         &sorted!([ | ||||
|             ("file-name", false, &crate::api2::types::BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|             ("file-name", false, &BACKUP_ARCHIVE_NAME_SCHEMA), | ||||
|         ]), | ||||
|     ) | ||||
| ); | ||||
|  | ||||
| @ -12,8 +12,9 @@ use proxmox::{ | ||||
|     list_subdirs_api_method, | ||||
| }; | ||||
|  | ||||
| use pbs_api_types::TapeDeviceInfo; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::TapeDeviceInfo, | ||||
|     tape::{ | ||||
|         lto_tape_device_list, | ||||
|         linux_tape_changer_list, | ||||
|  | ||||
| @ -3,7 +3,7 @@ use serde_json::Value; | ||||
|  | ||||
| use proxmox::api::{api, schema::{ApiType, Schema, StringSchema, ApiStringFormat}}; | ||||
|  | ||||
| use crate::api2::types::{ | ||||
| use pbs_api_types::{ | ||||
|     DNS_ALIAS_FORMAT, DNS_NAME_FORMAT, PROXMOX_SAFE_ID_FORMAT, | ||||
| }; | ||||
|  | ||||
|  | ||||
| @ -5,11 +5,11 @@ use serde::{Deserialize, Serialize}; | ||||
|  | ||||
| use proxmox::api::{api, schema::*}; | ||||
|  | ||||
| use pbs_api_types::StorageStatus; | ||||
|  | ||||
| mod acme; | ||||
| pub use acme::*; | ||||
|  | ||||
| pub use pbs_api_types::*; | ||||
|  | ||||
| // File names: may not contain slashes, may not start with "." | ||||
| pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| { | ||||
|     if name.starts_with('.') { | ||||
| @ -24,49 +24,6 @@ pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| { | ||||
|  | ||||
| // Complex type definitions | ||||
|  | ||||
| #[api( | ||||
|     properties: { | ||||
|         "gc-status": { | ||||
|             type: GarbageCollectionStatus, | ||||
|             optional: true, | ||||
|         }, | ||||
|         counts: { | ||||
|             type: Counts, | ||||
|             optional: true, | ||||
|         }, | ||||
|     }, | ||||
| )] | ||||
| #[derive(Serialize, Deserialize)] | ||||
| #[serde(rename_all="kebab-case")] | ||||
| /// Overall Datastore status and useful information. | ||||
| pub struct DataStoreStatus { | ||||
|     /// Total space (bytes). | ||||
|     pub total: u64, | ||||
|     /// Used space (bytes). | ||||
|     pub used: u64, | ||||
|     /// Available space (bytes). | ||||
|     pub avail: u64, | ||||
|     /// Status of last GC | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub gc_status: Option<GarbageCollectionStatus>, | ||||
|     /// Group/Snapshot counts | ||||
|     #[serde(skip_serializing_if="Option::is_none")] | ||||
|     pub counts: Option<Counts>, | ||||
| } | ||||
|  | ||||
| #[api()] | ||||
| #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] | ||||
| #[serde(rename_all = "lowercase")] | ||||
| pub enum TaskStateType { | ||||
|     /// Ok | ||||
|     OK, | ||||
|     /// Warning | ||||
|     Warning, | ||||
|     /// Error | ||||
|     Error, | ||||
|     /// Unknown | ||||
|     Unknown, | ||||
| } | ||||
|  | ||||
| // Regression tests | ||||
|  | ||||
|  | ||||
| @ -9,8 +9,7 @@ use anyhow::{bail, format_err, Error}; | ||||
| use serde_json::json; | ||||
|  | ||||
| use pbs_buildcfg::configdir; | ||||
|  | ||||
| use crate::api2::types::{Userid, UsernameRef, RealmRef}; | ||||
| use pbs_api_types::{Userid, UsernameRef, RealmRef}; | ||||
|  | ||||
| pub trait ProxmoxAuthenticator { | ||||
|     fn authenticate_user(&self, username: &UsernameRef, password: &str) -> Result<(), Error>; | ||||
|  | ||||
| @ -6,7 +6,7 @@ use std::time::Instant; | ||||
|  | ||||
| use anyhow::{bail, format_err, Error}; | ||||
|  | ||||
| use pbs_api_types::CryptMode; | ||||
| use pbs_api_types::{Authid, CryptMode, VerifyState, UPID, SnapshotVerifyState}; | ||||
| use pbs_datastore::{task_log, DataBlob, StoreProgress}; | ||||
| use pbs_datastore::backup_info::{BackupGroup, BackupDir, BackupInfo}; | ||||
| use pbs_datastore::index::IndexFile; | ||||
| @ -15,9 +15,7 @@ use pbs_datastore::task::TaskState; | ||||
| use pbs_tools::fs::lock_dir_noblock_shared; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::*, | ||||
|     backup::DataStore, | ||||
|     server::UPID, | ||||
|     tools::ParallelHandler, | ||||
| }; | ||||
|  | ||||
|  | ||||
| @ -26,17 +26,12 @@ use proxmox::{ | ||||
| }; | ||||
|  | ||||
| use pbs_config::drive::complete_changer_name; | ||||
| use pbs_api_types::{ | ||||
|     SCSI_CHANGER_PATH_SCHEMA, CHANGER_NAME_SCHEMA, ScsiTapeChanger, LtoTapeDrive, | ||||
| }; | ||||
|  | ||||
| use proxmox_backup::{ | ||||
|     tools::sgutils2::{ | ||||
|         scsi_inquiry, | ||||
|     }, | ||||
|     api2::types::{ | ||||
|         SCSI_CHANGER_PATH_SCHEMA, | ||||
|         CHANGER_NAME_SCHEMA, | ||||
|         ScsiTapeChanger, | ||||
|         LtoTapeDrive, | ||||
|     }, | ||||
|     tools::sgutils2::scsi_inquiry, | ||||
|     tape::{ | ||||
|         linux_tape_changer_list, | ||||
|         complete_changer_path, | ||||
|  | ||||
| @ -9,9 +9,13 @@ use proxmox::api::{api, cli::*, RpcEnvironment}; | ||||
| use pbs_client::{connect_to_localhost, display_task_log, view_task_result}; | ||||
| use pbs_tools::percent_encoding::percent_encode_component; | ||||
| use pbs_tools::json::required_string_param; | ||||
| use pbs_api_types::{ | ||||
|     DATASTORE_SCHEMA, UPID_SCHEMA, REMOTE_ID_SCHEMA, REMOVE_VANISHED_BACKUPS_SCHEMA, | ||||
|     IGNORE_VERIFIED_BACKUPS_SCHEMA, VERIFICATION_OUTDATED_AFTER_SCHEMA, | ||||
| }; | ||||
|  | ||||
| use proxmox_backup::config; | ||||
| use proxmox_backup::api2::{self, types::* }; | ||||
| use proxmox_backup::api2; | ||||
| use proxmox_backup::server::wait_for_local_worker; | ||||
|  | ||||
| mod proxmox_backup_manager; | ||||
|  | ||||
| @ -7,7 +7,7 @@ use proxmox_backup::api2; | ||||
| use proxmox_backup::tools::subscription; | ||||
|  | ||||
| async fn wait_for_local_worker(upid_str: &str) -> Result<(), Error> { | ||||
|     let upid: proxmox_backup::server::UPID = upid_str.parse()?; | ||||
|     let upid: pbs_api_types::UPID = upid_str.parse()?; | ||||
|     let sleep_duration = core::time::Duration::new(0, 100_000_000); | ||||
|  | ||||
|     loop { | ||||
|  | ||||
| @ -25,20 +25,14 @@ use pbs_config::drive::complete_drive_name; | ||||
| use pbs_config::media_pool::complete_pool_name; | ||||
| use pbs_config::datastore::complete_datastore_name; | ||||
|  | ||||
| use pbs_api_types::{ | ||||
|     Userid, Authid, DATASTORE_SCHEMA, DATASTORE_MAP_LIST_SCHEMA, | ||||
|     DRIVE_NAME_SCHEMA, MEDIA_LABEL_SCHEMA, MEDIA_POOL_NAME_SCHEMA, | ||||
|     TAPE_RESTORE_SNAPSHOT_SCHEMA, | ||||
| }; | ||||
|  | ||||
| use proxmox_backup::{ | ||||
|     api2::{ | ||||
|         self, | ||||
|         types::{ | ||||
|             Authid, | ||||
|             DATASTORE_SCHEMA, | ||||
|             DATASTORE_MAP_LIST_SCHEMA, | ||||
|             DRIVE_NAME_SCHEMA, | ||||
|             MEDIA_LABEL_SCHEMA, | ||||
|             MEDIA_POOL_NAME_SCHEMA, | ||||
|             Userid, | ||||
|             TAPE_RESTORE_SNAPSHOT_SCHEMA, | ||||
|         }, | ||||
|     }, | ||||
|     api2, | ||||
|     tape::{ | ||||
|         BlockReadError, | ||||
|         drive::{ | ||||
|  | ||||
| @ -16,13 +16,10 @@ use pbs_config::drive::{ | ||||
|     complete_changer_name, | ||||
| }; | ||||
|  | ||||
| use pbs_api_types::CHANGER_NAME_SCHEMA; | ||||
|  | ||||
| use proxmox_backup::{ | ||||
|     api2::{ | ||||
|         self, | ||||
|         types::{ | ||||
|             CHANGER_NAME_SCHEMA, | ||||
|         }, | ||||
|     }, | ||||
|     api2, | ||||
|     tape::{ | ||||
|         complete_changer_path, | ||||
|         drive::media_changer, | ||||
|  | ||||
| @ -7,8 +7,9 @@ use serde_json::Value; | ||||
| use proxmox::sys::error::SysError; | ||||
| use proxmox::tools::fs::{CreateOptions, file_read_string}; | ||||
|  | ||||
| use pbs_api_types::PROXMOX_SAFE_ID_REGEX; | ||||
|  | ||||
| use crate::api2::types::{ | ||||
|     PROXMOX_SAFE_ID_REGEX, | ||||
|     AcmeChallengeSchema, | ||||
|     KnownAcmeDirectory, | ||||
|     AcmeAccountName, | ||||
|  | ||||
| @ -7,7 +7,7 @@ use lazy_static::lazy_static; | ||||
|  | ||||
| use proxmox::tools::fs::{create_path, CreateOptions}; | ||||
|  | ||||
| use crate::api2::types::{RRDMode, RRDTimeFrameResolution}; | ||||
| use pbs_api_types::{RRDMode, RRDTimeFrameResolution}; | ||||
|  | ||||
| use super::*; | ||||
|  | ||||
|  | ||||
| @ -3,7 +3,7 @@ use std::path::Path; | ||||
|  | ||||
| use anyhow::Error; | ||||
|  | ||||
| use crate::api2::types::{RRDMode, RRDTimeFrameResolution}; | ||||
| use pbs_api_types::{RRDMode, RRDTimeFrameResolution}; | ||||
|  | ||||
| pub const RRD_DATA_ENTRIES: usize = 70; | ||||
|  | ||||
|  | ||||
| @ -4,11 +4,10 @@ use anyhow::{format_err, Error}; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| use pbs_tools::ticket::{self, Ticket}; | ||||
| use pbs_config::token_shadow; | ||||
| use pbs_config::{token_shadow, CachedUserInfo}; | ||||
| use pbs_api_types::{Authid, Userid}; | ||||
|  | ||||
| use crate::api2::types::{Authid, Userid}; | ||||
| use crate::auth_helpers::*; | ||||
| use pbs_config::CachedUserInfo; | ||||
| use crate::tools; | ||||
|  | ||||
| use hyper::header; | ||||
|  | ||||
| @ -1,9 +1,10 @@ | ||||
| use std::sync::Arc; | ||||
| use anyhow::Error; | ||||
|  | ||||
| use pbs_api_types::Authid; | ||||
|  | ||||
| use crate::{ | ||||
|     server::WorkerTask, | ||||
|     api2::types::*, | ||||
|     server::jobstate::Job, | ||||
|     backup::DataStore, | ||||
| }; | ||||
|  | ||||
| @ -48,15 +48,12 @@ use proxmox::tools::fs::{ | ||||
|  | ||||
| use pbs_systemd::time::{compute_next_event, parse_calendar_event}; | ||||
| use pbs_config::{open_backup_lockfile, BackupLockGuard}; | ||||
| use pbs_api_types::{UPID, JobScheduleStatus}; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::JobScheduleStatus, | ||||
|     server::{ | ||||
|         UPID, | ||||
|         TaskState, | ||||
|         upid_read_status, | ||||
|         worker_is_active_local, | ||||
|     }, | ||||
| use crate::server::{ | ||||
|     TaskState, | ||||
|     upid_read_status, | ||||
|     worker_is_active_local, | ||||
| }; | ||||
|  | ||||
| #[derive(Serialize, Deserialize)] | ||||
|  | ||||
| @ -32,13 +32,13 @@ use proxmox::http_err; | ||||
|  | ||||
| use pbs_tools::compression::{DeflateEncoder, Level}; | ||||
| use pbs_tools::stream::AsyncReaderStream; | ||||
| use pbs_api_types::{Authid, Userid}; | ||||
|  | ||||
| use super::auth::AuthError; | ||||
| use super::environment::RestEnvironment; | ||||
| use super::formatter::*; | ||||
| use super::ApiConfig; | ||||
|  | ||||
| use crate::api2::types::{Authid, Userid}; | ||||
| use crate::auth_helpers::*; | ||||
| use pbs_config::CachedUserInfo; | ||||
| use crate::tools; | ||||
|  | ||||
| @ -3,7 +3,8 @@ use std::fmt; | ||||
| use anyhow::{bail, Error}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
|  | ||||
| use crate::api2::types::Userid; | ||||
| use pbs_api_types::Userid; | ||||
|  | ||||
| use crate::config::tfa; | ||||
|  | ||||
| #[derive(Deserialize, Serialize)] | ||||
|  | ||||
| @ -1,5 +1,3 @@ | ||||
| pub use pbs_api_types::upid::UPID; | ||||
|  | ||||
| pub trait UPIDExt: private::Sealed { | ||||
|     /// Returns the absolute path to the task log file | ||||
|     fn log_path(&self) -> std::path::PathBuf; | ||||
| @ -7,10 +5,10 @@ pub trait UPIDExt: private::Sealed { | ||||
|  | ||||
| mod private { | ||||
|     pub trait Sealed {} | ||||
|     impl Sealed for super::UPID {} | ||||
|     impl Sealed for  pbs_api_types::UPID {} | ||||
| } | ||||
|  | ||||
| impl UPIDExt for UPID { | ||||
| impl UPIDExt for  pbs_api_types::UPID { | ||||
|     fn log_path(&self) -> std::path::PathBuf { | ||||
|         let mut path = std::path::PathBuf::from(super::PROXMOX_BACKUP_TASK_DIR); | ||||
|         path.push(format!("{:02X}", self.pstart % 256)); | ||||
|  | ||||
| @ -18,13 +18,13 @@ use proxmox::tools::fs::{create_path, replace_file, CreateOptions}; | ||||
|  | ||||
| use pbs_buildcfg; | ||||
| use pbs_tools::logrotate::{LogRotate, LogRotateFiles}; | ||||
| use pbs_api_types::{Authid, TaskStateType, UPID}; | ||||
| use pbs_config::{open_backup_lockfile, BackupLockGuard}; | ||||
|  | ||||
| use super::{UPID, UPIDExt}; | ||||
| use super::UPIDExt; | ||||
|  | ||||
| use crate::server; | ||||
| use crate::tools::{FileLogger, FileLogOptions}; | ||||
| use crate::api2::types::{Authid, TaskStateType}; | ||||
| use pbs_config::{open_backup_lockfile, BackupLockGuard}; | ||||
|  | ||||
| macro_rules! taskdir { | ||||
|     ($subdir:expr) => (concat!(pbs_buildcfg::PROXMOX_BACKUP_LOG_DIR_M!(), "/tasks", $subdir)) | ||||
|  | ||||
| @ -23,11 +23,7 @@ use proxmox::{ | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| use crate::api2::types::{ | ||||
|     SLOT_ARRAY_SCHEMA, | ||||
|     ScsiTapeChanger, | ||||
|     LtoTapeDrive, | ||||
| }; | ||||
| use pbs_api_types::{SLOT_ARRAY_SCHEMA, ScsiTapeChanger, LtoTapeDrive}; | ||||
|  | ||||
| /// Changer element status. | ||||
| /// | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| use anyhow::Error; | ||||
|  | ||||
| use pbs_tools::run_command; | ||||
| use pbs_api_types::ScsiTapeChanger; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::ScsiTapeChanger, | ||||
|     tape::changer::{ | ||||
|         MtxStatus, | ||||
|         mtx::parse_mtx_status, | ||||
|  | ||||
| @ -6,11 +6,9 @@ use anyhow::{bail, Error}; | ||||
| use proxmox::tools::Uuid; | ||||
| use proxmox::api::section_config::SectionConfigData; | ||||
|  | ||||
| use pbs_api_types::{VirtualTapeDrive, ScsiTapeChanger}; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::{ | ||||
|         VirtualTapeDrive, | ||||
|         ScsiTapeChanger, | ||||
|     }, | ||||
|     tape::{ | ||||
|         Inventory, | ||||
|         changer::{ | ||||
|  | ||||
| @ -11,6 +11,8 @@ use endian_trait::Endian; | ||||
|  | ||||
| use proxmox::tools::io::ReadExt; | ||||
|  | ||||
| use pbs_api_types::ScsiTapeChanger; | ||||
|  | ||||
| use crate::{ | ||||
|     tape::{ | ||||
|         changer::{ | ||||
| @ -28,7 +30,6 @@ use crate::{ | ||||
|         scsi_ascii_to_string, | ||||
|         scsi_inquiry, | ||||
|     }, | ||||
|     api2::types::ScsiTapeChanger, | ||||
| }; | ||||
|  | ||||
| const SCSI_CHANGER_DEFAULT_TIMEOUT: usize = 60*5; // 5 minutes | ||||
|  | ||||
| @ -29,11 +29,9 @@ use proxmox::{ | ||||
|     tools::io::{ReadExt, WriteExt}, | ||||
| }; | ||||
|  | ||||
| use pbs_api_types::{MamAttribute, Lp17VolumeStatistics}; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::{ | ||||
|         MamAttribute, | ||||
|         Lp17VolumeStatistics, | ||||
|     }, | ||||
|     tape::{ | ||||
|         BlockRead, | ||||
|         BlockReadError, | ||||
|  | ||||
| @ -7,12 +7,11 @@ use endian_trait::Endian; | ||||
|  | ||||
| use proxmox::tools::io::ReadExt; | ||||
|  | ||||
| use pbs_api_types::MamAttribute; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::MamAttribute, | ||||
|     tools::sgutils2::SgRaw, | ||||
|     tape::{ | ||||
|         drive::lto::TapeAlertFlags, | ||||
|     }, | ||||
|     tape::drive::lto::TapeAlertFlags, | ||||
| }; | ||||
|  | ||||
| // Read Medium auxiliary memory attributes (MAM) | ||||
|  | ||||
| @ -6,10 +6,9 @@ use endian_trait::Endian; | ||||
|  | ||||
| use proxmox::tools::io::ReadExt; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::Lp17VolumeStatistics, | ||||
|     tools::sgutils2::SgRaw, | ||||
| }; | ||||
| use pbs_api_types::Lp17VolumeStatistics; | ||||
|  | ||||
| use crate::tools::sgutils2::SgRaw; | ||||
|  | ||||
| /// SCSI command to query volume statistics | ||||
| /// | ||||
|  | ||||
| @ -41,6 +41,7 @@ use proxmox::tools::{ | ||||
|  | ||||
| use pbs_systemd::time::compute_next_event; | ||||
| use pbs_config::BackupLockGuard; | ||||
| use pbs_api_types::{MediaSetPolicy, RetentionPolicy, MediaStatus, MediaLocation}; | ||||
|  | ||||
| #[cfg(not(test))] | ||||
| use pbs_config::open_backup_lockfile; | ||||
| @ -56,12 +57,6 @@ fn open_backup_lockfile<P: AsRef<std::path::Path>>( | ||||
|  | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::{ | ||||
|         MediaSetPolicy, | ||||
|         RetentionPolicy, | ||||
|         MediaStatus, | ||||
|         MediaLocation, | ||||
|     }, | ||||
|     tape::{ | ||||
|         TAPE_STATUS_DIR, | ||||
|         MediaSet, | ||||
|  | ||||
| @ -4,14 +4,7 @@ use std::collections::HashMap; | ||||
| use anyhow::{bail, Error}; | ||||
|  | ||||
| use pbs_tools::fs::scan_subdir; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::{ | ||||
|         DeviceKind, | ||||
|         OptionalDeviceIdentification, | ||||
|         TapeDeviceInfo, | ||||
|     }, | ||||
| }; | ||||
| use pbs_api_types::{DeviceKind, OptionalDeviceIdentification, TapeDeviceInfo}; | ||||
|  | ||||
| lazy_static::lazy_static!{ | ||||
|     static ref SCSI_GENERIC_NAME_REGEX: regex::Regex = | ||||
|  | ||||
| @ -14,31 +14,25 @@ use serde::{Deserialize, Serialize}; | ||||
|  | ||||
| use proxmox::tools::Uuid; | ||||
|  | ||||
| use pbs_api_types::Fingerprint; | ||||
| use pbs_api_types::{ | ||||
|     Fingerprint, MediaStatus, MediaLocation, MediaSetPolicy, RetentionPolicy, | ||||
|     MediaPoolConfig, | ||||
| }; | ||||
| use pbs_systemd::time::compute_next_event; | ||||
| use pbs_config::BackupLockGuard; | ||||
|  | ||||
| use crate::{ | ||||
|     api2::types::{ | ||||
|         MediaStatus, | ||||
|         MediaLocation, | ||||
|         MediaSetPolicy, | ||||
|         RetentionPolicy, | ||||
|         MediaPoolConfig, | ||||
| use crate::tape::{ | ||||
|     MediaId, | ||||
|     MediaSet, | ||||
|     Inventory, | ||||
|     MediaCatalog, | ||||
|     lock_media_set, | ||||
|     lock_media_pool, | ||||
|     lock_unassigned_media_pool, | ||||
|     file_formats::{ | ||||
|         MediaLabel, | ||||
|         MediaSetLabel, | ||||
|     }, | ||||
|     tape::{ | ||||
|         MediaId, | ||||
|         MediaSet, | ||||
|         Inventory, | ||||
|         MediaCatalog, | ||||
|         lock_media_set, | ||||
|         lock_media_pool, | ||||
|         lock_unassigned_media_pool, | ||||
|         file_formats::{ | ||||
|             MediaLabel, | ||||
|             MediaSetLabel, | ||||
|         }, | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /// Media Pool | ||||
|  | ||||
| @ -7,7 +7,7 @@ use apt_pkg_native::Cache; | ||||
| use proxmox::const_regex; | ||||
| use proxmox::tools::fs::{file_read_optional_string, replace_file, CreateOptions}; | ||||
|  | ||||
| use crate::api2::types::APTUpdateInfo; | ||||
| use pbs_api_types::APTUpdateInfo; | ||||
|  | ||||
| const APT_PKG_STATE_FN: &str = "/var/lib/proxmox-backup/pkg-state.json"; | ||||
|  | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use serde::{Serialize, Deserialize}; | ||||
|  | ||||
| use proxmox::api::{ api, schema::* }; | ||||
| use crate::api2::types::SINGLE_LINE_COMMENT_FORMAT; | ||||
| use pbs_api_types::SINGLE_LINE_COMMENT_FORMAT; | ||||
|  | ||||
| pub const SYSTEMD_SECTION_NAME_SCHEMA: Schema = StringSchema::new( | ||||
|     "Section name") | ||||
|  | ||||
		Reference in New Issue
	
	Block a user