]>
Commit | Line | Data |
---|---|---|
4ebf0eab | 1 | use failure::*; |
fc189b19 | 2 | use ::serde::{Deserialize, Serialize}; |
4ebf0eab | 3 | |
fc189b19 | 4 | use proxmox::api::{api, const_regex, schema::*}; |
255f378a DM |
5 | use proxmox::tools::*; // required to use IPRE!() macro ??? |
6 | ||
7 | // File names: may not contain slashes, may not start with "." | |
8 | pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| { | |
9 | if name.starts_with('.') { | |
10 | bail!("file names may not start with '.'"); | |
11 | } | |
12 | if name.contains('/') { | |
13 | bail!("file names may not contain slashes"); | |
14 | } | |
15 | Ok(()) | |
16 | }); | |
17 | ||
b25f313d DM |
18 | macro_rules! DNS_LABEL { () => (r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") } |
19 | macro_rules! DNS_NAME { () => (concat!(r"(?:", DNS_LABEL!() , r"\.)*", DNS_LABEL!())) } | |
255f378a | 20 | |
163dc16c DM |
21 | // we only allow a limited set of characters |
22 | // colon is not allowed, because we store usernames in | |
23 | // colon separated lists)! | |
24 | // slash is not allowed because it is used as pve API delimiter | |
25 | // also see "man useradd" | |
26 | macro_rules! USER_NAME_REGEX_STR { () => (r"(?:[^\s:/[[:cntrl:]]]+)") } | |
27 | ||
28 | macro_rules! PROXMOX_SAFE_ID_REGEX_STR { () => (r"(?:[A-Za-z0-9_][A-Za-z0-9._\-]*)") } | |
29 | ||
255f378a DM |
30 | const_regex!{ |
31 | pub IP_FORMAT_REGEX = IPRE!(); | |
32 | pub SHA256_HEX_REGEX = r"^[a-f0-9]{64}$"; // fixme: define in common_regex ? | |
33 | pub SYSTEMD_DATETIME_REGEX = r"^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$"; // fixme: define in common_regex ? | |
d0adf270 DM |
34 | |
35 | /// Regex for safe identifiers. | |
36 | /// | |
37 | /// This | |
38 | /// [article](https://dwheeler.com/essays/fixing-unix-linux-filenames.html) | |
39 | /// contains further information why it is reasonable to restict | |
40 | /// names this way. This is not only useful for filenames, but for | |
41 | /// any identifier command line tools work with. | |
163dc16c | 42 | pub PROXMOX_SAFE_ID_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r"$"); |
454c13ed DM |
43 | |
44 | pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$"; | |
b25f313d DM |
45 | |
46 | pub HOSTNAME_REGEX = r"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$"; | |
47 | ||
48 | pub DNS_NAME_REGEX = concat!(r"^", DNS_NAME!(), r")$"); | |
49 | ||
50 | pub DNS_NAME_OR_IP_REGEX = concat!(r"^", DNS_NAME!(), "|", IPRE!(), r")$"); | |
163dc16c DM |
51 | |
52 | pub PROXMOX_USER_ID_REGEX = concat!(r"^", USER_NAME_REGEX_STR!(), r"@", PROXMOX_SAFE_ID_REGEX_STR!(), r"$"); | |
255f378a | 53 | } |
4ebf0eab | 54 | |
255f378a DM |
55 | pub const SYSTEMD_DATETIME_FORMAT: ApiStringFormat = |
56 | ApiStringFormat::Pattern(&SYSTEMD_DATETIME_REGEX); | |
4ebf0eab | 57 | |
255f378a DM |
58 | pub const IP_FORMAT: ApiStringFormat = |
59 | ApiStringFormat::Pattern(&IP_FORMAT_REGEX); | |
bbf9e7e9 | 60 | |
255f378a DM |
61 | pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = |
62 | ApiStringFormat::Pattern(&SHA256_HEX_REGEX); | |
63 | ||
d0adf270 DM |
64 | pub const PROXMOX_SAFE_ID_FORMAT: ApiStringFormat = |
65 | ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX); | |
66 | ||
454c13ed DM |
67 | pub const SINGLE_LINE_COMMENT_FORMAT: ApiStringFormat = |
68 | ApiStringFormat::Pattern(&SINGLE_LINE_COMMENT_REGEX); | |
69 | ||
b25f313d DM |
70 | pub const HOSTNAME_FORMAT: ApiStringFormat = |
71 | ApiStringFormat::Pattern(&HOSTNAME_REGEX); | |
72 | ||
73 | pub const DNS_NAME_FORMAT: ApiStringFormat = | |
74 | ApiStringFormat::Pattern(&DNS_NAME_REGEX); | |
75 | ||
76 | pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat = | |
77 | ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX); | |
78 | ||
163dc16c DM |
79 | pub const PROXMOX_USER_ID_FORMAT: ApiStringFormat = |
80 | ApiStringFormat::Pattern(&PROXMOX_USER_ID_REGEX); | |
81 | ||
454c13ed | 82 | |
255f378a DM |
83 | pub const PVE_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new(r#"\ |
84 | Prevent changes if current configuration file has different SHA256 digest. | |
85 | This can be used to prevent concurrent modifications. | |
86 | "# | |
87 | ) | |
88 | .format(&PVE_CONFIG_DIGEST_FORMAT) | |
89 | .schema(); | |
90 | ||
91 | ||
92 | pub const CHUNK_DIGEST_FORMAT: ApiStringFormat = | |
93 | ApiStringFormat::Pattern(&SHA256_HEX_REGEX); | |
94 | ||
95 | pub const CHUNK_DIGEST_SCHEMA: Schema = StringSchema::new("Chunk digest (SHA256).") | |
96 | .format(&CHUNK_DIGEST_FORMAT) | |
97 | .schema(); | |
98 | ||
99 | pub const NODE_SCHEMA: Schema = StringSchema::new("Node name (or 'localhost')") | |
100 | .format(&ApiStringFormat::VerifyFn(|node| { | |
101 | if node == "localhost" || node == proxmox::tools::nodename() { | |
102 | Ok(()) | |
103 | } else { | |
104 | bail!("no such node '{}'", node); | |
105 | } | |
106 | })) | |
107 | .schema(); | |
108 | ||
109 | pub const SEARCH_DOMAIN_SCHEMA: Schema = | |
110 | StringSchema::new("Search domain for host-name lookup.").schema(); | |
111 | ||
112 | pub const FIRST_DNS_SERVER_SCHEMA: Schema = | |
113 | StringSchema::new("First name server IP address.") | |
114 | .format(&IP_FORMAT) | |
115 | .schema(); | |
116 | ||
117 | pub const SECOND_DNS_SERVER_SCHEMA: Schema = | |
118 | StringSchema::new("Second name server IP address.") | |
119 | .format(&IP_FORMAT) | |
120 | .schema(); | |
121 | ||
122 | pub const THIRD_DNS_SERVER_SCHEMA: Schema = | |
123 | StringSchema::new("Third name server IP address.") | |
124 | .format(&IP_FORMAT) | |
125 | .schema(); | |
126 | ||
127 | pub const BACKUP_ARCHIVE_NAME_SCHEMA: Schema = | |
128 | StringSchema::new("Backup archive name.") | |
1ae5677d | 129 | .format(&PROXMOX_SAFE_ID_FORMAT) |
255f378a DM |
130 | .schema(); |
131 | ||
132 | pub const BACKUP_TYPE_SCHEMA: Schema = | |
133 | StringSchema::new("Backup type.") | |
134 | .format(&ApiStringFormat::Enum(&["vm", "ct", "host"])) | |
135 | .schema(); | |
136 | ||
137 | pub const BACKUP_ID_SCHEMA: Schema = | |
138 | StringSchema::new("Backup ID.") | |
1ae5677d | 139 | .format(&PROXMOX_SAFE_ID_FORMAT) |
255f378a DM |
140 | .schema(); |
141 | ||
142 | pub const BACKUP_TIME_SCHEMA: Schema = | |
143 | IntegerSchema::new("Backup time (Unix epoch.)") | |
144 | .minimum(1_547_797_308) | |
145 | .schema(); | |
5830c205 DM |
146 | |
147 | pub const UPID_SCHEMA: Schema = StringSchema::new("Unique Process/Task ID.") | |
148 | .max_length(256) | |
149 | .schema(); | |
66c49c21 DM |
150 | |
151 | pub const DATASTORE_SCHEMA: Schema = StringSchema::new("Datastore name.") | |
d0adf270 | 152 | .format(&PROXMOX_SAFE_ID_FORMAT) |
688fbe07 | 153 | .min_length(3) |
66c49c21 DM |
154 | .max_length(32) |
155 | .schema(); | |
fc189b19 | 156 | |
167971ed DM |
157 | pub const REMOTE_ID_SCHEMA: Schema = StringSchema::new("Remote ID.") |
158 | .format(&PROXMOX_SAFE_ID_FORMAT) | |
159 | .min_length(3) | |
160 | .max_length(32) | |
161 | .schema(); | |
162 | ||
454c13ed DM |
163 | pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (single line).") |
164 | .format(&SINGLE_LINE_COMMENT_FORMAT) | |
165 | .schema(); | |
fc189b19 | 166 | |
b25f313d DM |
167 | pub const HOSTNAME_SCHEMA: Schema = StringSchema::new("Hostname (as defined in RFC1123).") |
168 | .format(&HOSTNAME_FORMAT) | |
169 | .schema(); | |
170 | ||
171 | pub const DNS_NAME_OR_IP_SCHEMA: Schema = StringSchema::new("DNS name or IP address.") | |
172 | .format(&DNS_NAME_OR_IP_FORMAT) | |
173 | .schema(); | |
174 | ||
163dc16c DM |
175 | pub const PROXMOX_AUTH_REALM_SCHEMA: Schema = StringSchema::new("Authentication domain ID") |
176 | .format(&PROXMOX_SAFE_ID_FORMAT) | |
177 | .min_length(3) | |
178 | .max_length(32) | |
179 | .schema(); | |
180 | ||
181 | pub const PROXMOX_USER_ID_SCHEMA: Schema = StringSchema::new("User ID") | |
182 | .format(&PROXMOX_USER_ID_FORMAT) | |
183 | .min_length(3) | |
184 | .max_length(64) | |
185 | .schema(); | |
186 | ||
fc189b19 DM |
187 | |
188 | // Complex type definitions | |
189 | ||
190 | #[api( | |
fc189b19 DM |
191 | properties: { |
192 | "backup-type": { | |
193 | schema: BACKUP_TYPE_SCHEMA, | |
194 | }, | |
195 | "backup-id": { | |
196 | schema: BACKUP_ID_SCHEMA, | |
197 | }, | |
198 | "backup-time": { | |
199 | schema: BACKUP_TIME_SCHEMA, | |
200 | }, | |
71da3d6a DM |
201 | files: { |
202 | items: { | |
203 | schema: BACKUP_ARCHIVE_NAME_SCHEMA | |
204 | }, | |
205 | }, | |
fc189b19 DM |
206 | }, |
207 | )] | |
208 | #[derive(Serialize, Deserialize)] | |
209 | #[serde(rename_all="kebab-case")] | |
71da3d6a | 210 | /// Basic information about backup snapshot. |
fc189b19 DM |
211 | pub struct SnapshotListItem { |
212 | pub backup_type: String, // enum | |
213 | pub backup_id: String, | |
214 | pub backup_time: i64, | |
71da3d6a | 215 | /// List of contained archive files. |
fc189b19 | 216 | pub files: Vec<String>, |
71da3d6a | 217 | /// Overall snapshot size (sum of all archive sizes). |
fc189b19 DM |
218 | #[serde(skip_serializing_if="Option::is_none")] |
219 | pub size: Option<u64>, | |
220 | } |