]> git.proxmox.com Git - pve-cluster.git/blame - data/PVE/DataCenterConfig.pm
cluster: add get_guest_config_properties
[pve-cluster.git] / data / PVE / DataCenterConfig.pm
CommitLineData
ab966729
FG
1package PVE::DataCenterConfig;
2
3use strict;
4use warnings;
5
51866274 6use PVE::JSONSchema qw(parse_property_string);
ab966729
FG
7use PVE::Tools;
8use PVE::Cluster;
9
10my $migration_format = {
11 type => {
12 default_key => 1,
13 type => 'string',
14 enum => ['secure', 'insecure'],
15 description => "Migration traffic is encrypted using an SSH tunnel by " .
16 "default. On secure, completely private networks this can be " .
17 "disabled to increase performance.",
18 default => 'secure',
19 },
20 network => {
21 optional => 1,
22 type => 'string', format => 'CIDR',
23 format_description => 'CIDR',
24 description => "CIDR of the (sub) network that is used for migration."
25 },
26};
27
28my $ha_format = {
29 shutdown_policy => {
30 type => 'string',
28c22b8d
TL
31 enum => ['freeze', 'failover', 'conditional', 'migrate'],
32 description => "The policy for HA services on node shutdown. 'freeze' disables ".
33 "auto-recovery, 'failover' ensures recovery, 'conditional' recovers on ".
34 "poweroff and freezes on reboot. 'migrate' will migrate running services ".
35 "to other nodes, if possible. With 'freeze' or 'failover', HA Services will ".
36 "always get stopped first on shutdown.",
37 verbose_description => "Describes the policy for handling HA services on poweroff ".
38 "or reboot of a node. Freeze will always freeze services which are still located ".
39 "on the node on shutdown, those services won't be recovered by the HA manager. ".
40 "Failover will not mark the services as frozen and thus the services will get ".
41 "recovered to other nodes, if the shutdown node does not come up again quickly ".
42 "(< 1min). 'conditional' chooses automatically depending on the type of shutdown, ".
43 "i.e., on a reboot the service will be frozen but on a poweroff the service will ".
1818509b 44 "stay as is, and thus get recovered after about 2 minutes. ".
dc43b8a4
TL
45 "Migrate will try to move all running services to another node when a reboot or ".
46 "shutdown was triggered. The poweroff process will only continue once no running services ".
1818509b
TL
47 "are located on the node anymore. If the node comes up again, the service will ".
48 "be moved back to the previously powered-off node, at least if no other migration, ".
49 "reloaction or recovery took place.",
ab966729
FG
50 default => 'conditional',
51 }
52};
53
75e5d02e
TL
54my $next_id_format = {
55 lower => {
56 type => 'integer',
57 description => "Lower, inclusive boundary for free next-id API range.",
58 min => 100,
59 max => 1000 * 1000 * 1000 - 1,
60 default => 100,
61 optional => 1,
62 },
63 upper => {
64 type => 'integer',
8ca3c4bb 65 description => "Upper, exclusive boundary for free next-id API range.",
75e5d02e 66 min => 100,
8ca3c4bb 67 max => 1000 * 1000 * 1000,
75e5d02e
TL
68 default => 1000 * 1000, # lower than the maximum on purpose
69 optional => 1,
70 },
71};
72
bcfa5ac1 73my $u2f_format = {
ab966729
FG
74 appid => {
75 type => 'string',
76 description => "U2F AppId URL override. Defaults to the origin.",
77 format_description => 'APPID',
78 optional => 1,
79 },
80 origin => {
81 type => 'string',
82 description => "U2F Origin override. Mostly useful for single nodes with a single URL.",
83 format_description => 'URL',
84 optional => 1,
85 },
86};
87
8545a705
WB
88my $webauthn_format = {
89 rp => {
90 type => 'string',
91 description =>
92 'Relying party name. Any text identifier.'
93 .' Changing this *may* break existing credentials.',
94 format_description => 'RELYING_PARTY',
95 optional => 1,
96 },
97 origin => {
98 type => 'string',
99 description =>
100 'Site origin. Must be a `https://` URL (or `http://localhost`).'
101 .' Should contain the address users type in their browsers to access'
102 .' the web interface.'
103 .' Changing this *may* break existing credentials.',
104 format_description => 'URL',
105 optional => 1,
106 },
107 id => {
108 type => 'string',
109 description =>
3b0214b6 110 'Relying party ID. Must be the domain name without protocol, port or location.'
8545a705
WB
111 .' Changing this *will* break existing credentials.',
112 format_description => 'DOMAINNAME',
113 optional => 1,
114 },
3b0214b6
WB
115 'allow-subdomains' => {
116 type => 'boolean',
117 description => 'Whether to allow the origin to be a subdomain, rather than the exact URL.',
118 optional => 1,
119 default => 1,
120 },
8545a705 121};
ab966729
FG
122
123PVE::JSONSchema::register_format('mac-prefix', \&pve_verify_mac_prefix);
124sub pve_verify_mac_prefix {
125 my ($mac_prefix, $noerr) = @_;
126
127 if ($mac_prefix !~ m/^[a-f0-9][02468ace](?::[a-f0-9]{2}){0,2}:?$/i) {
128 return undef if $noerr;
129 die "value is not a valid unicast MAC address prefix\n";
130 }
131 return $mac_prefix;
132}
133
134my $datacenter_schema = {
135 type => "object",
136 additionalProperties => 0,
137 properties => {
138 keyboard => {
139 optional => 1,
140 type => 'string',
141 description => "Default keybord layout for vnc server.",
142 enum => PVE::Tools::kvmkeymaplist(),
143 },
144 language => {
145 optional => 1,
146 type => 'string',
147 description => "Default GUI language.",
148 enum => [
149 'ca',
150 'da',
151 'de',
152 'en',
153 'es',
154 'eu',
155 'fa',
156 'fr',
157 'he',
158 'it',
159 'ja',
160 'nb',
161 'nn',
162 'pl',
163 'pt_BR',
164 'ru',
165 'sl',
166 'sv',
167 'tr',
168 'zh_CN',
169 'zh_TW',
170 ],
171 },
172 http_proxy => {
173 optional => 1,
174 type => 'string',
175 description => "Specify external http proxy which is used for downloads (example: 'http://username:password\@host:port/')",
176 pattern => "http://.*",
177 },
0cc6e737 178 # FIXME: remove with 8.0 (add check to pve7to8!), merged into "migration" since 4.3
ab966729
FG
179 migration_unsecure => {
180 optional => 1,
181 type => 'boolean',
182 description => "Migration is secure using SSH tunnel by default. " .
183 "For secure private networks you can disable it to speed up " .
184 "migration. Deprecated, use the 'migration' property instead!",
185 },
75e5d02e
TL
186 'next-id' => {
187 optional => 1,
188 type => 'string',
189 format => $next_id_format,
190 description => "Control the range for the free VMID auto-selection pool.",
191 },
ab966729
FG
192 migration => {
193 optional => 1,
194 type => 'string', format => $migration_format,
195 description => "For cluster wide migration settings.",
196 },
197 console => {
198 optional => 1,
199 type => 'string',
0cc6e737
TL
200 description => "Select the default Console viewer. You can either use the builtin java"
201 ." applet (VNC; deprecated and maps to html5), an external virt-viewer comtatible application (SPICE), an HTML5 based vnc viewer (noVNC), or an HTML5 based console client (xtermjs). If the selected viewer is not available (e.g. SPICE not activated for the VM), the fallback is noVNC.",
202 # FIXME: remove 'applet' with 8.0 (add pve7to8 check!)
ab966729
FG
203 enum => ['applet', 'vv', 'html5', 'xtermjs'],
204 },
205 email_from => {
206 optional => 1,
207 type => 'string',
208 format => 'email-opt',
209 description => "Specify email address to send notification from (default is root@\$hostname)",
210 },
211 max_workers => {
212 optional => 1,
213 type => 'integer',
214 minimum => 1,
215 description => "Defines how many workers (per node) are maximal started ".
216 " on actions like 'stopall VMs' or task from the ha-manager.",
217 },
218 fencing => {
219 optional => 1,
220 type => 'string',
221 default => 'watchdog',
222 enum => [ 'watchdog', 'hardware', 'both' ],
223 description => "Set the fencing mode of the HA cluster. Hardware mode " .
224 "needs a valid configuration of fence devices in /etc/pve/ha/fence.cfg." .
225 " With both all two modes are used." .
226 "\n\nWARNING: 'hardware' and 'both' are EXPERIMENTAL & WIP",
227 },
228 ha => {
229 optional => 1,
230 type => 'string', format => $ha_format,
231 description => "Cluster wide HA settings.",
232 },
233 mac_prefix => {
234 optional => 1,
235 type => 'string',
236 format => 'mac-prefix',
237 description => 'Prefix for autogenerated MAC addresses.',
238 },
239 bwlimit => PVE::JSONSchema::get_standard_option('bwlimit'),
240 u2f => {
241 optional => 1,
242 type => 'string',
243 format => $u2f_format,
244 description => 'u2f',
245 },
8545a705
WB
246 webauthn => {
247 optional => 1,
248 type => 'string',
249 format => $webauthn_format,
250 description => 'webauthn configuration',
251 },
2ae1c0bb
DJ
252 description => {
253 type => 'string',
254 description => "Datacenter description. Shown in the web-interface datacenter notes panel."
255 ." This is saved as comment inside the configuration file.",
256 maxLength => 64 * 1024,
257 optional => 1,
258 },
ab966729
FG
259 },
260};
261
262# make schema accessible from outside (for documentation)
263sub get_datacenter_schema { return $datacenter_schema };
264
265sub parse_datacenter_config {
266 my ($filename, $raw) = @_;
267
b5e2b244
TL
268 $raw = '' if !defined($raw);
269
2ae1c0bb
DJ
270 # description may be comment or key-value pair (or both)
271 my $comment = '';
459f6084 272 for my $line (split(/\n/, $raw)) {
09b99550 273 if ($line =~ /^\#(.*)$/) {
2ae1c0bb
DJ
274 $comment .= PVE::Tools::decode_text($1) . "\n";
275 }
276 }
277
278 # parse_config ignores lines with # => use $raw
b5e2b244 279 my $res = PVE::JSONSchema::parse_config($datacenter_schema, $filename, $raw);
ab966729 280
2ae1c0bb
DJ
281 $res->{description} = $comment;
282
ab966729 283 if (my $migration = $res->{migration}) {
51866274 284 $res->{migration} = parse_property_string($migration_format, $migration);
ab966729
FG
285 }
286
75e5d02e
TL
287 if (my $next_id = $res->{'next-id'}) {
288 $res->{'next-id'} = parse_property_string($next_id_format, $next_id);
289 }
290
ab966729 291 if (my $ha = $res->{ha}) {
51866274 292 $res->{ha} = parse_property_string($ha_format, $ha);
ab966729
FG
293 }
294
bcfa5ac1 295 if (my $u2f = $res->{u2f}) {
51866274 296 $res->{u2f} = parse_property_string($u2f_format, $u2f);
bcfa5ac1
FG
297 }
298
8545a705 299 if (my $webauthn = $res->{webauthn}) {
51866274 300 $res->{webauthn} = parse_property_string($webauthn_format, $webauthn);
8545a705
WB
301 }
302
ab966729
FG
303 # for backwards compatibility only, new migration property has precedence
304 if (defined($res->{migration_unsecure})) {
305 if (defined($res->{migration}->{type})) {
306 warn "deprecated setting 'migration_unsecure' and new 'migration: type' " .
307 "set at same time! Ignore 'migration_unsecure'\n";
308 } else {
309 $res->{migration}->{type} = ($res->{migration_unsecure}) ? 'insecure' : 'secure';
310 }
311 }
312
313 # for backwards compatibility only, applet maps to html5
314 if (defined($res->{console}) && $res->{console} eq 'applet') {
315 $res->{console} = 'html5';
316 }
317
318 return $res;
319}
320
321sub write_datacenter_config {
322 my ($filename, $cfg) = @_;
323
324 # map deprecated setting to new one
325 if (defined($cfg->{migration_unsecure}) && !defined($cfg->{migration})) {
326 my $migration_unsecure = delete $cfg->{migration_unsecure};
327 $cfg->{migration}->{type} = ($migration_unsecure) ? 'insecure' : 'secure';
328 }
329
330 # map deprecated applet setting to html5
331 if (defined($cfg->{console}) && $cfg->{console} eq 'applet') {
332 $cfg->{console} = 'html5';
333 }
334
5b576e26 335 if (ref(my $migration = $cfg->{migration})) {
ab966729
FG
336 $cfg->{migration} = PVE::JSONSchema::print_property_string($migration, $migration_format);
337 }
338
75e5d02e
TL
339 if (defined(my $next_id = $cfg->{'next-id'})) {
340 $next_id = parse_property_string($next_id_format, $next_id) if !ref($next_id);
341
342 my $lower = int($next_id->{lower} // $next_id_format->{lower}->{default});
343 my $upper = int($next_id->{upper} // $next_id_format->{upper}->{default});
344
fe2bc758 345 die "lower ($lower) <= upper ($upper) boundary rule broken\n" if $lower > $upper;
75e5d02e
TL
346
347 $cfg->{'next-id'} = PVE::JSONSchema::print_property_string($next_id, $next_id_format);
348 }
349
5b576e26 350 if (ref(my $ha = $cfg->{ha})) {
ab966729
FG
351 $cfg->{ha} = PVE::JSONSchema::print_property_string($ha, $ha_format);
352 }
353
5b576e26 354 if (ref(my $u2f = $cfg->{u2f})) {
bcfa5ac1
FG
355 $cfg->{u2f} = PVE::JSONSchema::print_property_string($u2f, $u2f_format);
356 }
357
5b576e26 358 if (ref(my $webauthn = $cfg->{webauthn})) {
8545a705
WB
359 $cfg->{webauthn} = PVE::JSONSchema::print_property_string($webauthn, $webauthn_format);
360 }
361
2ae1c0bb
DJ
362 my $comment = '';
363 # add description as comment to top of file
364 my $description = $cfg->{description} || '';
365 foreach my $line (split(/\n/, $description)) {
366 $comment .= '#' . PVE::Tools::encode_text($line) . "\n";
367 }
368 delete $cfg->{description}; # add only as comment, no additional key-value pair
369 my $dump = PVE::JSONSchema::dump_config($datacenter_schema, $filename, $cfg);
370
371 return $comment . "\n" . $dump;
ab966729
FG
372}
373
02ce710f
TL
374PVE::Cluster::cfs_register_file(
375 'datacenter.cfg',
376 \&parse_datacenter_config,
377 \&write_datacenter_config,
378);
ab966729
FG
379
3801;