]> git.proxmox.com Git - pve-cluster.git/blame - data/PVE/DataCenterConfig.pm
datacenter.cfg: fix fall back for undefined config
[pve-cluster.git] / data / PVE / DataCenterConfig.pm
CommitLineData
ab966729
FG
1package PVE::DataCenterConfig;
2
3use strict;
4use warnings;
5
6use PVE::JSONSchema;
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
bcfa5ac1 54my $u2f_format = {
ab966729
FG
55 appid => {
56 type => 'string',
57 description => "U2F AppId URL override. Defaults to the origin.",
58 format_description => 'APPID',
59 optional => 1,
60 },
61 origin => {
62 type => 'string',
63 description => "U2F Origin override. Mostly useful for single nodes with a single URL.",
64 format_description => 'URL',
65 optional => 1,
66 },
67};
68
8545a705
WB
69my $webauthn_format = {
70 rp => {
71 type => 'string',
72 description =>
73 'Relying party name. Any text identifier.'
74 .' Changing this *may* break existing credentials.',
75 format_description => 'RELYING_PARTY',
76 optional => 1,
77 },
78 origin => {
79 type => 'string',
80 description =>
81 'Site origin. Must be a `https://` URL (or `http://localhost`).'
82 .' Should contain the address users type in their browsers to access'
83 .' the web interface.'
84 .' Changing this *may* break existing credentials.',
85 format_description => 'URL',
86 optional => 1,
87 },
88 id => {
89 type => 'string',
90 description =>
91 'Relying part ID. Must be the domain name without protocol, port or location.'
92 .' Changing this *will* break existing credentials.',
93 format_description => 'DOMAINNAME',
94 optional => 1,
95 },
96};
ab966729
FG
97
98PVE::JSONSchema::register_format('mac-prefix', \&pve_verify_mac_prefix);
99sub pve_verify_mac_prefix {
100 my ($mac_prefix, $noerr) = @_;
101
102 if ($mac_prefix !~ m/^[a-f0-9][02468ace](?::[a-f0-9]{2}){0,2}:?$/i) {
103 return undef if $noerr;
104 die "value is not a valid unicast MAC address prefix\n";
105 }
106 return $mac_prefix;
107}
108
109my $datacenter_schema = {
110 type => "object",
111 additionalProperties => 0,
112 properties => {
113 keyboard => {
114 optional => 1,
115 type => 'string',
116 description => "Default keybord layout for vnc server.",
117 enum => PVE::Tools::kvmkeymaplist(),
118 },
119 language => {
120 optional => 1,
121 type => 'string',
122 description => "Default GUI language.",
123 enum => [
124 'ca',
125 'da',
126 'de',
127 'en',
128 'es',
129 'eu',
130 'fa',
131 'fr',
132 'he',
133 'it',
134 'ja',
135 'nb',
136 'nn',
137 'pl',
138 'pt_BR',
139 'ru',
140 'sl',
141 'sv',
142 'tr',
143 'zh_CN',
144 'zh_TW',
145 ],
146 },
147 http_proxy => {
148 optional => 1,
149 type => 'string',
150 description => "Specify external http proxy which is used for downloads (example: 'http://username:password\@host:port/')",
151 pattern => "http://.*",
152 },
153 migration_unsecure => {
154 optional => 1,
155 type => 'boolean',
156 description => "Migration is secure using SSH tunnel by default. " .
157 "For secure private networks you can disable it to speed up " .
158 "migration. Deprecated, use the 'migration' property instead!",
159 },
160 migration => {
161 optional => 1,
162 type => 'string', format => $migration_format,
163 description => "For cluster wide migration settings.",
164 },
165 console => {
166 optional => 1,
167 type => 'string',
168 description => "Select the default Console viewer. You can either use the builtin java 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.",
169 enum => ['applet', 'vv', 'html5', 'xtermjs'],
170 },
171 email_from => {
172 optional => 1,
173 type => 'string',
174 format => 'email-opt',
175 description => "Specify email address to send notification from (default is root@\$hostname)",
176 },
177 max_workers => {
178 optional => 1,
179 type => 'integer',
180 minimum => 1,
181 description => "Defines how many workers (per node) are maximal started ".
182 " on actions like 'stopall VMs' or task from the ha-manager.",
183 },
184 fencing => {
185 optional => 1,
186 type => 'string',
187 default => 'watchdog',
188 enum => [ 'watchdog', 'hardware', 'both' ],
189 description => "Set the fencing mode of the HA cluster. Hardware mode " .
190 "needs a valid configuration of fence devices in /etc/pve/ha/fence.cfg." .
191 " With both all two modes are used." .
192 "\n\nWARNING: 'hardware' and 'both' are EXPERIMENTAL & WIP",
193 },
194 ha => {
195 optional => 1,
196 type => 'string', format => $ha_format,
197 description => "Cluster wide HA settings.",
198 },
199 mac_prefix => {
200 optional => 1,
201 type => 'string',
202 format => 'mac-prefix',
203 description => 'Prefix for autogenerated MAC addresses.',
204 },
205 bwlimit => PVE::JSONSchema::get_standard_option('bwlimit'),
206 u2f => {
207 optional => 1,
208 type => 'string',
209 format => $u2f_format,
210 description => 'u2f',
211 },
8545a705
WB
212 webauthn => {
213 optional => 1,
214 type => 'string',
215 format => $webauthn_format,
216 description => 'webauthn configuration',
217 },
2ae1c0bb
DJ
218 description => {
219 type => 'string',
220 description => "Datacenter description. Shown in the web-interface datacenter notes panel."
221 ." This is saved as comment inside the configuration file.",
222 maxLength => 64 * 1024,
223 optional => 1,
224 },
ab966729
FG
225 },
226};
227
228# make schema accessible from outside (for documentation)
229sub get_datacenter_schema { return $datacenter_schema };
230
231sub parse_datacenter_config {
232 my ($filename, $raw) = @_;
233
b5e2b244
TL
234 $raw = '' if !defined($raw);
235
2ae1c0bb
DJ
236 # description may be comment or key-value pair (or both)
237 my $comment = '';
238 my @lines = split(/\n/, $raw);
239 foreach my $line (@lines) {
240 if ($line =~ /^\#(.*)\s*$/) {
241 $comment .= PVE::Tools::decode_text($1) . "\n";
242 }
243 }
244
245 # parse_config ignores lines with # => use $raw
b5e2b244 246 my $res = PVE::JSONSchema::parse_config($datacenter_schema, $filename, $raw);
ab966729 247
2ae1c0bb
DJ
248 $res->{description} = $comment;
249
250
ab966729
FG
251 if (my $migration = $res->{migration}) {
252 $res->{migration} = PVE::JSONSchema::parse_property_string($migration_format, $migration);
253 }
254
255 if (my $ha = $res->{ha}) {
256 $res->{ha} = PVE::JSONSchema::parse_property_string($ha_format, $ha);
257 }
258
bcfa5ac1
FG
259 if (my $u2f = $res->{u2f}) {
260 $res->{u2f} = PVE::JSONSchema::parse_property_string($u2f_format, $u2f);
261 }
262
8545a705
WB
263 if (my $webauthn = $res->{webauthn}) {
264 $res->{webauthn} = PVE::JSONSchema::parse_property_string($webauthn_format, $webauthn);
265 }
266
ab966729
FG
267 # for backwards compatibility only, new migration property has precedence
268 if (defined($res->{migration_unsecure})) {
269 if (defined($res->{migration}->{type})) {
270 warn "deprecated setting 'migration_unsecure' and new 'migration: type' " .
271 "set at same time! Ignore 'migration_unsecure'\n";
272 } else {
273 $res->{migration}->{type} = ($res->{migration_unsecure}) ? 'insecure' : 'secure';
274 }
275 }
276
277 # for backwards compatibility only, applet maps to html5
278 if (defined($res->{console}) && $res->{console} eq 'applet') {
279 $res->{console} = 'html5';
280 }
281
282 return $res;
283}
284
285sub write_datacenter_config {
286 my ($filename, $cfg) = @_;
287
288 # map deprecated setting to new one
289 if (defined($cfg->{migration_unsecure}) && !defined($cfg->{migration})) {
290 my $migration_unsecure = delete $cfg->{migration_unsecure};
291 $cfg->{migration}->{type} = ($migration_unsecure) ? 'insecure' : 'secure';
292 }
293
294 # map deprecated applet setting to html5
295 if (defined($cfg->{console}) && $cfg->{console} eq 'applet') {
296 $cfg->{console} = 'html5';
297 }
298
299 if (ref($cfg->{migration})) {
300 my $migration = $cfg->{migration};
301 $cfg->{migration} = PVE::JSONSchema::print_property_string($migration, $migration_format);
302 }
303
304 if (ref($cfg->{ha})) {
305 my $ha = $cfg->{ha};
306 $cfg->{ha} = PVE::JSONSchema::print_property_string($ha, $ha_format);
307 }
308
bcfa5ac1
FG
309 if (ref($cfg->{u2f})) {
310 my $u2f = $cfg->{u2f};
311 $cfg->{u2f} = PVE::JSONSchema::print_property_string($u2f, $u2f_format);
312 }
313
8545a705
WB
314 if (ref($cfg->{webauthn})) {
315 my $webauthn = $cfg->{webauthn};
316 $cfg->{webauthn} = PVE::JSONSchema::print_property_string($webauthn, $webauthn_format);
317 }
318
2ae1c0bb
DJ
319 my $comment = '';
320 # add description as comment to top of file
321 my $description = $cfg->{description} || '';
322 foreach my $line (split(/\n/, $description)) {
323 $comment .= '#' . PVE::Tools::encode_text($line) . "\n";
324 }
325 delete $cfg->{description}; # add only as comment, no additional key-value pair
326 my $dump = PVE::JSONSchema::dump_config($datacenter_schema, $filename, $cfg);
327
328 return $comment . "\n" . $dump;
ab966729
FG
329}
330
331PVE::Cluster::cfs_register_file('datacenter.cfg',
332 \&parse_datacenter_config,
333 \&write_datacenter_config);
334
3351;